From 3782dd91ea79bd23f2e919c42653a480ec477d3e Mon Sep 17 00:00:00 2001 From: Emanuele Feliziani Date: Fri, 22 Sep 2023 16:22:06 +0200 Subject: [PATCH] Move Bitwarden tests to own file Signed-off-by: Emanuele Feliziani --- .../tests/bitwarden.macos.spec.js | 245 ++++++++++++++++++ .../tests/login-form.macos.spec.js | 235 +---------------- 2 files changed, 247 insertions(+), 233 deletions(-) create mode 100644 integration-test/tests/bitwarden.macos.spec.js diff --git a/integration-test/tests/bitwarden.macos.spec.js b/integration-test/tests/bitwarden.macos.spec.js new file mode 100644 index 000000000..ea2b87684 --- /dev/null +++ b/integration-test/tests/bitwarden.macos.spec.js @@ -0,0 +1,245 @@ +import {constants} from '../helpers/mocks.js' +import {createAutofillScript, forwardConsoleMessages, mockedCalls} from '../helpers/harness.js' +import {createWebkitMocks, macosContentScopeReplacements} from '../helpers/mocks.webkit.js' +import {createAvailableInputTypes} from '../helpers/utils.js' +import {loginPage, overlayPage} from '../helpers/pages.js' +import {expect, test as base} from '@playwright/test' + +/** + * Tests for various Bitwarden scenarios on macos + */ +const test = base.extend({}) + +const {personalAddress} = constants.fields.email +const password = '123456' + +test.describe('When Bitwarden is the password provider', () => { + test('When the native layer calls to unblock provider UI (on Catalina)', async ({page}) => { + // enable in-terminal exceptions + await forwardConsoleMessages(page) + + await createWebkitMocks() + .withAvailableInputTypes(createAvailableInputTypes({ + credentialsProviderStatus: 'locked' + })) + .withCredentials({ + id: 'provider_locked', + username: '', + password: '', + credentialsProvider: 'bitwarden' + }) + .withCheckCredentialsProviderStatus?.() + .applyTo(page) + + // Load the autofill.js script with replacements + await createAutofillScript() + .replaceAll(macosContentScopeReplacements({ + featureToggles: { + third_party_credentials_provider: true + } + })) + .platform('macos') + .applyTo(page) + + const login = loginPage(page) + await login.navigate() + await login.fieldsContainIcons() + + await login.assertTooltipNotOpen(personalAddress) + + // The call is executed every 2s and we have encoded responses in mocks.webkit.js + await page.waitForTimeout(2000) + + // unlocked with no credentials available + await login.fieldsDoNotContainIcons() + await page.waitForTimeout(2000) + + // unlocked with credentials available + await login.fieldsContainIcons() + await page.waitForTimeout(2000) + + // unlocked with only a password field + await login.onlyPasswordFieldHasIcon() + await page.waitForTimeout(2000) + + // back to being locked + await login.fieldsContainIcons() + }) + + test('When we have Bitwarden credentials', async ({page}) => { + // enable in-terminal exceptions + await forwardConsoleMessages(page) + + await createWebkitMocks() + .withAvailableInputTypes(createAvailableInputTypes()) + .withCredentials({ + id: '01', + username: personalAddress, + password, + credentialsProvider: 'bitwarden' + }) + .applyTo(page) + + // Load the autofill.js script with replacements + await createAutofillScript() + .replaceAll(macosContentScopeReplacements({ + featureToggles: { + third_party_credentials_provider: true + } + })) + .platform('macos') + .applyTo(page) + + const login = loginPage(page) + await login.navigate() + await login.fieldsContainIcons() + + await login.assertTooltipNotOpen(personalAddress) + + await login.assertBitwardenTooltipWorking(personalAddress, password) + }) + + test.describe('When bitwarden is locked', async () => { + test('in overlay', async ({page}) => { + await forwardConsoleMessages(page) + await createWebkitMocks() + .withAvailableInputTypes(createAvailableInputTypes({ + credentialsProviderStatus: 'locked' + })) + .withCredentials({ + id: 'provider_locked', + username: '', + password: '', + credentialsProvider: 'bitwarden' + }) + .withAskToUnlockProvider?.() + .applyTo(page) + + // Pretend we're running in a top-frame scenario + await createAutofillScript() + .replaceAll(macosContentScopeReplacements()) + .replace('isTopFrame', true) + .replace('supportsTopFrame', true) + .platform('macos') + .applyTo(page) + + const overlay = overlayPage(page) + await overlay.navigate() + await overlay.clickButtonWithText('Bitwarden is locked') + await overlay.doesNotCloseParentAfterCall('askToUnlockProvider') + + const autofillCalls = await mockedCalls(page, {names: ['setSize'], minCount: 1}) + expect(autofillCalls.length).toBeGreaterThanOrEqual(1) + }) + + test('when the native layer calls to unblock provider UI (on modern macOS versions)', async ({page}) => { + // enable in-terminal exceptions + await forwardConsoleMessages(page) + + await createWebkitMocks() + .withAvailableInputTypes(createAvailableInputTypes({ + credentialsProviderStatus: 'locked' + })) + .withCredentials({ + id: 'provider_locked', + username: '', + password: '', + credentialsProvider: 'bitwarden' + }) + .applyTo(page) + + // Load the autofill.js script with replacements + await createAutofillScript() + .replaceAll(macosContentScopeReplacements({ + featureToggles: { + third_party_credentials_provider: true + } + })) + .replace('hasModernWebkitAPI', true) + .platform('macos') + .applyTo(page) + + const login = loginPage(page) + await login.navigate() + await login.fieldsContainIcons() + + await login.assertTooltipNotOpen(personalAddress) + + // NOTE: I'm not creating separate test cases because these calls can happen multiple times + // in the page lifecycle with different values, so this is a realistic use case + + // unlocked with no credentials available + await page.evaluate(` + window.providerStatusUpdated({ + status: 'unlocked', + credentials: [], + availableInputTypes: {credentials: {password: false, username: false}} + }) + `) + + await login.fieldsDoNotContainIcons() + + // unlocked with credentials available + await page.evaluate(` + window.providerStatusUpdated({ + status: 'unlocked', + credentials: [ + {id: '3', password: '${password}', username: '${personalAddress}', credentialsProvider: 'bitwarden'} + ], + availableInputTypes: {credentials: {password: true, username: true}} + }) + `) + + await login.fieldsContainIcons() + + // unlocked with only a password field + await page.evaluate(` + window.providerStatusUpdated({ + status: 'unlocked', + credentials: [ + {id: '3', password: '${password}', username: '', credentialsProvider: 'bitwarden'} + ], + availableInputTypes: {credentials: {password: true, username: false}} + }) + `) + + await login.onlyPasswordFieldHasIcon() + }) + + test('without overlay (Catalina)', async ({page}) => { + // enable in-terminal exceptions + await forwardConsoleMessages(page) + + await createWebkitMocks() + .withAvailableInputTypes(createAvailableInputTypes({ + credentialsProviderStatus: 'locked' + })) + .withCredentials({ + id: 'provider_locked', + username: '', + password: '', + credentialsProvider: 'bitwarden' + }) + .withAskToUnlockProvider?.() + .applyTo(page) + + // Load the autofill.js script with replacements + await createAutofillScript() + .replaceAll(macosContentScopeReplacements({ + featureToggles: { + third_party_credentials_provider: true + } + })) + .platform('macos') + .applyTo(page) + + const login = loginPage(page) + await login.navigate() + await login.fieldsContainIcons() + + await login.assertTooltipNotOpen(personalAddress) + + await login.assertBitwardenLockedWorking() + }) + }) +}) diff --git a/integration-test/tests/login-form.macos.spec.js b/integration-test/tests/login-form.macos.spec.js index faa3b8c66..55000e509 100644 --- a/integration-test/tests/login-form.macos.spec.js +++ b/integration-test/tests/login-form.macos.spec.js @@ -1,8 +1,8 @@ import {constants} from '../helpers/mocks.js' import {createWebkitMocks, macosContentScopeReplacements} from '../helpers/mocks.webkit.js' -import {createAutofillScript, forwardConsoleMessages, mockedCalls} from '../helpers/harness.js' +import {createAutofillScript, forwardConsoleMessages} from '../helpers/harness.js' import {loginPage, overlayPage} from '../helpers/pages.js' -import {expect, test as base} from '@playwright/test' +import {test as base} from '@playwright/test' import {createAvailableInputTypes} from '../helpers/utils.js' /** @@ -329,237 +329,6 @@ test.describe('Auto-fill a login form on macOS', () => { }) }) - test.describe('When Bitwarden is the password provider', () => { - test('When we have Bitwarden credentials', async ({page}) => { - // enable in-terminal exceptions - await forwardConsoleMessages(page) - - await createWebkitMocks() - .withAvailableInputTypes(createAvailableInputTypes()) - .withCredentials({ - id: '01', - username: personalAddress, - password, - credentialsProvider: 'bitwarden' - }) - .applyTo(page) - - // Load the autofill.js script with replacements - await createAutofillScript() - .replaceAll(macosContentScopeReplacements({ - featureToggles: { - third_party_credentials_provider: true - } - })) - .platform('macos') - .applyTo(page) - - const login = loginPage(page) - await login.navigate() - await login.fieldsContainIcons() - - await login.assertTooltipNotOpen(personalAddress) - - await login.assertBitwardenTooltipWorking(personalAddress, password) - }) - - test.describe('When bitwarden is locked', async () => { - test('in overlay', async ({page}) => { - await forwardConsoleMessages(page) - await createWebkitMocks() - .withAvailableInputTypes(createAvailableInputTypes({ - credentialsProviderStatus: 'locked' - })) - .withCredentials({ - id: 'provider_locked', - username: '', - password: '', - credentialsProvider: 'bitwarden' - }) - .withAskToUnlockProvider?.() - .applyTo(page) - - // Pretend we're running in a top-frame scenario - await createAutofillScript() - .replaceAll(macosContentScopeReplacements()) - .replace('isTopFrame', true) - .replace('supportsTopFrame', true) - .platform('macos') - .applyTo(page) - - const overlay = overlayPage(page) - await overlay.navigate() - await overlay.clickButtonWithText('Bitwarden is locked') - await overlay.doesNotCloseParentAfterCall('askToUnlockProvider') - - const autofillCalls = await mockedCalls(page, {names: ['setSize'], minCount: 1}) - expect(autofillCalls.length).toBeGreaterThanOrEqual(1) - }) - - test('when the native layer calls to unblock provider UI (on modern macOS versions)', async ({page}) => { - // enable in-terminal exceptions - await forwardConsoleMessages(page) - - await createWebkitMocks() - .withAvailableInputTypes(createAvailableInputTypes({ - credentialsProviderStatus: 'locked' - })) - .withCredentials({ - id: 'provider_locked', - username: '', - password: '', - credentialsProvider: 'bitwarden' - }) - .applyTo(page) - - // Load the autofill.js script with replacements - await createAutofillScript() - .replaceAll(macosContentScopeReplacements({ - featureToggles: { - third_party_credentials_provider: true - } - })) - .replace('hasModernWebkitAPI', true) - .platform('macos') - .applyTo(page) - - const login = loginPage(page) - await login.navigate() - await login.fieldsContainIcons() - - await login.assertTooltipNotOpen(personalAddress) - - // NOTE: I'm not creating separate test cases because these calls can happen multiple times - // in the page lifecycle with different values, so this is a realistic use case - - // unlocked with no credentials available - await page.evaluate(` - window.providerStatusUpdated({ - status: 'unlocked', - credentials: [], - availableInputTypes: {credentials: {password: false, username: false}} - }) - `) - - await login.fieldsDoNotContainIcons() - - // unlocked with credentials available - await page.evaluate(` - window.providerStatusUpdated({ - status: 'unlocked', - credentials: [ - {id: '3', password: '${password}', username: '${personalAddress}', credentialsProvider: 'bitwarden'} - ], - availableInputTypes: {credentials: {password: true, username: true}} - }) - `) - - await login.fieldsContainIcons() - - // unlocked with only a password field - await page.evaluate(` - window.providerStatusUpdated({ - status: 'unlocked', - credentials: [ - {id: '3', password: '${password}', username: '', credentialsProvider: 'bitwarden'} - ], - availableInputTypes: {credentials: {password: true, username: false}} - }) - `) - - await login.onlyPasswordFieldHasIcon() - }) - - test('without overlay (Catalina)', async ({page}) => { - // enable in-terminal exceptions - await forwardConsoleMessages(page) - - await createWebkitMocks() - .withAvailableInputTypes(createAvailableInputTypes({ - credentialsProviderStatus: 'locked' - })) - .withCredentials({ - id: 'provider_locked', - username: '', - password: '', - credentialsProvider: 'bitwarden' - }) - .withAskToUnlockProvider?.() - .applyTo(page) - - // Load the autofill.js script with replacements - await createAutofillScript() - .replaceAll(macosContentScopeReplacements({ - featureToggles: { - third_party_credentials_provider: true - } - })) - .platform('macos') - .applyTo(page) - - const login = loginPage(page) - await login.navigate() - await login.fieldsContainIcons() - - await login.assertTooltipNotOpen(personalAddress) - - await login.assertBitwardenLockedWorking() - }) - - test('when the native layer calls to unblock provider UI (on Catalina)', async ({page}) => { - // enable in-terminal exceptions - await forwardConsoleMessages(page) - - await createWebkitMocks() - .withAvailableInputTypes(createAvailableInputTypes({ - credentialsProviderStatus: 'locked' - })) - .withCredentials({ - id: 'provider_locked', - username: '', - password: '', - credentialsProvider: 'bitwarden' - }) - .withCheckCredentialsProviderStatus?.() - .applyTo(page) - - // Load the autofill.js script with replacements - await createAutofillScript() - .replaceAll(macosContentScopeReplacements({ - featureToggles: { - third_party_credentials_provider: true - } - })) - .platform('macos') - .applyTo(page) - - const login = loginPage(page) - await login.navigate() - await login.fieldsContainIcons() - - await login.assertTooltipNotOpen(personalAddress) - - // The call is executed every 2s and we have encoded responses in mocks.webkit.js - await page.waitForTimeout(2000) - - // unlocked with no credentials available - await login.fieldsDoNotContainIcons() - await page.waitForTimeout(2000) - - // unlocked with credentials available - await login.fieldsContainIcons() - await page.waitForTimeout(2000) - - // unlocked with only a password field - await login.onlyPasswordFieldHasIcon() - await page.waitForTimeout(2000) - - // back to being locked - await login.fieldsContainIcons() - }) - }) - }) - test.describe('The manage button', () => { const testCases = [ {