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
10 changes: 3 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,8 @@
"playwright-core": "^1.62.1"
},
"peerDependencies": {
"@effect/platform": "^0.93.3",
"@playwright/test": "^1.62.1",
"effect": "^3.19.6"
"effect": "^4.0.0-rc.111"
},
"peerDependenciesMeta": {
"@playwright/test": {
Expand All @@ -61,14 +60,11 @@
},
"devDependencies": {
"@biomejs/biome": "2.5.9",
"@effect/cli": "^0.77.0",
"@effect/language-service": "0.87.2",
"@effect/platform": "^0.97.1",
"@effect/platform-node": "^0.108.1",
"@effect/vitest": "^0.30.0",
"@effect/vitest": "^4.0.0-rc.111",
"@playwright/test": "^1.62.1",
"@types/node": "^25.9.5",
"effect": "^3.22.1",
"effect": "^4.0.0-rc.111",
"pkg-pr-new": "^0.0.88",
"playwright": "^1.62.1",
"ts-morph": "^28.0.0",
Expand Down
463 changes: 26 additions & 437 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

7 changes: 2 additions & 5 deletions pnpm-workspace.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,5 @@ allowBuilds:
esbuild: false
msgpackr-extract: false
minimumReleaseAgeExclude:
- "@effect/cli@0.75.2"
- "@effect/cluster@0.59.0"
- "@effect/platform-node-shared@0.60.0"
- "@effect/platform-node@0.107.0"
- "@effect/workflow@0.18.2"
- '@effect/vitest@4.0.0-rc.111'
- effect@4.0.0-rc.111
25 changes: 6 additions & 19 deletions scripts/coverage.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Command } from "@effect/cli";
import { FileSystem, Path } from "@effect/platform";
import { NodeContext, NodeRuntime } from "@effect/platform-node";
Comment thread
fiws marked this conversation as resolved.
import { existsSync } from "node:fs";
import { join } from "node:path";
import { Console, Effect } from "effect";
import { type JSDocableNode, Project } from "ts-morph";

Expand Down Expand Up @@ -72,21 +71,17 @@ function isDeprecated(node: JSDocableNode): boolean {
}

const runCoverage = Effect.gen(function* () {
const fs = yield* FileSystem.FileSystem;
const pathService = yield* Path.Path;

const cwd = process.cwd();
const tsConfigFilePath = pathService.join(cwd, "tsconfig.json");
const pwTypesPath = pathService.join(
const tsConfigFilePath = join(cwd, "tsconfig.json");
const pwTypesPath = join(
cwd,
"node_modules",
"playwright-core",
"types",
"types.d.ts",
);

const exists = yield* fs.exists(pwTypesPath);
if (!exists) {
if (!existsSync(pwTypesPath)) {
return yield* Effect.fail(
new Error(`Could not find playwright-core types at ${pwTypesPath}`),
);
Expand Down Expand Up @@ -247,12 +242,4 @@ const runCoverage = Effect.gen(function* () {
);
yield* Console.log("=============================\n");
});

const command = Command.make("coverage", {}, () => runCoverage);

const run = Command.run(command, {
name: "effect-playwright-coverage",
version: "0.1.0",
});

run(process.argv).pipe(Effect.provide(NodeContext.layer), NodeRuntime.runMain);
await Effect.runPromise(runCoverage);
8 changes: 4 additions & 4 deletions src/browser-context.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ type TestWindow = Window & {
};

layer(PlaywrightSpawner.layer(chromium))("BrowserContext", (it) => {
it.scoped("should wrap context methods", () =>
it.effect("should wrap context methods", () =>
Effect.gen(function* () {
const browser = yield* Browser;
const context = yield* browser.newContext();
Expand Down Expand Up @@ -64,7 +64,7 @@ layer(PlaywrightSpawner.layer(chromium))("BrowserContext", (it) => {
}).pipe(PlaywrightSpawner.withBrowser),
);

it.scoped("addInitScript should execute script in all new pages", () =>
it.effect("addInitScript should execute script in all new pages", () =>
Effect.gen(function* () {
const browser = yield* Browser;
const context = yield* browser.newContext();
Expand Down Expand Up @@ -93,7 +93,7 @@ layer(PlaywrightSpawner.layer(chromium))("BrowserContext", (it) => {
}).pipe(PlaywrightSpawner.withBrowser),
);

it.scoped(
it.effect(
"isClosed should return the closed state of the browser context",
() =>
Effect.gen(function* () {
Expand All @@ -107,7 +107,7 @@ layer(PlaywrightSpawner.layer(chromium))("BrowserContext", (it) => {
assert.strictEqual(context.isClosed(), true);
}).pipe(PlaywrightSpawner.withBrowser),
);
it.scoped("credentials should create, get, and delete credentials", () =>
it.effect("credentials should create, get, and delete credentials", () =>
Effect.gen(function* () {
const browser = yield* Browser;
const context = yield* browser.newContext();
Expand Down
28 changes: 17 additions & 11 deletions src/browser-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* @since 0.1.0
*/

import { Context, Effect, identity, Option, Stream } from "effect";
import { Context, Effect, identity, Option, Queue, Stream } from "effect";
import type {
ConsoleMessage,
BrowserContext as CoreBrowserContext,
Expand Down Expand Up @@ -302,7 +302,7 @@ export interface BrowserContext {
* @category services
* @since 0.1.0
*/
export const BrowserContext = Context.GenericTag<BrowserContext>(
export const BrowserContext = Context.Service<BrowserContext>(
"effect-playwright/browser-context/BrowserContext",
);

Expand Down Expand Up @@ -339,7 +339,7 @@ export const makeBrowserContext = (
),
).pipe(Effect.asVoid),
browser: () =>
Option.fromNullable(context.browser()).pipe(Option.map(makeBrowser)),
Option.fromNullishOr(context.browser()).pipe(Option.map(makeBrowser)),
clearCookies: (options) => use((c) => c.clearCookies(options)),
clearPermissions: use((c) => c.clearPermissions()),
cookies: (urls) => use((c) => c.cookies(urls)),
Expand All @@ -356,19 +356,25 @@ export const makeBrowserContext = (
storageState: (options) => use((c) => c.storageState(options)),
setStorageState: (options) => use((c) => c.setStorageState(options)),
eventStream: <K extends keyof BrowserContextEvents>(event: K) =>
Stream.asyncPush<BrowserContextEvents[K]>((emit) =>
Effect.acquireRelease(
Stream.callback<BrowserContextEvents[K]>((queue) => {
const emit = (value: BrowserContextEvents[K]) => {
Queue.offerUnsafe(queue, value);
};
const end = () => {
Queue.endUnsafe(queue);
};
return Effect.acquireRelease(
Effect.sync(() => {
events.on(event, emit.single);
events.once("close", emit.end);
events.on(event, emit);
events.once("close", end);
}),
() =>
Effect.sync(() => {
events.off(event, emit.single);
events.off("close", emit.end);
events.off(event, emit);
events.off("close", end);
}),
),
).pipe(
);
}).pipe(
Stream.map((value) => {
const mapping = eventMappings[event];
// The selected event and mapping share the same generic event key.
Expand Down
28 changes: 14 additions & 14 deletions src/browser.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { assert, layer } from "@effect/vitest";
import { Chunk, Effect, Fiber, Stream } from "effect";
import { Effect, Fiber, Stream } from "effect";
import { chromium } from "playwright-core";
import type { Browser } from "./browser";
import { Playwright } from "./index";

layer(Playwright.layer)("Browser", (it) => {
it.scoped("newPage should create a page", () =>
it.effect("newPage should create a page", () =>
Effect.gen(function* () {
const playwright = yield* Playwright.Playwright;
const browser = yield* playwright.launchScoped(chromium);
Expand All @@ -15,7 +15,7 @@ layer(Playwright.layer)("Browser", (it) => {
}),
);

it.scoped("use should allow accessing raw browser", () =>
it.effect("use should allow accessing raw browser", () =>
Effect.gen(function* () {
const playwright = yield* Playwright.Playwright;
const browser = yield* playwright.launchScoped(chromium);
Expand All @@ -27,7 +27,7 @@ layer(Playwright.layer)("Browser", (it) => {
}),
);

it.scoped("browserType should return the browser type", () =>
it.effect("browserType should return the browser type", () =>
Effect.gen(function* () {
const playwright = yield* Playwright.Playwright;
const browser = yield* playwright.launchScoped(chromium);
Expand All @@ -37,7 +37,7 @@ layer(Playwright.layer)("Browser", (it) => {
}),
);

it.scoped("version should return the browser version", () =>
it.effect("version should return the browser version", () =>
Effect.gen(function* () {
const playwright = yield* Playwright.Playwright;
const browser = yield* playwright.launchScoped(chromium);
Expand All @@ -48,7 +48,7 @@ layer(Playwright.layer)("Browser", (it) => {
}),
);

it.scoped("close should close the browser", () =>
it.effect("close should close the browser", () =>
Effect.gen(function* () {
const playwright = yield* Playwright.Playwright;
const browser = yield* playwright.launchScoped(chromium);
Expand All @@ -61,7 +61,7 @@ layer(Playwright.layer)("Browser", (it) => {
assert.isFalse(isConnected);
}),
);
it.scoped("contexts should return the list of contexts", () =>
it.effect("contexts should return the list of contexts", () =>
Effect.gen(function* () {
const playwright = yield* Playwright.Playwright;
const browser = yield* playwright.launchScoped(chromium);
Expand All @@ -75,7 +75,7 @@ layer(Playwright.layer)("Browser", (it) => {
}),
);

it.scoped("newContext should create a new context", () =>
it.effect("newContext should create a new context", () =>
Effect.gen(function* () {
const playwright = yield* Playwright.Playwright;
const browser = yield* playwright.launchScoped(chromium);
Expand All @@ -88,7 +88,7 @@ layer(Playwright.layer)("Browser", (it) => {
}),
);

it.scoped("newContext should allow creating pages", () =>
it.effect("newContext should allow creating pages", () =>
Effect.gen(function* () {
const playwright = yield* Playwright.Playwright;
const browser = yield* playwright.launchScoped(chromium);
Expand All @@ -102,7 +102,7 @@ layer(Playwright.layer)("Browser", (it) => {
}),
);

it.scoped("contexts should reflect newPage creation", () =>
it.effect("contexts should reflect newPage creation", () =>
Effect.gen(function* () {
const playwright = yield* Playwright.Playwright;
const browser = yield* playwright.launchScoped(chromium);
Expand Down Expand Up @@ -144,20 +144,20 @@ layer(Playwright.layer)("Browser", (it) => {
assert.isFalse(isConnected);
}),
);
it.scoped("eventStream should emit disconnected event", () =>
it.effect("eventStream should emit disconnected event", () =>
Effect.gen(function* () {
const playwright = yield* Playwright.Playwright;
const browser = yield* playwright.launchScoped(chromium);

const eventsFiber = yield* browser
.eventStream("disconnected")
.pipe(Stream.runCollect, Effect.fork);
.pipe(Stream.runCollect, Effect.forkChild);

yield* browser.close;
const events = yield* Fiber.join(eventsFiber);
assert.strictEqual(Chunk.size(events), 1);
assert.strictEqual(events.length, 1);

const firstEvent = yield* Chunk.head(events);
const firstEvent = events[0];
assert.strictEqual(firstEvent.version(), browser.version());
}),
);
Expand Down
28 changes: 17 additions & 11 deletions src/browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* @since 0.1.0
*/

import { Context, Effect, Stream } from "effect";
import { Context, Effect, Queue, Stream } from "effect";
import type { Scope } from "effect/Scope";
import type {
BrowserType,
Expand Down Expand Up @@ -197,7 +197,7 @@ export interface Browser {
* @category services
* @since 0.1.0
*/
export const Browser = Context.GenericTag<Browser>(
export const Browser = Context.Service<Browser>(
"effect-playwright/browser/Browser",
);

Expand All @@ -220,27 +220,33 @@ export const makeBrowser = (browser: CoreBrowser): Browser => {
newContext: (options) =>
Effect.acquireRelease(
use((browser) => browser.newContext(options).then(makeBrowserContext)),
(context) => context.close.pipe(Effect.ignoreLogged),
(context) => context.close.pipe(Effect.ignore({ log: true })),
),
browserType: () => browser.browserType(),
version: () => browser.version(),
isConnected: () => browser.isConnected(),
bind: (title, options) => use((browser) => browser.bind(title, options)),
unbind: use((browser) => browser.unbind()),
eventStream: <K extends keyof BrowserEvents>(event: K) =>
Stream.asyncPush<BrowserEvents[K]>((emit) =>
Effect.acquireRelease(
Stream.callback<BrowserEvents[K]>((queue) => {
const emit = (value: BrowserEvents[K]) => {
Queue.offerUnsafe(queue, value);
};
const end = () => {
Queue.endUnsafe(queue);
};
return Effect.acquireRelease(
Effect.sync(() => {
events.on(event, emit.single);
events.once("disconnected", emit.end);
events.on(event, emit);
events.once("disconnected", end);
}),
() =>
Effect.sync(() => {
events.off(event, emit.single);
events.off("disconnected", emit.end);
events.off(event, emit);
events.off("disconnected", end);
}),
),
).pipe(
);
}).pipe(
Stream.map((value) => {
const mapping = eventMappings[event];
// The selected event and mapping share the same generic event key.
Expand Down
2 changes: 1 addition & 1 deletion src/clock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ export interface Clock {
* @since 0.1.0
* @category services
*/
export const Clock = Context.GenericTag<Clock>("effect-playwright/clock/Clock");
export const Clock = Context.Service<Clock>("effect-playwright/clock/Clock");

/**
* Creates a `Clock` from a Playwright `Clock` instance.
Expand Down
Loading
Loading