javascript - Playwright antes de cada uno para todos los archivos de especificación
Soy muy nuevo en Playwright. Debido a mis suites de prueba, necesito iniciar sesión en mi aplicación antes de ejecutar cada prueba. Dentro de un solo archivo de especificación eso es fácil, simplemente puedo llamar a test.beforeEach. Mi problema es: necesito iniciar sesión antes de cada prueba de cada archivo de especificación.
test.describe('Test', () => {
//I need to make the code inside this beforeEach a exported
//function to call inside the before each of every spec file I have
test.beforeEach(async ({ page }) => {
await page.goto('/login');
await page.click('text=Log in with Google account');
await page.fill('id=identifierId', LoginAutomationCredentials.USER);
await page.click('button[jsname="LgbsSe"]');
await page.fill('input[type="password"]', LoginAutomationCredentials.PASSWORD);
await page.click('button[jsname="LgbsSe"]');
const otp = authenticator.generateToken(LoginAutomationCredentials.TOKEN);
await page.fill('id=totpPin', otp);
await page.click('button[jsname="LgbsSe"]');
});
it('Some description', async ({ page }) => {
await page.goto('/foo');
const dateFilter = await page.inputValue('input[placeholder="2011/03/02"]');
expect(dateFilter).toBe('2021/12/07');
});
});
Intenté simplemente tomar ese código y convertirlo en una función dentro de un archivo .ts separado y luego importarlo, pero supuse que se necesita el contexto para hacer esto. Esto probablemente es algo que todo probador que usa Playwright conoce y usa regularmente, sin embargo, no encontré nada sobre el tema.
¿Cómo puedo evitar copiar todo el código de beforeEach y pegarlo en todos mis archivos de especificaciones? ¿Cómo puedo convertirlo en una función y llamarla cuando quiera?
Respuesta #1
Usa accesorios.
fixture.js:
const base = require('@playwright/test')
const newTest = base.test.extend({
login: async({page}, use) => {
await login();
await use(page); //runs test here
//logic after test
}
})
exports.newTest = newTest
exports.expect = newTest.expect
Entonces en tus pruebas:
const {newTest} = require('fixture.js')
newTest('mytest', async ({login}) => {
//test logic
login.goto(''); // using login here since I pass it as page in the fixture.
})
Respuesta #2
Hay dos enfoques:
Usa dependencia del proyecto
Con Playwright 1.31 y dependencia de proyecto puedes configurar qué prueba se ejecutará antes que cualquier otra prueba y pasar, por ejemplo, el almacenamiento del navegador entre pruebas.
Vea un ejemplo funcionando y probado (entrando en la página de búsqueda de Google y aceptando las políticas, y luego entrando nuevamente en esta página con cookies):
playwright.config.ts:
import { PlaywrightTestConfig } from "@playwright/test";
import path from "path";
//here you save session
export const STORAGE_STATE = path.join(__dirname, 'login.json')
const config: PlaywrightTestConfig = {
timeout: 10 * 1000,
expect: {
timeout: 3 * 1000,
},
testDir: './tests',
use:{
baseURL: 'https://google.com',
trace: 'retain-on-failure',
video: 'retain-on-failure',
},
// here we set main project and dependent one
projects: [
{
name: 'login',
grep: /@login/
},
{
name: 'depend e2e',
grep: /@e2e/,
dependencies: ['login'],
use: {
storageState: STORAGE_STATE
}
}
]
};
export default config;
tests/example.spec.ts:
import { test} from '@playwright/test';
import { STORAGE_STATE } from '../playwright.config';
test('login to service @login', async({page}) => {
await page.goto('/');
// below example is to reject cookies from google
await page.waitForLoadState('domcontentloaded');
await page.keyboard.press('Tab');
await page.keyboard.press('Enter');
await page.getByRole('menuitem', { name: "English (United States)" }).press('Enter');
await page.getByRole('button', { name: 'Reject all' }).click();
// Save storage:
await page.context().storageState({path: STORAGE_STATE})
})
test('logged in test @e2e', async ({page}) => {
await page.goto('/');
await page.waitForLoadState('domcontentloaded');
// BOOM - you are in!
// Screenshot shows that settings regarding cookies were saved
await page.screenshot({ path: 'screenshot.png' })
})
Video con ejemplo: https://www.youtube.com/watch?v=PI50YAPTAs4&t=286s
En el ejemplo anterior estoy usando etiquetas para identificar pruebas: https://playwright.dev/docs/test-annotations#tag-tests
Usa fixtures
Vamos a probar entrando a la página de búsqueda de Google y aceptando las políticas
En el archivo fixtures.ts:
import { test as base } from "@playwright/test";
export const test = base.extend({
page: async ({ baseURL, page }, use) => {
// We have a few cases where we need our app to know it's running in Playwright.
// This is inspired by Cypress that auto-injects window.Cypress.
await page.addInitScript(() => {
(window as any).Playwright = true;
});
await page.goto("/");
// below example is to reject cookies from google
await page.waitForLoadState("domcontentloaded");
await page.keyboard.press("Tab");
await page.keyboard.press("Enter");
await page
.getByRole("menuitem", { name: "English (United States)" })
.press("Enter");
await page.getByRole("button", { name: "Reject all" }).click();
use(page);
},
});
export { expect } from "@playwright/test";
Y luego en la prueba usa el nuevo objeto test en lugar de importarlo de "@playwright/test"
import { test, expect } from "../fixture";
test("logged in test @e2e", async ({ page }) => {
await page.goto("/");
await page.waitForLoadState("domcontentloaded");
// BOOM - you are in!
// Screenshot shows that it works
await page.screenshot({ path: "screenshot.png" });
});
Inspirado por: https://github.com/microsoft/playwright/issues/9468#issuecomment-1403214587
Si necesitas un ejemplo de interceptación de solicitudes globales, mira aquí: https://stackoverflow.com/a/76234592/1266040
