Я пишу E2E Playwright тесты на typescript в кровавом энтерпрайзе. Задача – выполнить полный рабочий цикл с так как это делает живой пользователь, симулировать ввод данных и клики мышкой. Последний этаж тестовой пирамиды, после которого можно и в продакшн. 

Достаточно часто всплывают проблемные места, на которых тест валится. Не просто изменившийся селектор, эту мелочь с помощью AI можно поправить за секунды. Что-нибудь посложнее – плохая гидрация, двойной рефреш или зависимые поля. Что говорить, если даже на самом сайте Playwright встречается такое.

У Playwright неплохие трейсы, но приходится перезапускать тест каждый раз. Исправил, перезапустил, упало, смотришь логи. И так по кругу, пока не заработает. Если проблема в конце теста, ждать приходилось долго. Куча времени потрачена просто на ожидание.

Хотелось бы менять код «на лету», без перезапуска. В консоли браузера я, например, могу в любой момент напечатать и запустить команду.

Хотелось бы такого и для  Plywright в связке с  TypeScript, только лучше. Чтобы запускать  прямо в редакторе Visual Studio Code, а не в консоли. Чтобы синтаксис проверялся, tslinter‘ы всякие работали, автодополнение на лету и прочий AI.

Напечатал

await page.getByRole("search", {name : "Search"});

 Запустил. Посмотрел на реакцию, поправил

 await page.getByRole("searchbox", {name : "Search"});

Запустил снова. И так много раз, если надо.  Можно несколько команд сразу запускать, если хочется. Модули импортировать на лету. Чтобы scope запоминался, если выполнил

const searchBox = page.getByRole("searchbox", {name "Search"})

то потом searchBox можно использовать дальше

await searchBox.click();

Мозговой штурм с агентом выдал следующие результаты:

Попытка 1 - Debug Console REPL (Read-Eval-Print Loop) в VSCode

По факту у эта консоль привязана к дебагу и и‑за этого возникает куча проблем:
Breakpoint останавливает Event Loop, значит запуск await — команды ничего не выполнит вплоть до нажатия F5/ F10 / F11. После этого Visual Studio с breakpoint'а уйдёт. Да, есть хак, можно каждый раз писать фиктивный цикл и ставить breakpoint внутрь, ��о каждый раз так делать это для сильных духом терминаторов. 

Попыка 2 - node:repl

Следующая попытка была использовать node:repl. Дебаг не нужен, просто добавляешь вызов REPL внутрь теста

const msg = 'message'; repl.start('> ').context.m = msg;

Когда тест выполнится до этого места, можно запускать Playwright команды прямо  в командной строке. Не зашло, потому что неудобно копировать текст из редактора и обратно, нужно  помнить синтаксис REPL. Впрочем, если VIM вам как родной, то будет ок. 

Попытка 3 – готовые REPL расширения для VSCode

Нашлись REPL расширения для VSCode! Целых 2! Одно не заработало, другое заброшено 6 лет назад. И всё это многообразие не рассчитано на Playwright, значит, как минимум точно будут проблемы с таймаутами.

  1. У нас большие таймауты на операции и навигацию, опечатаешься в локаторе и ждёшь полминуты.

  2. Забудешь увеличить таймаут на тест целиком – выкинет на самом интересном месте.

  3. Хотелось бы  Playwright – фишки, например лог для каждой операции как в trace viewer.

В существующих плагинах этого ожидать не приходится. Пришлось написать свой, Playwright – ориентированный, «PW Write-And-Run».

PW Write-And-Run

Ставишь Run Point через меню и запускаешь тест.

Выделяешь и запускаешь
Выделяешь и запускаешь

Желательно не забыть галочку «Show browser», иначе наблюдать реакцию системы на команды будет затруднительно. Тест запускается, со всеми fixture и прочей авторизацией. Когда он дойдёт до Run Point, индикатор поменяется на W&R✓ , теперь можно писать и запускать код. Поддерживается весь scope до строки с RunPoint: все константы, функции, всё, включая импорты.

Выделяешь нужный код и запускаешь. Тут же видишь результат в браузере. Меняешь, дописываешь, запускаешь снова. Много раз.Тест не упадёт по таймауту через минуту, потому что Run Point его отключает. Большие таймауты на операции/навигацию мешают в интерактивном режиме. В расширении их можно установить одной кнопкой.

Сложности и засады

Модули и их импорт

Во-первых, TypeScript при компиляции делает import elision и удаляет неиспользуемое.

import { test, expect } from '@playwright/test';

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

Здесь expect нигде не используется, поэтому будет вычищен при компиляции и потом нельзя (спойлер: теперь можно) написать и запустить

expect(1).toBe(1);

Конечно, import elision можно отключить в настройках, но признаемся честно, никто не будет править tsconfig ради одного VSCode - расширения. Решение было простым и прямолинейным - так как для eval всё равно создаётся своё окружение, принудительно импортируем туда все модули из теста. Теперь, раз у нас уже есть функция импорта, разрешаем её использовать для перезагрузки модулей.

Есть у вас модуль testusers.ts

export const testuser =  {name : „Max“};

И тест где этот модуль используется

import { testuser } from '../testusers'
...
expect(testuser.name).toBe(„Mustermann“);

Поправили имя в  testusers.ts и хотите проверить, что  expect теперь отрабатывает, без перезапуска теста.

Можно, конечно, самому написать и выполнить

const testuser = import('../testusers');

Но проще просто встать на строчку с импортом и нажать Ctrl+Enter.
Так расширение и  делает, автоматически преобразовывает  import в import(). 

Была попытка автоматизировать перезагрузку полностью, чтобы изменённые модули распознавались и перезагружались автоматически. Но в реальной жизни это привело только к излишней путанице, потому что вот здесь например надо дополнительно перезагружать константу, а люди это забывают и громко удивляются. 

import { TestuserClass } from '../testusersClasses';

test('simple title', async ({ page }) => {
  const testUser = new TestuserClass(usrName);
  expect(testUser.name).toBe(„Mustermann “);
});

 Кстати,  о константах.
 Обидно, когда вы запустили команду с опечаткой

const pageURL = 'htps://playwright.dev/';

 и при повторном запуске получаете

 SyntaxError: redeclaration of const

 В расширении это не проблема, запускайте сколько хотите. Всё перезапишется.

Прерывание команды

Хотелось бы иметь кнопку для прерывания команды. Увы, я не нашёл здесь решения. Playwright команда умирает только по таймауту или вместе с браузером. Запустить отдельный процесс не вариант, ибо как передашь ему весь scope?

Сюрпризы от Playwright

Если установлено расширение «Playwright Test for VSCode», некоторые локаторы подсвечиваются прямо в браузере.
Так же работает Pick Locator, Record New – можно записывать тест по шагам, рефакторить их с помощью CoPilot’а и тут же на лету выполнять\проверять.

Итог

Расширение находится в Visual Studio Code по названию - "Playwright Write-And-Run".
Репозиторий - здесь.
Чтобы заработало, нужно уста��овить модуль контекста в проект с тестами

npm install -D pw-execution-context

Расширение я активно использую. Оно позволяет быстро отладить проблемные участки. Цифра 5 взята не с потолка, а как результат пятидневного эксперимента команды QA инженеров.

Как неожиданный эффект, многим понравилось играться с Playwright в интерактивном режиме, смотреть как реагирует система.

Ставьте звёзды в репозитории, все кто поставил получат pro-версию бесплатно (если я когда-нибудь решусь её сделать).