Невозможно запустить пример драматурга «Написание утверждений»

TL;DR

Не удается заставить работать пример «Написание утверждений» со страницы « .

Полный рассказ

Я ищу в Playwright для написания тестов. Я прорабатываю примеры « Начало работы драматурга»Начало работы» , и у меня возникла проблема с Примером № 2 (Написание утверждений) . Я делаю это на своей рабочей машине (macOS), и у меня еще не было возможности попробовать это на своем компьютере с Linux дома, если это имеет значение.

Рассматриваемый пример:

      // example.spec.js
const { test, expect } = require('@playwright/test');

test('my test', async ({ page }) => {
  await page.goto('https://playwright.dev/');

  // Expect a title "to contain" a substring.
  await expect(page).toHaveTitle('Playwright');

  // Expect an attribute "to be strictly equal" to the value.
  await expect(page.locator('text=Get Started')).toHaveAttribute('href', '/docs/intro');

  // Expect an element "to be visible".
  await expect(page.locator('text=Learn more')).toBeVisible();

  await page.click('text=Get Started');
  // Expect some text to be visible on the page.
  await expect(page.locator('text=System requirements')).toBeVisible();

  // Compare screenshot with a stored reference.
  expect(await page.screenshot()).toMatchSnapshot('get-started.png');
});

Первоначальная проблема, с которой я столкнулся, заключалась в сбое этой строки:

      await expect(page).toHaveTitle('Playwright');

Я смог решить эту проблему, изменив .toHaveTitle() искать регулярное выражение, теперь оно выглядит следующим образом:

      // 02_writing_assertions.spec.js
const { test, expect } = require('@playwright/test');

test('my test', async ({ page }) => {
  await page.goto('https://playwright.dev/');

  // Expect a title "to contain" a substring.
  await expect(page).toHaveTitle(/Playwright/);  // Updated to regex

  // Expect an attribute "to be strictly equal" to the value.
  await expect(page.locator('text=Get Started')).toHaveAttribute('href', '/docs/intro');

  // Expect an element "to be visible".
  await expect(page.locator('text=Learn more')).toBeVisible();

  await page.click('text=Get Started');

  // Expect some text to be visible on the page.
  await expect(page.locator('text=System requirements')).toBeVisible();

  // Compare screenshot with a stored reference.
  expect(await page.screenshot()).toMatchSnapshot('get-started.png');
});

Однако, когда я запускаю его, я получаю следующее:

      ❯ npx playwright test tests/getting_started/02_writing_assertions.spec.js --headed

Running 1 test using 1 worker

  ✘  tests/getting_started/02_writing_assertions.spec.js:4:1 › my test (4s)


  1) tests/getting_started/02_writing_assertions.spec.js:4:1 › my test =============================

    locator.getAttribute: Evaluation failed: Error: strict mode violation: selector resolved to 2 elements.
        at u.querySelector (<anonymous>:3:34807)
        at eval (eval at evaluate (:3:1339), <anonymous>:7:32)
        at i (<anonymous>:3:37685)
        at <anonymous>:3:37773
        at Object.run (<anonymous>:3:38253)
        at eval (eval at evaluate (:3:1339), <anonymous>:1:14)
        at t.default.evaluate (<anonymous>:3:1362)
        at t.default.<anonymous> (<anonymous>:1:44)
    =========================== logs ===========================
      retrieving attribute "href" from "text=Get Started"
      strict mode violation: selector resolved to 2 elements.
    ============================================================

       9 |
      10 |   // Expect an attribute "to be strictly equal" to the value.
    > 11 |   await expect(page.locator('text=Get Started')).toHaveAttribute('href', '/docs/intro');
         |                                                  ^
      12 |
      13 |   // Expect an element "to be visible".
      14 |   await expect(page.locator('text=Learn more')).toBeVisible();

        at /Users/me/node_modules/@playwright/test/lib/test/matchers/matchers.js:131:27
        at /Users/me/node_modules/@playwright/test/lib/test/matchers/toMatchText.js:48:22
        at pollUntilDeadline (/Users/me/node_modules/@playwright/test/lib/test/util.js:119:42)
        at Object.toMatchText (/Users/me/node_modules/@playwright/test/lib/test/matchers/toMatchText.js:47:37)
        at Object.toHaveAttribute (/Users/me/node_modules/@playwright/test/lib/test/matchers/matchers.js:130:35)
        at Object.<anonymous> (/Users/me/node_modules/@playwright/test/lib/test/expect.js:94:30)
        at __EXTERNAL_MATCHER_TRAP__ (/Users/me/node_modules/expect/build/index.js:342:30)
        at Object.throwingMatcher (/Users/me/node_modules/expect/build/index.js:343:15)
        at /Users/me/dev/playwright/playwright-test/tests/getting_started/02_writing_assertions.spec.js:11:50
        at WorkerRunner._runTestWithBeforeHooks (/Users/me/node_modules/@playwright/test/lib/test/workerRunner.js:425:7)


  1 failed
    tests/getting_started/02_writing_assertions.spec.js:4:1 › my test ==============================

