summaryrefslogtreecommitdiff
path: root/www/crm/wp-content/plugins/civicrm/civicrm/ext/api4/tests/phpunit/Entity
diff options
context:
space:
mode:
Diffstat (limited to 'www/crm/wp-content/plugins/civicrm/civicrm/ext/api4/tests/phpunit/Entity')
-rw-r--r--www/crm/wp-content/plugins/civicrm/civicrm/ext/api4/tests/phpunit/Entity/ConformanceTest.php226
-rw-r--r--www/crm/wp-content/plugins/civicrm/civicrm/ext/api4/tests/phpunit/Entity/ContactJoinTest.php103
-rw-r--r--www/crm/wp-content/plugins/civicrm/civicrm/ext/api4/tests/phpunit/Entity/EntityTest.php35
-rw-r--r--www/crm/wp-content/plugins/civicrm/civicrm/ext/api4/tests/phpunit/Entity/ParticipantTest.php200
4 files changed, 564 insertions, 0 deletions
diff --git a/www/crm/wp-content/plugins/civicrm/civicrm/ext/api4/tests/phpunit/Entity/ConformanceTest.php b/www/crm/wp-content/plugins/civicrm/civicrm/ext/api4/tests/phpunit/Entity/ConformanceTest.php
new file mode 100644
index 00000000..79fe5b30
--- /dev/null
+++ b/www/crm/wp-content/plugins/civicrm/civicrm/ext/api4/tests/phpunit/Entity/ConformanceTest.php
@@ -0,0 +1,226 @@
+<?php
+
+namespace Civi\Test\Api4\Entity;
+
+use Civi\Api4\Generic\AbstractEntity;
+use Civi\Api4\Entity;
+use Civi\Test\Api4\Service\TestCreationParameterProvider;
+use Civi\Test\Api4\Traits\TableDropperTrait;
+use Civi\Test\Api4\UnitTestCase;
+
+/**
+ * @group headless
+ */
+class ConformanceTest extends UnitTestCase {
+
+ use TableDropperTrait;
+ use \Civi\Test\Api4\Traits\OptionCleanupTrait {
+ setUp as setUpOptionCleanup;
+ }
+
+ /**
+ * @var TestCreationParameterProvider
+ */
+ protected $creationParamProvider;
+
+ /**
+ * Set up baseline for testing
+ */
+ public function setUp() {
+ $tablesToTruncate = [
+ 'civicrm_custom_group',
+ 'civicrm_custom_field',
+ 'civicrm_group',
+ 'civicrm_event',
+ 'civicrm_participant',
+ ];
+ $this->dropByPrefix('civicrm_value_myfavorite');
+ $this->cleanup(['tablesToTruncate' => $tablesToTruncate]);
+ $this->setUpOptionCleanup();
+ $this->loadDataSet('ConformanceTest');
+ $this->creationParamProvider = \Civi::container()->get('test.param_provider');
+ parent::setUp();
+ // calculateTaxAmount() for contribution triggers a deprecation notice
+ \PHPUnit_Framework_Error_Deprecated::$enabled = FALSE;
+ }
+
+ public function getEntities() {
+ $result = [];
+ $entities = Entity::get()->setCheckPermissions(FALSE)->execute();
+ foreach ($entities as $entity) {
+ if ($entity['name'] != 'Entity') {
+ $result[] = [$entity['name']];
+ }
+ }
+ return $result;
+ }
+
+ /**
+ * Fixme: This should use getEntities as a dataProvider but that fails for some reason
+ */
+ public function testConformance() {
+ $entities = $this->getEntities();
+ $this->assertNotEmpty($entities);
+
+ foreach ($entities as $data) {
+ $entity = $data[0];
+ $entityClass = 'Civi\Api4\\' . $entity;
+
+ $this->checkActions($entityClass);
+ $this->checkFields($entityClass, $entity);
+ $id = $this->checkCreation($entity, $entityClass);
+ $this->checkGet($entityClass, $id, $entity);
+ $this->checkUpdateFailsFromCreate($entityClass, $id);
+ $this->checkWrongParamType($entityClass);
+ $this->checkDeleteWithNoId($entityClass);
+ $this->checkDeletion($entityClass, $id);
+ $this->checkPostDelete($entityClass, $id, $entity);
+ }
+ }
+
+ /**
+ * @param string $entityClass
+ * @param $entity
+ */
+ protected function checkFields($entityClass, $entity) {
+ $fields = $entityClass::getFields()
+ ->setCheckPermissions(FALSE)
+ ->setIncludeCustom(FALSE)
+ ->execute()
+ ->indexBy('name');
+
+ $errMsg = sprintf('%s is missing required ID field', $entity);
+ $subset = ['data_type' => 'Integer'];
+
+ $this->assertArraySubset($subset, $fields['id'], $errMsg);
+ }
+
+ /**
+ * @param string $entityClass
+ */
+ protected function checkActions($entityClass) {
+ $actions = $entityClass::getActions()
+ ->setCheckPermissions(FALSE)
+ ->execute()
+ ->indexBy('name');
+
+ $this->assertNotEmpty($actions->getArrayCopy());
+ }
+
+ /**
+ * @param string $entity
+ * @param AbstractEntity|string $entityClass
+ *
+ * @return mixed
+ */
+ protected function checkCreation($entity, $entityClass) {
+ $requiredParams = $this->creationParamProvider->getRequired($entity);
+ $createResult = $entityClass::create()
+ ->setValues($requiredParams)
+ ->setCheckPermissions(FALSE)
+ ->execute()
+ ->first();
+
+ $this->assertArrayHasKey('id', $createResult, "create missing ID");
+ $id = $createResult['id'];
+
+ $this->assertGreaterThanOrEqual(1, $id, "$entity ID not positive");
+
+ return $id;
+ }
+
+ /**
+ * @param AbstractEntity|string $entityClass
+ * @param int $id
+ */
+ protected function checkUpdateFailsFromCreate($entityClass, $id) {
+ $exceptionThrown = '';
+ try {
+ $entityClass::create()
+ ->setCheckPermissions(FALSE)
+ ->addValue('id', $id)
+ ->execute();
+ }
+ catch (\API_Exception $e) {
+ $exceptionThrown = $e->getMessage();
+ }
+ $this->assertContains('id', $exceptionThrown);
+ }
+
+ /**
+ * @param AbstractEntity|string $entityClass
+ * @param int $id
+ * @param string $entity
+ */
+ protected function checkGet($entityClass, $id, $entity) {
+ $getResult = $entityClass::get()
+ ->setCheckPermissions(FALSE)
+ ->addWhere('id', '=', $id)
+ ->execute();
+
+ $errMsg = sprintf('Failed to fetch a %s after creation', $entity);
+ $this->assertEquals(1, count($getResult), $errMsg);
+ }
+
+ /**
+ * @param AbstractEntity|string $entityClass
+ */
+ protected function checkDeleteWithNoId($entityClass) {
+ $exceptionThrown = '';
+ try {
+ $entityClass::delete()
+ ->execute();
+ }
+ catch (\API_Exception $e) {
+ $exceptionThrown = $e->getMessage();
+ }
+ $this->assertContains('required', $exceptionThrown);
+ }
+
+ /**
+ * @param AbstractEntity|string $entityClass
+ */
+ protected function checkWrongParamType($entityClass) {
+ $exceptionThrown = '';
+ try {
+ $entityClass::get()
+ ->setCheckPermissions('nada')
+ ->execute();
+ }
+ catch (\API_Exception $e) {
+ $exceptionThrown = $e->getMessage();
+ }
+ $this->assertContains('checkPermissions', $exceptionThrown);
+ $this->assertContains('type', $exceptionThrown);
+ }
+
+ /**
+ * @param AbstractEntity|string $entityClass
+ * @param int $id
+ */
+ protected function checkDeletion($entityClass, $id) {
+ $deleteResult = $entityClass::delete()
+ ->setCheckPermissions(FALSE)
+ ->addWhere('id', '=', $id)
+ ->execute();
+
+ // should get back an array of deleted id
+ $this->assertEquals([$id], (array) $deleteResult);
+ }
+
+ /**
+ * @param AbstractEntity|string $entityClass
+ * @param int $id
+ * @param string $entity
+ */
+ protected function checkPostDelete($entityClass, $id, $entity) {
+ $getDeletedResult = $entityClass::get()
+ ->setCheckPermissions(FALSE)
+ ->addWhere('id', '=', $id)
+ ->execute();
+
+ $errMsg = sprintf('Entity "%s" was not deleted', $entity);
+ $this->assertEquals(0, count($getDeletedResult), $errMsg);
+ }
+
+}
diff --git a/www/crm/wp-content/plugins/civicrm/civicrm/ext/api4/tests/phpunit/Entity/ContactJoinTest.php b/www/crm/wp-content/plugins/civicrm/civicrm/ext/api4/tests/phpunit/Entity/ContactJoinTest.php
new file mode 100644
index 00000000..392e0466
--- /dev/null
+++ b/www/crm/wp-content/plugins/civicrm/civicrm/ext/api4/tests/phpunit/Entity/ContactJoinTest.php
@@ -0,0 +1,103 @@
+<?php
+
+namespace Civi\Test\Api4\Entity;
+
+use Civi\Api4\Contact;
+use Civi\Api4\OptionValue;
+use Civi\Test\Api4\UnitTestCase;
+
+/**
+ * @group headless
+ */
+class ContactJoinTest extends UnitTestCase {
+
+ public function setUpHeadless() {
+ $relatedTables = [
+ 'civicrm_address',
+ 'civicrm_email',
+ 'civicrm_phone',
+ 'civicrm_openid',
+ 'civicrm_im',
+ 'civicrm_website',
+ 'civicrm_activity',
+ 'civicrm_activity_contact',
+ ];
+
+ $this->cleanup(['tablesToTruncate' => $relatedTables]);
+ $this->loadDataSet('SingleContact');
+
+ return parent::setUpHeadless();
+ }
+
+ public function testContactJoin() {
+
+ $contact = $this->getReference('test_contact_1');
+ $entitiesToTest = ['Address', 'OpenID', 'IM', 'Website', 'Email', 'Phone'];
+
+ foreach ($entitiesToTest as $entity) {
+ $results = civicrm_api4($entity, 'get', [
+ 'where' => [['contact_id', '=', $contact['id']]],
+ 'select' => ['contact.display_name', 'contact.id'],
+ ]);
+ foreach ($results as $result) {
+ $this->assertEquals($contact['id'], $result['contact']['id']);
+ $this->assertEquals($contact['display_name'], $result['contact']['display_name']);
+ }
+ }
+ }
+
+ public function testJoinToPCMWillReturnArray() {
+ $contact = Contact::create()->setValues([
+ 'preferred_communication_method' => [1, 2, 3],
+ 'contact_type' => 'Individual',
+ 'first_name' => 'Test',
+ 'last_name' => 'PCM',
+ ])->execute()->first();
+
+ $fetchedContact = Contact::get()
+ ->addWhere('id', '=', $contact['id'])
+ ->addSelect('preferred_communication_method')
+ ->execute()
+ ->first();
+
+ $this->assertCount(3, $fetchedContact["preferred_communication_method"]);
+ }
+
+ public function testJoinToPCMOptionValueWillShowLabel() {
+ $options = OptionValue::get()
+ ->addWhere('option_group.name', '=', 'preferred_communication_method')
+ ->execute()
+ ->getArrayCopy();
+
+ $optionValues = array_column($options, 'value');
+ $labels = array_column($options, 'label');
+
+ $contact = Contact::create()->setValues([
+ 'preferred_communication_method' => $optionValues,
+ 'contact_type' => 'Individual',
+ 'first_name' => 'Test',
+ 'last_name' => 'PCM',
+ ])->execute()->first();
+
+ $contact2 = Contact::create()->setValues([
+ 'preferred_communication_method' => $optionValues,
+ 'contact_type' => 'Individual',
+ 'first_name' => 'Test',
+ 'last_name' => 'PCM2',
+ ])->execute()->first();
+
+ $contactIds = array_column([$contact, $contact2], 'id');
+
+ $fetchedContact = Contact::get()
+ ->addWhere('id', 'IN', $contactIds)
+ ->addSelect('preferred_communication_method.label')
+ ->execute()
+ ->first();
+
+ $preferredMethod = $fetchedContact['preferred_communication_method'];
+ $returnedLabels = array_column($preferredMethod, 'label');
+
+ $this->assertEquals($labels, $returnedLabels);
+ }
+
+}
diff --git a/www/crm/wp-content/plugins/civicrm/civicrm/ext/api4/tests/phpunit/Entity/EntityTest.php b/www/crm/wp-content/plugins/civicrm/civicrm/ext/api4/tests/phpunit/Entity/EntityTest.php
new file mode 100644
index 00000000..8f7ecd00
--- /dev/null
+++ b/www/crm/wp-content/plugins/civicrm/civicrm/ext/api4/tests/phpunit/Entity/EntityTest.php
@@ -0,0 +1,35 @@
+<?php
+
+namespace Civi\Test\Api4\Entity;
+
+use Civi\Api4\Entity;
+use Civi\Test\Api4\UnitTestCase;
+
+/**
+ * @group headless
+ */
+class EntityTest extends UnitTestCase {
+
+ public function testEntityGet() {
+ $result = Entity::get()
+ ->setCheckPermissions(FALSE)
+ ->execute()
+ ->indexBy('name');
+ $this->assertArrayHasKey('Entity', $result,
+ "Entity::get missing itself");
+ $this->assertArrayHasKey('Participant', $result,
+ "Entity::get missing Participant");
+ }
+
+ public function testEntity() {
+ $result = Entity::getActions()
+ ->setCheckPermissions(FALSE)
+ ->execute()
+ ->indexBy('name');
+ $this->assertNotContains(
+ 'create',
+ array_keys((array) $result),
+ "Entity entity has more than basic actions");
+ }
+
+}
diff --git a/www/crm/wp-content/plugins/civicrm/civicrm/ext/api4/tests/phpunit/Entity/ParticipantTest.php b/www/crm/wp-content/plugins/civicrm/civicrm/ext/api4/tests/phpunit/Entity/ParticipantTest.php
new file mode 100644
index 00000000..8236efb0
--- /dev/null
+++ b/www/crm/wp-content/plugins/civicrm/civicrm/ext/api4/tests/phpunit/Entity/ParticipantTest.php
@@ -0,0 +1,200 @@
+<?php
+
+namespace Civi\Test\Api4\Entity;
+
+use Civi\Api4\Participant;
+use Civi\Test\Api4\UnitTestCase;
+
+/**
+ * @group headless
+ */
+class ParticipantTest extends UnitTestCase {
+
+ public function setUp() {
+ parent::setUp();
+ $cleanup_params = [
+ 'tablesToTruncate' => [
+ 'civicrm_event',
+ 'civicrm_participant',
+ ],
+ ];
+ $this->cleanup($cleanup_params);
+ }
+
+ public function testGetActions() {
+ $result = Participant::getActions()
+ ->setCheckPermissions(FALSE)
+ ->execute()
+ ->indexBy('name');
+
+ $getParams = $result['get']['params'];
+ $whereDescription = 'Criteria for selecting items.';
+
+ $this->assertEquals(TRUE, $getParams['checkPermissions']['default']);
+ $this->assertEquals($whereDescription, $getParams['where']['description']);
+ }
+
+ public function testGet() {
+ $rows = $this->getRowCount('civicrm_participant');
+ if ($rows > 0) {
+ $this->markTestSkipped('Participant table must be empty');
+ }
+
+ // With no records:
+ $result = Participant::get()->setCheckPermissions(FALSE)->execute();
+ $this->assertEquals(0, $result->count(), "count of empty get is not 0");
+
+ // Check that the $result knows what the inputs were
+ $this->assertEquals('Participant', $result->entity);
+ $this->assertEquals('get', $result->action);
+ $this->assertEquals(4, $result->version);
+
+ // Create some test related records before proceeding
+ $participantCount = 20;
+ $contactCount = 7;
+ $eventCount = 5;
+
+ // All events will either have this number or one less because of the
+ // rotating participation creation method.
+ $expectedFirstEventCount = ceil($participantCount / $eventCount);
+
+ $dummy = [
+ 'contacts' => $this->createEntity([
+ 'type' => 'Individual',
+ 'count' => $contactCount,
+ 'seq' => 1]),
+ 'events' => $this->createEntity([
+ 'type' => 'Event',
+ 'count' => $eventCount,
+ 'seq' => 1]),
+ 'sources' => ['Paddington', 'Springfield', 'Central'],
+ ];
+
+ // - create dummy participants record
+ for ($i = 0; $i < $participantCount; $i++) {
+ $dummy['participants'][$i] = $this->sample([
+ 'type' => 'Participant',
+ 'overrides' => [
+ 'event_id' => $dummy['events'][$i % $eventCount]['id'],
+ 'contact_id' => $dummy['contacts'][$i % $contactCount]['id'],
+ 'source' => $dummy['sources'][$i % 3], // 3 = number of sources
+ ]])['sample_params'];
+
+ Participant::create()
+ ->setValues($dummy['participants'][$i])
+ ->setCheckPermissions(FALSE)
+ ->execute();
+ }
+ $sqlCount = $this->getRowCount('civicrm_participant');
+ $this->assertEquals($participantCount, $sqlCount, "Unexpected count");
+
+ $firstEventId = $dummy['events'][0]['id'];
+ $secondEventId = $dummy['events'][1]['id'];
+ $firstContactId = $dummy['contacts'][0]['id'];
+
+ $firstOnlyResult = Participant::get()
+ ->setCheckPermissions(FALSE)
+ ->addClause('AND', ['event_id', '=', $firstEventId])
+ ->execute();
+
+ $this->assertEquals($expectedFirstEventCount, count($firstOnlyResult),
+ "count of first event is not $expectedFirstEventCount");
+
+ // get first two events using different methods
+ $firstTwo = Participant::get()
+ ->setCheckPermissions(FALSE)
+ ->addWhere('event_id', 'IN', [$firstEventId, $secondEventId])
+ ->execute();
+
+ $firstResult = $result->first();
+
+ // verify counts
+ // count should either twice the first event count or one less
+ $this->assertLessThanOrEqual(
+ $expectedFirstEventCount * 2,
+ count($firstTwo),
+ "count is too high"
+ );
+
+ $this->assertGreaterThanOrEqual(
+ $expectedFirstEventCount * 2 - 1,
+ count($firstTwo),
+ "count is too low"
+ );
+
+ $firstParticipantResult = Participant::get()
+ ->setCheckPermissions(FALSE)
+ ->addWhere('event_id', '=', $firstEventId)
+ ->addWhere('contact_id', '=', $firstContactId)
+ ->execute();
+
+ $this->assertEquals(1, count($firstParticipantResult), "more than one registration");
+
+ $firstParticipantId = $firstParticipantResult->first()['id'];
+
+ // get a result which excludes $first_participant
+ $otherParticipantResult = Participant::get()
+ ->setCheckPermissions(FALSE)
+ ->setSelect(['id'])
+ ->addClause('NOT', [
+ ['event_id', '=', $firstEventId],
+ ['contact_id', '=', $firstContactId],
+ ]
+ )
+ ->execute()
+ ->indexBy('id');
+
+ // check alternate syntax for NOT
+ $otherParticipantResult2 = Participant::get()
+ ->setCheckPermissions(FALSE)
+ ->setSelect(['id'])
+ ->addClause('NOT', 'AND', [
+ ['event_id', '=', $firstEventId],
+ ['contact_id', '=', $firstContactId],
+ ]
+ )
+ ->execute()
+ ->indexBy('id');
+
+ $this->assertEquals($otherParticipantResult, $otherParticipantResult2);
+
+ $this->assertEquals($participantCount - 1,
+ count($otherParticipantResult),
+ "failed to exclude a single record on complex criteria");
+ // check the record we have excluded is the right one:
+
+ $this->assertFalse(
+ $otherParticipantResult->offsetExists($firstParticipantId),
+ 'excluded wrong record');
+
+ // retrieve a participant record and update some records
+ $patchRecord = [
+ 'source' => "not " . $firstResult['source'],
+ ];
+
+ Participant::update()
+ ->addWhere('event_id', '=', $firstEventId)
+ ->setCheckPermissions(FALSE)
+ ->setLimit(20)
+ ->setValues($patchRecord)
+ ->setCheckPermissions(FALSE)
+ ->execute();
+
+ // - delete some records
+ $secondEventId = $dummy['events'][1]['id'];
+ $deleteResult = Participant::delete()
+ ->addWhere('event_id', '=', $secondEventId)
+ ->setCheckPermissions(FALSE)
+ ->execute();
+ $expectedDeletes = [2, 7, 12, 17];
+ $this->assertEquals($expectedDeletes, (array) $deleteResult,
+ "didn't delete every second record as expected");
+
+ $sqlCount = $this->getRowCount('civicrm_participant');
+ $this->assertEquals(
+ $participantCount - count($expectedDeletes),
+ $sqlCount,
+ "records not gone from database after delete");
+ }
+
+}