e2e tests (#17)
* Setup playwright for e2e tests Fixes #12 * Chromium * First working test, clean up * Merge actions * New headless mode * Clean up, bugfix * Bug fixes, cleaner sendMessage code * Rebase * Rebase * Load tokens and open public page * Test CI * Working test * Lint * Try to address flakyness * Clean up test * Comment * No export * More clean up * More clean up * Adds authorized pop up test * Adds comment * Add snapshots * New linux screenshots
This commit is contained in:
		
							
								
								
									
										8
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							@ -24,6 +24,14 @@ jobs:
 | 
			
		||||
 | 
			
		||||
            - run: yarn test
 | 
			
		||||
 | 
			
		||||
            - name: Run playwright e2e tests
 | 
			
		||||
              env:
 | 
			
		||||
                GITHUB_TOKEN: ${{secrets.GLOBAL_PAT}}
 | 
			
		||||
                KITTYCAD_TOKEN: ${{secrets.KITTYCAD_TOKEN}}
 | 
			
		||||
              run: |
 | 
			
		||||
                  yarn playwright install chromium --with-deps
 | 
			
		||||
                  yarn playwright test
 | 
			
		||||
 | 
			
		||||
            - uses: actions/upload-artifact@v3
 | 
			
		||||
              with:
 | 
			
		||||
                  path: build
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										5
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@ -23,3 +23,8 @@
 | 
			
		||||
npm-debug.log*
 | 
			
		||||
yarn-debug.log*
 | 
			
		||||
yarn-error.log*
 | 
			
		||||
/test-results/
 | 
			
		||||
/playwright-report/
 | 
			
		||||
/playwright/.cache/
 | 
			
		||||
 | 
			
		||||
.env*
 | 
			
		||||
 | 
			
		||||
@ -34,6 +34,7 @@
 | 
			
		||||
        "start": "react-scripts start",
 | 
			
		||||
        "build": "INLINE_RUNTIME_CHUNK=false craco build",
 | 
			
		||||
        "test": "react-scripts test",
 | 
			
		||||
        "e2e": "yarn build && yarn playwright test",
 | 
			
		||||
        "eject": "react-scripts eject"
 | 
			
		||||
    },
 | 
			
		||||
    "eslintConfig": {
 | 
			
		||||
@ -68,6 +69,8 @@
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    "devDependencies": {
 | 
			
		||||
        "@playwright/test": "^1.31.2",
 | 
			
		||||
        "dotenv": "^16.0.3",
 | 
			
		||||
        "eslint": "^8.35.0",
 | 
			
		||||
        "eslint-config-prettier": "^8.6.0",
 | 
			
		||||
        "eslint-config-react-app": "^7.0.1",
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										30
									
								
								playwright.config.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								playwright.config.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,30 @@
 | 
			
		||||
import { defineConfig, devices } from '@playwright/test'
 | 
			
		||||
 | 
			
		||||
export default defineConfig({
 | 
			
		||||
    testDir: './tests',
 | 
			
		||||
    timeout: 30 * 1000,
 | 
			
		||||
    expect: {
 | 
			
		||||
        timeout: 5000,
 | 
			
		||||
    },
 | 
			
		||||
    fullyParallel: true,
 | 
			
		||||
    forbidOnly: !!process.env.CI,
 | 
			
		||||
    retries: process.env.CI ? 2 : 0,
 | 
			
		||||
    workers: process.env.CI ? 1 : undefined,
 | 
			
		||||
    reporter: [['html', { open: 'never' }]],
 | 
			
		||||
    use: {
 | 
			
		||||
        actionTimeout: 0,
 | 
			
		||||
        trace: 'on-first-retry',
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    projects: [
 | 
			
		||||
        {
 | 
			
		||||
            name: 'chromium',
 | 
			
		||||
            use: {
 | 
			
		||||
                ...devices['Desktop Chrome'],
 | 
			
		||||
            },
 | 
			
		||||
        },
 | 
			
		||||
    ],
 | 
			
		||||
 | 
			
		||||
    /* Folder for test artifacts such as screenshots, videos, traces, etc. */
 | 
			
		||||
    // outputDir: 'test-results/',
 | 
			
		||||
})
 | 
			
		||||
@ -18,8 +18,8 @@ import {
 | 
			
		||||
} from './storage'
 | 
			
		||||
import { getFileDiff } from './diff'
 | 
			
		||||
 | 
			
		||||
let github: Octokit
 | 
			
		||||
let kittycad: Client
 | 
			
		||||
let github: Octokit | undefined
 | 
			
		||||
let kittycad: Client | undefined
 | 
			
		||||
 | 
			
		||||
async function initGithubApi() {
 | 
			
		||||
    try {
 | 
			
		||||
@ -28,38 +28,45 @@ async function initGithubApi() {
 | 
			
		||||
        console.log(`Logged in on github.com as ${octokitResponse.data.login}`)
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
        console.log('Couldnt initiate the github api client')
 | 
			
		||||
        github = undefined
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function initKittycadApi() {
 | 
			
		||||
    try {
 | 
			
		||||
        kittycad = new Client(await getStorageKittycadToken())
 | 
			
		||||
        const kittycadResponse = await users.get_user_self({ client: kittycad })
 | 
			
		||||
        console.log(
 | 
			
		||||
            `Logged in on kittycad.io as ${
 | 
			
		||||
                (kittycadResponse as KittycadUser).email
 | 
			
		||||
            }`
 | 
			
		||||
        )
 | 
			
		||||
        const response = await users.get_user_self({ client: kittycad })
 | 
			
		||||
        if ('error_code' in response) throw response
 | 
			
		||||
        const { email } = response
 | 
			
		||||
        if (!email) throw Error('Empty user, token is probably wrong')
 | 
			
		||||
        console.log(`Logged in on kittycad.io as ${email}`)
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
        console.log("Couldn't initiate the kittycad api client")
 | 
			
		||||
        kittycad = undefined
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function saveGithubTokenAndReload(token: string): Promise<void> {
 | 
			
		||||
    github = undefined
 | 
			
		||||
    await setStorageGithubToken(token)
 | 
			
		||||
    await initGithubApi()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function saveKittycadTokenAndReload(token: string): Promise<void> {
 | 
			
		||||
    kittycad = undefined
 | 
			
		||||
    await setStorageKittycadToken(token)
 | 
			
		||||
    await initKittycadApi()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
;(async () => {
 | 
			
		||||
    // Delay to allow for external storage sets before auth, like in e2e
 | 
			
		||||
    await new Promise(resolve => setTimeout(resolve, 1000))
 | 
			
		||||
    await initKittycadApi()
 | 
			
		||||
    await initGithubApi()
 | 
			
		||||
})()
 | 
			
		||||
 | 
			
		||||
const noClientError = new Error('API client is undefined')
 | 
			
		||||
 | 
			
		||||
chrome.runtime.onMessage.addListener(
 | 
			
		||||
    (
 | 
			
		||||
        message: Message,
 | 
			
		||||
@ -68,48 +75,68 @@ chrome.runtime.onMessage.addListener(
 | 
			
		||||
    ) => {
 | 
			
		||||
        console.log(`Received ${message.id} from ${sender.id}`)
 | 
			
		||||
        if (message.id === MessageIds.GetGithubPullFiles) {
 | 
			
		||||
            if (!github) {
 | 
			
		||||
                sendResponse({ error: noClientError })
 | 
			
		||||
                return false
 | 
			
		||||
            }
 | 
			
		||||
            const { owner, repo, pull } =
 | 
			
		||||
                message.data as MessageGetGithubPullFilesData
 | 
			
		||||
            github.rest.pulls
 | 
			
		||||
                .listFiles({ owner, repo, pull_number: pull })
 | 
			
		||||
                .then(r => sendResponse(r.data))
 | 
			
		||||
                .catch(e => sendResponse(e))
 | 
			
		||||
                .catch(error => sendResponse({ error }))
 | 
			
		||||
            return true
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (message.id === MessageIds.GetGithubPull) {
 | 
			
		||||
            if (!github) {
 | 
			
		||||
                sendResponse({ error: noClientError })
 | 
			
		||||
                return false
 | 
			
		||||
            }
 | 
			
		||||
            const { owner, repo, pull } =
 | 
			
		||||
                message.data as MessageGetGithubPullFilesData
 | 
			
		||||
            github.rest.pulls
 | 
			
		||||
                .get({ owner, repo, pull_number: pull })
 | 
			
		||||
                .then(r => sendResponse(r.data))
 | 
			
		||||
                .catch(e => sendResponse(e))
 | 
			
		||||
                .catch(error => sendResponse({ error }))
 | 
			
		||||
            return true
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (message.id === MessageIds.GetGithubCommit) {
 | 
			
		||||
            if (!github) {
 | 
			
		||||
                sendResponse({ error: noClientError })
 | 
			
		||||
                return false
 | 
			
		||||
            }
 | 
			
		||||
            const { owner, repo, sha } =
 | 
			
		||||
                message.data as MessageGetGithubCommitData
 | 
			
		||||
            github.rest.repos
 | 
			
		||||
                .getCommit({ owner, repo, ref: sha })
 | 
			
		||||
                .then(r => sendResponse(r.data))
 | 
			
		||||
                .catch(e => sendResponse(e))
 | 
			
		||||
                .catch(error => sendResponse({ error }))
 | 
			
		||||
            return true
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (message.id === MessageIds.GetGithubUser) {
 | 
			
		||||
            if (!github) {
 | 
			
		||||
                sendResponse({ error: noClientError })
 | 
			
		||||
                return false
 | 
			
		||||
            }
 | 
			
		||||
            github.rest.users
 | 
			
		||||
                .getAuthenticated()
 | 
			
		||||
                .then(r => sendResponse(r.data))
 | 
			
		||||
                .catch(e => sendResponse(e))
 | 
			
		||||
                .catch(error => sendResponse({ error }))
 | 
			
		||||
            return true
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (message.id === MessageIds.GetKittycadUser) {
 | 
			
		||||
            if (!kittycad) {
 | 
			
		||||
                sendResponse({ error: noClientError })
 | 
			
		||||
                return false
 | 
			
		||||
            }
 | 
			
		||||
            users
 | 
			
		||||
                .get_user_self({ client: kittycad })
 | 
			
		||||
                .then(r => sendResponse(r as KittycadUser))
 | 
			
		||||
                .catch(e => sendResponse(e))
 | 
			
		||||
                .catch(error => sendResponse({ error }))
 | 
			
		||||
            return true
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -117,7 +144,7 @@ chrome.runtime.onMessage.addListener(
 | 
			
		||||
            const { token } = message.data as MessageSaveToken
 | 
			
		||||
            saveGithubTokenAndReload(token)
 | 
			
		||||
                .then(() => sendResponse({ token }))
 | 
			
		||||
                .catch(e => sendResponse(e))
 | 
			
		||||
                .catch(error => sendResponse({ error }))
 | 
			
		||||
            return true
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -125,16 +152,20 @@ chrome.runtime.onMessage.addListener(
 | 
			
		||||
            const { token } = message.data as MessageSaveToken
 | 
			
		||||
            saveKittycadTokenAndReload(token)
 | 
			
		||||
                .then(() => sendResponse({ token }))
 | 
			
		||||
                .catch(e => sendResponse(e))
 | 
			
		||||
                .catch(error => sendResponse({ error }))
 | 
			
		||||
            return true
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (message.id === MessageIds.GetFileDiff) {
 | 
			
		||||
            if (!kittycad || !github) {
 | 
			
		||||
                sendResponse({ error: noClientError })
 | 
			
		||||
                return false
 | 
			
		||||
            }
 | 
			
		||||
            const { owner, repo, sha, parentSha, file } =
 | 
			
		||||
                message.data as MessageGetFileDiff
 | 
			
		||||
            getFileDiff(github, kittycad, owner, repo, sha, parentSha, file)
 | 
			
		||||
                .then(r => sendResponse(r))
 | 
			
		||||
                .catch(e => sendResponse(e))
 | 
			
		||||
                .catch(error => sendResponse({ error }))
 | 
			
		||||
            return true
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -28,11 +28,16 @@ async function injectDiff(
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (const { element, file } of map) {
 | 
			
		||||
        const fileDiff = await chrome.runtime.sendMessage<Message, FileDiff>({
 | 
			
		||||
        const response = await chrome.runtime.sendMessage({
 | 
			
		||||
            id: MessageIds.GetFileDiff,
 | 
			
		||||
            data: { owner, repo, sha, parentSha, file },
 | 
			
		||||
        })
 | 
			
		||||
        createRoot(element).render(React.createElement(CadDiff, fileDiff))
 | 
			
		||||
        if ('error' in response) {
 | 
			
		||||
            console.log(response.error)
 | 
			
		||||
        } else {
 | 
			
		||||
            const diff = response as FileDiff
 | 
			
		||||
            createRoot(element).render(React.createElement(CadDiff, diff))
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -76,6 +81,7 @@ gitHubInjection(async () => {
 | 
			
		||||
    const pullParams = getGithubPullUrlParams(url)
 | 
			
		||||
    if (pullParams) {
 | 
			
		||||
        const { owner, repo, pull } = pullParams
 | 
			
		||||
        console.log('Found PR diff: ', owner, repo, pull)
 | 
			
		||||
        await injectPullDiff(owner, repo, pull, window.document)
 | 
			
		||||
        return
 | 
			
		||||
    }
 | 
			
		||||
@ -83,6 +89,7 @@ gitHubInjection(async () => {
 | 
			
		||||
    const commitParams = getGithubCommitUrlParams(url)
 | 
			
		||||
    if (commitParams) {
 | 
			
		||||
        const { owner, repo, sha } = commitParams
 | 
			
		||||
        console.log('Found commit diff: ', owner, repo, sha)
 | 
			
		||||
        await injectCommitDiff(owner, repo, sha, window.document)
 | 
			
		||||
        return
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -55,6 +55,10 @@ export type MessageSaveToken = {
 | 
			
		||||
    token: string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export type MessageError = {
 | 
			
		||||
    error: Error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export type Message = {
 | 
			
		||||
    id: MessageIds
 | 
			
		||||
    data?:
 | 
			
		||||
@ -72,5 +76,5 @@ export type MessageResponse =
 | 
			
		||||
    | KittycadUser
 | 
			
		||||
    | MessageSaveToken
 | 
			
		||||
    | FileDiff
 | 
			
		||||
    | Error
 | 
			
		||||
    | MessageError
 | 
			
		||||
    | void
 | 
			
		||||
 | 
			
		||||
@ -15,9 +15,8 @@ export function Settings() {
 | 
			
		||||
            const response = await chrome.runtime.sendMessage({
 | 
			
		||||
                id: MessageIds.GetGithubUser,
 | 
			
		||||
            })
 | 
			
		||||
            if (Object.keys(response).length === 0) throw Error('no response')
 | 
			
		||||
            const user = response as User
 | 
			
		||||
            setGithubUser(user)
 | 
			
		||||
            if ('error' in response) throw response.error
 | 
			
		||||
            setGithubUser(response as User)
 | 
			
		||||
        } catch (e) {
 | 
			
		||||
            console.error(e)
 | 
			
		||||
            setGithubUser(undefined)
 | 
			
		||||
@ -29,9 +28,8 @@ export function Settings() {
 | 
			
		||||
            const response = await chrome.runtime.sendMessage({
 | 
			
		||||
                id: MessageIds.GetKittycadUser,
 | 
			
		||||
            })
 | 
			
		||||
            if (Object.keys(response).length === 0) throw Error('no response')
 | 
			
		||||
            const user = response as KittycadUser
 | 
			
		||||
            setKittycadUser(user)
 | 
			
		||||
            if ('error' in response) throw response.error
 | 
			
		||||
            setKittycadUser(response as KittycadUser)
 | 
			
		||||
        } catch (e) {
 | 
			
		||||
            console.error(e)
 | 
			
		||||
            setKittycadUser(undefined)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										46
									
								
								tests/extension.spec.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								tests/extension.spec.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,46 @@
 | 
			
		||||
import { test, expect } from './fixtures'
 | 
			
		||||
 | 
			
		||||
test('popup page', async ({ page, extensionId }) => {
 | 
			
		||||
    await page.goto(`chrome-extension://${extensionId}/index.html`)
 | 
			
		||||
    await expect(page.locator('body')).toContainText('Enter a GitHub token')
 | 
			
		||||
    await expect(page.locator('body')).toContainText('Enter a KittyCAD token')
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test('authorized popup page', async ({
 | 
			
		||||
    page,
 | 
			
		||||
    extensionId,
 | 
			
		||||
    authorizedBackground,
 | 
			
		||||
}) => {
 | 
			
		||||
    await page.goto(`chrome-extension://${extensionId}/index.html`)
 | 
			
		||||
    await page.waitForSelector('button')
 | 
			
		||||
    await expect(page.locator('body')).toContainText('Sign out')
 | 
			
		||||
    await expect(page.locator('button')).toHaveCount(2)
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test('pull request diff with an .obj file', async ({
 | 
			
		||||
    page,
 | 
			
		||||
    authorizedBackground,
 | 
			
		||||
}) => {
 | 
			
		||||
    page.on('console', msg => console.log(msg.text()))
 | 
			
		||||
 | 
			
		||||
    await page.goto('https://github.com/KittyCAD/kittycad.ts/pull/3/files')
 | 
			
		||||
    const element = await page.waitForSelector('.js-file-content canvas')
 | 
			
		||||
    await page.waitForTimeout(1000) // making sure the element fully settled in
 | 
			
		||||
    const screenshot = await element.screenshot()
 | 
			
		||||
    expect(screenshot).toMatchSnapshot()
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test('commit diff with an .obj file', async ({
 | 
			
		||||
    page,
 | 
			
		||||
    authorizedBackground,
 | 
			
		||||
}) => {
 | 
			
		||||
    page.on('console', msg => console.log(msg.text()))
 | 
			
		||||
 | 
			
		||||
    await page.goto(
 | 
			
		||||
        'https://github.com/KittyCAD/kittycad.ts/commit/08b50ee5a23b3ae7dd7b19383f14bbd520079cc1'
 | 
			
		||||
    )
 | 
			
		||||
    const element = await page.waitForSelector('.js-file-content canvas')
 | 
			
		||||
    await page.waitForTimeout(1000) // making sure the element fully settled in
 | 
			
		||||
    const screenshot = await element.screenshot()
 | 
			
		||||
    expect(screenshot).toMatchSnapshot()
 | 
			
		||||
})
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 44 KiB  | 
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 23 KiB  | 
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 39 KiB  | 
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 23 KiB  | 
							
								
								
									
										63
									
								
								tests/fixtures.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								tests/fixtures.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,63 @@
 | 
			
		||||
// From https://playwright.dev/docs/chrome-extensions#testing
 | 
			
		||||
import {
 | 
			
		||||
    test as base,
 | 
			
		||||
    chromium,
 | 
			
		||||
    Worker,
 | 
			
		||||
    type BrowserContext,
 | 
			
		||||
} from '@playwright/test'
 | 
			
		||||
import path from 'path'
 | 
			
		||||
import * as dotenv from 'dotenv'
 | 
			
		||||
dotenv.config()
 | 
			
		||||
 | 
			
		||||
export const test = base.extend<{
 | 
			
		||||
    context: BrowserContext
 | 
			
		||||
    extensionId: string
 | 
			
		||||
    background: Worker
 | 
			
		||||
    authorizedBackground: Worker
 | 
			
		||||
}>({
 | 
			
		||||
    context: async ({}, use) => {
 | 
			
		||||
        const pathToExtension = path.join(__dirname, '..', 'build')
 | 
			
		||||
        const context = await chromium.launchPersistentContext('', {
 | 
			
		||||
            headless: false,
 | 
			
		||||
            args: [
 | 
			
		||||
                `--headless=new`, // headless mode that allows for extensions
 | 
			
		||||
                `--disable-extensions-except=${pathToExtension}`,
 | 
			
		||||
                `--load-extension=${pathToExtension}`,
 | 
			
		||||
            ],
 | 
			
		||||
        })
 | 
			
		||||
        await use(context)
 | 
			
		||||
        await context.close()
 | 
			
		||||
    },
 | 
			
		||||
    background: async ({ context }, use) => {
 | 
			
		||||
        let [background] = context.serviceWorkers()
 | 
			
		||||
        if (!background)
 | 
			
		||||
            background = await context.waitForEvent('serviceworker')
 | 
			
		||||
 | 
			
		||||
        // Wait for the chrome object to be available
 | 
			
		||||
        await new Promise(resolve => setTimeout(resolve, 100))
 | 
			
		||||
        await use(background)
 | 
			
		||||
    },
 | 
			
		||||
    authorizedBackground: async ({ background }, use) => {
 | 
			
		||||
        // Load the env tokens in storage for auth
 | 
			
		||||
        const githubToken = process.env.GITHUB_TOKEN
 | 
			
		||||
        const kittycadToken = process.env.KITTYCAD_TOKEN
 | 
			
		||||
        await background.evaluate(
 | 
			
		||||
            async ([githubToken, kittycadToken]) => {
 | 
			
		||||
                await chrome.storage.local.set({
 | 
			
		||||
                    ktk: kittycadToken, // from src/chrome/storage.ts
 | 
			
		||||
                    gtk: githubToken, // from src/chrome/storage.ts
 | 
			
		||||
                })
 | 
			
		||||
            },
 | 
			
		||||
            [githubToken, kittycadToken]
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        // Wait for background auth
 | 
			
		||||
        await new Promise(resolve => setTimeout(resolve, 2000))
 | 
			
		||||
        await use(background)
 | 
			
		||||
    },
 | 
			
		||||
    extensionId: async ({ background }, use) => {
 | 
			
		||||
        const extensionId = background.url().split('/')[2]
 | 
			
		||||
        await use(extensionId)
 | 
			
		||||
    },
 | 
			
		||||
})
 | 
			
		||||
export const expect = test.expect
 | 
			
		||||
		Reference in New Issue
	
	Block a user