---
title: "От 10 строк к полной E2E-автоматизации: как вайб-кодинг работает на практике"
description: "Как Claude Code вырастил Playwright-скрипт из 10 строк в 142-строчную автоматизацию за 17 промптов: прокси-ротация, clipboard intercept, retry-логика"
url: "https://ifonin.ru/blog/playwright-automation-incremental-prompting/"
date: 2026-03-02
tags: ["vibe-coding","playwright","claude-code","automation"]
---

# От 10 строк к полной E2E-автоматизации: как вайб-кодинг работает на практике

Я начал с 10 строк JavaScript, которые просто открывали браузер и кликали по кнопкам. Через 17 последовательных промптов к Claude Code это превратилось в 142-строчный скрипт с прокси-ротацией, перехватом clipboard и рекурсивной retry-логикой - и всё на одной зависимости.

---

## Почему я не написал один большой промпт

Первый инстинкт был именно таким: описать всё сразу. "Мне нужен Playwright-скрипт, который открывает веб-сервис, регистрирует аккаунт через сервис временной почты, дожидается письма с кодом, копирует код из буфера обмена, использует прокси из файла и запускается 50 раз подряд". Звучит как нормальное ТЗ. На практике AI генерирует что-то похожее на правду, но когда запускаешь - половина не работает, и непонятно с какого конца чинить.

Я попробовал по-другому. Первый промпт: "напиши простой Playwright-скрипт, открой 2 вкладки". Результат - 15 строк, которые работали. С этого момента каждый следующий промпт добавлял одну конкретную вещь.

Это называется incremental prompting - подход, при котором задача разбивается на последовательные подзадачи. Каждая следующая опирается на результат предыдущей. Когда что-то ломается, сразу понятно что именно и в каком шаге. Контроль над генерацией принципиально другой: ты видишь каждое изменение в изоляции и можешь откатиться к последней рабочей точке.

---

## Как скрипт эволюционировал шаг за шагом

Первые три шага были базовые: открыть страницу, добавить прокси, выставить локаль EN-US. 15 строк превратились в 30. Всё работало, можно двигаться дальше.

Четвёртый промпт принёс переход к сервису временной почты вместо Google-авторизации. Здесь же - снятие чекбоксов на форме регистрации. Пятая и шестая итерации добавили генерацию случайного email, заполнение формы, polling-цикл ожидания письма с кодом подтверждения.

Седьмой промпт стал первым серьёзным препятствием. Скрипт падал с ошибкой:

```
Error: strict mode violation: getByRole('button', { name: 'Continue' })
resolved to 2 elements
```

На форме было две кнопки с текстом "Continue": обычная и "Continue with Google". Playwright требует, чтобы локатор указывал ровно на один элемент - это intentional поведение, которое защищает от случайного клика не туда. Решилось одной опцией:

```javascript
page.getByRole('button', { name: 'Continue', exact: true })
```

С `exact: true` Playwright ищет точное совпадение текста, а не подстроку. Кнопка "Continue with Google" перестала матчиться.

Промпты 8-9 - извлечение кода верификации из DOM письма. Следующая пара добавила обработку ситуации "email недоступен" - сервис временной почты иногда отказывал. Решение: рекурсивная retry-логика, где функция `generateEmail()` вызывает саму себя при ошибке. Не exponential backoff, а именно рекурсия - проще и достаточно для этой задачи.

Двенадцатый промпт оказался самым интересным технически.

---

## Три технических момента, которые стоит запомнить

**Перехват clipboard через monkey-patching.** Веб-сервис генерировал API-ключ и клал его в буфер обмена через встроенную кнопку "Copy". Задача: этот ключ нужно сохранить в файл. Проблема: Playwright не может напрямую читать clipboard после того, как страница сама туда записала.

Решение - подменить `navigator.clipboard.writeText` до загрузки страницы:

```javascript
await page.addInitScript(() => {
  const original = navigator.clipboard.writeText.bind(navigator.clipboard);
  navigator.clipboard.writeText = async (text) => {
    window.__copiedText = text;
    return original(text);
  };
});

// После клика на кнопку "Copy":
const apiKey = await page.evaluate(() => window.__copiedText);
```

