diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index a4b033f6..7dd6ece4 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -9,6 +9,9 @@ env: APIGEE_EDGE_INSTANCE_TYPE: ${{ secrets.APIGEE_EDGE_INSTANCE_TYPE }} APIGEE_INTEGRATION_ENABLE: ${{ secrets.APIGEE_INTEGRATION_ENABLE }} APIGEE_EDGE_ENDPOINT: ${{ secrets.APIGEE_EDGE_ENDPOINT }} + APIGEE_EDGE_ACCOUNT_JSON_KEY: ${{ secrets.APIGEE_EDGE_ACCOUNT_JSON_KEY }} + APIGEE_EDGE_HYBRID_ENDPOINT: ${{ secrets.APIGEE_EDGE_HYBRID_ENDPOINT }} + APIGEE_EDGE_HYBRID_ORGANIZATION: ${{ secrets.APIGEE_EDGE_HYBRID_ORGANIZATION }} BROWSERTEST_OUTPUT_DIRECTORY: "sites/simpletest/browser_output" BROWSERTEST_OUTPUT_BASE_URL: "" MINK_DRIVER_ARGS_WEBDRIVER: '["chrome", { "chromeOptions": { "w3c": false } }, "http://127.0.0.1:9515/wd/hub"]' @@ -24,7 +27,7 @@ jobs: runs-on: ubuntu-latest - name: "PHP ${{ matrix.php-version }} | Drupal ${{ matrix.drupal-core }}" + name: "PHP ${{ matrix.php-version }} | Drupal ${{ matrix.drupal-core }} | ${{ matrix.instance-type }}" strategy: fail-fast: false matrix: @@ -34,6 +37,9 @@ jobs: drupal-core: # Should update the following as the minimum supported version from Drupal.org - "9.5.x" + instance-type: + - "Edge" + - "X" steps: @@ -107,11 +113,17 @@ jobs: vendor/bin/drush en apigee_edge -y vendor/bin/drush rs 8000 & - - name: "PHPCS" + - name: "PHPCS and setting up Apigee X environment" + if: ${{ matrix.instance-type == 'X' }} run: | cd drupal cp modules/contrib/apigee_edge/phpcs.xml.dist . vendor/bin/phpcs --standard=./phpcs.xml.dist modules/contrib/apigee_edge -p -s -n --colors + # Setting environment variables to run Apigee X tests + echo "APIGEE_EDGE_INSTANCE_TYPE=hybrid" >> $GITHUB_ENV + echo "APIGEE_EDGE_ORGANIZATION=$APIGEE_EDGE_HYBRID_ORGANIZATION" >> $GITHUB_ENV + echo "APIGEE_EDGE_ENDPOINT=$APIGEE_EDGE_HYBRID_ENDPOINT" >> $GITHUB_ENV + composer show > composer-show.txt - name: "Drupal check" run: | @@ -136,20 +148,20 @@ jobs: run: | cd drupal cp modules/contrib/apigee_edge/phpunit.core.xml.dist core/phpunit.xml - vendor/bin/phpunit -c core --verbose --color --group apigee_edge --testsuite unit,kernel,functional,functional-javascript --debug --coverage-clover /tmp/coverage.xml modules/contrib/apigee_edge + vendor/bin/phpunit -c core --verbose --color --group apigee_edge --testsuite unit,kernel,functional,functional-javascript --debug --coverage-clover /tmp/coverage_${{ matrix.instance-type }}.xml modules/contrib/apigee_edge - name: Artifacts if: failure() uses: actions/upload-artifact@v3 with: - name: browser-output-${{ matrix.php-version }}-${{ matrix.drupal-core }}-artifact + name: browser-output-${{ matrix.php-version }}-${{ matrix.drupal-core }}-${{ matrix.instance-type }}-artifact path: drupal/sites/simpletest/browser_output/* - name: Upload coverage to Codecov if: ${{ matrix.drupal-core == '9.5.x' && matrix.php-version == '8.1' }} uses: codecov/codecov-action@v3 with: - files: /tmp/coverage.xml + files: /tmp/coverage_${{ matrix.instance-type }}.xml name: codecov-umbrella fail_ci_if_error: true verbose: true diff --git a/modules/apigee_edge_actions/tests/src/Kernel/ApigeeEdgeActionsRulesKernelTestBase.php b/modules/apigee_edge_actions/tests/src/Kernel/ApigeeEdgeActionsRulesKernelTestBase.php index 37fb03d8..6df089a1 100644 --- a/modules/apigee_edge_actions/tests/src/Kernel/ApigeeEdgeActionsRulesKernelTestBase.php +++ b/modules/apigee_edge_actions/tests/src/Kernel/ApigeeEdgeActionsRulesKernelTestBase.php @@ -20,6 +20,7 @@ namespace Drupal\Tests\apigee_edge_actions\Kernel; +use Drupal\apigee_edge\Plugin\EdgeKeyTypeInterface; use Drupal\Core\Database\Database; use Drupal\dblog\Controller\DbLogController; use Drupal\Tests\apigee_mock_api_client\Traits\ApigeeMockApiClientHelperTrait; @@ -67,6 +68,11 @@ class ApigeeEdgeActionsRulesKernelTestBase extends RulesKernelTestBase { * {@inheritdoc} */ protected function setUp(): void { + // Skipping the test if instance type is Public. + $instance_type = getenv('APIGEE_EDGE_INSTANCE_TYPE'); + if (!empty($instance_type) && $instance_type === EdgeKeyTypeInterface::INSTANCE_TYPE_HYBRID) { + $this->markTestSkipped('This test suite is expecting a PUBLIC instance type.'); + } parent::setUp(); $this->storage = $this->container->get('entity_type.manager')->getStorage('rules_reaction_rule'); diff --git a/modules/apigee_edge_teams/tests/src/Functional/ApigeeX/ApigeeEdgeTeamsFunctionalTestBase.php b/modules/apigee_edge_teams/tests/src/Functional/ApigeeX/ApigeeEdgeTeamsFunctionalTestBase.php new file mode 100644 index 00000000..253045ff --- /dev/null +++ b/modules/apigee_edge_teams/tests/src/Functional/ApigeeX/ApigeeEdgeTeamsFunctionalTestBase.php @@ -0,0 +1,83 @@ +testTokenData = [ + 'access_token' => mb_strtolower($this->randomMachineName(32)), + 'token_type' => 'bearer', + 'expires_in' => 300, + 'refresh_token' => mb_strtolower($this->randomMachineName(32)), + 'scope' => 'create', + ]; + $storage = $this->tokenStorage(); + + // Save the token. + $storage->saveToken($this->testTokenData); + } + + /** + * Returns a pre-configured token storage service for testing. + * + * @param bool $rebuild + * Enforces rebuild of the container and with the the token storage + * service. + * + * @return \Drupal\apigee_edge\OauthTokenFileStorage + * The configured and initialized OAuth file token storage service. + * + * @throws \Exception + */ + private function tokenStorage(bool $rebuild = FALSE): OauthTokenFileStorage { + $config = $this->config('apigee_edge.auth'); + $config->set('oauth_token_storage_location', OauthTokenFileStorage::DEFAULT_DIRECTORY)->save(); + if ($rebuild) { + $this->container->get('kernel')->rebuildContainer(); + } + return $this->container->get('apigee_edge.authentication.oauth_token_storage'); + } + +} diff --git a/modules/apigee_edge_teams/tests/src/Functional/ApigeeX/TeamInvitationsTest.php b/modules/apigee_edge_teams/tests/src/Functional/ApigeeX/TeamInvitationsTest.php new file mode 100644 index 00000000..42f3d05d --- /dev/null +++ b/modules/apigee_edge_teams/tests/src/Functional/ApigeeX/TeamInvitationsTest.php @@ -0,0 +1,236 @@ +storeToken(); + $this->addApigeexOrganizationMatchedResponse(); + $this->teamA = $this->createApigeexTeam(); + $this->teamB = $this->createApigeexTeam(); + + $this->accountAdmin = $this->createAccount(['administer team']); + $this->accountUser = $this->createAccount([ + 'accept own team invitation', + ]); + + if (!$this->integration_enabled) { + $this->queueDeveloperResponse($this->accountAdmin); + Developer::load($this->accountAdmin->getEmail()); + $this->queueDeveloperResponse($this->accountUser); + Developer::load($this->accountUser->getEmail()); + } + } + + /** + * {@inheritdoc} + */ + protected function tearDown(): void { + if (!$this->integration_enabled) { + return; + } + else { + $teams = [ + $this->teamA, + $this->teamB, + ]; + foreach ($teams as $team) { + if ($team !== NULL) { + try { + $team->delete(); + } + catch (\Exception $exception) { + $this->logException($exception); + } + } + } + + $accounts = [ + $this->accountAdmin, + $this->accountUser, + ]; + foreach ($accounts as $account) { + if ($account !== NULL) { + try { + $account->delete(); + } + catch (\Exception $exception) { + $this->logException($exception); + } + } + } + } + + parent::tearDown(); + } + + /** + * Tests that an email can be invited to one or more teams. + */ + public function testMultipleInvitations() { + $this->drupalLogin($this->accountAdmin); + + $teams = [ + $this->teamA, + $this->teamB, + ]; + $appgroups = [ + $this->teamA->decorated(), + $this->teamB->decorated(), + ]; + + $inCache = FALSE; + foreach ($teams as $team) { + if (!$inCache) { + $this->queueAppGroupResponse($team->decorated()); + } + $this->drupalGet(Url::fromRoute('entity.team.add_members', [ + 'team' => $team->id(), + ])); + + $this->assertSession()->pageTextContains('Invite members'); + + $this->queueAppGroupsResponse($appgroups); + $this->queueAppGroupsResponse($appgroups); + $this->queueDevsInCompanyResponse([]); + $this->submitForm([ + 'developers' => $this->accountUser->getEmail(), + ], 'Invite members'); + + $successMessage = t('The following developer has been invited to the @team @team_label: @developer.', [ + '@developer' => $this->accountUser->getEmail(), + '@team' => $team->label(), + '@team_label' => mb_strtolower($team->getEntityType()->getSingularLabel()), + ]); + + $this->assertSession()->pageTextContains($successMessage); + $inCache = TRUE; + } + } + + /** + * Tests that a user can see their list of invitations. + */ + public function testInvitationsList() { + // Ensure "team_invitations" views page is installed. + $this->assertNotNull(Views::getView('team_invitations')); + + /** @var \Drupal\apigee_edge_teams\Entity\Storage\TeamInvitationStorageInterface $teamInvitationStorage */ + $teamInvitationStorage = $this->entityTypeManager->getStorage('team_invitation'); + $selected_roles = [TeamRoleInterface::TEAM_MEMBER_ROLE => TeamRoleInterface::TEAM_MEMBER_ROLE]; + $teams = [ + $this->teamA, + $this->teamB, + ]; + $appgroups = [ + $this->teamA->decorated(), + $this->teamB->decorated(), + ]; + + // Invite user to both teams. + foreach ($teams as $team) { + $this->queueAppGroupResponse($team->decorated()); + $teamInvitationStorage->create([ + 'team' => ['target_id' => $team->id()], + 'team_roles' => array_values(array_map(function (string $role) { + return ['target_id' => $role]; + }, $selected_roles)), + 'recipient' => $this->accountUser->getEmail(), + ])->save(); + } + + // Check that user can see both invitations. + $this->drupalLogin($this->accountUser); + $invitationsUrl = Url::fromRoute('view.team_invitations.user', [ + 'user' => $this->accountUser->id(), + ]); + + $this->queueAppGroupsResponse($appgroups); + $this->queueDevsInCompanyResponse([]); + $this->drupalGet($invitationsUrl); + foreach ($teams as $team) { + $this->assertSession()->pageTextContains('Invitation to join ' . $team->label()); + } + } + +} diff --git a/modules/apigee_edge_teams/tests/src/Functional/ApigeeX/TeamMembershipManagerTest.php b/modules/apigee_edge_teams/tests/src/Functional/ApigeeX/TeamMembershipManagerTest.php new file mode 100644 index 00000000..8f36948e --- /dev/null +++ b/modules/apigee_edge_teams/tests/src/Functional/ApigeeX/TeamMembershipManagerTest.php @@ -0,0 +1,193 @@ +developerStorage = $this->container->get('entity_type.manager')->getStorage('developer'); + $this->teamStorage = $this->container->get('entity_type.manager')->getStorage('team'); + + for ($i = 0; $i < 2; $i++) { + $name = strtolower($this->randomMachineName()); + + // Developer. + $account = $this->createAccount(array_keys(\Drupal::service('user.permissions')->getPermissions())); + $this->account = new UserSession([ + 'uid' => $account->id(), + 'uuid' => $account->id(), + 'name' => $account->getAccountName(), + 'roles' => $account->getRoles(), + 'mail' => $account->getEmail(), + ]); + $this->developers[$i] = $account; + } + + $this->team = $this->teamStorage->create([ + 'name' => $this->getRandomGenerator()->name(), + 'attributes' => new AttributesProperty([ + 'name' => '__apigee_reserved__developer_details', + 'value' => '[{\"developer\":\"doe@example.com\",\"roles\":[\"admin\"]}]' + ]), + ]); + $this->team->save(); + } + + /** + * {@inheritdoc} + */ + protected function tearDown(): void { + foreach ($this->developers as $developer) { + try { + $this->developerStorage->delete([$developer]); + } + catch (\Exception $exception) { + $this->logException($exception); + } + } + + if ($this->team !== NULL) { + try { + $this->teamStorage->delete([$this->team]); + } + catch (\Exception $exception) { + $this->logException($exception); + } + } + + parent::tearDown(); + } + + /** + * Tests team membership manager service. + */ + public function testTeamMembershipManager() { + + $team_membership_manager = $this->container->get('apigee_edge_teams.team_membership_manager'); + $team_membership_cache = $this->container->get('apigee_edge_teams.cache.appgroup_membership_object'); + + // Ensure that the appgroup's member list is empty. + foreach ($this->developers as $developer) { + $this->assertEmpty($team_membership_manager->getTeams($developer->getEmail(), $this->team->getName())); + $this->assertEmpty($team_membership_manager->getMembers($this->team->getName())); + } + // Ensure that team membership cache is empty. + $this->assertEmpty($team_membership_cache->getMembership($this->team->getName())->getMembers()); + + // Adding the team members. + foreach ($this->developers as $developer) { + /** @var \Drupal\apigee_edge_teams\Entity\TeamMemberRoleInterface $team_member_roles */ + $team_member_role_storage = \Drupal::entityTypeManager()->getStorage('team_member_role'); + $team_member_role_storage->addTeamRoles($developer, $this->team, ['member']); + $team_member_roles = $team_member_role_storage->loadByDeveloperAndTeam($developer, $this->team); + $team_member_roles->save(); + } + + // Add developers to the team and check whether the related membership + // service functions work properly. + $team_membership_manager->addMembers($this->team->getName(), [$this->developers[0]->getEmail() => ['admin'], $this->developers[1]->getEmail() => ['member']]); + + foreach ($this->developers as $developer) { + $this->assertContains($this->team->getName(), $team_membership_manager->getTeams($developer->getEmail(), $this->team->getName())); + $this->assertContains($developer->getEmail(), $team_membership_manager->getMembers($this->team->getName())); + + // Check whether the team membership is correctly cached. + $this->assertArrayHasKey($developer->getEmail(), $team_membership_cache->getMembership($this->team->getName())->getMembers()); + } + + // Remove developers from the team and check whether the related + // membership service functions work properly. + foreach ($this->developers as $developer) { + $team_membership_manager->removeMembers($this->team->getName(), [$developer->getEmail()]); + $this->assertNotContains($this->team->getName(), $team_membership_manager->getTeams($developer->getEmail(), $this->team->getName())); + $this->assertNotContains($developer->getEmail(), $team_membership_manager->getMembers($this->team->getName())); + + // Check whether the team membership is correctly cached. + $this->assertArrayNotHasKey($developer->getEmail(), $team_membership_cache->getMembership($this->team->getName())->getMembers()); + } + + // Ensure that team membership cache is empty. + $this->assertEmpty($team_membership_cache->getMembership($this->team->getName())->getMembers()); + + // Add developer to appgroup then delete developer and check whether the + // developer is no longer member of the team. + $team_membership_manager->addMembers($this->team->getName(), [$this->developers[0]->getEmail() => ['admin'], $this->developers[1]->getEmail() => ['member']]); + $developer1 = $this->developerStorage->load($this->developers[0]->getEmail()); + $developer1->delete([$this->developers[0]]); + $this->assertNotContains($this->developers[0]->getEmail(), $team_membership_manager->getMembers($this->team->getName())); + // Check whether the team membership is correctly cached. + $this->assertArrayNotHasKey($this->developers[0]->getEmail(), $team_membership_cache->getMembership($this->team->getName())->getMembers()); + + // Delete the team and ensure that the team is removed from the team + // membership cache. + $this->teamStorage->delete([$this->team]); + } + +} diff --git a/modules/apigee_edge_teams/tests/src/Kernel/ApigeeX/Entity/TeamViewBuilderTest.php b/modules/apigee_edge_teams/tests/src/Kernel/ApigeeX/Entity/TeamViewBuilderTest.php new file mode 100644 index 00000000..79e69890 --- /dev/null +++ b/modules/apigee_edge_teams/tests/src/Kernel/ApigeeX/Entity/TeamViewBuilderTest.php @@ -0,0 +1,111 @@ +installConfig(['apigee_edge']); + $this->installConfig(['apigee_edge_teams']); + $this->installEntitySchema('user'); + $this->installEntitySchema('team_member_role'); + $this->installSchema('system', ['sequences']); + $this->installSchema('user', ['users_data']); + + $this->apigeeTestHelperSetup(); + $this->storeToken(); + $this->addApigeexOrganizationMatchedResponse(); + $this->entity = $this->createApigeexTeam(); + } + + /** + * Tests the cache max-age for the view builder. + */ + public function testViewCacheExpiration() { + /** @var \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager */ + $entity_type_manager = $this->container->get('entity_type.manager'); + $build = $entity_type_manager->getViewBuilder(static::ENTITY_TYPE)->view($this->entity); + + static::assertEquals(900, $build['#cache']['max-age']); + + // Update the cache setting. + $this->config('apigee_edge_teams.team_settings') + ->set('cache_expiration', 0) + ->save(); + + $build = $entity_type_manager->getViewBuilder(static::ENTITY_TYPE)->view($this->entity); + static::assertEquals(0, $build['#cache']['max-age']); + } + +} diff --git a/modules/apigee_edge_teams/tests/src/Kernel/ApigeeX/EntityControllerCacheTest.php b/modules/apigee_edge_teams/tests/src/Kernel/ApigeeX/EntityControllerCacheTest.php new file mode 100644 index 00000000..afbd37f1 --- /dev/null +++ b/modules/apigee_edge_teams/tests/src/Kernel/ApigeeX/EntityControllerCacheTest.php @@ -0,0 +1,85 @@ +container->get('apigee_edge_teams.controller.cache.team'); + /** @var \Drupal\apigee_edge\Entity\Controller\Cache\EntityIdCacheInterface $team_id_cache */ + $team_id_cache = $this->container->get('apigee_edge_teams.controller.cache.team_ids'); + + // Generate team entities with random data. + $teams = []; + for ($i = 0; $i < 3; $i++) { + $id = $this->getRandomUniqueId(); + $teams[$id] = new AppGroup([ + 'name' => $id, + ]); + } + + $this->saveAllEntitiesAndValidate($teams, $team_cache, $team_id_cache); + + /** @var \Apigee\Edge\Api\Management\Entity\AppGroupInterface $team */ + foreach ($teams as $team) { + // Load team by name. + $this->assertSame($team, $team_cache->getEntity($team->getName())); + $this->assertContains($team->getName(), $team_id_cache->getIds()); + + // Pass an invalid entity id to ensure it does not cause any trouble + // anymore. + // @see \Drupal\apigee_edge\Entity\Controller\Cache\EntityCache::removeEntities() + // @see https://www.drupal.org/project/drupal/issues/3017753 + $team_cache->removeEntities([$team->getName(), $this->getRandomGenerator()->string()]); + $this->assertNull($team_cache->getEntity($team->getName())); + $this->assertNotContains($team->getName(), $team_id_cache->getIds()); + } + + $this->assertEmptyCaches($team_cache, $team_id_cache); + } + +} diff --git a/modules/apigee_edge_teams/tests/src/Kernel/ApigeeX/Event/TeamInvitationEventsTest.php b/modules/apigee_edge_teams/tests/src/Kernel/ApigeeX/Event/TeamInvitationEventsTest.php new file mode 100644 index 00000000..b824b15c --- /dev/null +++ b/modules/apigee_edge_teams/tests/src/Kernel/ApigeeX/Event/TeamInvitationEventsTest.php @@ -0,0 +1,116 @@ +installConfig(['apigee_edge']); + $this->installConfig(['apigee_edge_teams']); + $this->installEntitySchema('user'); + $this->installEntitySchema('team_member_role'); + $this->installEntitySchema('team_invitation'); + $this->installSchema('system', ['sequences']); + $this->installSchema('user', ['users_data']); + + $this->baseSetUp(); + + $this->storeToken(); + $this->addApigeexOrganizationMatchedResponse(); + } + + /** + * Tests team_invitation events for AppGroup org. + */ + public function testEvents() { + $this->entity = $this->createApigeexTeam(); + $this->queueAppGroupResponse($this->entity->decorated()); + + /** @var \Drupal\apigee_edge_teams\Entity\TeamInvitationInterface $team_invitation */ + $team_invitation = TeamInvitation::create([ + 'team' => ['target_id' => $this->entity->id()], + 'team_roles' => [TeamRoleInterface::TEAM_MEMBER_ROLE], + 'recipient' => 'doe@example.com', + ]); + + // Created. + $team_invitation->save(); + $this->assertSame("CREATED", $team_invitation->getLabel()); + $this->assertTrue($team_invitation->isPending()); + + // Declined. + $team_invitation->setStatus(TeamInvitationInterface::STATUS_DECLINED)->save(); + $this->assertSame("DECLINED", $team_invitation->getLabel()); + $this->assertTrue($team_invitation->isDeclined()); + + // Accepted. + $team_invitation->setStatus(TeamInvitationInterface::STATUS_ACCEPTED)->save(); + $this->assertSame("ACCEPTED", $team_invitation->getLabel()); + $this->assertTrue($team_invitation->isAccepted()); + } + +} diff --git a/modules/apigee_edge_teams/tests/src/Kernel/Entity/TeamViewBuilderTest.php b/modules/apigee_edge_teams/tests/src/Kernel/Entity/TeamViewBuilderTest.php index 00556f92..c4dd0f4e 100644 --- a/modules/apigee_edge_teams/tests/src/Kernel/Entity/TeamViewBuilderTest.php +++ b/modules/apigee_edge_teams/tests/src/Kernel/Entity/TeamViewBuilderTest.php @@ -20,7 +20,7 @@ namespace Drupal\Tests\apigee_edge_teams\Kernel\Entity; -use Drupal\KernelTests\KernelTestBase; +use Drupal\Tests\apigee_edge\Kernel\ApigeeEdgeKernelTestBase; use Drupal\Tests\apigee_edge\Kernel\ApigeeEdgeKernelTestTrait; use Drupal\Tests\apigee_mock_api_client\Traits\ApigeeMockApiClientHelperTrait; @@ -32,7 +32,7 @@ * @group apigee_edge_teams * @group apigee_edge_teams_kernel */ -class TeamViewBuilderTest extends KernelTestBase { +class TeamViewBuilderTest extends ApigeeEdgeKernelTestBase { use ApigeeMockApiClientHelperTrait, ApigeeEdgeKernelTestTrait; diff --git a/modules/apigee_edge_teams/tests/src/Kernel/EntityControllerCacheTest.php b/modules/apigee_edge_teams/tests/src/Kernel/EntityControllerCacheTest.php index 595d59c7..6908898f 100644 --- a/modules/apigee_edge_teams/tests/src/Kernel/EntityControllerCacheTest.php +++ b/modules/apigee_edge_teams/tests/src/Kernel/EntityControllerCacheTest.php @@ -20,7 +20,7 @@ namespace Drupal\Tests\apigee_edge_teams\Kernel; use Apigee\Edge\Api\Management\Entity\Company; -use Drupal\KernelTests\KernelTestBase; +use Drupal\Tests\apigee_edge\Kernel\ApigeeEdgeKernelTestBase; use Drupal\Tests\apigee_edge\Traits\EntityControllerCacheUtilsTrait; /** @@ -31,7 +31,7 @@ * @group apigee_edge_teams * @group apigee_edge_teams_kernel */ -class EntityControllerCacheTest extends KernelTestBase { +class EntityControllerCacheTest extends ApigeeEdgeKernelTestBase { use EntityControllerCacheUtilsTrait; diff --git a/modules/apigee_edge_teams/tests/src/Kernel/Event/TeamInvitationEventsTest.php b/modules/apigee_edge_teams/tests/src/Kernel/Event/TeamInvitationEventsTest.php index 62435316..ae0a63fe 100644 --- a/modules/apigee_edge_teams/tests/src/Kernel/Event/TeamInvitationEventsTest.php +++ b/modules/apigee_edge_teams/tests/src/Kernel/Event/TeamInvitationEventsTest.php @@ -24,7 +24,7 @@ use Drupal\apigee_edge_teams\Entity\TeamInvitation; use Drupal\apigee_edge_teams\Entity\TeamInvitationInterface; use Drupal\apigee_edge_teams\Entity\TeamRoleInterface; -use Drupal\KernelTests\KernelTestBase; +use Drupal\Tests\apigee_edge\Kernel\ApigeeEdgeKernelTestBase; use Drupal\Tests\apigee_mock_api_client\Traits\ApigeeMockApiClientHelperTrait; /** @@ -35,7 +35,7 @@ * @group apigee_edge_teams * @group apigee_edge_teams_kernel */ -class TeamInvitationEventsTest extends KernelTestBase { +class TeamInvitationEventsTest extends ApigeeEdgeKernelTestBase { use ApigeeMockApiClientHelperTrait { apigeeTestHelperSetup as baseSetUp; diff --git a/tests/modules/apigee_mock_api_client/tests/response-templates/appgroup.json.twig b/tests/modules/apigee_mock_api_client/tests/response-templates/appgroup.json.twig new file mode 100644 index 00000000..16c5675e --- /dev/null +++ b/tests/modules/apigee_mock_api_client/tests/response-templates/appgroup.json.twig @@ -0,0 +1,31 @@ +{# +/** + * @file + * AppGroup + * + * Usage: + * @code {% include 'team.json.twig' %} @endcode + * + * Variables: + * - appgroup: The team (appgroup). + * - org_name: The org name. + */ +#} +{ + "name": "{{ appgroup.name|default('foo') }}", + "channelUri": "http:\/\/localhost:8080\/test\/web\/teams\/drupalteam", + "channelId": "devportal", + "displayName": "{{ appgroup.displayName }}", + "organization": "{{ org_name }}", + "status": "active", + "attributes": [ + { + "name": "__apigee_reserved__developer_details", + "value": "[{\"developer\":\"doe@example.com\",\"roles\":[\"admin\"]}]" + } + ], + "createdAt": 1506959878351, + "createdBy" : "user@example.com", + "lastModifiedAt": 1506959878351, + "lastModifiedBy" : "user@example.com" +} diff --git a/tests/modules/apigee_mock_api_client/tests/response-templates/appgroups.json.twig b/tests/modules/apigee_mock_api_client/tests/response-templates/appgroups.json.twig new file mode 100644 index 00000000..322717ef --- /dev/null +++ b/tests/modules/apigee_mock_api_client/tests/response-templates/appgroups.json.twig @@ -0,0 +1,19 @@ +{# +/** + * @file + * AppGroups + * + * Usage: + * @code {% include 'appgroups.json.twig' %} @endcode + * + * Variables: + * - appgroups: an array of appgroup objects. + */ +#} +{ + "appGroups" : [ + {% for appgroup in appgroups %} + {% include 'appgroup.json.twig' with {'appgroup': appgroup} %}{{ loop.last ? '' : ',' }} + {% endfor %} + ] +} diff --git a/tests/modules/apigee_mock_api_client/tests/src/Traits/ApigeeMockApiClientHelperTrait.php b/tests/modules/apigee_mock_api_client/tests/src/Traits/ApigeeMockApiClientHelperTrait.php index 4f480abd..3a8dc53b 100644 --- a/tests/modules/apigee_mock_api_client/tests/src/Traits/ApigeeMockApiClientHelperTrait.php +++ b/tests/modules/apigee_mock_api_client/tests/src/Traits/ApigeeMockApiClientHelperTrait.php @@ -19,6 +19,7 @@ namespace Drupal\Tests\apigee_mock_api_client\Traits; +use Apigee\Edge\Api\ApigeeX\Entity\AppGroup; use Apigee\Edge\Api\Management\Entity\App; use Apigee\Edge\Api\Management\Entity\Company; use Apigee\Edge\Api\Management\Entity\Organization; @@ -152,6 +153,31 @@ protected function addApigeexOrganizationMatchedResponse($organizationName = '', ); } + /** + * Helper function to queue up an Apigee X org response since every test will need it. + * + * @param string $runtimetype + * Whether or not the org is cloud, hybrid or non-hybrid. + * @param bool $monetized + * Whether or not the org is monetized. + * + * @throws \Exception + */ + protected function warmApigeexOrganizationCache($runtimetype = 'CLOUD', $monetized = TRUE) { + if (!$this->sdkConnector->getOrganization()) { + $this->addApigeexOrganizationMatchedResponse(); + } + $this->stack + ->queueMockResponse([ + 'get_apigeex_organization' => [ + 'runtimetype' => $runtimetype, + 'monetization_enabled' => $monetized ? 'true' : 'false', + 'timezone' => $this->org_default_timezone, + ], + ]); + $this->sdkConnector->getOrganization(); + } + /** * Add matched developer response. * @@ -240,6 +266,23 @@ protected function queueCompanyResponse(Company $company, $response_code = NULL) $this->stack->queueMockResponse(['company' => $context]); } + /** + * Queues up a mock appgroup response. + * + * @param \Apigee\Edge\Api\ApigeeX\Entity\AppGroup $appgroup + * The appgroup to get properties from. + * @param string|null $response_code + * Add a response code to override the default. + */ + protected function queueAppGroupResponse(AppGroup $appgroup, $response_code = NULL) { + $context = empty($response_code) ? [] : ['status_code' => $response_code]; + + $context['appgroup'] = $appgroup; + $context['org_name'] = $this->sdkConnector->getOrganization(); + + $this->stack->queueMockResponse(['appgroup' => $context]); + } + /** * Queues up a mock companies response. * @@ -255,6 +298,21 @@ protected function queueCompaniesResponse(array $companies, $response_code = NUL $this->stack->queueMockResponse(['companies' => $context]); } + /** + * Queues up a mock appgroups response. + * + * @param array $appgroups + * An array of appgroup objects. + * @param string|null $response_code + * Add a response code to override the default. + */ + protected function queueAppGroupsResponse(array $appgroups, $response_code = NULL) { + $context = empty($response_code) ? [] : ['status_code' => $response_code]; + $context['appgroups'] = $appgroups; + + $this->stack->queueMockResponse(['appgroups' => $context]); + } + /** * Queues up a mock developers in a company response. * @@ -319,6 +377,27 @@ protected function createTeam(): TeamInterface { return $team; } + /** + * Helper to create a Apigee X Team entity. + * + * @return \Drupal\apigee_edge_teams\Entity\TeamInterface + * A Team entity. + * + * @throws \Drupal\Core\Entity\EntityStorageException + */ + protected function createApigeexTeam(): TeamInterface { + /** @var \Drupal\apigee_edge_teams\Entity\TeamInterface $team */ + $team = Team::create([ + 'name' => $this->randomMachineName(), + 'displayName' => $this->randomGenerator->name(), + ]); + + $this->queueAppGroupResponse($team->decorated()); + $team->save(); + + return $team; + } + /** * Adds a user to a team. * diff --git a/tests/src/Functional/ApigeeEdgeFunctionalTestBase.php b/tests/src/Functional/ApigeeEdgeFunctionalTestBase.php index 08f32c1e..7beee478 100644 --- a/tests/src/Functional/ApigeeEdgeFunctionalTestBase.php +++ b/tests/src/Functional/ApigeeEdgeFunctionalTestBase.php @@ -19,6 +19,7 @@ namespace Drupal\Tests\apigee_edge\Functional; +use Drupal\apigee_edge\Plugin\EdgeKeyTypeInterface; use Drupal\Tests\apigee_edge\Traits\ApigeeEdgeFunctionalTestTrait; use Drupal\Tests\BrowserTestBase; @@ -40,6 +41,11 @@ abstract class ApigeeEdgeFunctionalTestBase extends BrowserTestBase { * {@inheritdoc} */ protected function setUp(): void { + // Skipping the test if instance type is Public. + $instance_type = getenv('APIGEE_EDGE_INSTANCE_TYPE'); + if (!empty($instance_type) && $instance_type === EdgeKeyTypeInterface::INSTANCE_TYPE_HYBRID) { + $this->markTestSkipped('This test suite is expecting a PUBLIC instance type.'); + } parent::setUp(); $this->initTestEnv(); } diff --git a/tests/src/Functional/ApigeeX/ApigeeEdgeFunctionalTestBase.php b/tests/src/Functional/ApigeeX/ApigeeEdgeFunctionalTestBase.php new file mode 100644 index 00000000..36722a64 --- /dev/null +++ b/tests/src/Functional/ApigeeX/ApigeeEdgeFunctionalTestBase.php @@ -0,0 +1,53 @@ +markTestSkipped('This test suite is expecting a HYBRID instance type.'); + } + parent::setUp(); + $this->initTestEnv(); + } + +} diff --git a/tests/src/FunctionalJavascript/ApigeeEdgeFunctionalJavascriptTestBase.php b/tests/src/FunctionalJavascript/ApigeeEdgeFunctionalJavascriptTestBase.php index b6131e22..32e3daa0 100644 --- a/tests/src/FunctionalJavascript/ApigeeEdgeFunctionalJavascriptTestBase.php +++ b/tests/src/FunctionalJavascript/ApigeeEdgeFunctionalJavascriptTestBase.php @@ -19,6 +19,7 @@ namespace Drupal\Tests\apigee_edge\FunctionalJavascript; +use Drupal\apigee_edge\Plugin\EdgeKeyTypeInterface; use Drupal\FunctionalJavascriptTests\WebDriverTestBase; use Drupal\Tests\apigee_edge\Traits\ApigeeEdgeFunctionalTestTrait; @@ -40,6 +41,11 @@ abstract class ApigeeEdgeFunctionalJavascriptTestBase extends WebDriverTestBase * {@inheritdoc} */ protected function setUp(): void { + // Skipping the test if instance type is Public. + $instance_type = getenv('APIGEE_EDGE_INSTANCE_TYPE'); + if (!empty($instance_type) && $instance_type === EdgeKeyTypeInterface::INSTANCE_TYPE_HYBRID) { + $this->markTestSkipped('This test suite is expecting a PUBLIC instance type.'); + } parent::setUp(); $this->initTestEnv(); } diff --git a/tests/src/Kernel/ApigeeEdgeKernelTestBase.php b/tests/src/Kernel/ApigeeEdgeKernelTestBase.php new file mode 100644 index 00000000..41446117 --- /dev/null +++ b/tests/src/Kernel/ApigeeEdgeKernelTestBase.php @@ -0,0 +1,42 @@ +markTestSkipped('This test suite is expecting a PUBLIC instance type.'); + } + parent::setUp(); + } + +} diff --git a/tests/src/Kernel/ApigeeX/ApigeeEdgeKernelTestBase.php b/tests/src/Kernel/ApigeeX/ApigeeEdgeKernelTestBase.php new file mode 100644 index 00000000..ab88b7ff --- /dev/null +++ b/tests/src/Kernel/ApigeeX/ApigeeEdgeKernelTestBase.php @@ -0,0 +1,89 @@ +markTestSkipped('This test suite is expecting a HYBRID instance type.'); + } + parent::setUp(); + } + + /** + * Stores pre-configured token storage service for testing. + */ + protected function storeToken() { + // Storing the token for Apigeex Hybrid Org. + $this->testTokenData = [ + 'access_token' => mb_strtolower($this->randomMachineName(32)), + 'token_type' => 'bearer', + 'expires_in' => 300, + 'refresh_token' => mb_strtolower($this->randomMachineName(32)), + 'scope' => 'create', + ]; + $storage = $this->tokenStorage(); + + // Save the token. + $storage->saveToken($this->testTokenData); + } + + /** + * Returns a pre-configured token storage service for testing. + * + * @param bool $rebuild + * Enforces rebuild of the container and with the the token storage + * service. + * + * @return \Drupal\apigee_edge\OauthTokenFileStorage + * The configured and initialized OAuth file token storage service. + * + * @throws \Exception + */ + private function tokenStorage(bool $rebuild = FALSE): OauthTokenFileStorage { + $config = $this->config('apigee_edge.auth'); + $config->set('oauth_token_storage_location', OauthTokenFileStorage::DEFAULT_DIRECTORY)->save(); + if ($rebuild) { + $this->container->get('kernel')->rebuildContainer(); + } + return $this->container->get('apigee_edge.authentication.oauth_token_storage'); + } + +} diff --git a/tests/src/Kernel/Entity/AppWarningsCheckerTest.php b/tests/src/Kernel/Entity/AppWarningsCheckerTest.php index 2e6b3843..1420b2be 100644 --- a/tests/src/Kernel/Entity/AppWarningsCheckerTest.php +++ b/tests/src/Kernel/Entity/AppWarningsCheckerTest.php @@ -25,7 +25,7 @@ use Drupal\apigee_edge\Entity\ApiProduct; use Drupal\apigee_edge\Entity\Developer; use Drupal\apigee_edge\Entity\DeveloperApp; -use Drupal\KernelTests\KernelTestBase; +use Drupal\Tests\apigee_edge\Kernel\ApigeeEdgeKernelTestBase; use Drupal\Tests\apigee_edge\Kernel\ApigeeEdgeKernelTestTrait; use Drupal\Tests\apigee_edge\Traits\CredsUtilsTrait; use Drupal\Tests\apigee_mock_api_client\Traits\ApigeeMockApiClientHelperTrait; @@ -39,7 +39,7 @@ * @group apigee_edge * @group apigee_edge_kernel */ -class AppWarningsCheckerTest extends KernelTestBase { +class AppWarningsCheckerTest extends ApigeeEdgeKernelTestBase { use ApigeeMockApiClientHelperTrait, ApigeeEdgeKernelTestTrait, UserCreationTrait, CredsUtilsTrait; diff --git a/tests/src/Kernel/Entity/ListBuilder/AppListBuilderTest.php b/tests/src/Kernel/Entity/ListBuilder/AppListBuilderTest.php index f92830c0..3ec5e6a8 100644 --- a/tests/src/Kernel/Entity/ListBuilder/AppListBuilderTest.php +++ b/tests/src/Kernel/Entity/ListBuilder/AppListBuilderTest.php @@ -27,7 +27,7 @@ use Drupal\apigee_edge\Entity\Developer; use Drupal\apigee_edge\Entity\DeveloperApp; use Drupal\Component\Utility\Html; -use Drupal\KernelTests\KernelTestBase; +use Drupal\Tests\apigee_edge\Kernel\ApigeeEdgeKernelTestBase; use Drupal\Tests\apigee_edge\Kernel\ApigeeEdgeKernelTestTrait; use Drupal\Tests\apigee_edge\Traits\CredsUtilsTrait; use Drupal\Tests\apigee_mock_api_client\Traits\ApigeeMockApiClientHelperTrait; @@ -41,7 +41,7 @@ * @group apigee_edge * @group apigee_edge_kernel */ -class AppListBuilderTest extends KernelTestBase { +class AppListBuilderTest extends ApigeeEdgeKernelTestBase { use ApigeeMockApiClientHelperTrait, ApigeeEdgeKernelTestTrait, UserCreationTrait, CredsUtilsTrait; diff --git a/tests/src/Kernel/Entity/ListBuilder/EntityListBuilderTest.php b/tests/src/Kernel/Entity/ListBuilder/EntityListBuilderTest.php index caa3ef75..0f4db6fb 100644 --- a/tests/src/Kernel/Entity/ListBuilder/EntityListBuilderTest.php +++ b/tests/src/Kernel/Entity/ListBuilder/EntityListBuilderTest.php @@ -22,7 +22,7 @@ use Drupal\Core\Entity\Entity\EntityViewMode; use Drupal\Core\Url; -use Drupal\KernelTests\KernelTestBase; +use Drupal\Tests\apigee_edge\Kernel\ApigeeEdgeKernelTestBase; use Drupal\Tests\apigee_edge\Kernel\ApigeeEdgeKernelTestTrait; use Drupal\Tests\apigee_mock_api_client\Traits\ApigeeMockApiClientHelperTrait; use Drupal\Tests\user\Traits\UserCreationTrait; @@ -35,7 +35,7 @@ * @group apigee_edge * @group apigee_edge_kernel */ -class EntityListBuilderTest extends KernelTestBase { +class EntityListBuilderTest extends ApigeeEdgeKernelTestBase { use ApigeeMockApiClientHelperTrait, ApigeeEdgeKernelTestTrait, UserCreationTrait; diff --git a/tests/src/Kernel/TestFrameworkKernelTest.php b/tests/src/Kernel/TestFrameworkKernelTest.php index 9705bf7d..b7b783be 100644 --- a/tests/src/Kernel/TestFrameworkKernelTest.php +++ b/tests/src/Kernel/TestFrameworkKernelTest.php @@ -21,7 +21,7 @@ use Drupal\apigee_edge\Entity\Developer; use Drupal\Core\Form\FormState; -use Drupal\KernelTests\KernelTestBase; +use Drupal\Tests\apigee_edge\Kernel\ApigeeEdgeKernelTestBase; use Drupal\Tests\apigee_mock_api_client\Traits\ApigeeMockApiClientHelperTrait; use Drupal\Tests\user\Traits\UserCreationTrait; use GuzzleHttp\Psr7\Response; @@ -33,7 +33,7 @@ * @group apigee_edge * @group apigee_edge_kernel */ -class TestFrameworkKernelTest extends KernelTestBase { +class TestFrameworkKernelTest extends ApigeeEdgeKernelTestBase { use ApigeeMockApiClientHelperTrait; use UserCreationTrait; diff --git a/tests/src/Kernel/Util/ApigeeEdgeManagementCliServiceTest.php b/tests/src/Kernel/Util/ApigeeEdgeManagementCliServiceTest.php index 15cca9ab..5d86cdf8 100644 --- a/tests/src/Kernel/Util/ApigeeEdgeManagementCliServiceTest.php +++ b/tests/src/Kernel/Util/ApigeeEdgeManagementCliServiceTest.php @@ -22,7 +22,7 @@ use Apigee\Edge\Exception\ClientErrorException; use Drupal\Core\DependencyInjection\ContainerBuilder; use Drupal\Core\DependencyInjection\ServiceModifierInterface; -use Drupal\KernelTests\KernelTestBase; +use Drupal\Tests\apigee_edge\Kernel\ApigeeEdgeKernelTestBase; use Drupal\Tests\apigee_mock_api_client\Traits\ApigeeMockApiClientHelperTrait; /** @@ -36,7 +36,7 @@ * @group apigee_edge * @group apigee_edge_kernel */ -class ApigeeEdgeManagementCliServiceTest extends KernelTestBase implements ServiceModifierInterface { +class ApigeeEdgeManagementCliServiceTest extends ApigeeEdgeKernelTestBase implements ServiceModifierInterface { use ApigeeMockApiClientHelperTrait; diff --git a/tests/src/Traits/ApigeeEdgeFunctionalTestTrait.php b/tests/src/Traits/ApigeeEdgeFunctionalTestTrait.php index c8162793..2f9dc441 100644 --- a/tests/src/Traits/ApigeeEdgeFunctionalTestTrait.php +++ b/tests/src/Traits/ApigeeEdgeFunctionalTestTrait.php @@ -99,7 +99,7 @@ protected function createAccount(array $permissions = [], bool $status = TRUE, s $edit = [ 'first_name' => $this->randomMachineName(), 'last_name' => $this->randomMachineName(), - 'name' => $this->randomMachineName(), + 'name' => strtolower($this->randomMachineName()), 'pass' => \Drupal::service('password_generator')->generate(), 'status' => $status, ];