Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
node_modules/
dist/
coverage/
*.log
.env
.env.*
!.env.example
tests/resources/application.properties
4 changes: 4 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
node_modules
dist
coverage
package-lock.json
8 changes: 8 additions & 0 deletions .prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"semi": true,
"singleQuote": true,
"trailingComma": "all",
"printWidth": 100,
"tabWidth": 2,
"endOfLine": "lf"
}
90 changes: 88 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,88 @@
# playwright-plugin
TestRigor plug-in for PlayWright
# @testrigor/playwright-plugin

Playwright integration for the testRigor cloud extension — natural-language locators, fluent commands, and self-healing.

## Install

```bash
npm install @testrigor/playwright-plugin playwright
npx playwright install chromium
```

## Quick start

```typescript
import { TestRigor } from '@testrigor/playwright-plugin';

const driver = await TestRigor.createBrowserPage(process.env.TESTRIGOR_API_TOKEN!);
driver.setTestContext('my_test');

await driver.get('https://example.com');
const button = await driver.findElement(TestRigor.byUserDescription('Sign in'));
await button.click();

await driver.quit();
```

Attach to an existing Playwright page:

```typescript
import { TestRigor } from '@testrigor/playwright-plugin';

const driver = TestRigor.extendPage(page, apiToken);
driver.setTestContext('my_test');
```

## Fluent commands

```typescript
import { TestRigor } from '@testrigor/playwright-plugin';

const { actions, validations, queries } = TestRigor;

await actions(driver).openUrl('https://example.com').click('Empty Page').execute();
await validations(driver).checkPageContains('expected text').execute();
const value = await queries(driver).grabValue('Some field');
```

`setTestContext` is required before locator self-healing (scopes healing data on the server).

## Configuration

Environment variables:

| Variable | Default |
| ------------------------------- | ---------------------------------- |
| `TESTRIGOR_API_TOKEN` | none - must be provided |
| `TESTRIGOR_GRPC_URI` | `selenium-extension.testrigor.com` |
| `TESTRIGOR_GRPC_PORT` | `443` |
| `TESTRIGOR_GRPC_USE_TLS` | auto (TLS enabled for port 443) |
| `TESTRIGOR_PLAYWRIGHT_BROWSER` | `chromium` |
| `TESTRIGOR_PLAYWRIGHT_HEADLESS` | `false` |

Manual integration tests load settings from `tests/resources/application.properties` (copy from `application.properties.example`). Override the path with `CONFIG_FILE` or `config.file`.

The API token is **not** read automatically by the library — pass it to `createBrowserPage` / `extendPage`, or set `testrigor.apiToken` / `TESTRIGOR_API_TOKEN` for manual tests only.

## Development

```bash
npm install
npm run check # lint + format + build + unit tests
npm run test:manual # live gRPC integration tests (requires service + config)
npm run test:manual:one # single manual test by name (-t flag)
```

## Layout

```
src/
application/ Extension service, gRPC connection, driver
protocol/ Remote driver commands → Playwright
elements/ Element registry and wrappers
locators/ Locators and self-healing finder
session/ Browser launch and page wrapping
commons/ gRPC client, command facades, shared types
testrigor.ts Public entry point
tests/manual/ Live gRPC integration tests
```
23 changes: 23 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import eslint from '@eslint/js';
import eslintConfigPrettier from 'eslint-config-prettier';
import tseslint from 'typescript-eslint';

export default tseslint.config(
{
ignores: ['dist/**', 'node_modules/**', 'coverage/**'],
},
eslint.configs.recommended,
...tseslint.configs.recommended,
eslintConfigPrettier,
{
files: ['**/*.ts'],
rules: {
'@typescript-eslint/no-unused-vars': [
'error',
{ argsIgnorePattern: '^_', varsIgnorePattern: '^_' },
],
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-empty-object-type': 'off',
},
},
);
Loading