Скрипт встраивается до инициализации страницы, перехватывает запись в буфер и параллельно сохраняет значение в `window.__copiedText`. Никаких permissions, никаких дополнительных зависимостей.

**Прокси-ротация из файла.** После того как без прокси скрипт заблокировали уже на третьей попытке, добавили чтение прокси из `proxies.txt` и round-robin ротацию:

```javascript
const proxies = fs.readFileSync('proxies.txt', 'utf8')
  .split('\n').filter(Boolean);

// В цикле на TOTAL_RUNS итераций:
const proxy = proxies[attempt % proxies.length];
const context = await browser.newContext({
  proxy: { server: proxy }
});
```

Каждый новый контекст получает следующий прокси по кругу. Прокси задаётся на уровне context, а не browser - это даёт изоляцию сессий между запусками.

**Параметризация через env.** Количество запусков задаётся переменной окружения:

```javascript
const TOTAL_RUNS = parseInt(process.env.TOTAL_RUNS || '50');
```

Дефолт 50, но для отладки достаточно `TOTAL_RUNS=3 node script.js`.

---

## Как я промптировал

Структура, которая сработала лучше всего: current state + desired state + constraint.

"У нас есть функция `generateEmail()`. Она иногда получает ошибку 'email unavailable' от сервиса. Добавь рекурсивную retry-логику - при ошибке функция должна вызывать саму себя и генерировать новый email. Без дополнительных зависимостей."

Три компонента: что есть, что хочу, что нельзя. Claude не переписывал всё с нуля, а точечно добавлял нужное. И это работает именно потому, что контекст сессии сохраняется - не нужно каждый раз прикладывать весь файл.

На тринадцатом шаге я добавил: "после успешного сохранения результата - вызывай `browser.close()`". До этого скрипт не закрывал браузер при выходе, и после нескольких запусков в памяти висели zombie-процессы. Одно предложение в промпте - три строки в коде - проблема исчезла.

Пятнадцатый промпт добавил логику пропуска: если письмо с кодом не пришло за 10 попыток polling - пропускаем итерацию и переходим к следующей. Без этого скрипт мог зависнуть на одном аккаунте навсегда.

---

## Что получилось в итоге

142 строки CommonJS. Одна зависимость - playwright. Скрипт запускается с `TOTAL_RUNS=100 node script.js`, читает прокси из файла, ротирует их по кругу, регистрирует аккаунты через сервис временной почты, перехватывает API-ключи из clipboard и сохраняет результаты в JSON. После финализации проработал автономно 4.5 часа.

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

---

## Что я вынес из этих 17 промптов

Не пытаться описать всё сразу. Разбить задачу на 4-5 шагов, где каждый шаг - одна конкретная фича. После каждого шага - запустить и убедиться, что работает. Только потом следующий.

Конкретность промпта важна. "Добавь прокси" и "добавь прокси-ротацию из файла proxies.txt с round-robin по модулю" - это принципиально разные промпты с принципиально разными результатами.

Strict mode violations - это не баги, это Playwright говорит "твой селектор неоднозначен". Лучше поймать это здесь, чем когда скрипт тихо кликает не туда.

Рекурсия для retry бывает чище exponential backoff - зависит от задачи. Если нужно просто попробовать снова с другими данными (другой email), рекурсивный вызов читается понятнее.

---

Вайб-кодинг в 2026 - это не "написал один хороший промпт и готово". Это диалог, где каждый следующий вопрос чуть сложнее предыдущего. AI хорошо держит контекст, хорошо добавляет конкретную фичу к работающему коду, хорошо объясняет почему что-то сломалось. Плохо справляется с "сделай всё сразу и чтобы работало".

Если сейчас начинаешь автоматизационный скрипт - напиши базовую версию за один промпт, запусти, убедись что работает. Потом по одной фиче. Это занимает больше времени в начале и кратно меньше - в конце.
