Skip to content

Commit

Permalink
Merge pull request oasisprotocol#1768 from oasisprotocol/lw/refactor-…
Browse files Browse the repository at this point in the history
…ext-tests

Refactor extension tests
  • Loading branch information
lukaw3d authored Nov 21, 2023
2 parents 29df7bb + 71b8dba commit eb6c62e
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 68 deletions.
1 change: 1 addition & 0 deletions .changelog/1768.internal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Refactor extension tests
55 changes: 10 additions & 45 deletions playwright/tests/extension.spec.ts
Original file line number Diff line number Diff line change
@@ -1,69 +1,34 @@
import { test as base, expect, BrowserContext, chromium } from '@playwright/test'
import path from 'path'
import { test } from '../utils/extensionTestExtend'
import { expect } from '@playwright/test'
import { warnSlowApi } from '../utils/warnSlowApi'
import { mockApi } from '../utils/mockApi'
import { expectNoErrorsInConsole } from '../utils/expectNoErrorsInConsole'
import { fillPrivateKeyWithoutPassword } from '../utils/fillPrivateKey'
import { privateKey, privateKeyAddress } from '../../src/utils/__fixtures__/test-inputs'

// Test dev build by default, but also allow testing production
const extensionPath = path.join(__dirname, '..', process.env.EXTENSION_PATH ?? '../build-dev/')

// eslint-disable-next-line @typescript-eslint/no-var-requires
const extensionManifest = require(path.join(extensionPath, '/manifest.json'))
const popupFile = extensionManifest.browser_action.default_popup

// From https://playwright.dev/docs/chrome-extensions
export const test = base.extend<{
context: BrowserContext
extensionId: string
}>({
// eslint-disable-next-line no-empty-pattern
context: async ({}, use) => {
const context = await chromium.launchPersistentContext('', {
headless: false,
args: [`--disable-extensions-except=${extensionPath}`, `--load-extension=${extensionPath}`],
})
await use(context)
await context.close()
},
extensionId: async ({ context }, use) => {
// for manifest v2:
let [background] = context.backgroundPages()
if (!background) background = await context.waitForEvent('backgroundpage')

// for manifest v3:
// let [background] = context.serviceWorkers()
// if (!background) background = await context.waitForEvent('serviceworker')

const extensionId = background.url().split('/')[2]
await use(extensionId)
},
})

test.beforeEach(async ({ context }) => {
await warnSlowApi(context)
await mockApi(context, 0)
})

