Browse Source

playwright: fix stale Master password selectors against bundled web vault

The bundled web vault dropped the "(required)" suffix from the
master-password input's label text (it likely became a separate visual
indicator). Every test that drives a master-password reprompt — account
creation, TOTP setup, email-2FA setup, SSO master-password flows,
organization-policy management — has been failing on the current
bundled vault because `getByLabel('Master password (required)',
{ exact: true })` no longer matches anything.

Two-line change in most files: switch to `getByLabel('Master password')`,
matching the pattern that `logUser` (setups/user.ts:46) and
`login.spec.ts:40` already use successfully. Substring matching is
case-sensitive in Playwright, so the selector is unambiguous against
the confirm-field ("Confirm master password" has a lowercase 'm').

`createAccount` step 2 (setups/user.ts) and `logNewUser` step 3
(setups/sso.ts) are special: the registration / "Join organisation"
form has three labels matching "Master password" as a case-insensitive
substring ("Master password\n(required)", "Confirm master password\n
(required)" which matches because Playwright's substring match is
case-insensitive in practice, and "Master password hint" which also
matches). Anchor those two fields by their stable `formcontrolname`
attribute (`newPassword` / `newPasswordConfirm`) instead of label text.

Verified empirically: with these changes, both `login.spec.ts` (3/3:
Account creation, Master password login, Authenticator 2fa) and
`sso_login.spec.ts` (8/8 including SSO Account creation, SSO login,
SSO login with TOTP 2fa, Non-SSO login fallback, SSO_ONLY, no SSO)
run green against bundled web-vault v2026.4.1.
pull/7248/head
Zaid Marji 3 weeks ago
parent
commit
c0589bbd74
  1. 9
      playwright/tests/organization.smtp.spec.ts
  2. 12
      playwright/tests/setups/2fa.ts
  3. 9
      playwright/tests/setups/sso.ts
  4. 10
      playwright/tests/setups/user.ts
  5. 7
      playwright/tests/sso_organization.smtp.spec.ts
  6. 2
      playwright/tests/sso_organization.spec.ts

9
playwright/tests/organization.smtp.spec.ts

