mirror of
https://github.com/hashicorp/vault.git
synced 2026-05-28 04:10:44 -04:00
* adds clipboard permissions for playwright tests * fixes access control link in playwright init setup * adds base page class with method for dismissing flash notifications * fixes nav links in playwright kv test and adds base page for dismissing flash messages * adds playwright test for tools workflows Co-authored-by: Jordan Reimer <zofskeez@gmail.com>
This commit is contained in:
parent
978293788d
commit
74237d6daa
5 changed files with 96 additions and 3 deletions
|
|
@ -41,7 +41,7 @@ setup('initialize vault and setup user for testing', async ({ page, userType })
|
|||
await page.getByRole('button', { name: 'Sign in' }).click();
|
||||
// create a policy for a specific user persona
|
||||
// defaults to superuser but should be passed in via the project config in playwright.config.ts
|
||||
await page.getByRole('link', { name: 'Access', exact: true }).click();
|
||||
await page.getByRole('link', { name: 'Access control', exact: true }).click();
|
||||
await page.getByRole('link', { name: 'Create ACL policy' }).click();
|
||||
await page.getByRole('textbox', { name: 'Policy name' }).fill(userType);
|
||||
await page.getByRole('radio', { name: 'Code editor' }).check();
|
||||
|
|
|
|||
19
ui/e2e/pages/base.ts
Normal file
19
ui/e2e/pages/base.ts
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
/**
|
||||
* Copyright IBM Corp. 2016, 2025
|
||||
* SPDX-License-Identifier: BUSL-1.1
|
||||
*/
|
||||
|
||||
import { Page } from '@playwright/test';
|
||||
|
||||
export class BasePage {
|
||||
constructor(protected page: Page) {}
|
||||
// remove all flash messages by clicking the dismiss button until there are no more
|
||||
// this is useful if many are rendered over top of a button preventing click in a test
|
||||
async dismissFlashMessages() {
|
||||
const locator = this.page.getByRole('button', { name: 'Dismiss' });
|
||||
// use a while loop because clicking one might cause the next one to shift or re-render.
|
||||
while ((await locator.count()) > 0) {
|
||||
await locator.first().click();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,11 +4,13 @@
|
|||
*/
|
||||
|
||||
import { test, expect } from '@playwright/test';
|
||||
import { BasePage } from '../../pages/base';
|
||||
|
||||
test('kvv2 workflow', async ({ page }) => {
|
||||
const basePage = new BasePage(page);
|
||||
await page.goto('dashboard');
|
||||
// enable kv secrets engine
|
||||
await page.getByRole('link', { name: 'Secrets Engines' }).click();
|
||||
await page.getByRole('link', { name: 'Secrets', exact: true }).click();
|
||||
await page.getByRole('link', { name: 'Enable new engine' }).click();
|
||||
await page.locator('div').filter({ hasText: 'KV' }).nth(4).click();
|
||||
await page.getByRole('textbox', { name: 'Path' }).click();
|
||||
|
|
@ -20,7 +22,7 @@ test('kvv2 workflow', async ({ page }) => {
|
|||
'No secrets yet When created, secrets will be listed here. Create a secret to get started.'
|
||||
);
|
||||
// verify that the kv engine appears in the list view
|
||||
await page.getByRole('link', { name: 'Secrets Engines' }).click();
|
||||
await page.getByLabel('Secrets Navigation Links').getByRole('link', { name: 'Secrets engines' }).click();
|
||||
await page.getByRole('link', { name: 'kv-test/' }).click();
|
||||
// create a secret
|
||||
await page.getByRole('link', { name: 'Create secret' }).click();
|
||||
|
|
@ -54,6 +56,8 @@ test('kvv2 workflow', async ({ page }) => {
|
|||
await page.getByRole('link', { name: 'Version History' }).click();
|
||||
await expect(page.locator('section')).toContainText('Version 1');
|
||||
await expect(page.locator('section')).toContainText('Current');
|
||||
// there are a stack of flash messages that are blocking the manage version button from being clicked
|
||||
await basePage.dismissFlashMessages();
|
||||
await page.getByRole('button', { name: 'Manage version' }).click();
|
||||
await page.getByRole('link', { name: 'Create new version from 1', exact: true }).click();
|
||||
await page.getByRole('textbox', { name: 'key' }).first().fill('bar-v2');
|
||||
|
|
|
|||
69
ui/e2e/tests/superuser/tools.spec.ts
Normal file
69
ui/e2e/tests/superuser/tools.spec.ts
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
/**
|
||||
* Copyright IBM Corp. 2016, 2025
|
||||
* SPDX-License-Identifier: BUSL-1.1
|
||||
*/
|
||||
|
||||
import { test, expect } from '@playwright/test';
|
||||
import { BasePage } from '../../pages/base';
|
||||
|
||||
test('tools workflow', async ({ page }) => {
|
||||
const basePage = new BasePage(page);
|
||||
await page.goto('dashboard');
|
||||
// wrap data
|
||||
await page.getByRole('link', { name: 'Operational tools' }).click();
|
||||
await page.getByRole('navigation', { name: 'toolbar filters' }).locator('label').click();
|
||||
await page.getByRole('textbox', { name: 'Key' }).fill('foo');
|
||||
await page.getByRole('textbox', { name: 'Value' }).fill('bar');
|
||||
await page.locator('label').filter({ hasText: 'Wrap TTL Vault will use the' }).click();
|
||||
await page.getByRole('textbox', { name: 'Number of units' }).fill('20');
|
||||
await page.getByLabel('ttl-unit').selectOption('h');
|
||||
await page.getByRole('button', { name: 'Wrap data' }).click();
|
||||
await page.getByRole('button', { name: 'copy hvs.' }).click();
|
||||
// access the clipboard to get the copied token value
|
||||
let clipboardValue = await page.evaluate(() => navigator.clipboard.readText());
|
||||
// lookup token
|
||||
await page.getByRole('link', { name: 'Lookup' }).click();
|
||||
await page.getByRole('textbox', { name: 'Wrapped token' }).fill(clipboardValue);
|
||||
await page.getByRole('button', { name: 'Lookup token' }).click();
|
||||
await expect(page.getByRole('heading', { name: 'Lookup token' })).toContainText('Lookup token');
|
||||
await expect(page.locator('section')).toContainText('about 20 hours');
|
||||
// rewrap token
|
||||
await page.getByRole('link', { name: 'Rewrap' }).click();
|
||||
await page.getByRole('textbox', { name: 'Wrapped token' }).fill(clipboardValue);
|
||||
await page.getByRole('button', { name: 'Rewrap token' }).click();
|
||||
await expect(page.locator('label')).toContainText('Rewrapped token');
|
||||
await page.getByRole('button', { name: 'copy hvs.' }).click();
|
||||
// access the clipboard to get the rewrapped token value
|
||||
clipboardValue = await page.evaluate(() => navigator.clipboard.readText());
|
||||
// unwrap token
|
||||
await page.getByRole('link', { name: 'Unwrap' }).click();
|
||||
await page.getByRole('textbox', { name: 'Wrapped token' }).fill(clipboardValue);
|
||||
await page.getByRole('button', { name: 'Unwrap data' }).click();
|
||||
await expect(page.getByRole('code')).toContainText('{ "foo": "bar" }');
|
||||
// generate random bytes
|
||||
await page.getByRole('link', { name: 'Random' }).click();
|
||||
await page.getByRole('spinbutton', { name: 'Number of bytes' }).fill('64');
|
||||
await page.getByLabel('Output format').selectOption('hex');
|
||||
await page.getByRole('button', { name: 'Generate' }).click();
|
||||
await expect(page.getByRole('button', { name: 'copy' })).toBeVisible();
|
||||
// hash
|
||||
await page.getByRole('link', { name: 'Hash', exact: true }).click();
|
||||
await page.getByRole('textbox', { name: 'Input' }).fill('foobar');
|
||||
await page.getByLabel('Algorithm').selectOption('sha2-512');
|
||||
await page.getByLabel('Output format').selectOption('hex');
|
||||
// there are a stack of flash messages that are blocking the encode button from being clicked
|
||||
await basePage.dismissFlashMessages();
|
||||
await page.getByRole('button', { name: 'Encode to base64' }).click();
|
||||
await page.getByRole('button', { name: 'Hash' }).click();
|
||||
await expect(page.getByLabel('copy')).toContainText(
|
||||
'0a50261ebd1a390fed2bf326f2673c145582a6342d523204973d0219337f81616a8069b012587cf5635f6925f1b56c360230c19b273500ee013e030601bf2425'
|
||||
);
|
||||
// API explorer
|
||||
await page.getByRole('link', { name: 'API explorer' }).click();
|
||||
await expect(page.getByRole('heading', { name: 'API explorer' })).toContainText('API explorer');
|
||||
await page.getByRole('textbox', { name: 'Filter by tag' }).fill('lookup-accessor');
|
||||
await expect(page.locator('#operations-0-tokenLookUpAccessor')).toContainText(
|
||||
'/auth/token/lookup-accessor'
|
||||
);
|
||||
await expect(page.locator('#operations-0-tokenLookUpAccessor')).toContainText('tokenLookUpAccessor');
|
||||
});
|
||||
|
|
@ -67,6 +67,7 @@ export default defineConfig<UserSetupOptions>({
|
|||
storageState: fs.existsSync(sessionFile) ? sessionFile : undefined,
|
||||
// start at port 8204 and increment for each project to allow them to run concurrently without conflicts
|
||||
baseURL: getURL(index),
|
||||
permissions: ['clipboard-read', 'clipboard-write'],
|
||||
},
|
||||
};
|
||||
}),
|
||||
|
|
|
|||
Loading…
Reference in a new issue