Búsqueda de sitios web

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

Artículos relacionados