Skip to content
Merged
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
5 changes: 2 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,8 @@ Use `pnpm` for all package management tasks.
```typescript
import { assert, layer } from "@effect/vitest";
import { Effect } from "effect";
import { chromium } from "playwright-core";
import { PlaywrightBrowser } from "./browser";
import { PlaywrightEnvironment } from "./experimental";
import { PlaywrightBrowser, chromium } from "effect-playwright";
import { PlaywrightEnvironment } from "effect-playwright/experimental";

// Use the PlaywrightEnvironment layer
layer(PlaywrightEnvironment.layer(chromium))("Suite Name", (it) => {
Expand Down
38 changes: 23 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,31 +13,26 @@ A Playwright wrapper for the Effect ecosystem. This library provides a set of se
## Installation

```bash
pnpm add effect-playwright playwright-core
pnpm add effect-playwright
pnpm effect-playwright install chromium
```

or

```bash
npm install effect-playwright playwright-core
```

You can also install `playwright` instead of `playwright-core` if you want the post-build auto install of the browsers.
Browser installation is not required if connecting to an existing browser via CDP or using a local browser.

## Quick Start

```ts
import { Playwright } from "effect-playwright";
import { Playwright, chromium } from "effect-playwright";
import { Effect } from "effect";
import { chromium } from "playwright-core";

const program = Effect.gen(function* () {
const playwright = yield* Playwright;
const browser = yield* playwright.launchScoped(chromium);
const page = yield* browser.newPage();

yield* page.goto("https://example.com");
console.log(`Page title: ${page.title()}`);
const title = yield* page.title;
yield* Effect.log(`Page title: ${title}`);
}).pipe(Effect.scoped, Effect.provide(Playwright.layer));

await Effect.runPromise(program);
Expand Down Expand Up @@ -92,10 +87,9 @@ The `PlaywrightEnvironment` simplifies setup by allowing you to configure the br
### Usage

```ts
import { PlaywrightBrowser } from "effect-playwright";
import { PlaywrightBrowser, chromium } from "effect-playwright";
import { PlaywrightEnvironment } from "effect-playwright/experimental";
import { Effect } from "effect";
import { chromium } from "playwright-core";

const liveLayer = PlaywrightEnvironment.layer(chromium, {
headless: false /** any other launch options */,
Expand Down Expand Up @@ -164,9 +158,8 @@ const program = Effect.gen(function* () {
If you need to access functionality from the underlying Playwright objects that isn't directly exposed, you can use the `use` method available on most services/objects (browsers, pages, locators).

```ts
import { Playwright } from "effect-playwright";
import { Playwright, chromium } from "effect-playwright";
import { Effect } from "effect";
import { chromium } from "playwright-core";

