From c41210b0f048418c5a6935a8155e6da13ea52936 Mon Sep 17 00:00:00 2001 From: Nikolaengel Date: Fri, 27 Mar 2026 16:41:59 +0300 Subject: [PATCH 1/7] docs: typescript-esm --- docs/basic-guides/tscript-esm.mdx | 1 + .../current/basic-guides/tscript-esm.mdx | 581 ++++++++++++++++++ 2 files changed, 582 insertions(+) create mode 100644 docs/basic-guides/tscript-esm.mdx create mode 100644 i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/tscript-esm.mdx diff --git a/docs/basic-guides/tscript-esm.mdx b/docs/basic-guides/tscript-esm.mdx new file mode 100644 index 0000000..3e39cbb --- /dev/null +++ b/docs/basic-guides/tscript-esm.mdx @@ -0,0 +1 @@ +# Typescript and ESM \ No newline at end of file diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/tscript-esm.mdx b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/tscript-esm.mdx new file mode 100644 index 0000000..2961c4f --- /dev/null +++ b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/tscript-esm.mdx @@ -0,0 +1,581 @@ +# Typescript и ESM + +## Typescript в Testplane + +Testplane поддерживает TypeScript из коробки — вам не нужно настраивать дополнительные инструменты для транспайлинга. Вы можете писать тесты, конфиги и плагины на TypeScript без предварительной компиляции. + +#### Начало работы + +Установите необходимые зависимости: + +```npm +npm install --save-dev typescript ts-node @types/node +``` + +Создайте `tsconfig.json` в корне проекта: + +```json +{ + "compilerOptions": { + "target": "ES2019", + "module": "commonjs", + "moduleResolution": "node", + "strict": true, + "esModuleInterop": true, + "outDir": "./dist", + "rootDir": "./" + }, + "include": ["**/*.ts"], + "exclude": ["node_modules", "dist"] +} +``` + +Testplane автоматически подхватит TypeScript-файлы через встроенную поддержку ts-node. + +#### Варианты транспайлинга + +По умолчанию Testplane использует `ts-node` для транспайлинга TypeScript. Это наиболее простой способ — никакой дополнительной конфигурации не требуется. + +```bash +npm install --save-dev ts-node +``` + +Testplane автоматически обнаружит `ts-node` и будет использовать его при запуске `.ts`-файлов. + +#### @swc/core + +Если вы хотите ускорить транспайлинг, используйте `@swc/core` вместо `ts-node`. SWC написан на Rust и значительно быстрее при больших объёмах кода. + +```bash +npm install --save-dev @swc/core +``` + +Настройте `.swcrc`: + +```json +{ + "jsc": { + "parser": { + "syntax": "typescript", + "decorators": true + }, + "target": "es2019" + }, + "module": { + "type": "commonjs" + } +} +``` + +В конфиге Testplane укажите транспайлер явно: + +```typescript +// .testplane.conf.ts +export default { + system: { + compilationCache: true + } +}; +``` + +#### esbuild + +Ещё один вариант для ускорения транспайлинга — `esbuild`: + +```bash +npm install --save-dev esbuild esbuild-register +``` + +В конфиге Testplane укажите транспайлер явно: + +```typescript +// .testplane.conf.ts +export default { + system: { + // esbuild подключается через require-хук + } +}; +``` + +#### Сравнение вариантов + +| Транспайлер | Скорость | Проверка типов | Декораторы | +| --- | --- | --- | --- | +| ts‑node | Средняя | ✅ | ✅ | +| @swc/core | Быстрая | ❌ | ✅ | +| esbuild | Быстрая | ❌ | ⚠️ | + +:::warning Важно +@swc/core и esbuild не выполняют проверку типов во время запуска тестов. Для проверки типов используйте отдельную команду `tsc --noEmit`. +::: + + +## Работа с путями в конфиге + +Многие проекты используют алиасы путей в `tsconfig.json`: + +```json +{ + "compilerOptions": { + "baseUrl": ".", + "paths": { + "@components/*": ["src/components/*"], + "@utils/*": ["src/utils/*"], + "@fixtures/*": ["tests/fixtures/*"] + } + } +} +``` + +Однако TypeScript-компилятор умеет резолвить эти пути только во время компиляции. В рантайме `Node.js` не знает об этих алиасах, и вы получите ошибку: + +```bash + Cannot find module '@components/Button'. +``` + +#### Резолв путей в рантайме + +Установите пакет `tsconfig-paths`: + +```bash +npm install --save-dev tsconfig-paths +``` + +#### Через require в конфиге + +Зарегистрируйте tsconfig-paths в конфиге Testplane: + +```typescript +// .testplane.conf.ts +import 'tsconfig-paths/register'; + +export default { + browsers: { + chrome: { + desiredCapabilities: { + browserName: 'chrome' + } + } + } +}; +``` + +#### С помощью NODE_OPTIONS + +```bash +NODE_OPTIONS="-r tsconfig-paths/register" npx testplane +``` + +Или добавьте в `package.json`: + +```json +{ + "scripts": { + "test": "NODE_OPTIONS='-r tsconfig-paths/register' testplane" + } +} +``` + +#### Через .testplane.conf.ts с явным указанием путей + +Если у вас нестандартный `tsconfig.json` или он находится не в корне: + +```typescript +// .testplane.conf.ts +import { register } from 'tsconfig-paths'; +import { loadConfig } from 'tsconfig-paths'; + +const tsConfig = loadConfig('./tsconfig.json'); + +if (tsConfig.resultType === 'success') { + register({ + baseUrl: tsConfig.absoluteBaseUrl, + paths: tsConfig.paths + }); +} + +export default { + // ваш конфиг +}; +``` + +#### Проверка настройки + +После настройки вы можете использовать алиасы в тестах: + +```typescript +// tests/auth.test.ts +import { LoginPage } from '@components/LoginPage'; +import { createUser } from '@utils/factories'; +import { userFixture } from '@fixtures/user'; + +describe('Auth', () => { + it('should login successfully', async ({ browser }) => { + const loginPage = new LoginPage(browser); + await loginPage.open(); + // ... + }); +}); +``` + +## Типизация конфига + +Testplane экспортирует типы для конфигурации, что позволяет получить автодополнение и проверку типов. + +#### Именованный конфиг с типом + +```typescript +// .testplane.conf.ts +import type { ConfigInput } from 'testplane'; + +const config: ConfigInput = { + gridUrl: 'http://localhost:4444/wd/hub', + + baseUrl: 'https://example.com', + + screenshotsDir: 'tests/screenshots', + + browsers: { + 'chrome-desktop': { + desiredCapabilities: { + browserName: 'chrome' + }, + windowSize: '1280x720' + }, + 'firefox-desktop': { + desiredCapabilities: { + browserName: 'firefox' + }, + windowSize: '1280x720' + } + }, + + sets: { + desktop: { + files: ['tests/desktop/**/*.testplane.ts'], + browsers: ['chrome-desktop', 'firefox-desktop'] + } + }, + + plugins: { + 'html-reporter/testplane': { + enabled: true, + path: 'testplane-report' + } + } +}; + +export default config; +``` + +#### Функциональный конфиг + +Если вам нужно использовать условную логику: + +```typescript +// .testplane.conf.ts +import type { ConfigInput } from 'testplane'; + +const isCI = process.env.CI === 'true'; + +export default { + gridUrl: isCI + ? process.env.GRID_URL + : 'http://localhost:4444/wd/hub', + + browsers: { + chrome: { + desiredCapabilities: { + browserName: 'chrome' + }, + retry: isCI ? 2 : 0, + testsPerSession: isCI ? 10 : 1 + } + } +} satisfies ConfigInput; +``` + +:::tip Совет +Используйте `satisfies ConfigInput` вместо явного указания типа, чтобы сохранить точные литеральные типы для последующего использования. +::: + +## Расширение типов команд браузера + +Если вы добавляете собственные команды через `browser.addCommand` или `element.addCommand`, TypeScript не будет знать об этих командах. Вам нужно расширить существующие интерфейсы через декларацию модуля (`Declaration Merging`). + +#### Добавление на уровне browser + +Создайте файл деклараций, например `types/testplane.d.ts`: + +```typescript +// types/testplane.d.ts +declare namespace WebdriverIO { + interface Browser { + /** + * Открывает страницу авторизации и выполняет вход + */ + login(username: string, password: string): Promise; + + /** + * Ожидает появления тостового уведомления + */ + waitForToast(text: string, timeout?: number): Promise; + + /** + * Делает скриншот и сравнивает с эталоном + */ + assertScreenshot(name: string): Promise; + } +} +``` + +#### Добавление команд на уровне element + +```typescript +// types/testplane.d.ts +declare namespace WebdriverIO { + interface Element { + /** + * Скроллит к элементу и кликает по нему + */ + scrollAndClick(): Promise; + + /** + * Проверяет, что элемент находится во вьюпорте + */ + isInViewport(): Promise; + + /** + * Устанавливает значение через React + */ + setReactValue(value: string): Promise; + } +} +``` + +#### Регистрация команд в тестах + +```typescript +// tests/helpers/commands.ts +export function registerCustomCommands(browser: WebdriverIO.Browser): void { + browser.addCommand( + 'login', + async function (this: WebdriverIO.Browser, username: string, password: string) { + await this.url('/login'); + await this.$('#username').setValue(username); + await this.$('#password').setValue(password); + await this.$('[type="submit"]').click(); + await this.waitForUrl('/dashboard'); + } + ); + + browser.addCommand( + 'waitForToast', + async function (this: WebdriverIO.Browser, text: string, timeout = 5000) { + await this.$(`.toast=${text}`).waitForDisplayed({ timeout }); + } + ); +} +``` + +Подключите команды в хуке `before`: + +```typescript +// .testplane.conf.ts +import type { ConfigInput } from 'testplane'; +import { registerCustomCommands } from './tests/helpers/commands'; + +export default { + browsers: { + chrome: { + desiredCapabilities: { browserName: 'chrome' } + } + }, + + prepareBrowser(browser) { + registerCustomCommands(browser); + } +} satisfies ConfigInput; +``` + +#### Использование в тестах + +После настройки TypeScript будет полностью знать о ваших кастомных командах: + +```typescript +// tests/auth.testplane.ts +it('should login and see dashboard', async ({ browser }) => { + // ✅ TypeScript знает об этой команде и её сигнатуре + await browser.login('admin', 'secret'); + + // ✅ Автодополнение работает + await browser.waitForToast('Welcome back!'); +}); +``` + +#### Подключение файла деклараций + +Убедитесь, что TypeScript видит ваш файл деклараций. Добавьте его в `tsconfig.json`: + +```json +{ + "compilerOptions": { + "typeRoots": ["./types", "./node_modules/@types"] + }, + "include": [ + "**/*.ts", + "types/**/*.d.ts" + ] +} +``` + +## Работа с ESM + +Testplane поддерживает ES Modules (ESM). Однако работа с ESM имеет ряд особенностей. + +:::info Примечание +Поддержка ESM в Testplane находится в активной разработке. Рекомендуем использовать CommonJS для продакшн-проектов, если у вас нет явной необходимости в ESM. +::: + +#### Настройка проекта для ESM + +Добавьте `"type": "module"` в `package.json`: + +```json +{ + "type": "module", + "scripts": { + "test": "testplane" + } +} +``` + +Обновите `tsconfig.json`: + +```json +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "bundler", + "esModuleInterop": true + } +} +``` + +#### Конфиг в формате ESM + +```typescript +// .testplane.conf.ts +import type { ConfigInput } from 'testplane'; + +export default { + browsers: { + chrome: { + desiredCapabilities: { + browserName: 'chrome' + } + } + } +} satisfies ConfigInput; +``` + +#### Тесты в формате ESM + +```typescript +// tests/example.testplane.ts +import { expect } from 'chai'; +import type { Browser } from 'webdriverio'; + +// ESM-импорты работают нативно +import { myHelper } from '../helpers/index.js'; // Обратите внимание на расширение .js + +it('should work with ESM', async ({ browser }: { browser: Browser }) => { + await browser.url('https://example.com'); + const title = await browser.getTitle(); + expect(title).to.equal('Example Domain'); +}); +``` + +:::warning Важно +В ESM при импорте TypeScript-файлов используйте расширение `.js`, а не `.ts`. TypeScript резолвит `.js` → `.ts` автоматически согласно спецификации ESM. +::: + +#### tsconfig-paths с ESM + +Для работы алиасов путей в ESM-окружении используйте tsconfig-paths/esm: + +```json +{ + "scripts": { + "test": "node --loader tsconfig-paths/esm --loader ts-node/esm node_modules/.bin/testplane" + } +} +``` + +Или через `NODE_OPTIONS`: + +```bash +NODE_OPTIONS="--loader ts-node/esm --loader tsconfig-paths/esm" npx testplane +``` + +#### Смешанный режим + +Если ваш проект использует `CommonJS`, но вы хотите импортировать отдельные ESM-пакеты, используйте динамические импорты: + +```typescript +// В CommonJS-проекте импорт ESM-пакета +it('should use esm package', async ({ browser }) => { + // Динамический импорт для ESM-only пакетов + const { nanoid } = await import('nanoid'); + const id = nanoid(); + // ... +}); +``` + +#### Полный пример конфигурации + +```typescript +// .testplane.conf.ts +import 'tsconfig-paths/register'; +import type { ConfigInput } from 'testplane'; +import { registerCustomCommands } from './tests/helpers/commands'; + +export default { + gridUrl: process.env.GRID_URL ?? 'http://localhost:4444/wd/hub', + baseUrl: process.env.BASE_URL ?? 'http://localhost:3000', + + screenshotsDir: 'tests/screenshots', + diffColor: '#ff0000', + + browsers: { + 'chrome-desktop': { + desiredCapabilities: { + browserName: 'chrome', + 'goog:chromeOptions': { + args: process.env.CI ? ['--headless', '--no-sandbox'] : [] + } + }, + windowSize: '1280x720', + retry: process.env.CI ? 2 : 0 + } + }, + + sets: { + desktop: { + files: ['tests/**/*.testplane.ts'], + browsers: ['chrome-desktop'] + } + }, + + prepareBrowser(browser) { + registerCustomCommands(browser); + }, + + plugins: { + 'html-reporter/testplane': { + enabled: true + } + } +} satisfies ConfigInput; +``` \ No newline at end of file From 829706c36d29451df854ca70df8ff60a300685ad Mon Sep 17 00:00:00 2001 From: Nikolaengel Date: Fri, 27 Mar 2026 16:43:19 +0300 Subject: [PATCH 2/7] docs: character-fix --- docs/basic-guides/tscript-esm.mdx | 2 +- .../current/basic-guides/tscript-esm.mdx | 504 +++++++++--------- 2 files changed, 250 insertions(+), 256 deletions(-) diff --git a/docs/basic-guides/tscript-esm.mdx b/docs/basic-guides/tscript-esm.mdx index 3e39cbb..efc2b30 100644 --- a/docs/basic-guides/tscript-esm.mdx +++ b/docs/basic-guides/tscript-esm.mdx @@ -1 +1 @@ -# Typescript and ESM \ No newline at end of file +# Typescript and ESM diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/tscript-esm.mdx b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/tscript-esm.mdx index 2961c4f..167c6d5 100644 --- a/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/tscript-esm.mdx +++ b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/tscript-esm.mdx @@ -16,17 +16,17 @@ npm install --save-dev typescript ts-node @types/node ```json { - "compilerOptions": { - "target": "ES2019", - "module": "commonjs", - "moduleResolution": "node", - "strict": true, - "esModuleInterop": true, - "outDir": "./dist", - "rootDir": "./" - }, - "include": ["**/*.ts"], - "exclude": ["node_modules", "dist"] + "compilerOptions": { + "target": "ES2019", + "module": "commonjs", + "moduleResolution": "node", + "strict": true, + "esModuleInterop": true, + "outDir": "./dist", + "rootDir": "./" + }, + "include": ["**/*.ts"], + "exclude": ["node_modules", "dist"] } ``` @@ -54,16 +54,16 @@ npm install --save-dev @swc/core ```json { - "jsc": { - "parser": { - "syntax": "typescript", - "decorators": true + "jsc": { + "parser": { + "syntax": "typescript", + "decorators": true + }, + "target": "es2019" }, - "target": "es2019" - }, - "module": { - "type": "commonjs" - } + "module": { + "type": "commonjs" + } } ``` @@ -72,9 +72,9 @@ npm install --save-dev @swc/core ```typescript // .testplane.conf.ts export default { - system: { - compilationCache: true - } + system: { + compilationCache: true, + }, }; ``` @@ -91,39 +91,38 @@ npm install --save-dev esbuild esbuild-register ```typescript // .testplane.conf.ts export default { - system: { - // esbuild подключается через require-хук - } + system: { + // esbuild подключается через require-хук + }, }; ``` #### Сравнение вариантов | Транспайлер | Скорость | Проверка типов | Декораторы | -| --- | --- | --- | --- | -| ts‑node | Средняя | ✅ | ✅ | -| @swc/core | Быстрая | ❌ | ✅ | -| esbuild | Быстрая | ❌ | ⚠️ | +| ----------- | -------- | -------------- | ---------- | +| ts‑node | Средняя | ✅ | ✅ | +| @swc/core | Быстрая | ❌ | ✅ | +| esbuild | Быстрая | ❌ | ⚠️ | :::warning Важно @swc/core и esbuild не выполняют проверку типов во время запуска тестов. Для проверки типов используйте отдельную команду `tsc --noEmit`. ::: - ## Работа с путями в конфиге Многие проекты используют алиасы путей в `tsconfig.json`: ```json { - "compilerOptions": { - "baseUrl": ".", - "paths": { - "@components/*": ["src/components/*"], - "@utils/*": ["src/utils/*"], - "@fixtures/*": ["tests/fixtures/*"] + "compilerOptions": { + "baseUrl": ".", + "paths": { + "@components/*": ["src/components/*"], + "@utils/*": ["src/utils/*"], + "@fixtures/*": ["tests/fixtures/*"] + } } - } } ``` @@ -147,16 +146,16 @@ npm install --save-dev tsconfig-paths ```typescript // .testplane.conf.ts -import 'tsconfig-paths/register'; +import "tsconfig-paths/register"; export default { - browsers: { - chrome: { - desiredCapabilities: { - browserName: 'chrome' - } - } - } + browsers: { + chrome: { + desiredCapabilities: { + browserName: "chrome", + }, + }, + }, }; ``` @@ -170,9 +169,9 @@ NODE_OPTIONS="-r tsconfig-paths/register" npx testplane ```json { - "scripts": { - "test": "NODE_OPTIONS='-r tsconfig-paths/register' testplane" - } + "scripts": { + "test": "NODE_OPTIONS='-r tsconfig-paths/register' testplane" + } } ``` @@ -182,20 +181,20 @@ NODE_OPTIONS="-r tsconfig-paths/register" npx testplane ```typescript // .testplane.conf.ts -import { register } from 'tsconfig-paths'; -import { loadConfig } from 'tsconfig-paths'; +import { register } from "tsconfig-paths"; +import { loadConfig } from "tsconfig-paths"; -const tsConfig = loadConfig('./tsconfig.json'); +const tsConfig = loadConfig("./tsconfig.json"); -if (tsConfig.resultType === 'success') { - register({ - baseUrl: tsConfig.absoluteBaseUrl, - paths: tsConfig.paths - }); +if (tsConfig.resultType === "success") { + register({ + baseUrl: tsConfig.absoluteBaseUrl, + paths: tsConfig.paths, + }); } export default { - // ваш конфиг + // ваш конфиг }; ``` @@ -205,16 +204,16 @@ export default { ```typescript // tests/auth.test.ts -import { LoginPage } from '@components/LoginPage'; -import { createUser } from '@utils/factories'; -import { userFixture } from '@fixtures/user'; - -describe('Auth', () => { - it('should login successfully', async ({ browser }) => { - const loginPage = new LoginPage(browser); - await loginPage.open(); - // ... - }); +import { LoginPage } from "@components/LoginPage"; +import { createUser } from "@utils/factories"; +import { userFixture } from "@fixtures/user"; + +describe("Auth", () => { + it("should login successfully", async ({ browser }) => { + const loginPage = new LoginPage(browser); + await loginPage.open(); + // ... + }); }); ``` @@ -226,43 +225,43 @@ Testplane экспортирует типы для конфигурации, ч ```typescript // .testplane.conf.ts -import type { ConfigInput } from 'testplane'; +import type { ConfigInput } from "testplane"; const config: ConfigInput = { - gridUrl: 'http://localhost:4444/wd/hub', - - baseUrl: 'https://example.com', - - screenshotsDir: 'tests/screenshots', - - browsers: { - 'chrome-desktop': { - desiredCapabilities: { - browserName: 'chrome' - }, - windowSize: '1280x720' + gridUrl: "http://localhost:4444/wd/hub", + + baseUrl: "https://example.com", + + screenshotsDir: "tests/screenshots", + + browsers: { + "chrome-desktop": { + desiredCapabilities: { + browserName: "chrome", + }, + windowSize: "1280x720", + }, + "firefox-desktop": { + desiredCapabilities: { + browserName: "firefox", + }, + windowSize: "1280x720", + }, }, - 'firefox-desktop': { - desiredCapabilities: { - browserName: 'firefox' - }, - windowSize: '1280x720' - } - }, - sets: { - desktop: { - files: ['tests/desktop/**/*.testplane.ts'], - browsers: ['chrome-desktop', 'firefox-desktop'] - } - }, + sets: { + desktop: { + files: ["tests/desktop/**/*.testplane.ts"], + browsers: ["chrome-desktop", "firefox-desktop"], + }, + }, - plugins: { - 'html-reporter/testplane': { - enabled: true, - path: 'testplane-report' - } - } + plugins: { + "html-reporter/testplane": { + enabled: true, + path: "testplane-report", + }, + }, }; export default config; @@ -274,24 +273,22 @@ export default config; ```typescript // .testplane.conf.ts -import type { ConfigInput } from 'testplane'; +import type { ConfigInput } from "testplane"; -const isCI = process.env.CI === 'true'; +const isCI = process.env.CI === "true"; export default { - gridUrl: isCI - ? process.env.GRID_URL - : 'http://localhost:4444/wd/hub', - - browsers: { - chrome: { - desiredCapabilities: { - browserName: 'chrome' - }, - retry: isCI ? 2 : 0, - testsPerSession: isCI ? 10 : 1 - } - } + gridUrl: isCI ? process.env.GRID_URL : "http://localhost:4444/wd/hub", + + browsers: { + chrome: { + desiredCapabilities: { + browserName: "chrome", + }, + retry: isCI ? 2 : 0, + testsPerSession: isCI ? 10 : 1, + }, + }, } satisfies ConfigInput; ``` @@ -310,22 +307,22 @@ export default { ```typescript // types/testplane.d.ts declare namespace WebdriverIO { - interface Browser { - /** - * Открывает страницу авторизации и выполняет вход - */ - login(username: string, password: string): Promise; - - /** - * Ожидает появления тостового уведомления - */ - waitForToast(text: string, timeout?: number): Promise; - - /** - * Делает скриншот и сравнивает с эталоном - */ - assertScreenshot(name: string): Promise; - } + interface Browser { + /** + * Открывает страницу авторизации и выполняет вход + */ + login(username: string, password: string): Promise; + + /** + * Ожидает появления тостового уведомления + */ + waitForToast(text: string, timeout?: number): Promise; + + /** + * Делает скриншот и сравнивает с эталоном + */ + assertScreenshot(name: string): Promise; + } } ``` @@ -334,22 +331,22 @@ declare namespace WebdriverIO { ```typescript // types/testplane.d.ts declare namespace WebdriverIO { - interface Element { - /** - * Скроллит к элементу и кликает по нему - */ - scrollAndClick(): Promise; - - /** - * Проверяет, что элемент находится во вьюпорте - */ - isInViewport(): Promise; - - /** - * Устанавливает значение через React - */ - setReactValue(value: string): Promise; - } + interface Element { + /** + * Скроллит к элементу и кликает по нему + */ + scrollAndClick(): Promise; + + /** + * Проверяет, что элемент находится во вьюпорте + */ + isInViewport(): Promise; + + /** + * Устанавливает значение через React + */ + setReactValue(value: string): Promise; + } } ``` @@ -358,23 +355,23 @@ declare namespace WebdriverIO { ```typescript // tests/helpers/commands.ts export function registerCustomCommands(browser: WebdriverIO.Browser): void { - browser.addCommand( - 'login', - async function (this: WebdriverIO.Browser, username: string, password: string) { - await this.url('/login'); - await this.$('#username').setValue(username); - await this.$('#password').setValue(password); - await this.$('[type="submit"]').click(); - await this.waitForUrl('/dashboard'); - } - ); - - browser.addCommand( - 'waitForToast', - async function (this: WebdriverIO.Browser, text: string, timeout = 5000) { - await this.$(`.toast=${text}`).waitForDisplayed({ timeout }); - } - ); + browser.addCommand( + "login", + async function (this: WebdriverIO.Browser, username: string, password: string) { + await this.url("/login"); + await this.$("#username").setValue(username); + await this.$("#password").setValue(password); + await this.$('[type="submit"]').click(); + await this.waitForUrl("/dashboard"); + }, + ); + + browser.addCommand( + "waitForToast", + async function (this: WebdriverIO.Browser, text: string, timeout = 5000) { + await this.$(`.toast=${text}`).waitForDisplayed({ timeout }); + }, + ); } ``` @@ -382,19 +379,19 @@ export function registerCustomCommands(browser: WebdriverIO.Browser): void { ```typescript // .testplane.conf.ts -import type { ConfigInput } from 'testplane'; -import { registerCustomCommands } from './tests/helpers/commands'; +import type { ConfigInput } from "testplane"; +import { registerCustomCommands } from "./tests/helpers/commands"; export default { - browsers: { - chrome: { - desiredCapabilities: { browserName: 'chrome' } - } - }, + browsers: { + chrome: { + desiredCapabilities: { browserName: "chrome" }, + }, + }, - prepareBrowser(browser) { - registerCustomCommands(browser); - } + prepareBrowser(browser) { + registerCustomCommands(browser); + }, } satisfies ConfigInput; ``` @@ -404,12 +401,12 @@ export default { ```typescript // tests/auth.testplane.ts -it('should login and see dashboard', async ({ browser }) => { - // ✅ TypeScript знает об этой команде и её сигнатуре - await browser.login('admin', 'secret'); +it("should login and see dashboard", async ({ browser }) => { + // ✅ TypeScript знает об этой команде и её сигнатуре + await browser.login("admin", "secret"); - // ✅ Автодополнение работает - await browser.waitForToast('Welcome back!'); + // ✅ Автодополнение работает + await browser.waitForToast("Welcome back!"); }); ``` @@ -419,13 +416,10 @@ it('should login and see dashboard', async ({ browser }) => { ```json { - "compilerOptions": { - "typeRoots": ["./types", "./node_modules/@types"] - }, - "include": [ - "**/*.ts", - "types/**/*.d.ts" - ] + "compilerOptions": { + "typeRoots": ["./types", "./node_modules/@types"] + }, + "include": ["**/*.ts", "types/**/*.d.ts"] } ``` @@ -443,10 +437,10 @@ Testplane поддерживает ES Modules (ESM). Однако работа ```json { - "type": "module", - "scripts": { - "test": "testplane" - } + "type": "module", + "scripts": { + "test": "testplane" + } } ``` @@ -454,12 +448,12 @@ Testplane поддерживает ES Modules (ESM). Однако работа ```json { - "compilerOptions": { - "target": "ES2022", - "module": "ESNext", - "moduleResolution": "bundler", - "esModuleInterop": true - } + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "bundler", + "esModuleInterop": true + } } ``` @@ -467,16 +461,16 @@ Testplane поддерживает ES Modules (ESM). Однако работа ```typescript // .testplane.conf.ts -import type { ConfigInput } from 'testplane'; +import type { ConfigInput } from "testplane"; export default { - browsers: { - chrome: { - desiredCapabilities: { - browserName: 'chrome' - } - } - } + browsers: { + chrome: { + desiredCapabilities: { + browserName: "chrome", + }, + }, + }, } satisfies ConfigInput; ``` @@ -484,16 +478,16 @@ export default { ```typescript // tests/example.testplane.ts -import { expect } from 'chai'; -import type { Browser } from 'webdriverio'; +import { expect } from "chai"; +import type { Browser } from "webdriverio"; // ESM-импорты работают нативно -import { myHelper } from '../helpers/index.js'; // Обратите внимание на расширение .js +import { myHelper } from "../helpers/index.js"; // Обратите внимание на расширение .js -it('should work with ESM', async ({ browser }: { browser: Browser }) => { - await browser.url('https://example.com'); - const title = await browser.getTitle(); - expect(title).to.equal('Example Domain'); +it("should work with ESM", async ({ browser }: { browser: Browser }) => { + await browser.url("https://example.com"); + const title = await browser.getTitle(); + expect(title).to.equal("Example Domain"); }); ``` @@ -507,9 +501,9 @@ it('should work with ESM', async ({ browser }: { browser: Browser }) => { ```json { - "scripts": { - "test": "node --loader tsconfig-paths/esm --loader ts-node/esm node_modules/.bin/testplane" - } + "scripts": { + "test": "node --loader tsconfig-paths/esm --loader ts-node/esm node_modules/.bin/testplane" + } } ``` @@ -525,11 +519,11 @@ NODE_OPTIONS="--loader ts-node/esm --loader tsconfig-paths/esm" npx testplane ```typescript // В CommonJS-проекте импорт ESM-пакета -it('should use esm package', async ({ browser }) => { - // Динамический импорт для ESM-only пакетов - const { nanoid } = await import('nanoid'); - const id = nanoid(); - // ... +it("should use esm package", async ({ browser }) => { + // Динамический импорт для ESM-only пакетов + const { nanoid } = await import("nanoid"); + const id = nanoid(); + // ... }); ``` @@ -537,45 +531,45 @@ it('should use esm package', async ({ browser }) => { ```typescript // .testplane.conf.ts -import 'tsconfig-paths/register'; -import type { ConfigInput } from 'testplane'; -import { registerCustomCommands } from './tests/helpers/commands'; +import "tsconfig-paths/register"; +import type { ConfigInput } from "testplane"; +import { registerCustomCommands } from "./tests/helpers/commands"; export default { - gridUrl: process.env.GRID_URL ?? 'http://localhost:4444/wd/hub', - baseUrl: process.env.BASE_URL ?? 'http://localhost:3000', - - screenshotsDir: 'tests/screenshots', - diffColor: '#ff0000', - - browsers: { - 'chrome-desktop': { - desiredCapabilities: { - browserName: 'chrome', - 'goog:chromeOptions': { - args: process.env.CI ? ['--headless', '--no-sandbox'] : [] - } - }, - windowSize: '1280x720', - retry: process.env.CI ? 2 : 0 - } - }, + gridUrl: process.env.GRID_URL ?? "http://localhost:4444/wd/hub", + baseUrl: process.env.BASE_URL ?? "http://localhost:3000", + + screenshotsDir: "tests/screenshots", + diffColor: "#ff0000", + + browsers: { + "chrome-desktop": { + desiredCapabilities: { + browserName: "chrome", + "goog:chromeOptions": { + args: process.env.CI ? ["--headless", "--no-sandbox"] : [], + }, + }, + windowSize: "1280x720", + retry: process.env.CI ? 2 : 0, + }, + }, - sets: { - desktop: { - files: ['tests/**/*.testplane.ts'], - browsers: ['chrome-desktop'] - } - }, + sets: { + desktop: { + files: ["tests/**/*.testplane.ts"], + browsers: ["chrome-desktop"], + }, + }, - prepareBrowser(browser) { - registerCustomCommands(browser); - }, + prepareBrowser(browser) { + registerCustomCommands(browser); + }, - plugins: { - 'html-reporter/testplane': { - enabled: true - } - } + plugins: { + "html-reporter/testplane": { + enabled: true, + }, + }, } satisfies ConfigInput; -``` \ No newline at end of file +``` From 76a3393c16ce133ee393efacca2d830e560fcd6f Mon Sep 17 00:00:00 2001 From: Nikolaengel Date: Fri, 27 Mar 2026 16:55:11 +0300 Subject: [PATCH 3/7] docs: character-fix --- .../current/basic-guides/tscript-esm.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/tscript-esm.mdx b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/tscript-esm.mdx index 167c6d5..caec7ce 100644 --- a/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/tscript-esm.mdx +++ b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/tscript-esm.mdx @@ -106,7 +106,7 @@ export default { | esbuild | Быстрая | ❌ | ⚠️ | :::warning Важно -@swc/core и esbuild не выполняют проверку типов во время запуска тестов. Для проверки типов используйте отдельную команду `tsc --noEmit`. +`@swc/core` и `esbuild` не выполняют проверку типов во время запуска тестов. Для проверки типов используйте отдельную команду `tsc --noEmit`. ::: ## Работа с путями в конфиге @@ -428,7 +428,7 @@ it("should login and see dashboard", async ({ browser }) => { Testplane поддерживает ES Modules (ESM). Однако работа с ESM имеет ряд особенностей. :::info Примечание -Поддержка ESM в Testplane находится в активной разработке. Рекомендуем использовать CommonJS для продакшн-проектов, если у вас нет явной необходимости в ESM. +Поддержка ESM в Testplane находится в активной разработке. Рекомендуем использовать `CommonJS` для продакшн-проектов, если у вас нет явной необходимости в ESM. ::: #### Настройка проекта для ESM From 3074cbfdd93fc66c684577ae84e7cf1ed3b9d1dc Mon Sep 17 00:00:00 2001 From: Nikolaengel Date: Tue, 7 Apr 2026 11:28:08 +0300 Subject: [PATCH 4/7] docs: name-fix --- docs/basic-guides/{tscript-esm.mdx => typescript-esm.mdx} | 0 .../current/basic-guides/{tscript-esm.mdx => typescript-esm.mdx} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename docs/basic-guides/{tscript-esm.mdx => typescript-esm.mdx} (100%) rename i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/{tscript-esm.mdx => typescript-esm.mdx} (100%) diff --git a/docs/basic-guides/tscript-esm.mdx b/docs/basic-guides/typescript-esm.mdx similarity index 100% rename from docs/basic-guides/tscript-esm.mdx rename to docs/basic-guides/typescript-esm.mdx diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/tscript-esm.mdx b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/typescript-esm.mdx similarity index 100% rename from i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/tscript-esm.mdx rename to i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/typescript-esm.mdx From be8f010eed40ae5ae1d82656cea13cd9c2547c2d Mon Sep 17 00:00:00 2001 From: Nikolaengel Date: Wed, 8 Apr 2026 17:38:03 +0300 Subject: [PATCH 5/7] docs: typescript-fix --- .../current/basic-guides/typescript-esm.mdx | 533 +++--------------- 1 file changed, 67 insertions(+), 466 deletions(-) diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/typescript-esm.mdx b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/typescript-esm.mdx index caec7ce..0dbca7c 100644 --- a/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/typescript-esm.mdx +++ b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/typescript-esm.mdx @@ -2,114 +2,64 @@ ## Typescript в Testplane -Testplane поддерживает TypeScript из коробки — вам не нужно настраивать дополнительные инструменты для транспайлинга. Вы можете писать тесты, конфиги и плагины на TypeScript без предварительной компиляции. +Testplane поддерживает TypeScript из коробки — вам не нужно настраивать дополнительные инструменты для транспайлинга, вы сразу можете писать тесты: -#### Начало работы - -Установите необходимые зависимости: - -```npm -npm install --save-dev typescript ts-node @types/node -``` - -Создайте `tsconfig.json` в корне проекта: - -```json -{ - "compilerOptions": { - "target": "ES2019", - "module": "commonjs", - "moduleResolution": "node", - "strict": true, - "esModuleInterop": true, - "outDir": "./dist", - "rootDir": "./" - }, - "include": ["**/*.ts"], - "exclude": ["node_modules", "dist"] -} -``` - -Testplane автоматически подхватит TypeScript-файлы через встроенную поддержку ts-node. - -#### Варианты транспайлинга - -По умолчанию Testplane использует `ts-node` для транспайлинга TypeScript. Это наиболее простой способ — никакой дополнительной конфигурации не требуется. - -```bash -npm install --save-dev ts-node -``` - -Testplane автоматически обнаружит `ts-node` и будет использовать его при запуске `.ts`-файлов. - -#### @swc/core - -Если вы хотите ускорить транспайлинг, используйте `@swc/core` вместо `ts-node`. SWC написан на Rust и значительно быстрее при больших объёмах кода. - -```bash -npm install --save-dev @swc/core -``` - -Настройте `.swcrc`: +```typescript +describe("test examples", () => { + it("Открыть главную страницу и проверить заголовок", async ({ browser }) => { + await browser.url("https://testplane.io/"); -```json -{ - "jsc": { - "parser": { - "syntax": "typescript", - "decorators": true - }, - "target": "es2019" - }, - "module": { - "type": "commonjs" - } -} + const title = await browser.getTitle(); + expect(title).toContain("Testplane"); + }); +}); ``` -В конфиге Testplane укажите транспайлер явно: +И указывать `.ts` файлы напрямую в конфиге: ```typescript -// .testplane.conf.ts +// .testplane.config.ts export default { - system: { - compilationCache: true, + sets: { + desktop: { + files: ["tests/**/*.ts"], + }, }, }; ``` -#### esbuild +## Варианты транспайлинга -Ещё один вариант для ускорения транспайлинга — `esbuild`: +Testplane автоматически использует `@swc/core` для транспайлинга, если этот пакет установлен в проекте, в противном случае он задействует `esbuild`, который уже включён в состав Testplane: -```bash -npm install --save-dev esbuild esbuild-register +```typescript +if (envVar && hasSwcCore()) { + // Используем @swc/core +} else { + // Используем esbuild +} ``` -В конфиге Testplane укажите транспайлер явно: +:::warning Важно +Проверку типов необходимо реализовывать отдельно с помощью `tsc` и конфига. +::: + +Если автоматический трайнспайлинг не подходит из-за специфики проекта, чтобы отключить его и настроить самостоятельно, опишите переменную окружения `TS_ENABLE=false` в конфигурационном файле: ```typescript -// .testplane.conf.ts -export default { - system: { - // esbuild подключается через require-хук - }, -}; +//typescript.ts +if (processWithTranspileSymbol[TESTPLANE_TRANSFORM_HOOK] || process.env.TS_ENABLE === "false") { + return; +} ``` -#### Сравнение вариантов +Чтобы передать нужный лоадер при настройке вручную, используйте опцию `--require`, например: -| Транспайлер | Скорость | Проверка типов | Декораторы | -| ----------- | -------- | -------------- | ---------- | -| ts‑node | Средняя | ✅ | ✅ | -| @swc/core | Быстрая | ❌ | ✅ | -| esbuild | Быстрая | ❌ | ⚠️ | - -:::warning Важно -`@swc/core` и `esbuild` не выполняют проверку типов во время запуска тестов. Для проверки типов используйте отдельную команду `tsc --noEmit`. -::: +```bash +-r ts-node/register +``` -## Работа с путями в конфиге +## Работа с алиасами в ипортах Многие проекты используют алиасы путей в `tsconfig.json`: @@ -140,9 +90,13 @@ export default { npm install --save-dev tsconfig-paths ``` -#### Через require в конфиге +Ипользуйте опцию `--require`: -Зарегистрируйте tsconfig-paths в конфиге Testplane: +```bash +npx testplane -r tsconfig-paths/register +``` + +Или опишите `tsconfig-paths` в конфиге Testplane: ```typescript // .testplane.conf.ts @@ -159,417 +113,64 @@ export default { }; ``` -#### С помощью NODE_OPTIONS - -```bash -NODE_OPTIONS="-r tsconfig-paths/register" npx testplane -``` - -Или добавьте в `package.json`: - -```json -{ - "scripts": { - "test": "NODE_OPTIONS='-r tsconfig-paths/register' testplane" - } -} -``` - -#### Через .testplane.conf.ts с явным указанием путей - -Если у вас нестандартный `tsconfig.json` или он находится не в корне: - -```typescript -// .testplane.conf.ts -import { register } from "tsconfig-paths"; -import { loadConfig } from "tsconfig-paths"; - -const tsConfig = loadConfig("./tsconfig.json"); - -if (tsConfig.resultType === "success") { - register({ - baseUrl: tsConfig.absoluteBaseUrl, - paths: tsConfig.paths, - }); -} - -export default { - // ваш конфиг -}; -``` - -#### Проверка настройки - -После настройки вы можете использовать алиасы в тестах: - -```typescript -// tests/auth.test.ts -import { LoginPage } from "@components/LoginPage"; -import { createUser } from "@utils/factories"; -import { userFixture } from "@fixtures/user"; - -describe("Auth", () => { - it("should login successfully", async ({ browser }) => { - const loginPage = new LoginPage(browser); - await loginPage.open(); - // ... - }); -}); -``` +Для более подробного знакомства с `tsconfig-paths` перейдите на [сайт с документацией пакета](https://www.typescriptlang.org/tsconfig/#paths). ## Типизация конфига -Testplane экспортирует типы для конфигурации, что позволяет получить автодополнение и проверку типов. - -#### Именованный конфиг с типом - -```typescript -// .testplane.conf.ts -import type { ConfigInput } from "testplane"; - -const config: ConfigInput = { - gridUrl: "http://localhost:4444/wd/hub", - - baseUrl: "https://example.com", - - screenshotsDir: "tests/screenshots", - - browsers: { - "chrome-desktop": { - desiredCapabilities: { - browserName: "chrome", - }, - windowSize: "1280x720", - }, - "firefox-desktop": { - desiredCapabilities: { - browserName: "firefox", - }, - windowSize: "1280x720", - }, - }, - - sets: { - desktop: { - files: ["tests/desktop/**/*.testplane.ts"], - browsers: ["chrome-desktop", "firefox-desktop"], - }, - }, - - plugins: { - "html-reporter/testplane": { - enabled: true, - path: "testplane-report", - }, - }, -}; - -export default config; -``` - -#### Функциональный конфиг - -Если вам нужно использовать условную логику: +Testplane экспортирует типы для конфигурации, например: ```typescript -// .testplane.conf.ts -import type { ConfigInput } from "testplane"; - -const isCI = process.env.CI === "true"; - export default { - gridUrl: isCI ? process.env.GRID_URL : "http://localhost:4444/wd/hub", - - browsers: { - chrome: { - desiredCapabilities: { - browserName: "chrome", - }, - retry: isCI ? 2 : 0, - testsPerSession: isCI ? 10 : 1, - }, - }, -} satisfies ConfigInput; + // ...конфиг +} satisfies import("testplane").ConfigInput; ``` -:::tip Совет -Используйте `satisfies ConfigInput` вместо явного указания типа, чтобы сохранить точные литеральные типы для последующего использования. -::: +Оператор `satisfies` проверяет совместимость значения с указанным типом при сохранении исходного типа этого значения. ## Расширение типов команд браузера -Если вы добавляете собственные команды через `browser.addCommand` или `element.addCommand`, TypeScript не будет знать об этих командах. Вам нужно расширить существующие интерфейсы через декларацию модуля (`Declaration Merging`). - -#### Добавление на уровне browser - -Создайте файл деклараций, например `types/testplane.d.ts`: +В Testplane имеется поддержка пользовательских команд с Typescript: ```typescript -// types/testplane.d.ts -declare namespace WebdriverIO { - interface Browser { - /** - * Открывает страницу авторизации и выполняет вход - */ - login(username: string, password: string): Promise; - - /** - * Ожидает появления тостового уведомления - */ - waitForToast(text: string, timeout?: number): Promise; - - /** - * Делает скриншот и сравнивает с эталоном - */ - assertScreenshot(name: string): Promise; - } -} -``` +import "webdriverio"; // Может быть любой импорт, не обязательно webdriverio -#### Добавление команд на уровне element - -```typescript -// types/testplane.d.ts -declare namespace WebdriverIO { - interface Element { - /** - * Скроллит к элементу и кликает по нему - */ - scrollAndClick(): Promise; - - /** - * Проверяет, что элемент находится во вьюпорте - */ - isInViewport(): Promise; - - /** - * Устанавливает значение через React - */ - setReactValue(value: string): Promise; +declare global { + declare namespace WebdriverIO { + interface Browser { + customCommand: (arg: any) => Promise; + } } } ``` -#### Регистрация команд в тестах - -```typescript -// tests/helpers/commands.ts -export function registerCustomCommands(browser: WebdriverIO.Browser): void { - browser.addCommand( - "login", - async function (this: WebdriverIO.Browser, username: string, password: string) { - await this.url("/login"); - await this.$("#username").setValue(username); - await this.$("#password").setValue(password); - await this.$('[type="submit"]').click(); - await this.waitForUrl("/dashboard"); - }, - ); - - browser.addCommand( - "waitForToast", - async function (this: WebdriverIO.Browser, text: string, timeout = 5000) { - await this.$(`.toast=${text}`).waitForDisplayed({ timeout }); - }, - ); -} -``` - -Подключите команды в хуке `before`: - -```typescript -// .testplane.conf.ts -import type { ConfigInput } from "testplane"; -import { registerCustomCommands } from "./tests/helpers/commands"; - -export default { - browsers: { - chrome: { - desiredCapabilities: { browserName: "chrome" }, - }, - }, - - prepareBrowser(browser) { - registerCustomCommands(browser); - }, -} satisfies ConfigInput; -``` - -#### Использование в тестах - -После настройки TypeScript будет полностью знать о ваших кастомных командах: - -```typescript -// tests/auth.testplane.ts -it("should login and see dashboard", async ({ browser }) => { - // ✅ TypeScript знает об этой команде и её сигнатуре - await browser.login("admin", "secret"); - - // ✅ Автодополнение работает - await browser.waitForToast("Welcome back!"); -}); -``` - -#### Подключение файла деклараций - -Убедитесь, что TypeScript видит ваш файл деклараций. Добавьте его в `tsconfig.json`: - -```json -{ - "compilerOptions": { - "typeRoots": ["./types", "./node_modules/@types"] - }, - "include": ["**/*.ts", "types/**/*.d.ts"] -} -``` +Подробнее об этом вы можете прочитать в статье про [кастомные команды](https://testplane-ci.website.yandexcloud.net/testplane-docs/website-static/23649641933-511-1/ru/docs/v8/basic-guides/custom-commands/#%D0%B8%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D1%81%D0%BA%D0%B8%D1%85-%D0%BA%D0%BE%D0%BC%D0%B0%D0%BD%D0%B4-%D1%81-typescript). ## Работа с ESM -Testplane поддерживает ES Modules (ESM). Однако работа с ESM имеет ряд особенностей. +#### Системные ограничения -:::info Примечание -Поддержка ESM в Testplane находится в активной разработке. Рекомендуем использовать `CommonJS` для продакшн-проектов, если у вас нет явной необходимости в ESM. -::: +Для работы с ESM вам понадобится `Node.js` версии v22.0.0, v20.17.0 и выше. -#### Настройка проекта для ESM +#### Настройка -Добавьте `"type": "module"` в `package.json`: +Укажите поле `type` в файле `packahe.json`: ```json { - "type": "module", - "scripts": { - "test": "testplane" - } + "type": "module" } ``` -Обновите `tsconfig.json`: +Добавьте необходимые поля в файле tsconfig.json: ```json { "compilerOptions": { - "target": "ES2022", - "module": "ESNext", - "moduleResolution": "bundler", - "esModuleInterop": true - } -} -``` - -#### Конфиг в формате ESM - -```typescript -// .testplane.conf.ts -import type { ConfigInput } from "testplane"; - -export default { - browsers: { - chrome: { - desiredCapabilities: { - browserName: "chrome", - }, - }, + "target": "ES2020", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "types": ["testplane"] }, -} satisfies ConfigInput; -``` - -#### Тесты в формате ESM - -```typescript -// tests/example.testplane.ts -import { expect } from "chai"; -import type { Browser } from "webdriverio"; - -// ESM-импорты работают нативно -import { myHelper } from "../helpers/index.js"; // Обратите внимание на расширение .js - -it("should work with ESM", async ({ browser }: { browser: Browser }) => { - await browser.url("https://example.com"); - const title = await browser.getTitle(); - expect(title).to.equal("Example Domain"); -}); -``` - -:::warning Важно -В ESM при импорте TypeScript-файлов используйте расширение `.js`, а не `.ts`. TypeScript резолвит `.js` → `.ts` автоматически согласно спецификации ESM. -::: - -#### tsconfig-paths с ESM - -Для работы алиасов путей в ESM-окружении используйте tsconfig-paths/esm: - -```json -{ - "scripts": { - "test": "node --loader tsconfig-paths/esm --loader ts-node/esm node_modules/.bin/testplane" - } + "include": ["tests/**/*.ts", ".testplane.conf.ts"] } ``` - -Или через `NODE_OPTIONS`: - -```bash -NODE_OPTIONS="--loader ts-node/esm --loader tsconfig-paths/esm" npx testplane -``` - -#### Смешанный режим - -Если ваш проект использует `CommonJS`, но вы хотите импортировать отдельные ESM-пакеты, используйте динамические импорты: - -```typescript -// В CommonJS-проекте импорт ESM-пакета -it("should use esm package", async ({ browser }) => { - // Динамический импорт для ESM-only пакетов - const { nanoid } = await import("nanoid"); - const id = nanoid(); - // ... -}); -``` - -#### Полный пример конфигурации - -```typescript -// .testplane.conf.ts -import "tsconfig-paths/register"; -import type { ConfigInput } from "testplane"; -import { registerCustomCommands } from "./tests/helpers/commands"; - -export default { - gridUrl: process.env.GRID_URL ?? "http://localhost:4444/wd/hub", - baseUrl: process.env.BASE_URL ?? "http://localhost:3000", - - screenshotsDir: "tests/screenshots", - diffColor: "#ff0000", - - browsers: { - "chrome-desktop": { - desiredCapabilities: { - browserName: "chrome", - "goog:chromeOptions": { - args: process.env.CI ? ["--headless", "--no-sandbox"] : [], - }, - }, - windowSize: "1280x720", - retry: process.env.CI ? 2 : 0, - }, - }, - - sets: { - desktop: { - files: ["tests/**/*.testplane.ts"], - browsers: ["chrome-desktop"], - }, - }, - - prepareBrowser(browser) { - registerCustomCommands(browser); - }, - - plugins: { - "html-reporter/testplane": { - enabled: true, - }, - }, -} satisfies ConfigInput; -``` From f452b795ed1e3605ca8a2163b33bb56fcb34c9b9 Mon Sep 17 00:00:00 2001 From: Nikolaengel Date: Sun, 3 May 2026 20:02:35 +0300 Subject: [PATCH 6/7] docs:esm-fix --- .../current/basic-guides/typescript-esm.mdx | 68 ++----------------- 1 file changed, 7 insertions(+), 61 deletions(-) diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/typescript-esm.mdx b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/typescript-esm.mdx index 0dbca7c..b7a44f2 100644 --- a/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/typescript-esm.mdx +++ b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/typescript-esm.mdx @@ -30,28 +30,13 @@ export default { ## Варианты транспайлинга -Testplane автоматически использует `@swc/core` для транспайлинга, если этот пакет установлен в проекте, в противном случае он задействует `esbuild`, который уже включён в состав Testplane: - -```typescript -if (envVar && hasSwcCore()) { - // Используем @swc/core -} else { - // Используем esbuild -} -``` +Testplane автоматически использует `@swc/core` для транспайлинга, если этот пакет установлен в проекте, в противном случае он задействует `esbuild`, который уже включён в состав Testplane. :::warning Важно Проверку типов необходимо реализовывать отдельно с помощью `tsc` и конфига. ::: -Если автоматический трайнспайлинг не подходит из-за специфики проекта, чтобы отключить его и настроить самостоятельно, опишите переменную окружения `TS_ENABLE=false` в конфигурационном файле: - -```typescript -//typescript.ts -if (processWithTranspileSymbol[TESTPLANE_TRANSFORM_HOOK] || process.env.TS_ENABLE === "false") { - return; -} -``` +Если автоматический трайнспайлинг не подходит из-за специфики проекта, вы можете отключить его с помощью переменной окружения `TS_ENABLE=false` и провести настройку самостоятельно. Чтобы передать нужный лоадер при настройке вручную, используйте опцию `--require`, например: @@ -96,23 +81,6 @@ npm install --save-dev tsconfig-paths npx testplane -r tsconfig-paths/register ``` -Или опишите `tsconfig-paths` в конфиге Testplane: - -```typescript -// .testplane.conf.ts -import "tsconfig-paths/register"; - -export default { - browsers: { - chrome: { - desiredCapabilities: { - browserName: "chrome", - }, - }, - }, -}; -``` - Для более подробного знакомства с `tsconfig-paths` перейдите на [сайт с документацией пакета](https://www.typescriptlang.org/tsconfig/#paths). ## Типизация конфига @@ -120,9 +88,11 @@ export default { Testplane экспортирует типы для конфигурации, например: ```typescript +import type { ConfigInput } from "testplane"; + export default { - // ...конфиг -} satisfies import("testplane").ConfigInput; + // ... +} satisfies ConfigInput; ``` Оператор `satisfies` проверяет совместимость значения с указанным типом при сохранении исходного типа этого значения. @@ -149,28 +119,4 @@ declare global { #### Системные ограничения -Для работы с ESM вам понадобится `Node.js` версии v22.0.0, v20.17.0 и выше. - -#### Настройка - -Укажите поле `type` в файле `packahe.json`: - -```json -{ - "type": "module" -} -``` - -Добавьте необходимые поля в файле tsconfig.json: - -```json -{ - "compilerOptions": { - "target": "ES2020", - "module": "NodeNext", - "moduleResolution": "NodeNext", - "types": ["testplane"] - }, - "include": ["tests/**/*.ts", ".testplane.conf.ts"] -} -``` +Для работы с ESM вам понадобится `Node.js` версии v22.0.0, v20.17.0 и выше. Взаимодействие с `ECMAScript` происходит с помощью [функции](https://nodejs.org/api/modules.html#loading-ecmascript-modules-using-require) `require()`. From 40591cfc2c344c16c3ea4226061af39193dbe61b Mon Sep 17 00:00:00 2001 From: Nikolaengel Date: Mon, 4 May 2026 11:19:59 +0300 Subject: [PATCH 7/7] docs: eng-version --- docs/basic-guides/typescript-esm.mdx | 121 ++++++++++++++++++ .../current/basic-guides/typescript-esm.mdx | 2 +- 2 files changed, 122 insertions(+), 1 deletion(-) diff --git a/docs/basic-guides/typescript-esm.mdx b/docs/basic-guides/typescript-esm.mdx index efc2b30..de430e6 100644 --- a/docs/basic-guides/typescript-esm.mdx +++ b/docs/basic-guides/typescript-esm.mdx @@ -1 +1,122 @@ # Typescript and ESM + +## TypeScript in Testplane + +Testplane supports TypeScript out of the box — you don’t need to set up additional tools for transpilation, you can start writing tests right away: + +```typescript +describe("test examples", () => { + it("Open the main page and check the title", async ({ browser }) => { + await browser.url("https://testplane.io/"); + + const title = await browser.getTitle(); + expect(title).toContain("Testplane"); + }); +}); +``` + +And you can specify `.ts` files directly in the config: + +```typescript +// .testplane.config.ts +export default { + sets: { + desktop: { + files: ["tests/**/*.ts"], + }, + }, +}; +``` + +## Transpilation options + +Testplane automatically uses `@swc/core` for transpilation if this package is installed in the project, otherwise, it uses `esbuild`, which is already included in Testplane. + +:::warning Warning +Type checking must be implemented separately using `tsc` and a config file. +::: + +If automatic transpilation doesn’t suit your project’s specifics, you can disable it using the `TS_ENABLE=false` environment variable and set it up manually. + +To pass the required loader when setting it up manually, use the `--require option`, for example: + +```bash +-r ts-node/register +``` + +## Working with import aliases + +Many projects use path aliases in `tsconfig.json`: + +```json +{ + "compilerOptions": { + "baseUrl": ".", + "paths": { + "@components/*": ["src/components/*"], + "@utils/*": ["src/utils/*"], + "@fixtures/*": ["tests/fixtures/*"] + } + } +} +``` + +However, the TypeScript compiler can resolve these paths only at compile time. At runtime, `Node.js` is unaware of these aliases, and you’ll get an error: + +```bash + Cannot find module '@components/Button'. +``` + +#### Resolving paths at runtime + +Install the `tsconfig-paths` package: + +```bash +npm install --save-dev tsconfig-paths +``` + +Use the `--require` option: + +```bash +npx testplane -r tsconfig-paths/register +``` + +For a more detailed introduction to `tsconfig-paths`, visit the [package documentation website](https://www.typescriptlang.org/tsconfig/#paths). + +## Config typing + +Testplane exports types for the configuration, for example: + +```typescript +import type { ConfigInput } from "testplane"; + +export default { + // ... +} satisfies ConfigInput; +``` + +The `satisfies` operator checks whether a value is compatible with the specified type while preserving the original type of that value. + +## Extending browser command types + +Testplane supports custom commands with TypeScript: + +```typescript +import "webdriverio"; // Any import can be used here — it doesn’t have to be webdriverio + +declare global { + declare namespace WebdriverIO { + interface Browser { + customCommand: (arg: any) => Promise; + } + } +} +``` + +You can read more about this in the [custom commands](https://testplane.io/docs/v8/basic-guides/custom-commands/) guide. + +## Working with ESM + +#### System limitations + +To work with ESM, you’ll need `Node.js` version v22.0.0, v20.17.0, or higher. Interaction with `ECMAScript` is handled via the `require()` [function](https://nodejs.org/api/modules.html#loading-ecmascript-modules-using-require). diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/typescript-esm.mdx b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/typescript-esm.mdx index b7a44f2..a4eb70c 100644 --- a/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/typescript-esm.mdx +++ b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/typescript-esm.mdx @@ -113,7 +113,7 @@ declare global { } ``` -Подробнее об этом вы можете прочитать в статье про [кастомные команды](https://testplane-ci.website.yandexcloud.net/testplane-docs/website-static/23649641933-511-1/ru/docs/v8/basic-guides/custom-commands/#%D0%B8%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D1%81%D0%BA%D0%B8%D1%85-%D0%BA%D0%BE%D0%BC%D0%B0%D0%BD%D0%B4-%D1%81-typescript). +Подробнее об этом вы можете прочитать в статье про [кастомные команды](https://testplane.io/ru/docs/v8/basic-guides/custom-commands/). ## Работа с ESM