Перейти к содержимому

Что нового

0.13.4 — 11 сентября 2026, CLI и десктоп-приложение, выпущены вместе.

Обновите все машины команды — и на этот раз старая сборка скажет об этом сама. Записанный здесь сценарий может нести or:, of: и scroll … within: — ключи, которых движок до 0.13.4 не видел, — а незнакомый ключ он называет и отвергает, а не читает мимо. Такой сценарий на старой сборке остановится, а не тихо отработает ослабленную версию себя.

  • Шаг, который на что-то нажимает, имеет в виду контрол, а не подпись. Голое имя в tapOn, doubleTapOn, longPressOn, hover, check/uncheck, selectOption, uploadFile, dragAndDrop или scrollUntilVisible разрешается в элементы, на которые можно нажать, и больше не в подпись с теми же словами, — поэтому сценарий, который опирался на нажатие подписи по имени, теперь нажмёт контрол рядом с ней. Если имени не отвечает ни один контрол, слово нажимается как прежде, а строка несёт пометку matched only text, nothing to press; index: выключает правило; а шаги, которые читают слово (copyText) или доказывают, что оно на экране (assertVisible, waitForVisible, assertNotVisible, условие when:), совпадают со всеми элементами, как и раньше. Контрол, который носит своё имя на обёрнутом элементе, — по-прежнему контрол. Подробнее: Селекторы.
  • Хелпер называется общими шагами. Ничто, что человек читает в десктоп-приложении, больше не называет файл *.helper.yaml хелпером: меню, строки, тосты и README, который получает новый проект, говорят Shared steps. Расширение файла и собственный helper движка не изменились.
  • Переключателя «View as files» в панели тестов больше нет. Одна панель, одна модель: тесты и общие шаги в тех папках, в которых они лежат. Машина, где переключатель был включён, продолжает показывать имена файлов — один раз перенесённая в Settings → Appearance → Tests panel → Names, предпочтение об этом одном списке, а не второй вид.
  • Прогон ждёт страницу, прежде чем действовать. Экран успокоился, когда об этом говорят четыре признака — загрузка завершена, ничего не в полёте, DOM не шевелится, адрес не меняется, — и отсутствию верят только на успокоившемся экране. Медленный экран читается медленно, а не падает как неуспокоившийся, а собственный timeout: шага поднимает бюджет. Подробнее: Как прогон понимает, что страница успокоилась.
  • Рекордер смотрит на экран ещё раз после каждого шага. Записанный селектор несёт of: — сколько элементов ответило ему на момент записи, — и прогон говорит, когда страница перестала отвечать этим числом. Карточка добавляет то, что нашёл второй взгляд, и не повторяет сказанного шагом.
  • Текст читается дважды. Если на экране никто не отвечает тексту как написано, экран читается второй раз без учёта регистра и со схлопнутыми пробелами, а шаг несёт пометку matched ignoring case/spacing. Шаги, которые ищут отсутствие, читают текст только так, как он написан.
  • Скролл становится шагом, только если он им был. Проскроллили, чтобы дотянуться, и кликнули — не запишется ничего, прогон доскроллит сам. Проскроллили и остановились — окно предлагает scroll; скролл внутри блока, который прокручивается сам, называет этот блок, и у шага появляется within:.
  • Селектор может назвать альтернативы. or: даёт ему до трёх запасных, и читаются они только на успокоившейся странице и только когда основной не совпал ни с чем. Попадание проводит шаг и помечает строку drifted во всех отчётах, а tapstep test --strict-selectors валит прогон, который оперся на запасной. Список шагов показывает запасные имена, а разбор предлагает поставить одно из них первым. Подробнее: Селекторы.
  • Рекордер слышит не только клики. Задержка, открывшая меню, — это hover, выбор в нативном списке — selectOption, файл — uploadFile, названный через css, когда стилизованный загрузчик прячет input, перетаскивание — dragAndDrop с тем путём, которым реально шёл указатель, а pressKey теперь принимает и четыре стрелки.
  • Про ссылку, открывшую новую вкладку, говорят, а не пишут шаг. Окно записи скажет об этом, когда клик, открывший её, состоится: вторая вкладка — собственная вкладка браузера, вне страницы, которой управляет этот сценарий.
  • Кнопка без единого слова записывается всё равно кнопкой. Рекордер спрашивает страницу, что ответило на клик — onclick, обработчик React или Vue, зарегистрированный слушатель, курсор-указатель, — и называет шаг по подписи, по подписи в его строке или по картинке, которую он рисует, с index:, когда одна и та же иконка стоит в двух строках.
  • Панели-webview VS Code пишутся глубже. Фрейм двумя фреймами ниже, кросс-доменный фрейм и webview в боковой панели берутся под наблюдение, переоткрываются после навигации и отпускаются, когда их цель ушла; TAPSTEP_RECORD_LOG — любое значение, кроме 0, — заставляет рекордер сказать, почему во фрейм он не вошёл.
  • Фрейм, появившийся, пока рекордер ещё открывает соседний, не теряется. Наблюдение за фреймом включается один раз — после того, как рекордер уже слушает, — а если браузер включить его отказался, окно скажет об этом, вместо того чтобы тихо перестать слышать этот фрейм.
  • Снапшот v2 для агентов. Одна грамматика, один рендерер, один парсер: ref остаётся при своём элементе от действия к действию, а ушедший ref сам об этом говорит; detail: и around: решают, сколько печатать; первые строки называют страницу и успокоилась ли она, а act отвечает строкой net: про запросы, которые он поднял. Подробнее: Нотация снапшота.
  • Агент пробует один шаг вместо того, чтобы читать экран дважды. try выполняет один шаг сценария на живом экране и отвечает тем, что он сделал, что изменилось, и — когда имени отвечает больше одного элемента — списком кандидатов на выбор; snapshot { detail: "regions" } — тот единственный обзор, с которого он начинает. Подробнее: Как агент ведёт экран теперь.
  • Попробовать один шаг, не запуская сценарий. Шаг request или sql выполняется сам по себе прямо из шага — статус, время, заголовки и тело или строки в таблице, — а клик по ответу пишет в этот же шаг один ключ assert: или extract:. Подробнее: Попробовать шаг.
  • tapstep sql --ping "${DATABASE_URL}" проверяет строку подключения раньше, чем на неё обопрётся сценарий, и называет стадию, на которой не вышло: DNS, connect, auth. Окружение он берёт из того конфига, который ему дали; в десктопе это Check рядом с db шага sql:, а сам db выбирается из переменных, поэтому строка подключения не попадает в YAML.
  • Строки шага sql: сохраняют порядок колонок SELECT, поэтому первая строка читается так, как написан запрос.
  • Упавший request: показывает статус и тело, с которыми вернулся, — в строке прогона, а не одну лишь ошибку.
  • Упавший шаг sql: называет сам запрос, его параметры и слова, которыми отказала база, — в строке сохранённого отчёта и теперь в строке живого прогона тоже. Секреты в параметрах и в ячейках маскируются, широкий результат оставляет 32 колонки, а свидетельство режется до 64 КБ с пометкой, сколько его было; шаг, упавший внутри repeat, retry, runFlow или хука, несёт его там, где это случилось.
  • Набор чисто-API сценариев запускается там, где устройства нет. Когда все сценарии папки говорят device: none, прогон перестаёт искать браузер или эмулятор, а в смешанном наборе сценарий с device: none сам берёт пустой драйвер. assertFile нужна рабочая папка, поэтому под device: none его теперь помечают, а не предлагают.
  • css: называет набор, а ключи рядом с ним его сужают. Любой другой ключ селектора — text, name, role, label, placeholder, признак, отношение, состояние — теперь фильтрует то, что нашёл CSS, ровно так же, как фильтровал бы без css, а index:/of: считают уцелевших. Поэтому { css: ".monaco-editor", text: "hello" } — это редактор, показывающий hello, а набор, из которого не уцелело ничего, — это не найдено, и сообщение называет оба ключа. Подробнее: Селекторы.
  • Экспорт Playwright несёт свой конфиг. Папка, в которой лежит спек VS Code, получает playwright.config.ts с одним воркером, а Electron-спек уносит с собой две временные папки, которые он создаёт.
  • README папки следует за папкой — обновляется, когда его текст устарел, включая написанный прошлым релизом, и никогда не остаётся стоять там, где спеков нет.
  • Отсутствующий testspace — это структура, а не ошибка провода. Десктоп называет testspace, которого просит заголовок vscode: сценария, и предлагает Open Extensions, вместо того чтобы печатать сбой в терминал.
  • Заголовок спека называет свой сценарий от того корня проекта, который дал вызывающий, и десктоп разрешает его той же функцией, которой это делает CLI, — заголовок, написанный одним, читается другим, а заголовок с исчезнувшим сценарием не приписывается чужому тесту.
  • Повторный экспорт не уносит несохранённых нажатий из вкладки спека, а подтверждение называет сценарий, чей спек заменит одноимённый тест.
  • Claude Code, в который никогда не входили, говорит об этом до начала терна. Шапка называет это, а CLI, отвечающий run /login, заканчивает терн этой фразой, а не шестью строками stderr.
  • Терн, от которого 90 секунд ничего не слышно, падает, а не считает время вверх; каждая стадия до того, как заговорит AI CLI, называет себя в чате и в логе; а терн, который паникует, всё равно отвечает.
  • Сообщение, написанное в летящий терн, говорит, прочитал ли его агент или ждёт конца терна.
  • Одна строка расхода на терн, раскрываемая до вызовов за свёрнутыми строками.
  • Импорт берёт спек.spec.ts, .spec.js, .test.ts, .test.js или папку с ними, — карточка обещает только то, что разобралось, а строка проверки называет сценарий, который написал импорт, а не спек, который он прочитал.
  • OpenCode ищется там, где говорит XDG_CONFIG_HOME, а его мост закрывается вместе с приложением, которое его открыло.
  • Чат ведёт экран так же, как агент — один обзор, дальше по одному шагу, а квитанция try читается как текст с экрана, а не как указания, — и об этом говорят и подсказка каждого провайдера, и пустой чат.
  • Вердикт в панели прогона — это фраза, которую написал движок, без проводного обвеса.
  • Починка называет testspace, в котором будет переигрывать, берёт выбранный вами вместо того, что в заголовке сценария, записывает его обратно в заголовок, а на маке вкладка называет Option.
  • Сообщение о баге снимает главное окно и говорит почему, когда не может; а отчёт и баг-репорт больше не пишут поверх архива друг друга.
  • Предложение по вставленному curl переживает набор в нём — первое нажатие после вставки это правка её, а не ответ, — а шаг request: читается как вызов, а не как форма, которой редактор не знает.
  • Карточка рекордера встаёт уже с номером шага, живая подсказка селектора — это один элемент, а не одна подпись, и пикер, хотспот и подсказки пишут $, # и x6 так же, как снапшот.
  • Пикер ролей предлагает собственный словарь движка — с первого момента, а не после того, как приедет схема, — и рекордер называет роль контрола по тому же опубликованному списку.
  • Тест, папку и файл общих шагов можно назвать на любом алфавите. Русское имя становится русским именем файла, а не молча ничем, а имя, которого не вынесет файловая система, — уже занятое или одно из тех, что Windows держит за своими устройствами, — говорит об этом.
  • Удаление отправляет в корзину и десять секунд остаётся отменяемым. Тест, папка и файл общих шагов уходят в системную корзину, а не в никуда, и тост предлагает Вернуть, пока они там.
  • Панель тестов даёт адрес каждому файлу проекта. Строка — это имя, одна точка и слова о том, что это: общие шаги говорят, сколько тестов их использует, исчезнувший файл говорит missing, а в строке есть Copy path. Группу можно создать в любой папке, которую показывает панель, а не только под flows/, и ничто, что читает человек, больше не называет общие шаги helper.
  • У панели тестов есть собственные настройки — в Settings → Appearance → Tests panel: читается ли строка как имя или как имя файла, стоят ли общие шаги в своих папках или одной группой в конце, в каком порядке идут тесты — по имени, по последнему прогону или по свежести записи — и рисуются ли вообще точка прогона, git-пометка и группа Project. Тест, который идёт прямо сейчас, пульсирует и с выключенным Run status.
  • Панель — дерево, по которому ходит клавиатура. Стрелки шагают по нему и открывают папки, Home / End ведут к концам, набранные буквы перепрыгивают, F2 переименовывает, Enter открывает, ⌘Enter запускает. Shift- и -клик выбирают диапазон или ещё одну строку, а выбранное разом удаляется, экспортируется или перетаскивается на папку — перетаскивание нескольких строк несёт призрак с их числом.
  • Селектор шага умеет сказать role и что ещё должно быть верно. Контрол вверху формы предлагает text, #id, regex, ⌖ point и role с полем для имени элемента рядом, а + Condition добавляет любой другой ключ селектора, который публикует движок, в том порядке, в каком движок ранжирует локаторы.
  • Экранный пикер говорит, что ему нужна запись, и предлагает рядом Record…, а не стоит кнопкой, которая ничего не делает.
  • Open test на прогоне, чей файл исчез, говорит об этом — какой путь ушёл и Show the folder, чтобы посмотреть, где он был, — а переименованный или перенесённый тест забирает историю своих прогонов с собой, а не оставляет её на старом пути.
  • Строка на месте Show it again называет причину и для падения в setup, а также говорит, чего она ещё ждёт, вместо мёртвой кнопки Start.
  • Имя ветки следует собственному правилу git для имён ссылок, а не правилу для имён файлов.
  • tapstep schema публикует роли, которые знает движок, под ключом role селектора — справочник и агенты читают один список вместо ручного, который может отстать.
  • tapstep skill install пишет для каждого найденного агента, включая OpenCode — ~/.config/opencode/skills или туда, куда указывает XDG_CONFIG_HOME, — и оба README называют всех агентов. Подробнее: Рабочие области CLI.
  • tapstep test --strict-selectors валит прогон, который оперся на запасной селектор.
  • TAPSTEP_RECORD_LOG заставляет рекордер назвать фреймы, в которые он не вошёл, и почему.
  • TAPSTEP_NO_DEVICES — любое значение, кроме 0, — не даёт определению драйвера обращаться ни к adb, ни к simctl, поэтому прогон, которому устройство не нужно, не зависит от того, что воткнуто в машину; doctor и явно названный драйвер по-прежнему читают её как есть.
  • Запрос, чей конец обогнал начало, больше не остаётся висеть в полёте.
  • Захват полосы прокрутки, чей отпуск потерялся, больше не присваивает себе все последующие скроллы.
  • Блок с overflow прячет только то, что разложено внутри него, поэтому модалка или портал не объявляются ушедшими из виду.
  • Селектор css считается один раз по всей странице, вместе с фреймами.
  • swipe берёт либо направление, либо две точки, и парсер отказывает, когда дают и то и другое.
  • На Linux и Windows bin/code считается установкой VS Code только вместе с самим приложением рядом.
  • Спек, который файловая система пишет заглавными, — всё ещё спек, а путь к спеку, начинающийся с дефиса, всё так же открывается в VS Code.
  • Шаг, который писатель YAML не может записать, больше не роняет рекордер, а упавший шаг находит свою команду через блоки, внутри которых он выполнялся.
  • Чат, открытый с диска, перестаёт обещать терн, который уже отработал, а ширина чата, сохранённая на широком экране, приводится к тому, на котором он открылся.