test.describe('The extension popup should load', () => {
test('should successfully load javascript chunks', async ({ page, extensionId }) => {
await page.goto(`chrome-extension://${extensionId}/${popupFile}`)
test('should successfully load javascript chunks', async ({ page, extensionPopupURL }) => {
await page.goto(`${extensionPopupURL}/`)
await expect(page.getByRole('link', { name: /Open wallet/i })).toBeVisible()
await expect(page.getByRole('link', { name: /Create wallet/i })).toBeVisible()
})

test('get state from background page through webext-redux', async ({ page, extensionId }) => {
await page.goto(`chrome-extension://${extensionId}/${popupFile}`)
test('get state from background page through webext-redux', async ({ page, extensionPopupURL }) => {
await page.goto(`${extensionPopupURL}/`)
await page.getByRole('button', { name: /Dark mode/i }).click()
await page.getByRole('button', { name: /Light mode/i }).click()

await page.getByRole('link', { name: /Create wallet/i }).click()
await expect(page.getByTestId('mnemonic-grid').locator('> *')).toHaveCount(24)
})

test('ask for USB permissions in ledger popup', async ({ page, context, extensionId }) => {
await page.goto(`chrome-extension://${extensionId}/${popupFile}#/open-wallet`)
test('ask for USB permissions in ledger popup', async ({ page, context, extensionPopupURL }) => {
await page.goto(`${extensionPopupURL}/open-wallet`)
const popupPromise = context.waitForEvent('page')
await page.getByRole('button', { name: /Grant access to your Ledger/i }).click()
const popup = await popupPromise
Expand All @@ -74,15 +39,15 @@ test.describe('The extension popup should load', () => {
await expect(popup.getByText('error').or(popup.getByText('fail'))).toBeHidden()
})

test('should allow embedded Transak widget', async ({ page, extensionId }) => {
test('should allow embedded Transak widget', async ({ page, extensionPopupURL }) => {
await expectNoErrorsInConsole(page, {
ignoreError: msg => {
// Odd errors inside Transak
if (msg.text().includes('responded with a status of 403')) return true
if (msg.text().includes('`sessionKey` is a required property')) return true
},
})
await page.goto(`chrome-extension://${extensionId}/${popupFile}#/open-wallet/private-key`)
await page.goto(`${extensionPopupURL}/open-wallet/private-key`)
await fillPrivateKeyWithoutPassword(page, {
privateKey: privateKey,
privateKeyAddress: privateKeyAddress,
Expand Down
6 changes: 3 additions & 3 deletions playwright/tests/migrating-persisted-state.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ import { test, expect } from '@playwright/test'
import { mockApi } from '../utils/mockApi'
import { warnSlowApi } from '../utils/warnSlowApi'
import { expectNoFatal } from '../utils/expectNoFatal'
import { addPersistedStorage, clearPersistedStorage } from '../utils/storage'
import { addPersistedStorageV1, clearPersistedStorage } from '../utils/storage'
import { password, privateKeyUnlockedState } from '../../src/utils/__fixtures__/test-inputs'
import { RootState } from '../../src/types/RootState'

test.beforeEach(async ({ context, page }) => {
await warnSlowApi(context)
await mockApi(context, 0)
await clearPersistedStorage(page)
await clearPersistedStorage(page, '/app.webmanifest')
})

test.afterEach(async ({ context }, testInfo) => {
Expand All @@ -18,7 +18,7 @@ test.afterEach(async ({ context }, testInfo) => {

test.describe('Migrating persisted state', () => {
test('Decrypting V1 state should result in valid RootState', async ({ context, page }) => {
await addPersistedStorage(page)
await addPersistedStorageV1(page, '/app.webmanifest')
await page.goto('/')
await page.getByPlaceholder('Enter your password here').fill(password)
await page.keyboard.press('Enter')
Expand Down
14 changes: 7 additions & 7 deletions playwright/tests/persist.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { test, expect, Page } from '@playwright/test'
import { mockApi } from '../utils/mockApi'
import { warnSlowApi } from '../utils/warnSlowApi'
import { expectNoFatal } from '../utils/expectNoFatal'
import { addPersistedStorage, clearPersistedStorage } from '../utils/storage'
import { addPersistedStorageV1, clearPersistedStorage } from '../utils/storage'
import {
mnemonicAddress0,
mnemonic,
Expand All @@ -18,7 +18,7 @@ import { fillPrivateKeyWithoutPassword, fillPrivateKeyAndPassword } from '../uti
test.beforeEach(async ({ context, page }) => {
await warnSlowApi(context)
await mockApi(context, 0)
await clearPersistedStorage(page)
await clearPersistedStorage(page, '/app.webmanifest')
})

test.afterEach(async ({ context }, testInfo) => {
Expand Down Expand Up @@ -139,7 +139,7 @@ test.describe('Persist', () => {
context,
page,
}) => {
await addPersistedStorage(page)
await addPersistedStorageV1(page, '/app.webmanifest')
await page.goto('/')
await mockApi(context, 123)
await page.getByPlaceholder('Enter your password here').fill(password)
Expand Down Expand Up @@ -182,7 +182,7 @@ test.describe('Persist', () => {
})

test('Should NOT persist changes after user skips unlocking', async ({ page }) => {
await addPersistedStorage(page)
await addPersistedStorageV1(page, '/app.webmanifest')
await page.goto('/')
await page.getByRole('button', { name: /Continue without the profile/ }).click()
await page.getByRole('button', { name: /Open wallet/ }).click()
Expand All @@ -202,7 +202,7 @@ test.describe('Persist', () => {
})

test('Should NOT crash after quickly locking a wallet', async ({ page }) => {
await addPersistedStorage(page)
await addPersistedStorageV1(page, '/app.webmanifest')
await page.goto('/')
await page.getByRole('button', { name: /Continue without the profile/ }).click()
await page.getByRole('button', { name: /Unlock profile/ }).click()
Expand All @@ -219,7 +219,7 @@ test.describe('Persist', () => {
})

test('deleting stored', async ({ page }) => {
await addPersistedStorage(page)
await addPersistedStorageV1(page, '/app.webmanifest')
await page.goto('/')
await testDeletingAndCreatingNew(page)
})
Expand All @@ -243,7 +243,7 @@ test.describe('Persist', () => {
})

test('Password should not be cached in input field', async ({ page }) => {
await addPersistedStorage(page)
await addPersistedStorageV1(page, '/app.webmanifest')
await page.goto('/')
await page.getByPlaceholder('Enter your password here').fill(password)
await page.keyboard.press('Enter')
Expand Down
18 changes: 9 additions & 9 deletions playwright/tests/syncTabs.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ import {
privateKey2AddressPretty,
mnemonic,
} from '../../src/utils/__fixtures__/test-inputs'
import { addPersistedStorage, clearPersistedStorage } from '../utils/storage'
import { addPersistedStorageV1, clearPersistedStorage } from '../utils/storage'
import { fillPrivateKeyWithoutPassword, fillPrivateKeyAndPassword } from '../utils/fillPrivateKey'
import type { AccountsRow } from '../../src/vendors/oasisscan/index'

test.beforeEach(async ({ context, page }) => {
await warnSlowApi(context)
await mockApi(context, 0)
await clearPersistedStorage(page)
await clearPersistedStorage(page, '/app.webmanifest')
})

test.afterEach(async ({ context }, testInfo) => {
Expand Down Expand Up @@ -50,7 +50,7 @@ test.describe('syncTabs', () => {
})

test('incognito', async ({ page, context }) => {
await addPersistedStorage(page)
await addPersistedStorageV1(page, '/app.webmanifest')
await page.goto('/')
await page.getByRole('button', { name: 'Continue without the profile' }).click()
await expect(page.getByTestId('account-selector')).toBeHidden()
Expand Down Expand Up @@ -103,7 +103,7 @@ test.describe('syncTabs', () => {
})

test('persisted', async ({ page, context }) => {
await addPersistedStorage(page)
await addPersistedStorageV1(page, '/app.webmanifest')
await page.goto('/')
await page.getByPlaceholder('Enter your password here').fill(password)
await page.keyboard.press('Enter')
Expand All @@ -112,7 +112,7 @@ test.describe('syncTabs', () => {
})

test('incognito', async ({ page, context }) => {
await addPersistedStorage(page)
await addPersistedStorageV1(page, '/app.webmanifest')
await page.goto('/')
await page.getByRole('button', { name: 'Continue without the profile' }).click()
const tab2 = await context.newPage()
Expand Down Expand Up @@ -144,7 +144,7 @@ test.describe('syncTabs', () => {

test.describe('adding and removing contacts in tabs', () => {
test('persisted', async ({ page, context }) => {
await addPersistedStorage(page)
await addPersistedStorageV1(page, '/app.webmanifest')
await page.goto('/')
await page.getByPlaceholder('Enter your password here').fill(password)
await page.keyboard.press('Enter')
Expand Down Expand Up @@ -208,7 +208,7 @@ test.describe('syncTabs', () => {
})

test('persisted', async ({ page, context }) => {
await addPersistedStorage(page)
await addPersistedStorageV1(page, '/app.webmanifest')
await page.goto('/')
await page.getByPlaceholder('Enter your password here').fill(password)
await page.keyboard.press('Enter')
Expand All @@ -217,7 +217,7 @@ test.describe('syncTabs', () => {
})

test('incognito', async ({ page, context }) => {
await addPersistedStorage(page)
await addPersistedStorageV1(page, '/app.webmanifest')
await page.goto('/')
await page.getByRole('button', { name: 'Continue without the profile' }).click()
const tab2 = await context.newPage()
Expand Down Expand Up @@ -300,7 +300,7 @@ test.describe('syncTabs', () => {
page,
context,
}) => {
await addPersistedStorage(page)
await addPersistedStorageV1(page, '/app.webmanifest')
await page.goto('/')
await page.getByPlaceholder('Enter your password here').fill(password)
await page.keyboard.press('Enter')
Expand Down
41 changes: 41 additions & 0 deletions playwright/utils/extensionTestExtend.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { test as base, BrowserContext, chromium } from '@playwright/test'
import path from 'path'

// Test dev build by default, but also allow testing production
const extensionPath = path.join(__dirname, '..', process.env.EXTENSION_PATH ?? '../build-dev/')

// eslint-disable-next-line @typescript-eslint/no-var-requires
const extensionManifest = require(path.join(extensionPath, '/manifest.json'))
const popupFile = extensionManifest.browser_action.default_popup

// From https://playwright.dev/docs/chrome-extensions
export const test = base.extend<{
context: BrowserContext
extensionId: string
extensionPopupURL: `chrome-extension://${string}`
}>({
// eslint-disable-next-line no-empty-pattern
context: async ({}, use) => {
const context = await chromium.launchPersistentContext('', {
headless: false,
args: [`--disable-extensions-except=${extensionPath}`, `--load-extension=${extensionPath}`],
})
await use(context)
await context.close()
},
extensionId: async ({ context }, use) => {
// for manifest v2:
let [background] = context.backgroundPages()
if (!background) background = await context.waitForEvent('backgroundpage')

// for manifest v3:
// let [background] = context.serviceWorkers()
// if (!background) background = await context.waitForEvent('serviceworker')

const extensionId = background.url().split('/')[2]
await use(extensionId)
},
extensionPopupURL: async ({ extensionId }, use) => {
await use(`chrome-extension://${extensionId}/${popupFile}#`)
},
})
14 changes: 10 additions & 4 deletions playwright/utils/storage.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
import type { Page } from '@playwright/test'
import { privateKeyPersistedState } from '../../src/utils/__fixtures__/test-inputs'

export async function clearPersistedStorage(page: Page) {
export async function clearPersistedStorage(
page: Page,
url: '/app.webmanifest' | `chrome-extension://${string}`,
) {
// Move to the right domain, but don't needlessly load HTML and JS.
await page.goto('/app.webmanifest')
await page.goto(url)
await page.evaluate(() => window.localStorage.clear())
}

export async function addPersistedStorage(page: Page) {
export async function addPersistedStorageV1(
page: Page,
url: '/app.webmanifest' | `chrome-extension://${string}`,
) {
// Move to the right domain, but don't needlessly load HTML and JS.
await page.goto('/app.webmanifest')
await page.goto(url)
await page.evaluate(
([privateKeyPersistedState]) => {
window.localStorage.setItem('oasis_wallet_persist_v1', privateKeyPersistedState)
Expand Down

0 comments on commit eb6c62e

Please sign in to comment.