const program = Effect.gen(function* () {
const playwright = yield* Playwright;
Expand All @@ -183,3 +176,18 @@ const program = Effect.gen(function* () {
All methods return effects that can fail with a `PlaywrightError`. This error wraps the original error from Playwright.
Note that Playwright does not support interruption, so `Effect.timeout` or similar code does not behave like you
might expect. Playwright provides its own `timeout` option for almost every method.

## CLI Wrapper

`effect-playwright` includes a lightweight command-line wrapper that forwards all commands directly to the underlying `playwright-core` CLI. You can use it to install browsers, generate code, or inspect traces:

```bash
# Install browsers
pnpm effect-playwright install chromium

# Code generation
pnpm effect-playwright codegen https://example.com

# Open inspector / trace viewer
pnpm effect-playwright show-trace trace.zip
```
10 changes: 10 additions & 0 deletions bin/cli.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/usr/bin/env node
import { createRequire } from "node:module";
import path from "node:path";

const require = createRequire(import.meta.url);
const cliPath = path.join(
path.dirname(require.resolve("playwright-core/package.json")),
"cli.js",
);
require(cliPath);
9 changes: 7 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,12 @@
"./experimental": "./dist/experimental/index.mjs",
"./package.json": "./package.json"
},
"bin": {
"effect-playwright": "./bin/cli.mjs"
},
"files": [
"dist"
"dist",
"bin"
],
"scripts": {
"build": "tsdown",
Expand All @@ -28,7 +32,8 @@
"type-check": "tsc --noEmit",
"coverage": "tsx scripts/coverage.ts",
"generate-docs": "typedoc",
"format": "biome format --fix"
"format": "biome format --fix",
"check": "biome check --fix"
},
"keywords": [
"effect",
Expand Down
4 changes: 2 additions & 2 deletions src/experimental/environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ export class PlaywrightEnvironment extends Context.Tag(
* @example
*
* ```ts
* import { chromium } from "effect-playwright";
* import { PlaywrightEnvironment } from "effect-playwright/experimental";
* import { chromium } from "playwright-core";
*
* const playwrightEnv = PlaywrightEnvironment.layer(chromium);
*
Expand Down Expand Up @@ -79,8 +79,8 @@ const withBrowserUnscoped = Effect.provideServiceEffect(
* @example
*
* ```ts
* import { chromium } from "effect-playwright";
* import { PlaywrightEnvironment } from "effect-playwright/experimental";
* import { chromium } from "playwright-core";
*
* const env = PlaywrightEnvironment.layer(chromium);
*
Expand Down
4 changes: 2 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/**
* An Effect-based wrapper for Playwright, bringing the power of functional programming
* and structured concurrency to browser automation.
* An Effect-based wrapper for Playwright.
*
* ## Features
*
Expand All @@ -14,6 +13,7 @@
* @packageDocumentation
*/

export { chromium, firefox, webkit } from "playwright-core";
export * from "./browser";
export {
PlaywrightBrowserContext,
Expand Down
21 changes: 11 additions & 10 deletions src/playwright.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ export interface PlaywrightService {
* {@link launchScoped} instead.
*
* ```ts
* import { Playwright, chromium } from "effect-playwright";
* import { Effect } from "effect";
* import { Playwright } from "effect-playwright";
* import { chromium } from "playwright-core";
*
* const program = Effect.gen(function* () {
* const browser = yield* Playwright.launch(chromium);
* const playwright = yield* Playwright;
* const browser = yield* playwright.launch(chromium);
* // ... use browser ...
* yield* browser.close;
* });
Expand All @@ -53,12 +53,12 @@ export interface PlaywrightService {
* This method automatically closes the browser when the scope is closed.
*
* ```ts
* import { Playwright, chromium } from "effect-playwright";
* import { Effect } from "effect";
* import { Playwright } from "effect-playwright";
* import { chromium } from "playwright-core";
*
* const program = Effect.gen(function* () {
* const browser = yield* Playwright.launchScoped(chromium);
* const playwright = yield* Playwright;
* const browser = yield* playwright.launchScoped(chromium);
* // Browser will be closed automatically when scope closes
* });
*
Expand Down Expand Up @@ -89,9 +89,8 @@ export interface PlaywrightService {
* Closing this context also closes the underlying browser process.
*
* ```ts
* import { Playwright, chromium } from "effect-playwright";
* import { Effect } from "effect";
* import { Playwright } from "effect-playwright";
* import { chromium } from "playwright-core";
*
* const program = Effect.gen(function* () {
* const playwright = yield* Playwright;
Expand All @@ -113,6 +112,9 @@ export interface PlaywrightService {
* If you call this non-scoped variant inside a scope, add a finalizer for cleanup:
*
* ```ts
* import { Playwright, chromium } from "effect-playwright";
* import { Effect } from "effect";
*
* const program = Effect.gen(function* () {
* const playwright = yield* Playwright;
* const context = yield* playwright.launchPersistentContext(
Expand Down Expand Up @@ -143,9 +145,8 @@ export interface PlaywrightService {
* when the scope is closed.
*
* ```ts
* import { Playwright, chromium } from "effect-playwright";
* import { Effect } from "effect";
* import { Playwright } from "effect-playwright";
* import { chromium } from "playwright-core";
*
* const program = Effect.gen(function* () {
* const playwright = yield* Playwright;
Expand Down
Loading