From 601ab7bb71cd83de6cf136d850fe9becd325c0a6 Mon Sep 17 00:00:00 2001 From: Dominic Tubach Date: Thu, 26 Oct 2023 10:39:48 +0200 Subject: [PATCH] SelectFactory: Select `Extra` fields only if explicitly selected Fix tests by using `Group` entity instead of `Product` because `Product` is not in CiviCRM core, anymore. --- Civi/RemoteTools/Helper/SelectFactory.php | 18 +- tests/phpunit/Civi/Api4/RemoteEntityTest.php | 247 +++++++++--------- ...tRemoteProduct.php => TestRemoteGroup.php} | 6 +- ... TestRemoteGroupReadOnlyEntityProfile.php} | 6 +- ...TestRemoteGroupReadWriteEntityProfile.php} | 9 +- .../{ProductFixture.php => GroupFixture.php} | 14 +- .../RemoteTools/Helper/SelectFactoryTest.php | 42 +++ tests/phpunit/bootstrap.php | 14 +- 8 files changed, 210 insertions(+), 146 deletions(-) rename tests/phpunit/Civi/Api4/{TestRemoteProduct.php => TestRemoteGroup.php} (86%) rename tests/phpunit/Civi/RemoteTools/EntityProfile/{TestRemoteProductReadOnlyEntityProfile.php => TestRemoteGroupReadOnlyEntityProfile.php} (82%) rename tests/phpunit/Civi/RemoteTools/EntityProfile/{TestRemoteProductReadWriteEntityProfile.php => TestRemoteGroupReadWriteEntityProfile.php} (85%) rename tests/phpunit/Civi/RemoteTools/Fixture/{ProductFixture.php => GroupFixture.php} (79%) diff --git a/Civi/RemoteTools/Helper/SelectFactory.php b/Civi/RemoteTools/Helper/SelectFactory.php index 8ebfcdb..7b12d45 100644 --- a/Civi/RemoteTools/Helper/SelectFactory.php +++ b/Civi/RemoteTools/Helper/SelectFactory.php @@ -25,6 +25,8 @@ final class SelectFactory implements SelectFactoryInterface { /** * @inheritDoc + * + * phpcs:disable Generic.Metrics.CyclomaticComplexity.TooHigh */ public function getSelects( array $select, @@ -32,12 +34,20 @@ public function getSelects( array $remoteFields, callable $implicitJoinAllowedCallback ): array { + // phpcs:enable if ([] === $select || in_array('*', $select, TRUE)) { $rowCountSelected = in_array('row_count', $select, TRUE); - $select = array_filter( - array_keys($remoteFields), - fn (string $fieldName) => !FieldUtil::isJoinedField($fieldName), - ); + $select = array_keys(array_filter( + $remoteFields, + // @phpstan-ignore-next-line + fn (array $field) => (!FieldUtil::isJoinedField($field['name']) + // CiviCRM excludes fields of type "Extra" if not explicitly selected, + // see \Civi\Api4\Query\Api4SelectQuery. This includes fields like + // "has_base" for managed entity types which are fetched using a sub + // query. + && 'Extra' !== ($field['type'] ?? NULL)) + || in_array($field['name'], $select, TRUE), + )); if ($rowCountSelected) { $select[] = 'row_count'; } diff --git a/tests/phpunit/Civi/Api4/RemoteEntityTest.php b/tests/phpunit/Civi/Api4/RemoteEntityTest.php index e73e544..99202e1 100644 --- a/tests/phpunit/Civi/Api4/RemoteEntityTest.php +++ b/tests/phpunit/Civi/Api4/RemoteEntityTest.php @@ -21,10 +21,10 @@ use Civi\API\Exception\UnauthorizedException; use Civi\RemoteTools\AbstractRemoteToolsHeadlessTestCase; -use Civi\RemoteTools\EntityProfile\TestRemoteProductReadOnlyEntityProfile; -use Civi\RemoteTools\EntityProfile\TestRemoteProductReadWriteEntityProfile; +use Civi\RemoteTools\EntityProfile\TestRemoteGroupReadOnlyEntityProfile; +use Civi\RemoteTools\EntityProfile\TestRemoteGroupReadWriteEntityProfile; use Civi\RemoteTools\Exception\ValidationFailedException; -use Civi\RemoteTools\Fixture\ProductFixture; +use Civi\RemoteTools\Fixture\GroupFixture; use DMS\PHPUnitExtensions\ArraySubset\ArraySubsetAsserts; /** @@ -38,15 +38,18 @@ final class RemoteEntityTest extends AbstractRemoteToolsHeadlessTestCase { protected function setUp(): void { parent::setUp(); - $this->setUserPermissions(['access TestRemoteProduct']); + $this->setUserPermissions(['access TestRemoteGroup']); + Group::delete(FALSE) + ->addWhere('id', 'IS NOT NULL') + ->execute(); } /** * @covers \Civi\RemoteTools\Api4\Action\RemoteCheckAccessAction */ public function testCheckAccess(): void { - $result = TestRemoteProduct::checkAccess() - ->setProfile(TestRemoteProductReadOnlyEntityProfile::NAME) + $result = TestRemoteGroup::checkAccess() + ->setProfile(TestRemoteGroupReadOnlyEntityProfile::NAME) ->setAction('get') ->addValue('id', 1) ->execute(); @@ -59,8 +62,8 @@ public function testCheckAccess(): void { */ public function testCheckAccessPermissionMissing(): void { $this->setUserPermissions(['access CiviCRM']); - $result = TestRemoteProduct::checkAccess() - ->setProfile(TestRemoteProductReadOnlyEntityProfile::NAME) + $result = TestRemoteGroup::checkAccess() + ->setProfile(TestRemoteGroupReadOnlyEntityProfile::NAME) ->setAction('get') ->addValue('id', 1) ->execute(); @@ -74,7 +77,7 @@ public function testCheckAccessPermissionMissing(): void { public function testCheckAccessWithoutProfile(): void { $this->expectException(\CRM_Core_Exception::class); $this->expectExceptionMessage('Parameter "profile" is required.'); - TestRemoteProduct::checkAccess() + TestRemoteGroup::checkAccess() ->setAction('get') ->addValue('id', 1) ->execute(); @@ -84,31 +87,31 @@ public function testCheckAccessWithoutProfile(): void { * @covers \Civi\RemoteTools\Api4\Action\RemoteDeleteAction */ public function testDelete(): void { - $product1 = ProductFixture::addProduct(); - $product2 = ProductFixture::addProduct(); + $group1 = GroupFixture::addGroup(); + $group2 = GroupFixture::addGroup(); - $result = TestRemoteProduct::delete() - ->setProfile(TestRemoteProductReadWriteEntityProfile::NAME) - ->addWhere('id', '=', $product1['id']) + $result = TestRemoteGroup::delete() + ->setProfile(TestRemoteGroupReadWriteEntityProfile::NAME) + ->addWhere('id', '=', $group1['id']) ->execute(); - static::assertArraySubset([['id' => $product1['id']]], $result->getArrayCopy()); + static::assertArraySubset([['id' => $group1['id']]], $result->getArrayCopy()); - static::assertSame([$product2['id']], Product::get(FALSE)->execute()->column('id')); + static::assertSame([$group2['id']], Group::get(FALSE)->execute()->column('id')); } /** * @covers \Civi\RemoteTools\Api4\Action\RemoteDeleteAction */ public function testDeletePermissionMissing(): void { - $product = ProductFixture::addProduct(); + $group = GroupFixture::addGroup(); - $result = TestRemoteProduct::delete() - ->setProfile(TestRemoteProductReadOnlyEntityProfile::NAME) - ->addWhere('id', '=', $product['id']) + $result = TestRemoteGroup::delete() + ->setProfile(TestRemoteGroupReadOnlyEntityProfile::NAME) + ->addWhere('id', '=', $group['id']) ->execute(); static::assertSame([], $result->getArrayCopy()); - static::assertSame([$product['id']], Product::get(FALSE)->execute()->column('id')); + static::assertSame([$group['id']], Group::get(FALSE)->execute()->column('id')); } /** @@ -117,7 +120,7 @@ public function testDeletePermissionMissing(): void { public function testDeleteWithoutProfile(): void { $this->expectException(\CRM_Core_Exception::class); $this->expectExceptionMessage('Parameter "profile" is required.'); - TestRemoteProduct::delete() + TestRemoteGroup::delete() ->addWhere('id', '=', 12) ->execute(); } @@ -126,7 +129,7 @@ public function testDeleteWithoutProfile(): void { * @covers \Civi\RemoteTools\Api4\Action\RemoteGetActions */ public function testGetActions(): void { - $result = TestRemoteProduct::getActions()->execute(); + $result = TestRemoteGroup::getActions()->execute(); static::assertEquals([ 'checkAccess', 'delete', @@ -146,11 +149,11 @@ public function testGetActions(): void { * @covers \Civi\RemoteTools\Api4\Action\RemoteGetFieldsAction */ public function testGetFields(): void { - $result = TestRemoteProduct::getFields() - ->setProfile(TestRemoteProductReadOnlyEntityProfile::NAME) + $result = TestRemoteGroup::getFields() + ->setProfile(TestRemoteGroupReadOnlyEntityProfile::NAME) ->execute(); - $expectedFieldNames = Product::getFields(FALSE)->execute()->column('name'); + $expectedFieldNames = Group::getFields(FALSE)->execute()->column('name'); static::assertArraySubset($expectedFieldNames, $result->column('name')); } @@ -158,7 +161,7 @@ public function testGetFields(): void { * @covers \Civi\RemoteTools\Api4\Action\RemoteGetFieldsAction */ public function testGetFieldsWithoutProfile(): void { - $result = TestRemoteProduct::getFields()->execute(); + $result = TestRemoteGroup::getFields()->execute(); static::assertCount(1, $result); static::assertSame(['id'], $result->column('name')); } @@ -167,36 +170,37 @@ public function testGetFieldsWithoutProfile(): void { * @covers \Civi\RemoteTools\Api4\Action\RemoteGetAction */ public function testGet(): void { - $result = TestRemoteProduct::get() - ->setProfile(TestRemoteProductReadOnlyEntityProfile::NAME) + $result = TestRemoteGroup::get() + ->setProfile(TestRemoteGroupReadOnlyEntityProfile::NAME) ->execute(); static::assertCount(0, $result); - $product = ProductFixture::addProduct(); - $product = Product::get(FALSE) - ->addWhere('id', '=', $product['id']) + $group = GroupFixture::addGroup(); + $group = Group::get(FALSE) + ->addWhere('id', '=', $group['id']) ->execute() ->single(); - $result = TestRemoteProduct::get() - ->setProfile(TestRemoteProductReadOnlyEntityProfile::NAME) + $result = TestRemoteGroup::get() + ->setProfile(TestRemoteGroupReadOnlyEntityProfile::NAME) + ->addSelect('*', 'CAN_delete', 'CAN_update') ->execute(); static::assertCount(1, $result); - $expectedRemoteProduct = $product + [ + $expectedRemoteGroup = $group + [ 'CAN_delete' => FALSE, 'CAN_update' => FALSE, ]; - static::assertEquals([$expectedRemoteProduct], $result->getArrayCopy()); + static::assertEquals([$expectedRemoteGroup], $result->getArrayCopy()); - $result = TestRemoteProduct::get() - ->setProfile(TestRemoteProductReadOnlyEntityProfile::NAME) - ->addWhere('id', '=', $product['id']) + $result = TestRemoteGroup::get() + ->setProfile(TestRemoteGroupReadOnlyEntityProfile::NAME) + ->addWhere('id', '=', $group['id']) ->execute(); static::assertCount(1, $result); - static::assertEquals([$expectedRemoteProduct], $result->getArrayCopy()); + static::assertEquals([$group], $result->getArrayCopy()); - $result = TestRemoteProduct::get() - ->setProfile(TestRemoteProductReadOnlyEntityProfile::NAME) - ->addWhere('id', '=', $product['id'] + 1) + $result = TestRemoteGroup::get() + ->setProfile(TestRemoteGroupReadOnlyEntityProfile::NAME) + ->addWhere('id', '=', $group['id'] + 1) ->execute(); static::assertCount(0, $result); } @@ -207,15 +211,15 @@ public function testGet(): void { public function testGetWithoutProfile(): void { $this->expectException(\CRM_Core_Exception::class); $this->expectExceptionMessage('Parameter "profile" is required.'); - TestRemoteProduct::get()->execute(); + TestRemoteGroup::get()->execute(); } /** * @covers \Civi\RemoteTools\Api4\Action\RemoteGetCreateFormAction */ public function testGetCreateForm(): void { - $result = TestRemoteProduct::getCreateForm() - ->setProfile(TestRemoteProductReadWriteEntityProfile::NAME) + $result = TestRemoteGroup::getCreateForm() + ->setProfile(TestRemoteGroupReadWriteEntityProfile::NAME) ->setArguments(['x' => 'y']) ->execute(); $resultJson = json_encode($result->getArrayCopy(), JSON_THROW_ON_ERROR); @@ -229,8 +233,8 @@ public function testGetCreateForm(): void { public function testGetCreateFormUnauthorized(): void { $this->expectException(UnauthorizedException::class); $this->expectExceptionMessage('Permission to create entity is missing'); - TestRemoteProduct::getCreateForm() - ->setProfile(TestRemoteProductReadOnlyEntityProfile::NAME) + TestRemoteGroup::getCreateForm() + ->setProfile(TestRemoteGroupReadOnlyEntityProfile::NAME) ->setArguments(['x' => 'y']) ->execute(); } @@ -241,7 +245,7 @@ public function testGetCreateFormUnauthorized(): void { public function testGetCreateFormWithoutProfile(): void { $this->expectException(\CRM_Core_Exception::class); $this->expectExceptionMessage('Parameter "profile" is required.'); - $result = TestRemoteProduct::getCreateForm() + $result = TestRemoteGroup::getCreateForm() ->execute(); } @@ -249,20 +253,20 @@ public function testGetCreateFormWithoutProfile(): void { * @covers \Civi\RemoteTools\Api4\Action\RemoteValidateCreateFormAction */ public function testValidateCreateForm(): void { - $result = TestRemoteProduct::validateCreateForm() - ->setProfile(TestRemoteProductReadWriteEntityProfile::NAME) + $result = TestRemoteGroup::validateCreateForm() + ->setProfile(TestRemoteGroupReadWriteEntityProfile::NAME) ->setArguments(['x' => 'y']) - ->setData(['foo' => 'bar']) + ->setData(['name' => 'bar', 'foo' => 'bar']) ->execute(); static::assertFalse($result['valid']); - // "name" is required, additional properties are not allowed. + // "title" is required, additional properties (foo) are not allowed. // @phpstan-ignore-next-line static::assertCount(2, $result['errors']['']); - $result = TestRemoteProduct::validateCreateForm() - ->setProfile(TestRemoteProductReadWriteEntityProfile::NAME) + $result = TestRemoteGroup::validateCreateForm() + ->setProfile(TestRemoteGroupReadWriteEntityProfile::NAME) ->setArguments(['x' => 'y']) - ->setData(['name' => 'bar']) + ->setData(['name' => 'bar', 'title' => 'Bar']) ->execute(); static::assertTrue($result['valid']); @@ -275,8 +279,8 @@ public function testValidateCreateForm(): void { public function tesValidateCreateFormUnauthorized(): void { $this->expectException(UnauthorizedException::class); $this->expectExceptionMessage('Permission to create entity is missing'); - TestRemoteProduct::validateCreateForm() - ->setProfile(TestRemoteProductReadOnlyEntityProfile::NAME) + TestRemoteGroup::validateCreateForm() + ->setProfile(TestRemoteGroupReadOnlyEntityProfile::NAME) ->setArguments(['x' => 'y']) ->setData(['foo' => 'bar']) ->execute(); @@ -288,7 +292,7 @@ public function tesValidateCreateFormUnauthorized(): void { public function testValidateCreateFormWithoutProfile(): void { $this->expectException(\CRM_Core_Exception::class); $this->expectExceptionMessage('Parameter "profile" is required.'); - TestRemoteProduct::validateCreateForm() + TestRemoteGroup::validateCreateForm() ->execute(); } @@ -296,15 +300,16 @@ public function testValidateCreateFormWithoutProfile(): void { * @covers \Civi\RemoteTools\Api4\Action\RemoteSubmitCreateFormAction */ public function testSubmitCreateForm(): void { - $result = TestRemoteProduct::submitCreateForm() - ->setProfile(TestRemoteProductReadWriteEntityProfile::NAME) + $result = TestRemoteGroup::submitCreateForm() + ->setProfile(TestRemoteGroupReadWriteEntityProfile::NAME) ->setArguments(['x' => 'y']) - ->setData(['name' => 'bar']) + ->setData(['name' => 'bar', 'title' => 'Bar']) ->execute(); static::assertSame(['message' => 'Saved successfully'], $result->getArrayCopy()); - $result = Product::get(FALSE) + $result = Group::get(FALSE) ->addWhere('name', '=', 'bar') + ->addWhere('title', '=', 'Bar') ->execute(); static::assertCount(1, $result); } @@ -315,8 +320,8 @@ public function testSubmitCreateForm(): void { public function testSubmitCreateFormUnauthorized(): void { $this->expectException(UnauthorizedException::class); $this->expectExceptionMessage('Permission to create entity is missing'); - TestRemoteProduct::submitCreateForm() - ->setProfile(TestRemoteProductReadOnlyEntityProfile::NAME) + TestRemoteGroup::submitCreateForm() + ->setProfile(TestRemoteGroupReadOnlyEntityProfile::NAME) ->setArguments(['x' => 'y']) ->setData(['foo' => 'bar']) ->execute(); @@ -328,7 +333,7 @@ public function testSubmitCreateFormUnauthorized(): void { public function testSubmitCreateFormWithoutProfile(): void { $this->expectException(\CRM_Core_Exception::class); $this->expectExceptionMessage('Parameter "profile" is required.'); - TestRemoteProduct::submitCreateForm() + TestRemoteGroup::submitCreateForm() ->execute(); } @@ -337,8 +342,8 @@ public function testSubmitCreateFormWithoutProfile(): void { */ public function testSubmitCreateFormInvalidData(): void { $this->expectException(ValidationFailedException::class); - TestRemoteProduct::submitCreateForm() - ->setProfile(TestRemoteProductReadWriteEntityProfile::NAME) + TestRemoteGroup::submitCreateForm() + ->setProfile(TestRemoteGroupReadWriteEntityProfile::NAME) ->setArguments(['x' => 'y']) ->setData(['foo' => 'bar']) ->execute(); @@ -348,10 +353,10 @@ public function testSubmitCreateFormInvalidData(): void { * @covers \Civi\RemoteTools\Api4\Action\RemoteGetUpdateFormAction */ public function testGetUpdateForm(): void { - $product = ProductFixture::addProduct(); - $result = TestRemoteProduct::getUpdateForm() - ->setProfile(TestRemoteProductReadWriteEntityProfile::NAME) - ->setId($product['id']) + $group = GroupFixture::addGroup(); + $result = TestRemoteGroup::getUpdateForm() + ->setProfile(TestRemoteGroupReadWriteEntityProfile::NAME) + ->setId($group['id']) ->execute(); $resultJson = json_encode($result->getArrayCopy(), JSON_THROW_ON_ERROR); static::assertStringContainsString('Update Form Title', $resultJson); @@ -362,13 +367,13 @@ public function testGetUpdateForm(): void { * @covers \Civi\RemoteTools\Api4\Action\RemoteGetUpdateFormAction */ public function testGetUpdateFormUnauthorized(): void { - $product = ProductFixture::addProduct(); + $group = GroupFixture::addGroup(); $this->expectException(UnauthorizedException::class); $this->expectExceptionMessage('Permission to update entity is missing'); - TestRemoteProduct::getUpdateForm() - ->setProfile(TestRemoteProductReadOnlyEntityProfile::NAME) - ->setId($product['id']) + TestRemoteGroup::getUpdateForm() + ->setProfile(TestRemoteGroupReadOnlyEntityProfile::NAME) + ->setId($group['id']) ->execute(); } @@ -376,13 +381,13 @@ public function testGetUpdateFormUnauthorized(): void { * @covers \Civi\RemoteTools\Api4\Action\RemoteGetUpdateFormAction */ public function testGetUpdateFormEntityMissing(): void { - $product = ProductFixture::addProduct(); + $group = GroupFixture::addGroup(); $this->expectException(UnauthorizedException::class); $this->expectExceptionMessage('Permission to update entity is missing'); - TestRemoteProduct::getUpdateForm() - ->setProfile(TestRemoteProductReadWriteEntityProfile::NAME) - ->setId($product['id'] + 1) + TestRemoteGroup::getUpdateForm() + ->setProfile(TestRemoteGroupReadWriteEntityProfile::NAME) + ->setId($group['id'] + 1) ->execute(); } @@ -390,12 +395,12 @@ public function testGetUpdateFormEntityMissing(): void { * @covers \Civi\RemoteTools\Api4\Action\RemoteGetUpdateFormAction */ public function testGetUpdateFormWithoutProfile(): void { - $product = ProductFixture::addProduct(); + $group = GroupFixture::addGroup(); $this->expectException(\CRM_Core_Exception::class); $this->expectExceptionMessage('Parameter "profile" is required.'); - TestRemoteProduct::getUpdateForm() - ->setId($product['id']) + TestRemoteGroup::getUpdateForm() + ->setId($group['id']) ->execute(); } @@ -403,11 +408,11 @@ public function testGetUpdateFormWithoutProfile(): void { * @covers \Civi\RemoteTools\Api4\Action\RemoteValidateUpdateFormAction */ public function testValidateUpdateForm(): void { - $product = ProductFixture::addProduct(); + $group = GroupFixture::addGroup(); - $result = TestRemoteProduct::validateUpdateForm() - ->setProfile(TestRemoteProductReadWriteEntityProfile::NAME) - ->setId($product['id']) + $result = TestRemoteGroup::validateUpdateForm() + ->setProfile(TestRemoteGroupReadWriteEntityProfile::NAME) + ->setId($group['id']) ->setData(['name' => 'x']) ->execute(); @@ -416,9 +421,9 @@ public function testValidateUpdateForm(): void { // @phpstan-ignore-next-line static::assertCount(1, $result['errors']['name']); - $result = TestRemoteProduct::validateUpdateForm() - ->setProfile(TestRemoteProductReadWriteEntityProfile::NAME) - ->setId($product['id']) + $result = TestRemoteGroup::validateUpdateForm() + ->setProfile(TestRemoteGroupReadWriteEntityProfile::NAME) + ->setId($group['id']) ->setData(['name' => 'xy']) ->execute(); @@ -430,13 +435,13 @@ public function testValidateUpdateForm(): void { * @covers \Civi\RemoteTools\Api4\Action\RemoteValidateUpdateFormAction */ public function testValidateUpdateFormUnauthorized(): void { - $product = ProductFixture::addProduct(); + $group = GroupFixture::addGroup(); $this->expectException(UnauthorizedException::class); $this->expectExceptionMessage('Permission to update entity is missing'); - TestRemoteProduct::validateUpdateForm() - ->setProfile(TestRemoteProductReadOnlyEntityProfile::NAME) - ->setId($product['id']) + TestRemoteGroup::validateUpdateForm() + ->setProfile(TestRemoteGroupReadOnlyEntityProfile::NAME) + ->setId($group['id']) ->setData(['foo' => 'bar']) ->execute(); } @@ -445,13 +450,13 @@ public function testValidateUpdateFormUnauthorized(): void { * @covers \Civi\RemoteTools\Api4\Action\RemoteValidateUpdateFormAction */ public function testValidateUpdateFormEntityMissing(): void { - $product = ProductFixture::addProduct(); + $group = GroupFixture::addGroup(); $this->expectException(UnauthorizedException::class); $this->expectExceptionMessage('Permission to update entity is missing'); - TestRemoteProduct::validateUpdateForm() - ->setProfile(TestRemoteProductReadWriteEntityProfile::NAME) - ->setId($product['id'] + 1) + TestRemoteGroup::validateUpdateForm() + ->setProfile(TestRemoteGroupReadWriteEntityProfile::NAME) + ->setId($group['id'] + 1) ->setData(['name' => 'test']) ->execute(); } @@ -460,12 +465,12 @@ public function testValidateUpdateFormEntityMissing(): void { * @covers \Civi\RemoteTools\Api4\Action\RemoteValidateUpdateFormAction */ public function testValidateUpdateFormWithoutProfile(): void { - $product = ProductFixture::addProduct(); + $group = GroupFixture::addGroup(); $this->expectException(\CRM_Core_Exception::class); $this->expectExceptionMessage('Parameter "profile" is required.'); - TestRemoteProduct::validateUpdateForm() - ->setId($product['id']) + TestRemoteGroup::validateUpdateForm() + ->setId($group['id']) ->execute(); } @@ -473,16 +478,16 @@ public function testValidateUpdateFormWithoutProfile(): void { * @covers \Civi\RemoteTools\Api4\Action\RemoteSubmitUpdateFormAction */ public function testSubmitUpdateForm(): void { - $product = ProductFixture::addProduct(); + $group = GroupFixture::addGroup(); - $result = TestRemoteProduct::submitUpdateForm() - ->setProfile(TestRemoteProductReadWriteEntityProfile::NAME) - ->setId($product['id']) + $result = TestRemoteGroup::submitUpdateForm() + ->setProfile(TestRemoteGroupReadWriteEntityProfile::NAME) + ->setId($group['id']) ->setData(['name' => 'xy']) ->execute(); static::assertSame(['message' => 'Saved successfully'], $result->getArrayCopy()); - $result = Product::get(FALSE) + $result = Group::get(FALSE) ->addWhere('name', '=', 'xy') ->execute(); static::assertCount(1, $result); @@ -492,13 +497,13 @@ public function testSubmitUpdateForm(): void { * @covers \Civi\RemoteTools\Api4\Action\RemoteSubmitUpdateFormAction */ public function testSubmitUpdateFormUnauthorized(): void { - $product = ProductFixture::addProduct(); + $group = GroupFixture::addGroup(); $this->expectException(UnauthorizedException::class); $this->expectExceptionMessage('Permission to update entity is missing'); - TestRemoteProduct::submitUpdateForm() - ->setProfile(TestRemoteProductReadOnlyEntityProfile::NAME) - ->setId($product['id']) + TestRemoteGroup::submitUpdateForm() + ->setProfile(TestRemoteGroupReadOnlyEntityProfile::NAME) + ->setId($group['id']) ->setData(['foo' => 'bar']) ->execute(); } @@ -507,13 +512,13 @@ public function testSubmitUpdateFormUnauthorized(): void { * @covers \Civi\RemoteTools\Api4\Action\RemoteSubmitUpdateFormAction */ public function testSubmitUpdateFormEntityMissing(): void { - $product = ProductFixture::addProduct(); + $group = GroupFixture::addGroup(); $this->expectException(UnauthorizedException::class); $this->expectExceptionMessage('Permission to update entity is missing'); - TestRemoteProduct::submitUpdateForm() - ->setProfile(TestRemoteProductReadWriteEntityProfile::NAME) - ->setId($product['id'] + 1) + TestRemoteGroup::submitUpdateForm() + ->setProfile(TestRemoteGroupReadWriteEntityProfile::NAME) + ->setId($group['id'] + 1) ->setData(['name' => 'test']) ->execute(); } @@ -522,12 +527,12 @@ public function testSubmitUpdateFormEntityMissing(): void { * @covers \Civi\RemoteTools\Api4\Action\RemoteSubmitUpdateFormAction */ public function testSubmitUpdateFormWithoutProfile(): void { - $product = ProductFixture::addProduct(); + $group = GroupFixture::addGroup(); $this->expectException(\CRM_Core_Exception::class); $this->expectExceptionMessage('Parameter "profile" is required.'); - TestRemoteProduct::submitUpdateForm() - ->setId($product['id']) + TestRemoteGroup::submitUpdateForm() + ->setId($group['id']) ->execute(); } @@ -535,12 +540,12 @@ public function testSubmitUpdateFormWithoutProfile(): void { * @covers \Civi\RemoteTools\Api4\Action\RemoteSubmitUpdateFormAction */ public function testSubmitUpdateFormInvalidData(): void { - $product = ProductFixture::addProduct(); + $group = GroupFixture::addGroup(); $this->expectException(ValidationFailedException::class); - TestRemoteProduct::submitUpdateForm() - ->setProfile(TestRemoteProductReadWriteEntityProfile::NAME) - ->setId($product['id']) + TestRemoteGroup::submitUpdateForm() + ->setProfile(TestRemoteGroupReadWriteEntityProfile::NAME) + ->setId($group['id']) ->setData(['name' => 'x']) ->execute(); } diff --git a/tests/phpunit/Civi/Api4/TestRemoteProduct.php b/tests/phpunit/Civi/Api4/TestRemoteGroup.php similarity index 86% rename from tests/phpunit/Civi/Api4/TestRemoteProduct.php rename to tests/phpunit/Civi/Api4/TestRemoteGroup.php index c8cad0f..58bce86 100644 --- a/tests/phpunit/Civi/Api4/TestRemoteProduct.php +++ b/tests/phpunit/Civi/Api4/TestRemoteGroup.php @@ -22,7 +22,7 @@ use Civi\Remoteactivity\Api4\Permissions; use Civi\RemoteTools\Api4\AbstractRemoteEntity; -final class TestRemoteProduct extends AbstractRemoteEntity { +final class TestRemoteGroup extends AbstractRemoteEntity { /** * @inheritDoc @@ -31,8 +31,8 @@ final class TestRemoteProduct extends AbstractRemoteEntity { */ public static function permissions(): array { return [ - 'meta' => ['access TestRemoteProduct'], - 'default' => ['access TestRemoteProduct'], + 'meta' => ['access TestRemoteGroup'], + 'default' => ['access TestRemoteGroup'], ]; } diff --git a/tests/phpunit/Civi/RemoteTools/EntityProfile/TestRemoteProductReadOnlyEntityProfile.php b/tests/phpunit/Civi/RemoteTools/EntityProfile/TestRemoteGroupReadOnlyEntityProfile.php similarity index 82% rename from tests/phpunit/Civi/RemoteTools/EntityProfile/TestRemoteProductReadOnlyEntityProfile.php rename to tests/phpunit/Civi/RemoteTools/EntityProfile/TestRemoteGroupReadOnlyEntityProfile.php index 01a2b03..c7324c0 100644 --- a/tests/phpunit/Civi/RemoteTools/EntityProfile/TestRemoteProductReadOnlyEntityProfile.php +++ b/tests/phpunit/Civi/RemoteTools/EntityProfile/TestRemoteGroupReadOnlyEntityProfile.php @@ -19,13 +19,13 @@ namespace Civi\RemoteTools\EntityProfile; -final class TestRemoteProductReadOnlyEntityProfile extends ReadOnlyRemoteEntityProfile { +final class TestRemoteGroupReadOnlyEntityProfile extends ReadOnlyRemoteEntityProfile { public const NAME = 'readOnlyTest'; - public const ENTITY_NAME = 'Product'; + public const ENTITY_NAME = 'Group'; - public const REMOTE_ENTITY_NAME = 'TestRemoteProduct'; + public const REMOTE_ENTITY_NAME = 'TestRemoteGroup'; public function __construct() { parent::__construct(self::NAME, self::ENTITY_NAME, self::REMOTE_ENTITY_NAME); diff --git a/tests/phpunit/Civi/RemoteTools/EntityProfile/TestRemoteProductReadWriteEntityProfile.php b/tests/phpunit/Civi/RemoteTools/EntityProfile/TestRemoteGroupReadWriteEntityProfile.php similarity index 85% rename from tests/phpunit/Civi/RemoteTools/EntityProfile/TestRemoteProductReadWriteEntityProfile.php rename to tests/phpunit/Civi/RemoteTools/EntityProfile/TestRemoteGroupReadWriteEntityProfile.php index ad58129..3176a4b 100644 --- a/tests/phpunit/Civi/RemoteTools/EntityProfile/TestRemoteProductReadWriteEntityProfile.php +++ b/tests/phpunit/Civi/RemoteTools/EntityProfile/TestRemoteGroupReadWriteEntityProfile.php @@ -22,13 +22,13 @@ use Civi\RemoteTools\Form\FormSpec\Field\TextField; use Civi\RemoteTools\Form\FormSpec\FormSpec; -final class TestRemoteProductReadWriteEntityProfile extends AbstractRemoteEntityProfile { +final class TestRemoteGroupReadWriteEntityProfile extends AbstractRemoteEntityProfile { public const NAME = 'readWriteTest'; - public const ENTITY_NAME = 'Product'; + public const ENTITY_NAME = 'Group'; - public const REMOTE_ENTITY_NAME = 'TestRemoteProduct'; + public const REMOTE_ENTITY_NAME = 'TestRemoteGroup'; public function getEntityName(): string { return self::ENTITY_NAME; @@ -46,6 +46,9 @@ public function getCreateFormSpec(array $arguments, array $entityFields, ?int $c return (new FormSpec('Create Form Title')) ->addElement( (new TextField('name', 'Enter Name'))->setRequired(TRUE) + ) + ->addElement( + (new TextField('title', 'Enter Name'))->setRequired(TRUE) ); } diff --git a/tests/phpunit/Civi/RemoteTools/Fixture/ProductFixture.php b/tests/phpunit/Civi/RemoteTools/Fixture/GroupFixture.php similarity index 79% rename from tests/phpunit/Civi/RemoteTools/Fixture/ProductFixture.php rename to tests/phpunit/Civi/RemoteTools/Fixture/GroupFixture.php index c5dc592..4947071 100644 --- a/tests/phpunit/Civi/RemoteTools/Fixture/ProductFixture.php +++ b/tests/phpunit/Civi/RemoteTools/Fixture/GroupFixture.php @@ -19,9 +19,9 @@ namespace Civi\RemoteTools\Fixture; -use Civi\Api4\Product; +use Civi\Api4\Group; -final class ProductFixture { +final class GroupFixture { /** * @param array $values @@ -31,10 +31,14 @@ final class ProductFixture { * * @throws \CRM_Core_Exception */ - public static function addProduct(array $values = []): array { - return Product::create(FALSE) + public static function addGroup(array $values = []): array { + static $count = 0; + ++$count; + + return Group::create(FALSE) ->setValues($values + [ - 'name' => 'TestProduct', + 'name' => 'TestGroup' . $count, + 'title' => 'TestTitle' . $count, ])->execute()->single(); } diff --git a/tests/phpunit/Civi/RemoteTools/Helper/SelectFactoryTest.php b/tests/phpunit/Civi/RemoteTools/Helper/SelectFactoryTest.php index 5eeb90d..fdf5c9c 100644 --- a/tests/phpunit/Civi/RemoteTools/Helper/SelectFactoryTest.php +++ b/tests/phpunit/Civi/RemoteTools/Helper/SelectFactoryTest.php @@ -142,6 +142,48 @@ public function testGetSelectsImplicitJoinInRemote(): void { )); } + public function testGetSelectsExtraFields(): void { + $entityFields = [ + 'fieldA' => [ + 'name' => 'fieldA', + 'type' => 'Extra', + ], + ]; + $remoteFields = [ + 'fieldA' => [ + 'name' => 'fieldA', + 'type' => 'Extra', + ], + 'fieldB' => [ + 'name' => 'fieldB', + ], + ]; + + $expectedSelectAll = [ + 'entity' => [], + 'remote' => ['fieldB'], + ]; + + static::assertSame($expectedSelectAll, $this->selectFactory->getSelects( + [], + $entityFields, + $remoteFields, + fn() => FALSE, + )); + + $expectedSelectExplicitly = [ + 'entity' => ['fieldA'], + 'remote' => ['fieldA', 'fieldB'], + ]; + + static::assertSame($expectedSelectExplicitly, $this->selectFactory->getSelects( + ['*', 'fieldA'], + $entityFields, + $remoteFields, + fn() => FALSE, + )); + } + public function testGetSelectsImplicitJoinNotInRemote(): void { $entityFields = [ 'fieldA' => [ diff --git a/tests/phpunit/bootstrap.php b/tests/phpunit/bootstrap.php index 14272d2..749989f 100644 --- a/tests/phpunit/bootstrap.php +++ b/tests/phpunit/bootstrap.php @@ -1,7 +1,7 @@ autowire(TestRemoteProductReadOnlyEntityProfile::class) - ->addTag(TestRemoteProductReadOnlyEntityProfile::SERVICE_TAG); + $container->autowire(TestRemoteGroupReadOnlyEntityProfile::class) + ->addTag(TestRemoteGroupReadOnlyEntityProfile::SERVICE_TAG); - $container->autowire(TestRemoteProductReadWriteEntityProfile::class) - ->addTag(TestRemoteProductReadWriteEntityProfile::SERVICE_TAG); + $container->autowire(TestRemoteGroupReadWriteEntityProfile::class) + ->addTag(TestRemoteGroupReadWriteEntityProfile::SERVICE_TAG); } /** @@ -85,4 +85,4 @@ function cv($cmd, $decode = 'json') { default: throw new RuntimeException("Bad decoder format ($decode)"); } -} +} \ No newline at end of file