test(e2e): Update tests due to 0.17.0 changes (#2401)

* test(e2e): Only clean up org if org hasn't been deleted yet

* test(e2e): Use new worker filter tab

* test(e2e): Update selector for updated Manage button

Some pages now use a Manage button instead of a Manage link. The "Title" selector was not being picked up on the Manage button.

* test(e2e): Fix flakiness due to race condition

The test should navigate to the home page after creating all of the resources using the API

* test(e2e): Add cleanup to test
This commit is contained in:
Michael Li authored and GitHub committed 2024-07-24 14:55:51 -04:00
1 parent 25a99a4fb6
commit e73bded6ae
10 files changed
+218 -189

No files matched your search

+32 -41
View File
@@ -683,46 +683,6 @@ exports.createSshTargetWithAddressAndAlias = async (
return targetName;
};
/**
* Uses the UI to create a new SSH target with address in boundary-enterprise
* Assumes you have selected the desired project.
* @param {Page} page Playwright page object
* @param {string} address Address of the target
* @param {string} port Port of the target
* @param {string} workerFilterEgress Egress worker filter
* @returns Name of the target
*/
exports.createSshTargetWithAddressAndWorkerFilterEnt = async (
page,
address,
port,
workerFilterEgress,
) => {
const targetName = 'Target ' + nanoid();
await page
.getByRole('navigation', { name: 'Resources' })
.getByRole('link', { name: 'Targets' })
.click();
await page.getByRole('link', { name: 'New', exact: true }).click();
await page.getByLabel('Name').fill(targetName);
await page.getByLabel('Description').fill('This is an automated test');
await page.getByRole('group', { name: 'Type' }).getByLabel('SSH').click();
await page.getByLabel('Target Address').fill(address);
await page.getByLabel('Default Port').fill(port);
await page.getByLabel('Egress worker filter').click();
await page.getByRole('textbox', { name: 'Filter' }).fill(workerFilterEgress);
await page.getByRole('button', { name: 'Save' }).click();
await expect(
page.getByRole('alert').getByText('Success', { exact: true }),
).toBeVisible();
await page.getByRole('button', { name: 'Dismiss' }).click();
await expect(
page.getByRole('navigation', { name: 'breadcrumbs' }).getByText(targetName),
).toBeVisible();
return targetName;
};
/**
* Uses the UI to create an alias
* @param {Page} page Playwright page object
@@ -774,7 +734,7 @@ exports.createAliasForTarget = async (page, alias, targetId) => {
* @param {Page} page Playwright page object
*/
exports.deleteResource = async (page) => {
await page.getByTitle('Manage').click();
await page.getByText('Manage').click();
await page.getByRole('button', { name: /^(Delete|Remove Worker)/ }).click();
await page.getByText('OK', { exact: true }).click();
await expect(
@@ -837,6 +797,37 @@ exports.addHostSourceToTarget = async (page, hostSourceName) => {
await expect(page.getByRole('link', { name: hostSourceName })).toBeVisible();
};
/**
* Uses the UI to add an egress worker filter to a target. Assume you have selected the desired target.
* @param {Page} page Playwright page object
* @param {string} filter Egress worker filter to be added to the target
*/
exports.addEgressWorkerFilterToTarget = async (page, filter) => {
await page.getByRole('link', { name: 'Workers', exact: true }).click();
await expect(
page.getByRole('navigation', { name: 'breadcrumbs' }).getByText('Workers'),
).toBeVisible();
await page
.getByText('Egress workers')
.locator('..')
.getByRole('link', { name: 'Edit worker filter' })
.click();
await expect(
page
.getByRole('navigation', { name: 'breadcrumbs' })
.getByText('Edit Egress Worker Filter'),
).toBeVisible();
await page.getByRole('textbox').fill(filter);
await page.getByRole('button', { name: 'Save' }).click();
await expect(
page.getByRole('alert').getByText('Success', { exact: true }),
).toBeVisible();
await page.getByRole('button', { name: 'Dismiss' }).click();
};
/**
* Uses the UI to navigate to Sessions and waits for the session to appear
* and be in Active state.
@@ -74,6 +74,7 @@ test('Verify resources can be deleted (enterprise) @ent @aws', async ({
page,
}) => {
let orgId;
let orgDeleted = false;
try {
orgId = await createOrgCli();
let projectId = await createProjectCli(orgId);
@@ -170,8 +171,9 @@ test('Verify resources can be deleted (enterprise) @ent @aws', async ({
await deleteResource(page);
await page.goto(`/scopes/${orgId}/edit`);
await deleteResource(page);
orgDeleted = true;
} finally {
if (orgId) {
if (orgId && orgDeleted == false) {
await deleteOrgCli(orgId);
}
}
@@ -71,6 +71,7 @@ test.beforeEach(async () => {
test('Verify resources can be deleted @ce @aws', async ({ page }) => {
let orgId;
let orgDeleted = false;
try {
// Create boundary resources using CLI
orgId = await createOrgCli();
@@ -191,9 +192,10 @@ test('Verify resources can be deleted @ce @aws', async ({ page }) => {
// Delete org
await page.goto(`/scopes/${orgId}/edit`);
await deleteResource(page);
orgDeleted = true;
} finally {
// Delete org in case the test failed before deleting the org using UI
if (orgId) {
if (orgId && orgDeleted === false) {
await deleteOrgCli(orgId);
}
}
@@ -5,8 +5,13 @@
/* eslint-disable no-undef */
const { test, expect } = require('@playwright/test');
import { execSync } from 'child_process';
const { nanoid } = require('nanoid');
const { checkEnv, authenticatedState } = require('../helpers/general');
const {
authenticateBoundaryCli,
deleteOrgCli,
} = require('../helpers/boundary-cli');
const {
addHostSourceToTarget,
createHostCatalog,
@@ -37,151 +42,173 @@ test.describe('AWS', async () => {
test('Create an AWS Dynamic Host Catalog and set up Host Sets @ce @ent @aws', async ({
page,
}) => {
await createOrg(page);
await createProject(page);
let orgName;
try {
orgName = await createOrg(page);
await createProject(page);
// Create host catalog
const hostCatalogName = 'Host Catalog ' + nanoid();
await page
.getByRole('navigation', { name: 'Resources' })
.getByRole('link', { name: 'Host Catalogs' })
.click();
await page.getByRole('link', { name: 'New', exact: true }).click();
await page.getByLabel('Name').fill(hostCatalogName);
await page.getByLabel('Description').fill('This is an automated test');
await page
.getByRole('group', { name: 'Type' })
.getByLabel('Dynamic')
.click();
await page
.getByRole('group', { name: 'Provider' })
.getByLabel('AWS')
.click();
await page.getByLabel('AWS Region').fill(process.env.E2E_AWS_REGION);
await page
.getByLabel('Access Key ID')
.fill(process.env.E2E_AWS_ACCESS_KEY_ID);
await page
.getByLabel('Secret Access Key')
.fill(process.env.E2E_AWS_SECRET_ACCESS_KEY);
await page.getByLabel('Disable credential rotation').click({ force: true });
await page.getByRole('button', { name: 'Save' }).click();
await expect(
page.getByRole('alert').getByText('Success', { exact: true }),
).toBeVisible();
await page.getByRole('button', { name: 'Dismiss' }).click();
await expect(
page
.getByRole('navigation', { name: 'breadcrumbs' })
.getByText(hostCatalogName),
).toBeVisible();
// Create first host set
const hostSetName = 'Host Set ' + nanoid();
await page.getByRole('link', { name: 'Host Sets' }).click();
await page.getByRole('link', { name: 'New', exact: true }).click();
await page.getByLabel('Name (Optional)').fill(hostSetName);
await page.getByLabel('Description').fill('This is an automated test');
await page
.getByRole('group', { name: 'Filter' })
.getByRole('textbox')
.fill(process.env.E2E_AWS_HOST_SET_FILTER);
await page
.getByRole('group', { name: 'Filter' })
.getByRole('button', { name: 'Add' })
.click();
await page.getByRole('button', { name: 'Save' }).click();
await expect(
page.getByRole('alert').getByText('Success', { exact: true }),
).toBeVisible();
await page.getByRole('button', { name: 'Dismiss' }).click();
await expect(
page
.getByRole('navigation', { name: 'breadcrumbs' })
.getByText(hostSetName),
).toBeVisible();
await page.getByRole('link', { name: 'Hosts' }).click();
await expect(
page.getByRole('navigation', { name: 'breadcrumbs' }).getByText('Hosts'),
).toBeVisible();
// Check number of hosts in host set
let i = 0;
let rowCount = 0;
let expectedHosts = JSON.parse(process.env.E2E_AWS_HOST_SET_IPS);
do {
i = i + 1;
// Getting the number of rows in the second rowgroup (the first rowgroup is the header row)
rowCount = await page
.getByRole('table')
.getByRole('rowgroup')
.nth(1)
.getByRole('row')
.count();
await page.reload();
// Create host catalog
const hostCatalogName = 'Host Catalog ' + nanoid();
await page
.getByRole('navigation', { name: 'breadcrumbs' })
.getByText(hostSetName)
.waitFor();
} while (i < 5);
expect(rowCount).toBe(expectedHosts.length);
// Navigate to each host in the host set
for (let i = 0; i < expectedHosts.length; i++) {
const host = await page
.getByRole('table')
.getByRole('rowgroup')
.nth(1)
.getByRole('row')
.nth(i)
.getByRole('link');
let hostName = await host.innerText();
await host.click();
.getByRole('navigation', { name: 'Resources' })
.getByRole('link', { name: 'Host Catalogs' })
.click();
await page.getByRole('link', { name: 'New', exact: true }).click();
await page.getByLabel('Name').fill(hostCatalogName);
await page.getByLabel('Description').fill('This is an automated test');
await page
.getByRole('group', { name: 'Type' })
.getByLabel('Dynamic')
.click();
await page
.getByRole('group', { name: 'Provider' })
.getByLabel('AWS')
.click();
await page.getByLabel('AWS Region').fill(process.env.E2E_AWS_REGION);
await page
.getByLabel('Access Key ID')
.fill(process.env.E2E_AWS_ACCESS_KEY_ID);
await page
.getByLabel('Secret Access Key')
.fill(process.env.E2E_AWS_SECRET_ACCESS_KEY);
await page
.getByLabel('Disable credential rotation')
.click({ force: true });
await page.getByRole('button', { name: 'Save' }).click();
await expect(
page.getByRole('alert').getByText('Success', { exact: true }),
).toBeVisible();
await page.getByRole('button', { name: 'Dismiss' }).click();
await expect(
page
.getByRole('navigation', { name: 'breadcrumbs' })
.getByText(hostName),
.getByText(hostCatalogName),
).toBeVisible();
// Create first host set
const hostSetName = 'Host Set ' + nanoid();
await page.getByRole('link', { name: 'Host Sets' }).click();
await page.getByRole('link', { name: 'New', exact: true }).click();
await page.getByLabel('Name (Optional)').fill(hostSetName);
await page.getByLabel('Description').fill('This is an automated test');
await page
.getByRole('navigation', { name: 'breadcrumbs' })
.getByText(hostSetName)
.getByRole('group', { name: 'Filter' })
.getByRole('textbox')
.fill(process.env.E2E_AWS_HOST_SET_FILTER);
await page
.getByRole('group', { name: 'Filter' })
.getByRole('button', { name: 'Add' })
.click();
await page.getByRole('button', { name: 'Save' }).click();
await expect(
page.getByRole('alert').getByText('Success', { exact: true }),
).toBeVisible();
await page.getByRole('button', { name: 'Dismiss' }).click();
await expect(
page
.getByRole('navigation', { name: 'breadcrumbs' })
.getByText(hostSetName),
).toBeVisible();
await page.getByRole('link', { name: 'Hosts' }).click();
await expect(
page
.getByRole('navigation', { name: 'breadcrumbs' })
.getByText('Hosts'),
).toBeVisible();
// Check number of hosts in host set
let i = 0;
let rowCount = 0;
let expectedHosts = JSON.parse(process.env.E2E_AWS_HOST_SET_IPS);
do {
i = i + 1;
// Getting the number of rows in the second rowgroup (the first rowgroup is the header row)
rowCount = await page
.getByRole('table')
.getByRole('rowgroup')
.nth(1)
.getByRole('row')
.count();
await page.reload();
await page
.getByRole('navigation', { name: 'breadcrumbs' })
.getByText(hostSetName)
.waitFor();
} while (i < 5);
expect(rowCount).toBe(expectedHosts.length);
// Navigate to each host in the host set
for (let i = 0; i < expectedHosts.length; i++) {
const host = await page
.getByRole('table')
.getByRole('rowgroup')
.nth(1)
.getByRole('row')
.nth(i)
.getByRole('link');
let hostName = await host.innerText();
await host.click();
await expect(
page
.getByRole('navigation', { name: 'breadcrumbs' })
.getByText(hostName),
).toBeVisible();
await page
.getByRole('navigation', { name: 'breadcrumbs' })
.getByText(hostSetName)
.click();
await page.getByRole('link', { name: 'Hosts' }).click();
}
// Create a target and add DHC host set as a host source
const targetName = await createTarget(page, process.env.E2E_TARGET_PORT);
await addHostSourceToTarget(page, hostSetName);
// Add another host source
await createHostCatalog(page);
const newHostSetName = await createHostSet(page);
await page
.getByRole('navigation', { name: 'Resources' })
.getByRole('link', { name: 'Targets' })
.click();
await page.getByRole('link', { name: targetName }).click();
await addHostSourceToTarget(page, newHostSetName);
// Remove the host source from the target
await page
.getByRole('link', { name: newHostSetName })
.locator('..')
.locator('..')
.getByRole('button', { name: 'Manage' })
.click();
await page.getByRole('button', { name: 'Remove' }).click();
await page.getByRole('button', { name: 'OK', exact: true }).click();
await expect(
page.getByRole('alert').getByText('Success', { exact: true }),
).toBeVisible();
await page.getByRole('button', { name: 'Dismiss' }).click();
// Add the host source back
await addHostSourceToTarget(page, newHostSetName);
} finally {
await authenticateBoundaryCli(
process.env.BOUNDARY_ADDR,
process.env.E2E_PASSWORD_AUTH_METHOD_ID,
process.env.E2E_PASSWORD_ADMIN_LOGIN_NAME,
process.env.E2E_PASSWORD_ADMIN_PASSWORD,
);
if (orgName) {
const orgs = JSON.parse(execSync('boundary scopes list -format json'));
const org = orgs.items.filter((obj) => obj.name == orgName)[0];
if (org) {
await deleteOrgCli(org.id);
}
}
}
// Create a target and add DHC host set as a host source
const targetName = await createTarget(page, process.env.E2E_TARGET_PORT);
await addHostSourceToTarget(page, hostSetName);
// Add another host source
await createHostCatalog(page);
const newHostSetName = await createHostSet(page);
await page
.getByRole('navigation', { name: 'Resources' })
.getByRole('link', { name: 'Targets' })
.click();
await page.getByRole('link', { name: targetName }).click();
await addHostSourceToTarget(page, newHostSetName);
// Remove the host source from the target
await page
.getByRole('link', { name: newHostSetName })
.locator('..')
.locator('..')
.getByRole('button', { name: 'Manage' })
.click();
await page.getByRole('button', { name: 'Remove' }).click();
await page.getByRole('button', { name: 'OK', exact: true }).click();
await expect(
page.getByRole('alert').getByText('Success', { exact: true }),
).toBeVisible();
await page.getByRole('button', { name: 'Dismiss' }).click();
// Add the host source back
await addHostSourceToTarget(page, newHostSetName);
});
});
+1 -1
View File
@@ -14,7 +14,6 @@ test('Search and Pagination (Targets) @ce @ent @aws @docker', async ({
page,
request,
}) => {
await page.goto('/');
let org;
try {
const newOrg = await request.post(`/v1/scopes`, {
@@ -52,6 +51,7 @@ test('Search and Pagination (Targets) @ce @ent @aws @docker', async ({
}
// Navigate to targets page
await page.goto('/');
await page.getByRole('link', { name: org.name }).click();
await page.getByRole('link', { name: project.name }).click();
await page
@@ -17,7 +17,6 @@ const {
deletePolicyCli,
} = require('../helpers/boundary-cli');
const {
createSshTargetWithAddressAndWorkerFilterEnt,
waitForSessionToBeVisible,
createStorageBucketAws,
enableSessionRecording,
@@ -27,7 +26,9 @@ const {
createProject,
createStaticCredentialStore,
createStaticCredentialKeyPair,
createSshTargetWithAddressEnt,
addInjectedCredentialsToTarget,
addEgressWorkerFilterToTarget,
} = require('../helpers/boundary-ui');
test.use({ storageState: authenticatedState });
@@ -98,10 +99,13 @@ test('Session Recording Test (AWS) @ent @aws', async ({ page }) => {
await expect(page.getByRole('heading', { name: 'Orgs' })).toBeVisible();
await page.getByRole('link', { name: orgName }).click();
await page.getByRole('link', { name: projectName }).click();
const targetName = await createSshTargetWithAddressAndWorkerFilterEnt(
const targetName = await createSshTargetWithAddressEnt(
page,
process.env.E2E_TARGET_ADDRESS,
process.env.E2E_TARGET_PORT,
);
await addEgressWorkerFilterToTarget(
page,
`"${process.env.E2E_WORKER_TAG_EGRESS}" in "/tags/type"`,
);
const targets = JSON.parse(
@@ -17,7 +17,6 @@ const {
deletePolicyCli,
} = require('../helpers/boundary-cli');
const {
createSshTargetWithAddressAndWorkerFilterEnt,
waitForSessionToBeVisible,
createStorageBucketMinio,
enableSessionRecording,
@@ -27,7 +26,9 @@ const {
createProject,
createStaticCredentialStore,
createStaticCredentialKeyPair,
createSshTargetWithAddressEnt,
addInjectedCredentialsToTarget,
addEgressWorkerFilterToTarget,
} = require('../helpers/boundary-ui');
test.use({ storageState: authenticatedState });
@@ -100,12 +101,16 @@ test('Session Recording Test (MinIO) @ent @docker', async ({ page }) => {
await expect(page.getByRole('heading', { name: 'Orgs' })).toBeVisible();
await page.getByRole('link', { name: orgName }).click();
await page.getByRole('link', { name: projectName }).click();
const targetName = await createSshTargetWithAddressAndWorkerFilterEnt(
const targetName = await createSshTargetWithAddressEnt(
page,
process.env.E2E_TARGET_ADDRESS,
process.env.E2E_TARGET_PORT,
);
await addEgressWorkerFilterToTarget(
page,
`"${process.env.E2E_WORKER_TAG_EGRESS}" in "/tags/type"`,
);
const targets = JSON.parse(
execSync('boundary targets list -format json -scope-id ' + projectId),
);
@@ -39,7 +39,6 @@ test.beforeAll(async () => {
'E2E_TARGET_ADDRESS',
'E2E_SSH_USER',
'E2E_SSH_KEY_PATH',
'E2E_WORKER_TAG_EGRESS',
]);
await checkBoundaryCli();
@@ -38,7 +38,6 @@ test.beforeAll(async () => {
'E2E_SSH_KEY_PATH',
'E2E_TARGET_ADDRESS',
'E2E_TARGET_PORT',
'E2E_WORKER_TAG_EGRESS',
]);
await checkBoundaryCli();
+4 -4
View File
@@ -23,6 +23,7 @@ const {
createTargetWithAddress,
waitForSessionToBeVisible,
addHostSourceToTarget,
addEgressWorkerFilterToTarget,
} = require('../helpers/boundary-ui');
test.use({ storageState: authenticatedState });
@@ -195,15 +196,14 @@ test('Verify TCP target is updated @ce @aws @docker', async ({ page }) => {
await page.getByLabel('Default Client Port').fill('10');
await page.getByLabel('Maximum Duration').fill('1000');
await page.getByLabel('Maximum Connections').fill('10');
await page.getByLabel('Egress worker filter').click();
await page
.getByRole('textbox', { name: /^Filter/, exact: true })
.fill('"dev" in "/tags/type"');
await page.getByRole('button', { name: 'Save' }).click();
await expect(
page.getByRole('alert').getByText('Success', { exact: true }),
).toBeVisible();
await page.getByRole('button', { name: 'Dismiss' }).click();
await addEgressWorkerFilterToTarget(page, '"dev" in "/tags/type"');
} finally {
await authenticateBoundaryCli(
process.env.BOUNDARY_ADDR,