我有一系列 Playwright 测试,可能需要我在不同的应用程序中进行身份验证。我有一个有用的函数,允许我简单地传递一个 URL,它将设置具有特定存储状态的浏览器上下文。看起来像这样:
export const visitWithAuth = async (browser: Browser, url: string) => {
let storageFile = ''
if (url.includes('myFirstSite')) {
storageFile = FIRST_SITE_FILE
} else if (url.includes('mySecondSite')) {
storageFile = SECOND_SITE_FILE
}
if (!storageFile) {
throw new Error('Invalid URL or no matching storage state found.')
}
const context = await browser.newContext({ storageState: storageFile })
const page = await context.newPage()
await page.goto(url)
return { page, context }
}
所以在测试中,它会看起来像这样:
test('make sure the thing works really good', async ({ browser }) => {
const { page, context } = await visitWithAuth(browser, 'https://www.myfirstsite.com')
await page.dostuff()
await expect(page.otherstuff).toBeWhatever()
await context.close()
})
我发现我需要手动确保在每一项测试结束时都有
await context.close()
。似乎当测试签名使用正常的 test('make sure the thing works really good', async ({ page })
时,跟踪查看器中存在 after
挂钩,可以根据需要关闭所有内容。
有没有一种方法可以简单地设置某种配置,以便在测试完成后自动关闭任何上下文?我希望我可以简单地通过调用
nextContext
或 newPage
来传递一些新选项,但我在文档中没有看到任何内容。
FWIW,Playwright 的文档还在其示例中提到了手动关闭上下文:https://playwright.dev/docs/auth#testing-multiple-roles-together
经过一些研究,发现最好的方法是通过固定装置。夹具的作用类似于钩子,允许在实际测试中发生的测试步骤之前和之后发生操作。
这是原始问题之后的一个小代码片段/示例:
type AuthFixtures = {
myFirstSite: Page
mySecondSite: Page
}
export const test = baseTest.extend<AuthFixtures>({
myFirstSite: async ({ browser }, use) => {
const { page: authorizedPage, context: authorizedContext } = await createAuthContext(browser, `${process.env.MY_FIRST_SITE_URL}`)
await use(authorizedPage)
await authorizedContext.close()
},
mySecondSite: async ({ browser }, use) => {
const { page: authorizedPage, context: authorizedContext } = await createAuthContext(browser, `${process.env.MY_SECOND_SITE_URL}`)
await use(authorizedPage)
await authorizedContext.close()
}
})
函数“createAuthContext”返回页面和上下文。这意味着我们对
use(page)
的调用与测试步骤中发生的情况一致,并且在夹具中我们可以调用 context.close()
而无需在测试本身中执行。这意味着我们现在可以编写这样的测试:
test('do some tests while authed into myFirstSite', async ({ myFirstSite: page }) => {
page.doStuff()
})
对于任何 Ruby 爱好者来说,
await use(page)
几乎模仿了 yield
在 Ruby 中的作用。