Комментирование каждого из утверждений просто повторяет ошибку в следующем утверждении. Если я закомментирую их все, то await page.click(...) работает как положено, но следующий await expect(...) снова терпит неудачу.

Обновлять

Итак ... похоже, что проблема в том, что page.locator(...) как написано, возвращает несколько элементов, что должно было быть сразу очевидно из-за того, что я вижу следующую ошибку:

Ошибка оценки: ошибка: нарушение строгого режима: селектор разрешен до 2 элементов.

Поэтому я изменил следующую строку:

      await expect(page.locator('text=Get Started')).toHaveAttribute('href', '/docs/intro');

к

      await expect(page.locator('//a[text()="Get Started"][1]')).toHaveAttribute('href', '/docs/intro');

что, как я думал, решило бы проблему. Однако сейчас у меня тайм-аут.

1 ответ

Я смог решить (почти) все проблемы. Единственная проблема с исходным скриптом, которую я пока не смог решить, - это следующая строка:

      // Expect some text to be visible on the page.
await expect(page.locator('text=System requirements')).toBeVisible();

Эта строка дважды появляется на странице. Пытаясь различными способами найти строку (т. Е.), Мой код либо возвращал оба элемента, либо истек время ожидания. Поскольку это была произвольная строка на странице, а не элемент, который нужно было щелкнуть, чтобы перейти к следующему шагу, я просто подставил другую строку.

Рабочий сценарий выглядит следующим образом:

      // 02_writing_assertions.spec.js
const { test, expect } = require('@playwright/test');

test('my test', async ({ page }) => {
  await page.goto('https://playwright.dev/');

  // Expect a title "to contain" a substring.
  await expect(page).toHaveTitle(/Playwright/);

  // Expect an attribute "to be strictly equal" to the value.
  await expect(page.locator('(//a[translate(text(),"get started","GET STARTED")="GET STARTED"])[1]')).toHaveAttribute('href', '/docs/intro');

  // Expect an element "to be visible".
  await expect(page.locator('(//a[translate(text(),"learn more", "LEARN MORE")="LEARN MORE"])[1]')).toBeVisible();

  // Click "Get Started"
  await page.click('(//a[translate(text(),"get started","GET STARTED")="GET STARTED"])[1]')

  // Expect some text to be visible on the page.
  await expect(page.locator('(//h1[contains(translate(text(),"getting started","GETTING STARTED"),"GETTING STARTED")])[1]')).toBeVisible()

  // Compare screenshot with a stored reference.
  expect(await page.screenshot()).toMatchSnapshot('get-started.png');
});

Несколько пунктов о моих высказываниях:

  • Я всегда перевожу свои текстовые строки в верхний регистр для сравнения, просто чтобы укрепить тест против будущей опечатки, которая превращает «Get Started» в «GEt Started».

  • То же самое с постоянным обращением к xpathвозврат, установленный конкретным элементом; он защищает от того, что второй экземпляр того же URL-адреса будет добавлен кем-то в будущем.

Другие вопросы по тегам