Desktop
Десктоп-приложение — это путь без кода, и всё, что оно создаёт, — обычный файл
.flow.yaml, который инженер откроет в любом редакторе. Эта страница — экскурсия
по приложению; сам язык сценариев описан в разделе Reference.
Вход и первый запуск
Заголовок раздела «Вход и первый запуск»При первом запуске лицензия, условия и политика конфиденциальности показываются одним скроллом — три документа целиком, один под другим, и Agree and continue внизу. Один чекбокс включает анонимные данные об использовании; по умолчанию он выключен и честно говорит, что уходит: какие функции используются, версия приложения, ОС и тип процессора, случайный id этой установки и автоматические отчёты о сбоях (текст ошибки и стек) — никогда ваши тесты, сценарии и их данные. Переключается потом в Settings → General, документы остаются в Settings → Legal.
Затем — экран входа, и теперь он объясняет, зачем он тут: бесплатный аккаунт, чтобы ваши тесты оставались вашими на любой машине, а после этого приложение работает офлайн. Sign in / Create account делает один круг через браузер и SSO tapstep. Если браузер так и не вернулся, экран это объясняет, а не крутится вечно — нет сети или сервер входа не отвечает — и предлагает открыть страницу заново. Идентичность кэшируется в keychain ОС (macOS Keychain, Windows Credential Manager, Secret Service в Linux). Account внизу рельса открывает поповер: кто вошёл, Manage account / Change password (обе открываются в браузере) и Sign out.
Раскладка
Заголовок раздела «Раскладка»Пять зон, и они стоят на месте, чем бы приложение ни занималось.
- Рельс (слева, с подписями): Tests, Runs, Devices — в проекте VS Code вместо него Extensions, — Settings внизу и Account под ними.
- Сайдбар: одна колонка, и раздел выбирает, что в ней стоит, — тесты,
прогоны, устройства этой машины. У Devices и Extensions есть ссылка
Manage…, которая открывает их полный экран вкладкой. Смена раздела не
двигает ничего больше: вкладка, в которой вы работали, остаётся открытой и
активной.
Ctrl+B/⌘Bпрячет колонку. - Вкладки: плоская полоса. Home закреплён у левого края и назван именем проекта; у каждой другой вкладки — иконка того, чем она занята, крестик, а в правом конце полосы меню ⋯ со списком всех открытых.
- Нижняя панель (
Ctrl+J/⌘J): Run output · Network · Console · Terminal · AI chat. Свёрнутая — полоска этих имён со счётчиками. Терминал — настоящий шелл, открытый в корне проекта: для CLI, git и всего, что вы бы и так набирали;Ctrl+`по-прежнему ведёт прямо в него. - Строка состояния: тумблер панели; что идёт прямо сейчас —
▶ Running Login · step 4/7,● Recording · 7 steps → flows/pay.flow.yaml, и клик по нему переводит на ту вкладку; чип таргета (Web (Chrome) · 1280×800, клик — выбрать другое устройство, а в проекте VS Code — другой testspace); сохранён ли проект; его имя и число тестов; версия и чип обновления. Если окно узкое, сегменты гаснут снизу вверх по важности — то, что идёт, не гаснет никогда. - Титульная строка: меню проекта, переключатель окружения (см. Окружения), контролы ветки и Publish, когда подключён remote, и Report a bug.
Settings — вкладка, а не экран, подменяющий вашу работу: General / Appearance / AI / Project / Storage / Legal сбоку. Account — поповер с рельса: кто вошёл, History и Share with the team…, пока не подключён remote.
Палитра команд (Ctrl+K / ⌘K): запись, новый пустой тест, Save version /
Publish, показать/скрыть панель, терминал или чат, History, перейти в любой
раздел, открыть или запустить любой тест по имени.
Приложение говорит по-английски и по-русски и следует языку системы, пока
вы не выберете один в Settings → General → Language; переключение работает
без перезапуска. Меню View делает весь интерфейс крупнее (Ctrl+= / ⌘=),
мельче (Ctrl+- / ⌘-) или снова его собственного размера (Ctrl+0 / ⌘0) —
см. Settings.
Панель тестов
Заголовок раздела «Панель тестов»Tests в сайдбаре — один список с одной моделью: тесты проекта и его общие
шаги, в тех папках, в которых они лежат. Подпапка — это группа, а папку можно
создать в любой папке, которую показывает панель, — не только под flows/.
Строка — это имя, одна точка и слова о том, что это. Точка после имени говорит, как прошёл последний прогон — passed, failed, stopped, not run, — а тест, который идёт прямо сейчас, пульсирует независимо от того, включена эта точка или нет. Файл общих шагов несёт после имени слова Shared steps, а Used by N tests — в подсказке и в меню ⋯; виды экспорта, которыми тест может уйти, сворачиваются в одну иконку, подсказка которой их перечисляет. В меню ⋯ — Run on…, Rename…, Duplicate, Convert to shared steps / Convert to test, Export и Delete….
Имена пишутся на любом алфавите — русское имя становится русским именем
файла, — и убирается только то, чего не вынесет путь. Имя, от которого ничего
не осталось, уже занятое или одно из тех, что Windows держит за своими
устройствами (CON, PRN, AUX, NUL, COM1–COM9, LPT1–LPT9), об
этом говорит, а не молча ничего не делает.
Delete отправляет файл в системную корзину, а тост десять секунд предлагает Undo; папка уходит со всем, что внутри. Машина без корзины откатывается к тому, что было всегда: сначала спросят.
Группа Project
Заголовок раздела «Группа Project»Внизу панели, под Suites, сворачиваемая группа Project даёт адрес каждому файлу, который называет README проекта, вместо того чтобы оставить его вне списка. В строках — настоящие имена файлов, а клик открывает тот экран, который этот файл и так редактирует:
config.yaml→ Settings → Project. Если файл удалён, строка говорит missing, а клик предлагает написать его заново — тем же кодом, что и мастер..envи каждый.env.<name>, который лежит в папке, → Variables проекта с выбранным окружением.reports/→ результат самого свежего прогона. До первого прогона строка говорит no runs yet и ничего не открывает.playwright/,extester/→ блок Exports, как только папка существует или её называетconfig.yaml.fixtures/→ рельс Extensions, в проекте VS Code.README.mdи остальной markdown в корне проекта → вкладка.
Меню ⋯ каждой строки — Reveal in Finder, Copy path и Open in VS Code там, где VS Code есть на этой машине. Ничто в этой группе не таскается и не принимает перетаскивание.
Что показывает панель
Заголовок раздела «Что показывает панель»Settings → Appearance → Tests panel хранит четыре предпочтения об этом одном списке. Каждое — перерисовка, а не пересканирование, и ни одно не заводит второй вид:

- Names — Friendly (
Pay broken) или File (pay-broken.flow.yaml, моноширинным). Это только текст строки: порядок, фильтр и подсказка по-прежнему читают читаемое имя и путь. Список Suites следует той же настройке. - Shared steps — Inline, в тех папках, где они лежат, или Grouped: одна сворачиваемая группа Shared steps в конце списка, где папка становится суффиксом после имени. Папка, в которой не было ничего, кроме общих шагов, уходит вместе с ними.
- Sort — Name, Last run (сначала упавшие, потом не запускавшиеся, потом прошедшие по свежести) или Changed (сначала записанные позже всех). Папки держат порядок по имени.
- Show — три переключателя: Run status (точка), Git changes (пометка на тесте, который изменило рабочее дерево) и Project files (группа Project).
Клавиатура и выделение
Заголовок раздела «Клавиатура и выделение»Список — дерево с одной точкой табуляции. ↑ / ↓ идут по строкам так, как они
нарисованы, → / ← открывают и закрывают папку или входят в неё и выходят,
Home / End ведут к концам, а буквы, набранные с интервалом меньше
полусекунды, перепрыгивают к следующей строке, которая с них начинается.
Enter открывает тест или открывает и закрывает папку; ⌘Enter его запускает,
Space его выбирает, F2 переименовывает, Delete / Backspace отправляет в
корзину, а Esc снимает выделение, потом фильтр.
Клик выбирает одну строку, Shift-клик — диапазон, ⌘-клик переключает одну.
Над выделением панель предлагает Export what is picked… (одна пачка, одна
папка) и Delete (один тост отмены на всех). Перетаскивание выбранной строки
несёт на папку всё выделение — перетаскивание невыбранной несёт только её, — а
перетаскивание больше одной строки показывает призрак с их числом. Фильтр не
убирает дерево: он оставляет его стоять и открывает те папки, в которых что-то
совпало; сам фильтр, выделение и строка в фокусе переживают уход из раздела и
возвращение.
Проекты
Заголовок раздела «Проекты»Welcome ведёт одной карточкой — New project, — а две другие двери оставляет тихими ссылками под ней: Open a folder you already have и Join a team workspace by URL (любой git URL; токен доступа опционален — для приватных репозиториев и Publish). Ниже — недавние проекты, они же в меню проекта в заголовке окна.
New project спрашивает имя, платформы, которые проект тестирует (чекбоксы
web / android / ios — подсказка по умолчанию, а не ограничение; меняется позже в
Settings) и является ли он проектом VS Code extension testing
(экспериментально — тестирует .vsix в реальном воркспейсе, нужен установленный
VS Code). URL он не спрашивает: его спросят при первой записи и оттуда же
запомнят.
Пока в проекте не было ни одного прогона, Home — одна кнопка Record a test и три строки о том, что произойдёт: You click — we write the steps. You press Run — the machine repeats them. Something breaks — you see which step, with the screenshot. Под ними тихая ссылка Or write a test by hand. Как только прогоны появились, Home становится местом, куда возвращаются: Failing now, Tests, которых вы касались последними, с кнопкой Run у каждого, Recent runs с All runs → и Record в углу.
Проект — это папка: config.yaml, тесты *.flow.yaml в flows/ (подпапки
становятся группами), общие шаги *.helper.yaml и reports/ для последнего отчёта
прогона. Под капотом каждый проект — git-репозиторий, который приложение
инициализирует само, без отдельного шага.
Settings → Project хранит общее для всей команды: Staging address
(env.STAGING_URL в config.yaml — откуда стартуют Record и openLink),
Target platforms, Git remote и инвентарь Variables проекта (каждая
${VAR}, которую упоминают сценарии и конфиг, её закоммиченное значение по
умолчанию и локальное из .env — недостающие задаются прямо там), Hooks
проекта (верхнеуровневые before: / after: из config.yaml — то, что каждый
тест проекта выполняет вокруг своих шагов; в редакторе такие
строки помечены from project), матрицу Environments и папки Exports.
Окружения
Заголовок раздела «Окружения»Тест пишут один раз, а гоняют сегодня против staging, завтра против интеграционного, поэтому адрес и креденшелы — не часть теста. Переключатель окружения в титульной строке говорит, против какого окружения работает каждый прогон, каждая запись и каждая панель окна; Environments… в нём открывает матрицу.
Матрица — одна таблица: колонка на окружение, строка на переменную и чип у
каждого значения, говорящий, где оно живёт: shared (config.yaml env:,
коммитится, для всех окружений), имя самого окружения (environments.<имя>,
коммитится, для этого окружения) или local secret (.env / .env.<имя>, не
коммитится никогда). Ячейка, которую окружение не переопределяет, читается как
inherits. Окружение можно переименовать, продублировать, удалить, сделать
дефолтным для проекта, добавить переменную туда, где ей место, Promote to
shared или Reset to shared — каждая правка пишет config.yaml или
dotenv-файл, так что результат остаётся текстом, который git умеет
диффать. Секрет локален для каждого окружения: «повысить» его — значит
скопировать в общий .env, а не закоммитить.
Переключатель дотягивается до остального приложения:
- Record говорит, против какого окружения идёт запись, и пишет значение,
которое это окружение уже называет, как
${VAR}, а не буквой, — карточка предлагает keep literal, если вы имели в виду именно текст. - Панель Variables над шагами показывает и значение, и его источник, так
что
${BASE_URL}читается по-разному в staging и в prod, а файл не меняется. - В диалоге прогона есть чип окружения: он выбирает, в каком окружении прогон разрешает переменные, — а не копирует значения этого окружения в строки ниже, которые остаются переопределениями поверх. Shared only — это прогон только на общих переменных.
- Отчёт прогона называет окружение, против которого он шёл, — как и отчёты JUnit, Allure и HTML, которые пишет CLI.
- AI-чат предупреждает, когда его собственные прогоны идут в дефолтное окружение проекта, а не в то, на котором стоит титульная строка.
Файловая сторона всего этого — environments:, defaultEnvironment,
.env.<имя>, ${TAPSTEP_ENV} и порядок слоёв — на странице
config.yaml.
Record a test открывает диалог What are we testing? — по строке на цель: A website (откроется в браузере на этой машине), An Android app, An iPhone app и Desktop app (:port), когда приложение уже на мосту tapstep. Устройство, на которое показывает строка состояния, уже выбрано. Недоступная цель говорит об этом на месте, вместе с тем, что делать, и ссылкой Check devices, которая смотрит на машину заново прямо в диалоге, а не уводит вас на другой экран: No browser found — install Chrome, Connect a phone or start an emulator, Start a simulator in Xcode. Для сайта спрашивают адрес, и первый введённый становится Staging-адресом проекта — в следующий раз он уже подставлен. Android и iOS спрашивают id приложения. Проект VS Code записывает поверх запущенного testspace, так что сначала запустите его в Extensions.
What are we testing? — staging-адрес запоминается после первой записи.
Дальше у записи появляется собственное окно рядом с тем, что вы записываете, а её вкладка показывает REC рядом с устройством — Web (Chrome), — счётчик шагов и кнопки Show the recording window и Discard.
Окно записи — журнал того, что вы сделали, а не редактор, и шапка у него одна
строка: ● REC 0:41 · 7 steps, затем Check, Save и ⋯. Всё, что
реже, живёт в меню ⋯ — Add a step by hand…, Check the page address
(веб), Re-read the window (Refresh hotspots на зеркале), Card beside
clicks, Prefers … — stop, пока взведено предпочтение селектора, и Discard
recording…. Под шапкой стоит одна строка о том, куда кликать, — Click in the
browser window — each click becomes a step here. — и уходит с первым шагом;
через пятнадцать секунд без шага на её месте Not seeing your clicks? Some pages
block recording….
Подвала нет. Save — в шапке, выключена, пока нет ни одного шага (Nothing
recorded yet, ⌘S её нажимает), и спрашивает имя только после нажатия: шапка
превращается в пустое поле Name this test, а под ним по мере ввода растёт
файл, которым тест станет. Enter записывает, Esc возвращает к записи, которая не
останавливалась. Из адреса ничего не подставляется, имя хранит набранный регистр,
а занятое имя так и говорит — sign-in.flow.yaml is taken — saving as
sign-in-2. Save & run больше нет: главное окно открывает сохранённый тест и
предлагает Run в тосте.
Discard переспрашивает один раз, и вопрос называет, что вернётся назад: шаги
уходят вместе с окном, а всё, что запись успела записать в проект, — staging-адрес
в config.yaml, пароль, уехавший в .env, — забирается обратно. То, что в этих
файлах было до неё, остаётся как было.
Веб и VS Code — в вашем собственном окне
Заголовок раздела «Веб и VS Code — в вашем собственном окне»Запись веба открывает настоящее окно браузера и ставит окно записи рядом, по его высоте, не двигая и не будя его. Запись VS Code ведёт то окно VS Code, которое у вас уже открыто. Зеркала между вами и целью нет — вы кликаете в своём окне, каждый клик приходит в окно записи шагом, а то, что вы печатаете, становится шагом, когда вы уходите из поля.
Браузер открывается новым окном на одноразовом профиле, а не тем, что у вас открыт: без закладок, без логинов, без расширений, так что баннер про cookie будет каждый раз. Размер — 1280×800. Подходит любой Chromium — Chrome, Edge, Brave, Chromium. Firefox отклоняется сразу: он не умеет рассказать, что вы делаете в его собственном окне; прогоняться на Firefox сценарии по-прежнему могут, просто не записываются там.
Части страницы, которые не приложение. Пометьте их data-tapstep-ignore —
панель разработчика, журнал запросов, виджет обратной связи, который команда
кладёт в staging-сборку. Клик, ввод или прокрутка внутри такого элемента (и во
всём, что вложено в него, фреймы тоже) не становятся шагом, и карточка их не
предлагает. Прогон элемент по-прежнему видит: сценарий, написанный руками, может
с ним работать.
Карточка рядом с тем, куда вы кликнули. Рядом с самим элементом встаёт маленькая карточка и говорит, что только что записано: Step 7 · Click button “Pay”, одна строка действий и убывающая полоска — знак того, что карточка уйдёт сама и делать с ней ничего не нужно. Элемент, о котором она, обведён отдельным окном, так что видно, о каком именно речь.
Вопрос карточка задаёт только там, где движок не уверен. Если его выбор
единственный по подписи, тексту, роли с именем, placeholder, test id или id —
спрашивать нечего, карточка просто подтверждает. Если отзывается несколько, она
спрашивает тем, что видно глазами, а не селекторами: ⚠ 6 buttons say “Pay” —
the step takes the 2nd, и ответы — the one in row “#1042”, the 2nd “Pay”
или by position. У набранного текста два ответа, Keep it as text и Make it
a variable, — отправить его в секреты или назвать только хвост можно из ⋯
карточки. Поле-маска не спрашивается вовсе: значение ушло в .env, и карточка
называет ключ — Step 5 · Type into “Password” · saved to .env as PASSWORD.
Каждая строка — и кнопка, и клавиша: ⌥1, ⌥2… отвечают, ⌥0 отзывает
шаг, ⌥Esc закрывает карточку (⌃⌥, когда записывается окно VS Code;
Ctrl+Shift+ в Windows и Linux, а закрытие — Ctrl+Alt+Esc). Клик по карточке
не забирает клавиатуру у страницы, которую вы записываете, а пока вы не нажали
три клавиши, они написаны словами. Наведение, ⋯ карточки или удержание
модификатора раскрывают её целиком — все способы найти элемент, все проверки,
которые предлагает экран, и выходы. Card beside clicks в меню ⋯
выключает карточку совсем; у записи через зеркало карточки нет — ей не рядом с
чем стоять.
Имя, под которым сохраняется секрет, берётся из подписи поля (Your password →
YOUR_PASSWORD, запасной вариант — PASSWORD), а занятое имя получает суффикс,
а не перезаписывается. Шаг становится inputText: ${NAME}, а само значение не
попадает ни в список шагов, ни в лог, ни в файл сценария.
Check в шапке взводит следующий клик как проверку. Нажмите — кнопка
подсвечивается, а строка под шапкой читается Click what should be on the
screen — и кликните по тому, что должно быть на экране: проверка записана, а
страница этого клика не видела — и в браузере, и в VS Code. Дальше кнопка
разоружается сама. Alt-клик (Option на macOS) по-прежнему делает то же без
кнопки.
Пункт Check the page address в меню ⋯ (только веб) записывает проверку,
что страница на том адресе, на котором она сейчас. Если этот адрес лежит под
Staging-адресом проекта, он пишется через плейсхолдер — ${STAGING_URL}/cart, —
и переезд staging его не ломает; адрес вне staging пишется буквально.
Клики внутри собственной панели расширения (vscode-webview://) тоже
записываются — включая панели, открытые уже во время записи, и те, что
перезаписывают собственный документ.
Мобилка — зеркало устройства
Заголовок раздела «Мобилка — зеркало устройства»Android и iOS записываются через зеркало устройства: клик → tapOn,
перетаскивание → swipe, удержание → long-press, набор на клавиатуре →
inputText, колесо → скролл. Back записывает шаг pressKey: back и есть
только на Android, где такая клавиша существует. Раскрывающееся Type into the
focused field… с кнопками Type и Clear (записывает clearText) — для
значений, которые долго набирать. Там, где элемент не распознан, всё равно можно
кликнуть куда угодно — тап запишется по координатам.
Переключатель Tap / Check превращает клик из тапа в проверку — на зеркале
это настоящий режим, в котором вы остаётесь, а не один взведённый клик: в режиме
Check клик записывает assertVisible и тут же выполняет его на живом экране,
так что проверка, которая упала бы на повторе, падает прямо при вас.
Чип Fresh email заполняет сфокусированное поле адресом qa+…@example.com и
держит его в переменной EMAIL, чтобы поле подтверждения взяло тот же самый, —
второй клик даёт тот же адрес, а не новый. В env: сценария уходит выражение
qa+${Date.now()}@example.com, которое движок вычисляет один раз за
прогон: свежее на каждый прогон, одинаковое
во всех его шагах.
Шаги по мере записи
Заголовок раздела «Шаги по мере записи»Записанный шаг читается фразой — словами, которыми говорит тестировщик, а не селекторами: Click button “Pay”, Type “demo@acme.test” into “Email”, Type into “Password” с 🔒 рядом, Check “Paid” is shown, Open the staging address. Имя — самое человеческое из тех, что шаг уже несёт: подпись, затем текст, затем роль с именем, placeholder, test id. Селектор в файле не меняется — меняется только то, как шаг читается.
Один ⚠ отмечает шаг, на который стоит взглянуть ещё раз, и только при настоящем риске: на имя отзывается несколько элементов (6 buttons say “Pay” — the step takes the 2nd), элемент не нашёлся заново, когда страница успокоилась (Not found again once the page settled — check this step), или он адресован по позиции (Found by position — may break when the layout moves). Причина — по наведению. Наведение на саму строку достаёт 🗑 и ⋯; в ⋯ — Details, Other ways to find it (N), Make it a variable… (Rename or remove ${NAME}, когда она уже переменная), Add a check after this step… и keep literal там, где запись сама подставила переменную. В конце списка + a step добавляет шаг руками — то же меню, что и в шапке.
Окно записи — журнал, а не редактор: каждый шаг фразой, ⚠ только там, где есть настоящий риск, и Undo прямо там, где шаг удалили.
Удаление оставляет призрак. Удалённый шаг остаётся на своём месте
зачёркнутым, рядом с ним Step 7 deleted · Undo, а следующие шаги
перенумеровываются сразу. Призрак стоит десять секунд или до следующего шага;
⌘Z делает то же. Отзыв шага из карточки идёт тем же путём и называет, что ушло
вместе с ним.
То, за чем запись не смогла пойти, — новая вкладка, загрузка файла — сказано серой строкой в журнале на своём месте по времени, а не баннером поверх всей записи. Отказ самого драйвера по-прежнему красный баннер сверху.
Скролл. Скролл, который вы делаете сами, замечается, чем бы вы его ни
делали — колесо, полоса прокрутки, палец, стрелки, — а скролл, который страница
делает сама, не замечается. Что из него выйдет, решает то, что вы сделаете
дальше. Проскроллили, чтобы дотянуться, и кликнули — не запишется ничего: при
повторе каждое действие само подводит свою цель в поле зрения, так что сценарий
не зависит от того, где стояла страница. Окно так и говорит, чтобы вы не искали
шаг, которого нет, — Прокрутили вниз, чтобы дотянуться — прогон прокрутит
сам. Проскроллили, и после этого ничего — вы читали, — и запись предлагает шаг:
в браузере и в VS Code на карточке, под зеркалом — полосой предложений; принятое
предложение пишет scroll, по половине
окна за раз. Скролл внутри блока, который прокручивается сам — список
результатов, боковая панель, — называет этот блок: у шага появляется within:,
и прогон двигает тот же блок, а не середину окна. Вбок — это
swipe.
Клик, на который на экране ничего не отозвалось, записывается координатой, и строка несёт ⚠, который так и говорит — Found by position — may break when the layout moves. Это единственный случай, когда скролл перед ним всё-таки выписывается: координата не едет вместе со страницей, поэтому шагу нужно, чтобы страницу вернули туда, где она была.
Шаг — не всегда клик. Enter и аккорд, под который у карточки нет своей
клавиши — Ctrl+Shift+P, — пишутся как
pressKey, следом за тем, что вы
только что набрали. Задержка, от которой открылось меню, пишется как
hover — перед кликом внутри того, что
открылось; задержка, от которой не открылось ничего, шагом не становится.
Выбор в нативном списке — это
selectOption: клик, поднявший
список, был собственным окном браузера, и прогону там не за что взяться. Файл,
отданный загрузчику, — это
uploadFile, названный через css,
если страница прячет тот input, куда уходят файлы (у стилизованного загрузчика
так и есть). Перетаскивание — это
dragAndDrop с тем путём, которым
на самом деле шёл указатель, чтобы список, считающий движения между концами,
их получил; оба конца должны быть элементами, и о перетаскивании, концы
которого никто не называет, окно говорит вместо того, чтобы его записать.
Сказано, а не записано. Ссылка, открывающая новую вкладку, шагом не
становится — вторая вкладка собственная у браузера, вне той страницы, которую
ведёт этот сценарий, — и журнал говорит об этом на её месте. Допишите openLink
руками или запишите ту вкладку отдельным сценарием.
Переключатели и чекбоксы пишутся как check / uncheck, а не tapOn, и
глагол берётся из состояния, которое застало нажатие, а не из того, которое
оставил клик: вслепую тап переворачивает то, во что попал, а check сначала
читает состояние и ничего не делает, если галочка уже стоит. Радиокнопка —
всегда check. Контрол, который вообще не сообщает состояния, остаётся
tapOn.
Контрол, который никто не назвал — тот самый переключатель без подписи —
адресуется подписью рядом с ним, реляционным селектором: { role: switch, leftOf: "Published" }. Сторона — это сторона контрола, а не подписи; сначала
берётся подпись из собственной строки контрола, потом та, что стоит над его
колонкой, и только затем ближайший текст выше. Если одна подпись достаёт до
нескольких контролов, шаг закрепляется через index:, отсчитанный от подписи,
карточка говорит, какой именно взят, а остальные предлагает вариантами.
Кнопка без единого слова — иконка корзины в конце строки — всё равно
записывается как кнопка: рекордер смотрит, что ответило на клик (собственный
onclick элемента, обработчик React или Vue, слушатель, о котором знает
браузер, или курсор-указатель под ним), и дальше называет её меткой, подписью
из её же строки или той картинкой, которую она рисует — { css: "[data-icon=\"trash\"]" },
с index:, если одинаковая иконка стоит в двух строках. Details в ⋯
строки говорит, что именно его назвало, а координата остаётся только для клика,
на который ничего не ответило.
Журнал — не редактор: перетаскиванием переставить, удалить, в конце добавить шаг
руками, а всё остальное ждёт файла. У шага Type с обычным текстом есть Make
it a variable… в ⋯ строки: значение уходит в env: теста под предложенным
именем, а шаг переписывается на ${NAME}.
Save, имя, Enter — тест появляется в рельсе Tests как .flow.yaml и
открывается в редакторе, а Run предлагается тостом.
Первый прогон теста открывает диалог Run; дальше Run повторяет тот же выбор на таргете из строки состояния, ничего не спрашивая. Run on… открывает диалог всегда. Если таргет, на котором тест шёл прошлый раз, не поднят, диалог открывается с невыбранной строкой, и Run неактивен, пока вы не выберете, — молча ничего не подставляется.
Диалог перечисляет устройства на этой машине — браузеры, Android-устройства
и эмуляторы, симуляторы iOS и Desktop app (:port), когда поднято приложение
с мостом tapstep (см. Тестирование десктоп-приложений).
Список сужен до целевых платформ проекта. Проекты VS Code вместо этого выбирают
testspace, а Launch сначала открывает окно VS Code — и прогоны с
записями цепляются к этому окну, а не открывают второе: именно поэтому
vscodeCommand по id продолжает отвечать через то вспомогательное
расширение, с которым окно запускали. У testspace может
быть включён Start clean — подготовка, которая закрывает редакторы, панели
и уведомления, оставшиеся от прошлого прогона, чтобы тест не стартовал там, где
окно случайно оказалось; это пресет before: clean, и выключают его, когда для
этого testspace нужна своя подготовка. Хуки на Extensions принадлежат
самому testspace; то, что вокруг каждого теста выполняет весь проект, лежит
в Settings → Project → Hooks и помечено from project в
редакторе.
Опции: Show the browser window, пресеты Browser size (1280×800 по умолчанию, Laptop, Full HD, Tablet, Phone), Record video и — для браузеров — Video quality: Actual size или Sharp · 2× (для демо). Выбор запоминается.
Видео прогона (Record video, Actual size) — то, что ложится рядом со сценарием как <flow>.mp4.
Variables внизу: окружение, в котором прогон разрешает переменные (или
Shared only), и свободные строки NAME / value, которые его переопределяют;
запоминается по каждому тесту. API-сценарии (device: none) пропускают список
устройств и показывают только эту секцию — и устройство у них не спрашивают
вовсе.
Прогон идёт в собственной вкладке теста: экран, зеленеющие шаги и 0:03 · Cancel в углу. Run output, Network (по выбранному шагу или All) и
Console стримятся в нижнюю панель и остаются там после прогона, так что
читать их можно из любой вкладки. Второй Run, пока идёт первый, отклоняется, а
не отменяет предыдущий молча: тост говорит Login is running — stop it first, а
кнопка Show ведёт к нему. Закрытие вкладки сначала спрашивает Stop the
run?.
После каждого прогона отчёт записывается в проект как reports/<flow>.html —
report: в config.yaml переопределяет формат (html / junit / json) и
директорию.
Зелёный прогон — в той же вкладке, из которой был запущен, а вывод и трафик держит панель.
Зелёный прогон заканчивается вердиктом и видео в той же вкладке. Красный предлагает See what broke, и вкладка становится разбором этого падения.
Runs, разбор, история
Заголовок раздела «Runs, разбор, история»- Runs — лента в сайдбаре, сгруппированная как Failing now, Suite runs и All runs (набор = все тесты с тегом, запускается из рельса Tests). Строка набора открывает его HTML-отчёт вкладкой и предлагает Export Allure; строка одиночного прогона — Export JUnit. Клик по прогону открывает его в собственной вкладке теста, а прогон постарше — или прогон теста, чья вкладка занята записью или прогоном, — открывается рядом, так что два результата видны бок о бок.
- Разбор — скриншот падения или записанное видео, список шагов с телами общих шагов и итерациями repeat, вложенными под свой шаг, Network и Console в панели с меткой на упавшем шаге и кнопки Open test, Fix with AI, Re-run, а также Show it again from here, когда упавший шаг можно перезаписать на месте — см. ниже.
- History — из поповера Account; открывается вкладкой: версии → изменённые файлы → diff.
Open test на прогоне, чей файл исчез, больше не делает ничего: он сначала пересканирует, потом говорит Test not found и называет путь, который переименовали, перенесли или удалили после того прогона, и предлагает Show the folder — ближайшую папку того старого пути, которая в проекте ещё есть.
Разбор упавшего прогона — Show it again from here как главное действие, Re-run рядом.
Починка с места падения
Заголовок раздела «Починка с места падения»Когда тест упал на шаге N, разбор предлагает Show it again from here вместо
того, чтобы записывать всё заново. Это главное действие на экране; Re-run
отходит рядом на второй план.
Сначала — лист подтверждения, потому что шаги до падения сейчас выполнятся по-настоящему: Show step N again называет, сколько их прогонится, на каком устройстве и с какими переменными (и то и другое там же меняется), и прямым текстом предупреждает, что шаги 1–N−1 выполняются на цели по-настоящему: если один из них оформляет заказ или отправляет письмо, это случится снова. Если упал первый шаг, вместо этого написано, что до него ничего не выполняется — цель просто откроется. Устройство берётся то, на котором упал прогон: повтор шагов на другом — уже не тот тест.
Лист перед починкой: что переиграется, где, и предупреждение, что эти шаги выполнятся по-настоящему.
Подтвердите — и починка идёт в той же вкладке: tapstep доводит цель до шага
N и передаёт её вам на зеркале устройства под заголовком Fixing
flows/pay.flow.yaml · step 7, с переключателем Do / Check и хотспотами
экрана. Собственные шаги файла обрамляют заменяемый — те, что до него, сверху,
остальные снизу, — так что показать надо только один шаг. Save кладёт в тот
же файл только этот шаг, оставляя все прочие шаги, ключи и комментарии на месте;
Delete this step from the test вместо этого его удаляет. Перед сохранением
снимается версия всего проекта, так что правка всегда в одном шаге git от
отката. Когда шаг лёг, тост говорит Step 7 replaced и даёт кнопку Re-run:
сама починка не прогон. Cancel или Esc возвращают к результату, а крестик
вкладки сначала спрашивает Cancel the repair?.
Показ шага 7 заново — шаги файла обрамляют заменяемый; новый встаёт на его место.
Прогон VS Code тоже можно показать заново: лист выбирает testspace (по умолчанию тот, в котором шёл прогон), переигровка открывает то самое окно с его расширениями и папкой, и шаг вы показываете в настоящем редакторе, а не в зеркале. Веб-починка пока идёт через зеркало: запись в собственном окне браузера к починке ещё не подключена.
Хуки before: сценария переигрываются перед шагами, так что и шаг 1 чинится в
том состоянии, в которое его приводит прогон.
Он отказывает, а не работает наполовину. Если цель, на которой шёл
прогон, не поднята, вас попросят поднять её, а не переигрывать на чём-то другом.
А когда шаг не из тех, что можно заменить в одиночку, кнопки просто нет — вместо
неё строка с причиной, потому что исчезнувшая кнопка без слов рядом читается как
сломанная. Падение случилось в setup, а не в шаге — значит, чинить сначала шаг
setup. Либо цель прогона вообще нельзя вести заново — платформа, которую
приложение не открывает повторно, или её отсутствие. Либо заблокирован сам шаг:
он пришёл из общих шагов (откройте тот файл), он внутри блока repeat /
retry / runFlow или условного, он принадлежит before / after, сценарий
не ведёт устройство (device: none), не хватило переменной или параметра,
прогон не сохранил отчёта о своих шагах, прогон не дошёл ни до одного шага или
файл изменился после прогона и шаг N теперь другой.
Если файл поменяется, пока починка открыта, сохранение отклоняется целиком — ничего не пишется, — вместо замены не того шага.
Редактор
Заголовок раздела «Редактор»Steps ⇄ YAML: два вида одного файла; источник истины — YAML, комментарии и
форматирование переживают правки в Steps. Вид Steps — три зоны: Before
(выполняется до шага 1 — ошибка здесь пропускает шаги), Steps
(нумерованные) и After (выполняется всегда после последнего шага, что бы
ни случилось); в файле это before: / after: (прежние имена onFlowStart /
onFlowComplete всё ещё работают). Строки, которые дают проект или testspace,
помечены from project / from testspace <имя> и читаются выше и ниже
собственных строк сценария; переключатель Inherit, выключенный, — это
inheritHooks: false. Зона, стоящая на пресете (before: clean), так и
говорит и предлагает Expand into steps вместо добавления строки. Пошаговые
скриншоты последнего прогона видны прямо в списке.
Вид Steps записанного входа — тот же файл, что показывает вкладка YAML.
Что ищет шаг — один контрол вверху его формы: text, #id, regex,
⌖ point или role; в режиме role рядом встают собственный список ролей
движка и поле для имени элемента — именно так рекордер пишет кнопку.
+ Condition добавляет любой другой ключ селектора, который публикует
движок, — testId, label, placeholder, css, index:, enabled:,
above / below / leftOf / rightOf и прочие, — в том порядке, в каком
движок ранжирует локаторы. Ключи, которые только сужают совпадение, —
index:, of:, enabled:, checked:, focused:, selected:,
tolerance: — ждут, пока селектор скажет, что он ищет: сами по себе они дают
селектор, который движок не примет. Прицел рядом выбирает элемент прямо с экрана; экран для чтения у него
есть только при живой записи, поэтому без неё он говорит Start a recording to
pick from the screen и предлагает рядом Record….
${ автодополняет переменные сценария в YAML-редакторе и в полях шагов;
неопределённые ссылки ${NAME} подсвечиваются. Панель Variables над шагами
перечисляет каждое имя, которое видит сценарий, его значение и источник — default
(params:), flow, config, .env, runtime (с шагом-источником) — и позволяет
задать неопределённую переменную в .env прямо на месте.
Общие шаги: + → Blank shared steps; в меню строки теста есть Convert to
shared steps / Convert to test; заголовок редактора такого файла говорит
Shared steps — used by N tests. Шаг Include flow (runFlow) имеет пикер
(сначала общие шаги, + New shared steps…) и форму для объявленных params:
цели. Блоки repeat / retry вкладывают свои шаги.
Экспорты
Заголовок раздела «Экспорты»Тест может уйти чужим тестом. В меню строки теста — и в чате — есть
Export: Playwright (*.spec.ts) для чего угодно и ExTester
(*.test.ts) только там, где у теста есть заголовок vscode:. Массовый
экспорт берёт те сценарии, которые выбранный вид умеет унести, и говорит,
мимо скольких прошёл.
Куда лягут файлы — настройка проекта, а не вопрос на каждый экспорт: в
Settings → Project → Exports по папке на каждый вид. Относительный путь
едет вместе с проектом, и вся команда экспортирует в одно место; абсолютный —
только ваш, и именно так работает QA-сюита в своём репозитории. Пусто означает
playwright/ и extester/ внутри проекта. Первый экспорт каждого вида
спрашивает один раз — Playwright tests land in playwright/ — Export? — и
рядом стоит Change….
На Home одна секция Exports, по блоку на папку: сколько спеков в ней лежит, когда экспортировали в последний раз, Re-export all, Reveal, Open in VS Code — и чип статуса у каждого файла: exported (спек — это то, что говорит тест), stale (тест с тех пор изменился), edited (спек правили руками, и повторный экспорт эту правку потеряет) или not from a test (нет заголовка tapstep). У папки внутри проекта есть ещё переключатель Track in git; папка в другом репозитории так и говорит и оставляет это решение там.
Про перезапись спрашивают, и вопрос разделяет два случая: спеки, которые это приложение экспортировало раньше, и спеки, которые кто-то правил руками.
Вкладка ✨ AI chat нижней панели — агент, который видит устройство и воркспейс: записывает шаги, пишет и правит сценарии, запускает их и чинит селекторы. Провайдеры, в меню ⋯ чата: Anthropic API key, OpenAI-compatible (Ollama, LM Studio, OpenAI…), Claude Code, Codex, Gemini CLI, OpenCode. Переключатели: Fast (урезанное размышление) и Draft / Verified (Verified обязан дойти до зелёного прогона, прежде чем завершить ход). Летящий ход можно подруливать, набирая текст; вложения и история чата хранятся по проекту.
Чат — одна лента: шаги агента стоят прямо в переписке, там, где случились, а не в отдельном экране, и один переключатель Details открывает или закрывает вход и результат всех шагов сразу. Строка состояния под лентой называет фазу — Thinking, Working (и над чем именно) или Verifying, — а любой ход заканчивается done, чем бы он ни кончился. Если титульная строка стоит на окружении, отличном от дефолтного для проекта, чат об этом предупреждает: его собственные прогоны идут в дефолтное.
Когда агенту нужен настоящий креденшел, он открывает диалог вместо вопроса в
переписке — значение ложится в .env проекта, сценарий ссылается на ${NAME},
модель значения не видит. Settings → AI включает Privacy masking
(модель на устройстве маскирует имена, email, телефоны и секреты до того, как
запрос покинет машину), открывает MCP server для Claude Code, Cursor и др. и
устанавливает Agent skill. Подробнее: AI-агенты.
Save version и Publish
Заголовок раздела «Save version и Publish»Save version = локальная контрольная точка с комментарием; работает офлайн.
Как только подключён git-remote, та же кнопка становится Publish to team и
стоит в заголовке окна; до этого путь внутрь — Account → Share with the
team… или Settings → Project → Git remote. Подключите любой remote —
https://… или git@…: SSH использует ваши ключи / ssh-agent, HTTPS —
credential helper git этого компьютера; токен нужен только на машине, где git не
настроен (он хранится в keychain ОС). Локальные операции (init, commit, история,
clone) встроены в приложение; fetch и push идут через системный git, так что
для Publish git должен быть установлен.
Ветки: переключатель в заголовке окна с New branch… (личная ветка
user/<you> держит правки вне main до публикации). Перед публикацией
приложение сканирует коммитимые файлы (config.yaml, env: сценариев) на
значения, похожие на креденшелы, и просит перенести их в .env, оставив
плейсхолдеры — есть и Publish anyway. Конфликты решаются целым файлом, без
merge-маркеров: Keep mine / Take {Name}’s / Compare.
Устройства
Заголовок раздела «Устройства»Сайдбар Devices — короткая версия: устройства этой машины, клик делает одно
из них таргетом, Boot поднимает эмулятор или симулятор, который ещё не
поднят, и кнопка обновления. Manage… открывает полный экран вкладкой —
графический tapstep doctor: обнаружить → починить. Locate existing… /
Install SDK… для Android, Install · ~170 MB для managed Chromium
(зафиксированная сборка, та же, что в CI), Boot для эмуляторов и
симуляторов. Stop в строке эмулятора выполняет adb emu kill — и заодно
убирает зомби-экземпляр без окна. Список пересканируется всякий раз, когда окно
получает фокус.
Settings
Заголовок раздела «Settings»Settings открывается вкладкой, со своими разделами сбоку:
- General — Language & updates: Language (System / English / Русский; System следует за компьютером, переключение не требует перезапуска), обновления (Check for updates), Report a problem (собирает логи приложения и информацию о версии в zip; изучите локально или отправьте — вы получите id отчёта, а строка покажет его статус), Anonymous statistics.
- Appearance — вид на этой машине, четырьмя группами (ниже).
- AI — провайдер чата, privacy masking, MCP server, agent skill.
- Project — Staging-адрес, целевые платформы, git-remote, переменные,
Hooks проекта (его собственные
before:/after:), матрица Environments, папки Exports. - Storage — что tapstep хранит на этой машине (история прогонов, зоны testspace, временные остатки) с кнопками Clear.
- Legal — лицензия, условия, политика конфиденциальности, уведомления о сторонних компонентах.
Внешний вид
Заголовок раздела «Внешний вид»Всё здесь — про машину, а не про проект, и каждая правка применяется сразу: перезапуска не ждёт ничего.
- Interface — Theme (System / Light / Dark; System следует за
компьютером), Interface scale (80–150 %, шаг 10; двигают
⌘=/⌘−/⌘0и меню View), Density (Comfortable / Compact — насколько плотно стоят строки в рельсах и списках) и Reduce motion (Off / On / System, где System смотрит наprefers-reduced-motion). - Editor font — им набраны редакторы, терминал и панели: Family (JetBrains Mono, SF Mono, Menlo, Fira Code, Cascadia Code или имя, набранное руками; шрифт, которого на этом компьютере нет, откатывается к умолчательному), Size (11–20 px), Line height (1.2–2) и Ligatures.
- Tests panel — как читается список тестов: Names, Shared steps, Sort и что строки Show — см. Панель тестов.
- Editor — Word wrap, Line numbers, Highlight the current line и Autosave delay (200–2000 мс: сколько правка ждёт, прежде чем файл будет записан).
Reset appearance возвращает тему, масштаб, шрифт, настройки редактора, плотность, настройку движения и собственные настройки панели тестов к свежей установке. Больше про окно ничего не меняется: открытые вкладки и размеры панелей — это Reset the interface в Storage, другая кнопка.
Сообщить о баге
Заголовок раздела «Сообщить о баге»Report a bug в титульной строке открывает форму — после входа: issue несёт ваше имя, чтобы к вам можно было вернуться, и анонимно оттуда не уходит ничего. Заголовок, серьёзность (low / medium / high) и три необязательных поля: What I did, What I expected, What happened — заполнить надо хотя бы одно. Можно приложить скриншот (Retake переснимает его) и логи приложения; логи маскируются, если установлена локальная privacy-модель, и чекбокс прямо говорит, когда они не маскированы.
Ваши issue перечислены под формой со статусом — new, seen, fixed (с версией, в которой починили) или closed, — а на кнопке висит бейдж, пока хоть один открыт. Офлайн показывается последний виденный список, и об этом сказано. Это подписанный, отслеживаемый путь; Settings → General → Report a problem — второй, он отправляет логи анонимно и issue не заводит.
Обновления
Заголовок раздела «Обновления»Обновления скачиваются в фоне. Статус-бар показывает
Downloading v{X} · N%, затем чип v{X} ready · Relaunch — один клик
устанавливает его.
Тестирование десктоп-приложений
Заголовок раздела «Тестирование десктоп-приложений»Tauri/webview-приложение с мостом tapstep появляется в диалоге Run как
Desktop app (:port), с кнопкой Launch app, когда config.yaml
объявляет, как его запускать — см.
Тестирование десктоп-приложений.