Skip to content
This repository has been archived by the owner on Jul 16, 2024. It is now read-only.

Commit

Permalink
added tests
Browse files Browse the repository at this point in the history
  • Loading branch information
jessekelly881 committed Dec 6, 2023
1 parent 8ece61b commit d2841ef
Show file tree
Hide file tree
Showing 6 changed files with 269 additions and 108 deletions.
10 changes: 5 additions & 5 deletions packages/platform-browser/examples/webSocket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
* @since 1.0.0
*/

import * as WebSocket from "@effect/platform-browser/WebSocket"
import * as WS from "@effect/platform-browser/WebSocket"
import * as Effect from "effect/Effect"

const test = Effect.gen(function*(_) {
const ws = yield* _(WebSocket.layer("ws://localhost:3000"))
const program = Effect.gen(function*(_) {
const ws = yield* _(WS.Socket)
yield* _(ws.send("abc"))
}).pipe(Effect.scoped, Effect.tapError((err) => Effect.logError(err)))
}).pipe(Effect.provide(WS.layer("")), Effect.scoped, Effect.tapError((err) => Effect.logError(err)))

Effect.runFork(test)
Effect.runFork(program)
3 changes: 2 additions & 1 deletion packages/platform-browser/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@
"build-annotate": "babel build --plugins annotate-pure-calls --out-dir build --source-maps"
},
"dependencies": {
"@effect/platform": "workspace:*"
"@effect/platform": "workspace:*",
"vitest-websocket-mock": "^0.2.2"
},
"peerDependencies": {
"effect": "2.0.0-next.59"
Expand Down
5 changes: 4 additions & 1 deletion packages/platform-browser/src/WebSocket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
*
* Also includes exports from [`@effect/platform/WebSocket`](https://effect-ts.github.io/platform/platform/WebSocket.ts.html).
*/
import type * as Socket from "@effect/platform-browser/WebSocket"
import type { PlatformError } from "@effect/platform/Error"
import type * as Layer from "effect/Layer"
import * as internal from "./internal/webSocket.js"

/**
Expand All @@ -16,4 +19,4 @@ export * from "@effect/platform/WebSocket"
* @since 1.0.0
* @category models
*/
export const layer = internal.layer
export const layer: (url: string | URL) => Layer.Layer<never, PlatformError, Socket.Socket> = internal.layer
25 changes: 22 additions & 3 deletions packages/platform-browser/src/internal/webSocket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import * as Socket from "@effect/platform/WebSocket"
import * as Chunk from "effect/Chunk"
import * as Effect from "effect/Effect"
import * as Layer from "effect/Layer"
import * as Option from "effect/Option"
import * as Stream from "effect/Stream"

const make = (impl: Omit<Socket.Socket, Socket.TypeId>) =>
Expand All @@ -14,6 +15,14 @@ const make = (impl: Omit<Socket.Socket, Socket.TypeId>) =>
...impl
})

const closedByHostError = PlatformError.SystemError({
module: "WebSocket",
reason: "BadResource",
message: "Socket was closed by host",
method: "",
pathOrDescriptor: ""
})

/** @internal */
const createSocket = (url: string | URL) =>
Effect.acquireRelease(
Expand All @@ -30,19 +39,22 @@ const createSocket = (url: string | URL) =>
})
}),
(socket) =>
Effect.async<never, never, WebSocket>((resume) => {
Effect.async<never, PlatformError.PlatformError, WebSocket>((resume) => {
socket.addEventListener("close", () => {
resume(Effect.fail(closedByHostError))
})
socket.addEventListener("open", () => {
resume(Effect.succeed(socket))
})
})
),
(s) => Effect.succeed(s.close(1001)) // .close is unsafe..
(s) => Effect.succeed(s.close(1000))
)

/**
* @since 1.0.0
*/
export const layer = (url: string | URL): Layer.Layer<never, PlatformError.SystemError, Socket.Socket> =>
export const layer = (url: string | URL): Layer.Layer<never, PlatformError.PlatformError, Socket.Socket> =>
Layer.scoped(
Socket.Socket,
Effect.gen(function*(_) {
Expand All @@ -55,12 +67,19 @@ export const layer = (url: string | URL): Layer.Layer<never, PlatformError.Syste
socket.addEventListener("message", (event) => {
emit(Effect.succeed(Chunk.of(event.data as string | Blob | ArrayBuffer)))
})
socket.addEventListener("close", () => {
emit(Effect.fail(Option.none()))
})
})

const errors = Stream.async<never, never, Event>((emit) => {
socket.addEventListener("error", (event) => {
emit(Effect.succeed(Chunk.of(event)))
})

socket.addEventListener("close", () => {
emit(Effect.fail(Option.none()))
})
})

return make({ send, messages, errors })
Expand Down
60 changes: 60 additions & 0 deletions packages/platform-browser/test/WebSocket.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/**
* @since 1.0.0
*/

import * as Socket from "@effect/platform-browser/WebSocket";
import { Chunk, Effect, Sink, Stream } from 'effect';
import { afterEach, describe, expect, it } from 'vitest';
import 'vitest-websocket-mock';
import WS from 'vitest-websocket-mock';

const url = 'ws://localhost:1234'
const run = <E, A>(effect: Effect.Effect<Socket.Socket, E, A>) =>
Effect.runPromise(Effect.provide(effect, Socket.layer(url)))


describe("WebSocket", () => {

afterEach(() => {
WS.clean();
})

it("send", async () => {
const server = new WS(url);

await run(Effect.gen(function* (_) {
const ws = yield* _(Socket.Socket)
yield* _(ws.send("Hello"))
}))

// @ts-ignore
await expect(server).toReceiveMessage('Hello');
})

it("messages", async () => {
const server = new WS(url);
const msgStream = Effect.map(Socket.Socket, socket => socket.messages).pipe(Stream.unwrap)

run(Stream.run(msgStream, Sink.collectAll())).then(msg =>
expect(msg).toEqual(Chunk.fromIterable(["first", "second"]))
)

await server.connected
server.send("first")
server.send("second")
server.close()
})

it("errors", async () => {
const server = new WS(url);
const errStream = Effect.map(Socket.Socket, socket => socket.errors).pipe(Stream.unwrap)

run(Stream.run(errStream, Sink.collectAll())).then(msg =>
expect(msg.length).toEqual(1)
)

await server.connected
server.error()
})

})
Loading

0 comments on commit d2841ef

Please sign in to comment.