diff --git a/src/common.test.ts b/src/common.test.ts index 6c4f21b..705e6cc 100644 --- a/src/common.test.ts +++ b/src/common.test.ts @@ -1,5 +1,5 @@ import { assert, layer } from "@effect/vitest"; -import { Effect, Fiber, Option, Stream } from "effect"; +import { Chunk, Effect, Fiber, Option, Stream } from "effect"; import { chromium } from "playwright-core"; import { PlaywrightBrowser } from "./browser"; import { PlaywrightEnvironment } from "./experimental"; @@ -140,6 +140,14 @@ layer(PlaywrightEnvironment.layer(chromium))("PlaywrightCommon", (it) => { assert((yield* download.suggestedFilename) === "test.txt"); const url = yield* download.url; assert(url.startsWith("data:")); + + const text = yield* download.stream.pipe( + Stream.decodeText(), + Stream.runCollect, + Effect.map(Chunk.join("")), + ); + + assert.strictEqual(text, "hello world"); }).pipe(PlaywrightEnvironment.withBrowser), ); }); diff --git a/src/common.ts b/src/common.ts index f4345e7..44ab728 100644 --- a/src/common.ts +++ b/src/common.ts @@ -1,3 +1,4 @@ +import { Readable } from "node:stream"; import { Data, Effect, Option, Stream } from "effect"; import type { Dialog, @@ -8,7 +9,7 @@ import type { Response, Worker, } from "playwright-core"; -import type { PlaywrightError } from "./errors"; +import { type PlaywrightError, wrapError } from "./errors"; import { PlaywrightFrame, type PlaywrightFrameService } from "./frame"; import { PlaywrightPage, type PlaywrightPageService } from "./page"; import type { PageFunction } from "./playwright-types"; @@ -262,7 +263,12 @@ export class PlaywrightFileChooser extends Data.TaggedClass( */ export class PlaywrightDownload extends Data.TaggedClass("PlaywrightDownload")<{ cancel: Effect.Effect; - createReadStream: Stream.Stream; + /** + * Creates a stream of the download data. + * @category custom + * @since 0.2.0 + */ + stream: Stream.Stream; delete: Effect.Effect; failure: Effect.Effect, PlaywrightError>; page: () => PlaywrightPageService; @@ -279,8 +285,17 @@ export class PlaywrightDownload extends Data.TaggedClass("PlaywrightDownload")<{ return new PlaywrightDownload({ cancel: use(() => download.cancel()), - /** TODO: implement createReadStream / effect wrapper for it */ - createReadStream: Stream.empty, + stream: use(() => + download.createReadStream().then((s) => Readable.toWeb(s)), + ).pipe( + Effect.map((s) => + Stream.fromReadableStream( + () => s as ReadableStream, + wrapError, + ), + ), + Stream.unwrap, + ), delete: use(() => download.delete()), failure: use(() => download.failure()).pipe( Effect.map(Option.fromNullable), diff --git a/tsconfig.json b/tsconfig.json index 347f91f..51dbadb 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -14,7 +14,7 @@ "isolatedModules": true, "verbatimModuleSyntax": true, "skipLibCheck": true, - "types": ["vitest/importMeta"], + "types": ["vitest/importMeta", "node"], "paths": { "effect-playwright": ["./src/index.ts"], "effect-playwright/experimental": ["./src/experimental/index.ts"]