You are here

public function GroupTest::testGroupMembership in farmOS 2.x

Test asset group membership.

File

modules/asset/group/tests/src/Kernel/GroupTest.php, line 76

Class

GroupTest
Tests for farmOS group membership logic.

Namespace

Drupal\Tests\farm_group\Kernel

Code

public function testGroupMembership() {

  // Create an animal asset.

  /** @var \Drupal\asset\Entity\AssetInterface $animal */
  $animal = Asset::create([
    'type' => 'animal',
    'name' => $this
      ->randomMachineName(),
    'status' => 'active',
  ]);
  $animal
    ->save();

  // Populate a cache value dependent on the animal's cache tags.
  $this
    ->populateEntityTestCache($animal);

  // Create group assets.

  /** @var \Drupal\asset\Entity\AssetInterface $first_group */
  $first_group = Asset::create([
    'type' => 'group',
    'name' => $this
      ->randomMachineName(),
    'status' => 'active',
  ]);
  $first_group
    ->save();

  /** @var \Drupal\asset\Entity\AssetInterface $second_group */
  $second_group = Asset::create([
    'type' => 'group',
    'name' => $this
      ->randomMachineName(),
    'status' => 'active',
  ]);
  $second_group
    ->save();

  // When an asset has no group assignment logs, it has no group membership.
  $this
    ->assertFalse($this->groupMembership
    ->hasGroup($animal), 'New assets do not have group membership.');
  $this
    ->assertEmpty($this->groupMembership
    ->getGroup($animal), 'New assets do not reference any groups.');
  $this
    ->assertEmpty($this->groupMembership
    ->getGroupMembers([
    $first_group,
  ]), 'New groups have no members.');
  $this
    ->assertEmpty($this->groupMembership
    ->getGroupMembers([
    $second_group,
  ]), 'New groups have no members.');

  // Assert that the animal's cache tags were not invalidated.
  $this
    ->assertEntityTestCache($animal, TRUE);

  // Create a "done" log that assigns the animal to the group.

  /** @var \Drupal\log\Entity\LogInterface $first_log */
  $first_log = Log::create([
    'type' => 'test',
    'status' => 'done',
    'is_group_assignment' => TRUE,
    'group' => [
      'target_id' => $first_group
        ->id(),
    ],
    'asset' => [
      'target_id' => $animal
        ->id(),
    ],
  ]);
  $first_log
    ->save();

  // When an asset has a done group assignment logs, it has group membership.
  $this
    ->assertTrue($this->groupMembership
    ->hasGroup($animal), 'Asset with group assignment has group membership.');
  $this
    ->assertEquals($first_group
    ->id(), $this->groupMembership
    ->getGroup($animal)[0]
    ->id(), 'Asset with group assignment is in the assigned group.');
  $this
    ->assertEquals(1, count($this->groupMembership
    ->getGroupMembers([
    $first_group,
  ])), 'When an asset becomes a group member, the group has one member.');
  $this
    ->assertEmpty($this->groupMembership
    ->getGroupMembers([
    $second_group,
  ]), 'When an asset becomes a group member, other groups are unaffected.');

  // Assert that the animal's cache tags were invalidated.
  $this
    ->assertEntityTestCache($animal, FALSE);

  // Re-populate a cache value dependent on the animal's cache tags.
  $this
    ->populateEntityTestCache($animal);

  // Create a "pending" log that assigns the animal to the second group.

  /** @var \Drupal\log\Entity\LogInterface $second_log */
  $second_log = Log::create([
    'type' => 'test',
    'status' => 'pending',
    'is_group_assignment' => TRUE,
    'group' => [
      'target_id' => $second_group
        ->id(),
    ],
    'asset' => [
      'target_id' => $animal
        ->id(),
    ],
  ]);
  $second_log
    ->save();

  // When an asset has a pending group assignment logs, it still has the same
  // group membership as before.
  $this
    ->assertEquals($first_group
    ->id(), $this->groupMembership
    ->getGroup($animal)[0]
    ->id(), 'Pending group assignment logs do not affect membership.');
  $this
    ->assertEmpty($this->groupMembership
    ->getGroupMembers([
    $second_group,
  ]), 'Groups with only pending membership have zero members.');

  // Assert that the animal's cache tags were not invalidated.
  $this
    ->assertEntityTestCache($animal, TRUE);

  // When the log is marked as "done", the asset's membership is updated.
  $second_log->status = 'done';
  $second_log
    ->save();
  $this
    ->assertEquals($second_group
    ->id(), $this->groupMembership
    ->getGroup($animal)[0]
    ->id(), 'A second group assignment log updates group membership.');
  $this
    ->assertEquals(1, count($this->groupMembership
    ->getGroupMembers([
    $second_group,
  ])), 'Completed group assignment logs add group members.');

  // Assert that the animal's cache tags were invalidated.
  $this
    ->assertEntityTestCache($animal, FALSE);

  // Re-populate a cache value dependent on the animal's cache tags.
  $this
    ->populateEntityTestCache($animal);

  // Create a third "done" log in the future.

  /** @var \Drupal\log\Entity\LogInterface $third_log */
  $third_log = Log::create([
    'type' => 'test',
    'timestamp' => \Drupal::time()
      ->getRequestTime() + 86400,
    'status' => 'done',
    'is_group_assignment' => TRUE,
    'group' => [
      'target_id' => $first_group
        ->id(),
    ],
    'asset' => [
      'target_id' => $animal
        ->id(),
    ],
  ]);
  $third_log
    ->save();

  // When an asset has a "done" group assignment log in the future, the asset
  // group membership remains the same as the previous "done" movement log.
  $this
    ->assertEquals($second_group
    ->id(), $this->groupMembership
    ->getGroup($animal)[0]
    ->id(), 'A third group assignment log in the future does not update group membership.');
  $this
    ->assertEquals(1, count($this->groupMembership
    ->getGroupMembers([
    $second_group,
  ])), 'Future group assignment logs do not affect members.');

  // Assert that the animal's cache tags were not invalidated.
  $this
    ->assertEntityTestCache($animal, TRUE);

  // Create a fourth log with no group reference.

  /** @var \Drupal\log\Entity\LogInterface $fourth_log */
  $fourth_log = Log::create([
    'type' => 'test',
    'status' => 'done',
    'is_group_assignment' => TRUE,
    'group' => [],
    'asset' => [
      'target_id' => $animal
        ->id(),
    ],
  ]);
  $fourth_log
    ->save();

  // When a group assignment log is created with no group references, it
  // effectively "unsets" the asset's group membership.
  $this
    ->assertFalse($this->groupMembership
    ->hasGroup($animal), 'Asset group membership can be unset.');
  $this
    ->assertEmpty($this->groupMembership
    ->getGroup($animal), 'Unset group membership does not reference any groups.');
  $this
    ->assertEquals(0, count($this->groupMembership
    ->getGroupMembers([
    $first_group,
  ])), 'Unset group membership unsets group members.');
  $this
    ->assertEquals(0, count($this->groupMembership
    ->getGroupMembers([
    $second_group,
  ])), 'Unset group membership unsets group members.');

  // Assert that the animal's cache tags were invalidated.
  $this
    ->assertEntityTestCache($animal, FALSE);

  // Re-populate a cache value dependent on the animal's cache tags.
  $this
    ->populateEntityTestCache($animal);

  // Delete the fourth log.
  $fourth_log
    ->delete();

  // When a group membership is deleted the last group membership log is used.
  $this
    ->assertEquals($second_group
    ->id(), $this->groupMembership
    ->getGroup($animal)[0]
    ->id(), 'Deleting a group membership log updates group membership.');
  $this
    ->assertEquals(1, count($this->groupMembership
    ->getGroupMembers([
    $second_group,
  ])), 'Deleting a group membership log updates group members.');

  // Assert that the animal's cache tags were invalidated.
  $this
    ->assertEntityTestCache($animal, FALSE);

  // Create a second animal.

  /** @var \Drupal\asset\Entity\AssetInterface $second_animal */
  $second_animal = Asset::create([
    'type' => 'animal',
    'name' => $this
      ->randomMachineName(),
    'status' => 'active',
  ]);
  $second_animal
    ->save();

  // Create a "done" log that assigns the second animal to the first group.

  /** @var \Drupal\log\Entity\LogInterface $fifth_log */
  $fifth_log = Log::create([
    'type' => 'test',
    'status' => 'done',
    'is_group_assignment' => TRUE,
    'group' => [
      'target_id' => $first_group
        ->id(),
    ],
    'asset' => [
      'target_id' => $second_animal
        ->id(),
    ],
  ]);
  $fifth_log
    ->save();

  // Assert that group members from multiple groups can be queried together.
  $this
    ->assertEquals($second_group
    ->id(), $this->groupMembership
    ->getGroup($animal)[0]
    ->id(), 'The first animal is in the second group.');
  $this
    ->assertEquals($first_group
    ->id(), $this->groupMembership
    ->getGroup($second_animal)[0]
    ->id(), 'The second animal is in the first group.');
  $group_members = $this->groupMembership
    ->getGroupMembers([
    $first_group,
    $second_group,
  ]);
  $this
    ->assertEquals(2, count($group_members), 'Group members from multiple groups can be queried together.');
}