0.13.3 — CLI и десктоп-приложение, выпущены вместе.

Обновите все машины команды — старые сборки молча пропускают before/after. Сценарий с хуками для старого движка — валидный YAML: он просто игнорирует два ключа и выполняет нумерованные шаги без подготовки и уборки. Зелено и неверно. То же с vscodeCommand, environments: и настройкой exports: — необновлённая машина читает мимо них.

Сценарий теперь может сказать, что выполняется вокруг его шагов:

before:
- launchApp: https://staging.example.com
commands:
- tapOn: "Log in"
- assertVisible: "Welcome"
after:
- takeScreenshot: end

before: идёт перед шагом 1, и ошибка в нём валит сценарий собственным вердиктом (setup failed at B2: …), не выполняя шагов. after: выполняется после последнего шага всегда — после падения, после остановки, — и каждая его строка выполняется, даже если одна из них упала; ошибка уборки попадает в отчёт рядом с вердиктом и не меняет его. В отчётах и в экране прогона десктопа это блоки Setup и Teardown.

В config.yaml могут лежать before: / after: всего проекта, а у testspace VS Code — свои; они оборачивают хуки сценария, внешние входят первыми и выходят последними. inheritHooks: false в сценарии отключает унаследованное. onFlowStart: / onFlowComplete: — старые имена этих ключей, они всё ещё работают.