@ -57,8 +57,13 @@ test('invited with new account', async ({ page }) => {
await expect(page).toHaveTitle(/Create account | Vaultwarden Web/);
//await page.getByLabel('Name').fill(users.user2.name);
await page.getByLabel('Master password (required)', { exact: true }).fill(users.user2.password);
await page.getByLabel('Confirm master password (').fill(users.user2.password);
// Three labels match "Master password" via Playwright's case-insensitive
// substring matching ("Master password (required)", "Confirm master
// password (required)", "Master password hint"), so anchor by
// formcontrolname — same pattern as setups/user.ts:createAccount and
// setups/sso.ts:logNewUser.
await page.locator('input[formcontrolname="newPassword"]').fill(users.user2.password);
await page.locator('input[formcontrolname="newPasswordConfirm"]').fill(users.user2.password);
await page.getByRole('button', { name: 'Create account' }).click();
await utils.checkNotification(page, 'Your new account has been created');

12
playwright/tests/setups/2fa.ts

@ -11,7 +11,7 @@ export async function activateTOTP(test: Test, page: Page, user: { name: string,
await page.getByRole('link', { name: 'Security' }).click();
await page.getByRole('link', { name: 'Two-step login' }).click();
await page.locator('bit-item').filter({ hasText: /Authenticator app/ }).getByRole('button').click();
await page.getByLabel('Master password (required)').fill(user.password);
await page.getByLabel('Master password').fill(user.password);
await page.getByRole('button', { name: 'Continue' }).click();
const secret = await page.getByLabel('Key').innerText();
@ -33,8 +33,8 @@ export async function disableTOTP(test: Test, page: Page, user: { password: stri
await page.getByRole('link', { name: 'Security' }).click();
await page.getByRole('link', { name: 'Two-step login' }).click();
await page.locator('bit-item').filter({ hasText: /Authenticator app/ }).getByRole('button').click();
await page.getByLabel('Master password (required)').click();
await page.getByLabel('Master password (required)').fill(user.password);
await page.getByLabel('Master password').click();
await page.getByLabel('Master password').fill(user.password);
await page.getByRole('button', { name: 'Continue' }).click();
await page.getByRole('button', { name: 'Turn off' }).click();
await page.getByRole('button', { name: 'Yes' }).click();
@ -49,7 +49,7 @@ export async function activateEmail(test: Test, page: Page, user: { name: string
await page.getByRole('link', { name: 'Security' }).click();
await page.getByRole('link', { name: 'Two-step login' }).click();
await page.locator('bit-item').filter({ hasText: 'Enter a code sent to your email' }).getByRole('button').click();
await page.getByLabel('Master password (required)').fill(user.password);
await page.getByLabel('Master password').fill(user.password);
await page.getByRole('button', { name: 'Continue' }).click();
await page.getByRole('button', { name: 'Send email' }).click();
});
@ -81,8 +81,8 @@ export async function disableEmail(test: Test, page: Page, user: { password: str
await page.getByRole('link', { name: 'Security' }).click();
await page.getByRole('link', { name: 'Two-step login' }).click();
await page.locator('bit-item').filter({ hasText: 'Email' }).getByRole('button').click();
await page.getByLabel('Master password (required)').click();
await page.getByLabel('Master password (required)').fill(user.password);
await page.getByLabel('Master password').click();
await page.getByLabel('Master password').fill(user.password);
await page.getByRole('button', { name: 'Continue' }).click();
await page.getByRole('button', { name: 'Turn off' }).click();
await page.getByRole('button', { name: 'Yes' }).click();

9
playwright/tests/setups/sso.ts

@ -33,8 +33,13 @@ export async function logNewUser(
await test.step('Create Vault account', async () => {
await expect(page.getByRole('heading', { name: 'Join organisation' })).toBeVisible();
await page.getByLabel('Master password (required)', { exact: true }).fill(user.password);
await page.getByLabel('Confirm master password (').fill(user.password);
// Three labels on this form match "Master password" via Playwright's
// case-insensitive substring matching ("Master password (required)",
// "Confirm master password (required)", "Master password hint"), so
// anchor by formcontrolname (the pattern setups/user.ts:createAccount
// also uses for the same reason).
await page.locator('input[formcontrolname="newPassword"]').fill(user.password);
await page.locator('input[formcontrolname="newPasswordConfirm"]').fill(user.password);
await page.getByRole('button', { name: 'Create account' }).click();
});

10
playwright/tests/setups/user.ts

@ -16,9 +16,13 @@ export async function createAccount(test, page: Page, user: { email: string, nam
await page.getByLabel('Name').fill(user.name);
await page.getByRole('button', { name: 'Continue' }).click();
// Vault finish Creation
await page.getByLabel('Master password (required)', { exact: true }).fill(user.password);
await page.getByLabel('Confirm master password (').fill(user.password);
// Vault finish Creation. The current bundled web-vault renders the
// required field's label as "Master password\n(required)", so a bare
// substring match for "Master password" is ambiguous with the
// "Master password hint" label on the same page. Anchor to the
// password input by its formcontrolname instead.
await page.locator('input[formcontrolname="newPassword"]').fill(user.password);
await page.locator('input[formcontrolname="newPasswordConfirm"]').fill(user.password);
await page.getByRole('button', { name: 'Create account' }).click();
await utils.checkNotification(page, 'Your new account has been created')

7
playwright/tests/sso_organization.smtp.spec.ts

@ -67,8 +67,11 @@ test('invited with new account', async ({ page }) => {
await test.step('Create Vault account', async () => {
await expect(page.getByRole('heading', { name: 'Join organisation' })).toBeVisible();
await page.getByLabel('Master password (required)', { exact: true }).fill(users.user2.password);
await page.getByLabel('Confirm master password (').fill(users.user2.password);
// Three labels match "Master password" via Playwright's case-insensitive
// substring matching, so anchor by formcontrolname — same pattern as
// setups/sso.ts:logNewUser.
await page.locator('input[formcontrolname="newPassword"]').fill(users.user2.password);
await page.locator('input[formcontrolname="newPasswordConfirm"]').fill(users.user2.password);
await page.getByRole('button', { name: 'Create account' }).click();
await utils.checkNotification(page, 'Account successfully created!');

2
playwright/tests/sso_organization.spec.ts

@ -68,7 +68,7 @@ test('Enforce password policy', async ({ page }) => {
await page.locator("input[type=email].vw-email-sso").fill(users.user1.email);
await page.getByRole('button', { name: 'Use single sign-on' }).click();
await page.getByRole('textbox', { name: 'Master password (required)' }).fill(users.user1.password);
await page.getByLabel('Master password').fill(users.user1.password);
await page.getByRole('button', { name: 'Unlock' }).click();
await expect(page.getByRole('heading', { name: 'Update master password' })).toBeVisible();

Loading…
Cancel
Save