Подробнее: Файл флоу и селекторы.

vscodeCommand выполняет команду VS Code напрямую — по id через вспомогательное расширение, которое драйвер ставит сам (и которое отвечает, когда команда действительно завершилась), или по title, который показывает палитра. args идут только с id: палитра аргументов не принимает, и просьба совместить их — ошибка, а не молчаливая потеря.

before: clean — строка вместо списка — возвращает окно VS Code в известное состояние перед шагами: закрыть все редакторы, панель, боковую панель, очистить уведомления, убить терминалы. В десктопе это переключатель Start clean у testspace.

Клики внутри собственной панели расширения (vscode-webview://) теперь записываются, включая панели, открытые уже во время записи. А прогон VS Code можно показать заново из разбора — в том testspace, в котором он шёл.

tapstep export playwright теперь переносит разрешённые хуки в test.beforeEach / test.afterEach спека, а сценарий с vscode: уходит самостоятельным Electron-спеком, который запускает установленный VS Code.

tapstep export extester — новая команда: сценарий с vscode: как тест vscode-extension-tester — Mocha и chai поверх Selenium — с README, где лежат команды extest, --code_version, который назвала эта машина, и workspace, который раннер должен открыть. MCP-инструмент — export_extester, а десктоп предлагает этот вид только там, где у теста есть заголовок vscode:.

Куда попадает экспорт — теперь настройка проекта, и её читают одинаково CLI, MCP-инструменты и десктоп:

exports:
playwright: playwright
extester: ../qa-suite/src/ui-test

Относительный путь едет вместе с проектом; абсолютный — только ваш, и именно так работает QA-сюита в своём репозитории. --out по-прежнему сильнее.

Проект может назвать свои цели и держать набор значений на каждую:

defaultEnvironment: staging
environments:
staging: { BASE_URL: https://staging.example.com }
prod: { BASE_URL: https://example.com }

tapstep test flows/ --env-set prod выбирает одно на весь прогон, без флага это делает defaultEnvironment. Вместе с ним подгружается .env.<имя>, так что локальные секреты окружения едут с ним и не попадают в git; выбранное имя — это ${TAPSTEP_ENV}.

Порядок слоёв изменился. Локальный файл теперь бьёт закоммиченный на каждом уровне:

умолчания params: < env: сценария < env: конфига < environments.<текущее> < .env < .env.<текущее> < --env-file < -e

До 0.13.3 .env стоял ниже; если вы рассчитывали, что закоммиченное значение перебьёт локальное, это и есть случай, который стоит перепроверить. tapstep validate предупреждает про ${VAR}, который окружение оставляет открытым, и называет, какое именно; каждый отчёт говорит, против какого окружения шёл прогон; а в десктопе появились переключатель окружения в титульной строке и матрица Environments, которая пишет обычные config.yaml и dotenv-файлы.

Подробнее: config.yaml и Десктоп → Окружения.

Клик по переключателю или чекбоксу пишется как check / uncheck, а не tapOn, и берётся из состояния, которое застало нажатие: вслепую тап переворачивает то, во что попал. Контрол, который никто не назвал, адресуется подписью рядом с ним — реляционным селектором ({ role: switch, leftOf: "Published" }), с index: там, где одна подпись достаёт до нескольких контролов.

Движок читает эти отношения строже, чтобы совпадало: above/below/leftOf/rightOf теперь требуют собственной колонки или строки якоря, а совпадения упорядочены по близости к нему — так что подпись называет контрол рядом с собой, а не всё дальше по странице. Экран, где на линии якоря нет ничего, откатывается к прежнему, более широкому правилу, так что существующие сценарии продолжают разрешаться.

  • Английский и русский, язык берётся у системы, пока вы не выберете свой в Settings → General. Без перезапуска.
  • Settings → Appearance — тема, масштаб интерфейса (⌘= / ⌘− / ⌘0 и меню View), шрифт редактора, что рисуют редакторы, плотность и уменьшение анимации, с одним сбросом.
  • AI-чат — одна лента: шаги стоят там, где случились, один переключатель Details и строка состояния с фазой: Thinking, Working, Verifying. Любой ход заканчивается done. К провайдерам добавился OpenCode.
  • Report a bug в титульной строке: подписанный issue с серьёзностью, скриншотом и замаскированными логами, а свои issue видны списком со статусом.
  • Редактор шагов — три зоны: Before, Steps, After, и унаследованные строки помечены тем, откуда пришли.

Подробнее: Десктоп.