diff --git a/.github/workflows/bumper.yml b/.github/workflows/bumper.yml index d640a0b..574f7cc 100644 --- a/.github/workflows/bumper.yml +++ b/.github/workflows/bumper.yml @@ -7,7 +7,7 @@ jobs: update-dep: strategy: matrix: - deno: ["1.3.3"] + deno: ["1.4.2"] runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 diff --git a/.github/workflows/master.yml b/.github/workflows/master.yml index 6d6250e..68f3605 100644 --- a/.github/workflows/master.yml +++ b/.github/workflows/master.yml @@ -13,7 +13,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, windows-latest, macos-latest] - deno: ["1.3.3"] + deno: ["1.4.2"] runs-on: ${{ matrix.os }} steps: @@ -36,7 +36,7 @@ jobs: linter: strategy: matrix: - deno: ["1.3.3"] + deno: ["1.4.2"] # Only one OS is required since fmt is cross platform runs-on: ubuntu-latest diff --git a/deps.ts b/deps.ts index 77b4a1e..f6c10e0 100644 --- a/deps.ts +++ b/deps.ts @@ -4,11 +4,10 @@ export { Server as DenoServer, serve, serveTLS, -} from "https://deno.land/std@0.68.0/http/server.ts"; +} from "https://deno.land/std@0.71.0/http/server.ts"; export { WebSocket, acceptWebSocket, - connectWebSocket, isWebSocketCloseEvent, -} from "https://deno.land/std@0.68.0/ws/mod.ts"; +} from "https://deno.land/std@0.71.0/ws/mod.ts"; diff --git a/tests/deps.ts b/tests/deps.ts index f670116..d9da1d3 100644 --- a/tests/deps.ts +++ b/tests/deps.ts @@ -1,11 +1,14 @@ export { WebSocket, acceptWebSocket, - connectWebSocket, isWebSocketCloseEvent, serve, } from "../deps.ts"; export { Rhum, -} from "https://deno.land/x/rhum@v1.1.2/mod.ts"; +} from "https://deno.land/x/rhum@v1.1.4/mod.ts"; + +export { + deferred, +} from "https://deno.land/std@0.71.0/async/deferred.ts"; diff --git a/tests/integration/app_3000/tests.ts b/tests/integration/app_3000/tests.ts index b46d902..2037851 100644 --- a/tests/integration/app_3000/tests.ts +++ b/tests/integration/app_3000/tests.ts @@ -1,95 +1,35 @@ import { Packet, Server } from "../../../mod.ts"; -import { Rhum, WebSocket, connectWebSocket, serve } from "../../deps.ts"; +import { Rhum, WebSocket, deferred } from "../../deps.ts"; const decoder = new TextDecoder(); +interface ResolvableMethods { + resolve: (value?: T | PromiseLike) => void; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + reject: (reason?: any) => void; +} + //////////////////////////////////////////////////////////////////////////////// -// SERVER SETUP //////////////////////////////////////////////////////////////// +// WEB SOCKET SERVER SETUP ///////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// -const server = new Server({ reconnect: false }); +const WSServer = new Server({ reconnect: false }); -await server.run({ +await WSServer.run({ hostname: "127.0.0.1", port: 3000, }); -console.log( - `Server listening: http://${server.hostname}:${server.port}`, -); - -let storage: any = { - chan1: [], - chan2: [], - connected: [], -}; - // Set up connect channel -server.on("connect", (packet: Packet) => { - storage.connected.push(packet); +WSServer.on("connect", (packet: Packet) => { + WSServer.to("chan1", packet.message); }); // Set up the chan1 channel -server.openChannel("chan1"); -server.on("chan1", (packet: Packet) => { - storage.chan1.push(packet.message); +WSServer.openChannel("chan1"); +WSServer.on("chan1", (packet: Packet) => { + WSServer.to("chan1", packet.message); }); -let client: WebSocket | null = null; - -// Create a basic raw Deno web server. This web server will take in HTTP -// requests and make calls to the socket server based on what is passed in the -// body of the HTTP request. For example, if {"connect_to": ["chan1"]} was -// passed in the body of the request, then the web server will pass that -// information to the socket server and the socket server will handle that -// packet accordingly. -const webServer = serve({ hostname: "localhost", port: 3001 }); -(async () => { - for await (const req of webServer) { - const packet = - JSON.parse(decoder.decode(await Deno.readAll(req.body))).data; - if (!client) { - client = await connectWebSocket(`ws://${server.hostname}:${server.port}`); - } - if (packet) { - await client.send(JSON.stringify(packet)); - } - req.respond({}); - } -})(); - -console.log( - `Web server listening: http://localhost:3001`, -); - -//////////////////////////////////////////////////////////////////////////////// -// PERFORM EVENTS TO TEST AGAINST ////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// - -await sendPacket(JSON.stringify({ - data: { - connect_to: ["chan1"], - }, -})); - -await sendPacket(JSON.stringify({ - data: { - send_packet: { - to: "chan1", - message: "hello", - }, - }, -})); - -async function sendPacket(packet?: string) { - const headers = new Headers(); - headers.set("Content-Type", "application/json"); - const response = await fetch("http://localhost:3001", { - headers, - body: packet ?? "", - }); - await response.text(); -} - //////////////////////////////////////////////////////////////////////////////// // TESTS /////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// @@ -101,16 +41,136 @@ console.log( Rhum.testPlan("app_3000", () => { Rhum.testSuite("server", () => { Rhum.testCase("should allow clients to connect", async () => { - Rhum.asserts.assertEquals(storage.connected.length, 1); - }); - }); - Rhum.testSuite("chan1", () => { - Rhum.testCase("should exist", () => { - Rhum.asserts.assertEquals(server.getChannel("chan1").name, "chan1"); - }); - Rhum.testCase("should have one message", () => { - Rhum.asserts.assertEquals(storage.chan1, ["hello"]); + const promise = deferred(); + const WSClient = new WebSocket( + `ws://${WSServer.hostname}:${WSServer.port}`, + ); + WSClient.onopen = function () { + WSClient.send(JSON.stringify({ + connect_to: ["chan1"], + })); + }; + WSClient.onmessage = function (message: any) { + Rhum.asserts.assertEquals(message.data, "Connected to chan1."); + WSClient.close(); + }; + WSClient.onclose = function () { + promise.resolve(); + }; + await promise; }); + Rhum.testCase( + "should allow messages to be sent back and forth, after connecting to a channel", + async () => { + const promise = deferred(); + const WSClient = new WebSocket( + `ws://${WSServer.hostname}:${WSServer.port}`, + ); + WSClient.onopen = function () { + WSClient.send(JSON.stringify({ + connect_to: ["chan1"], + })); + WSClient.send(JSON.stringify({ + send_packet: { + to: "chan1", + message: "Hi server :)", + }, + })); + }; + let messageCount = 0; + WSClient.onmessage = function (message: any) { + messageCount++; + if (messageCount === 2) { + Rhum.asserts.assertEquals(JSON.parse(message.data), { + from: "Server", + to: "chan1", + message: "Hi server :)", + }); + WSClient.close(); + } + }; + WSClient.onclose = function () { + promise.resolve(); + }; + await promise; + }, + ); + // Rhum.testCase("Cannot send messages to channels a user hasn't connected to", async () => { + // const promise = deferred(); + // const WSClient1 = new WebSocket( + // `ws://${WSServer.hostname}:${WSServer.port}`, + // ); + // const WSClient2 = new WebSocket( + // `ws://${WSServer.hostname}:${WSServer.port}`, + // ); + // // Have one client connected so we can ensure they dont get a message + // WSClient1.onopen = function () { + // WSClient1.send(JSON.stringify({ + // connect_to: ["chan1"] + // })); + // } + // WSClient2.onopen = function () { + // WSClient2.send(JSON.stringify({ + // send_packet: { + // to: "chan1", + // message: "This message was sent from the client, but the client shouldn't be allowed to do this" + // }, + // })); + // }; + // WSClient2.onmessage = function (message) { + // Rhum.asserts.assertEquals(message.data, 'Client 9 is not connected to chan1'); + // WSClient2.close(); + // }; + // WSClient1.onmessage = function (message) { + // console.log('ws client 1 got message') + // console.log(message) + // WSClient1.close() + // } + // WSClient1.onclose = function () { + // promise.resolve(); + // }; + // await promise; + // }) + Rhum.testCase( + "Does not allow connecting and sending a message to a channel that isn't opened", + async () => { + const promise = deferred(); + const WSClient = new WebSocket( + `ws://${WSServer.hostname}:${WSServer.port}`, + ); + WSClient.onopen = function () { + WSClient.send(JSON.stringify({ + connect_to: ["chan2"], + })); + WSClient.send(JSON.stringify({ + send_packet: { + to: "chan2", + message: "Message to chan2 from client", + }, + })); + }; + let messageCount = 0; + WSClient.onmessage = function (message: any) { + messageCount++; + if (messageCount === 1) { + Rhum.asserts.assertEquals( + message.data, + 'Channel \"chan2\" does not exist.', + ); + } else { + Rhum.asserts.assertEquals( + message.data, + "Client 8 is not connected to chan2", + ); + WSClient.close(); + } + }; + WSClient.onclose = function () { + promise.resolve(); + }; + await promise; + }, + ); }); }); @@ -120,8 +180,7 @@ Deno.test({ name: "Stop the server", async fn() { try { - server.close(); - webServer.close(); + WSServer.close(); } catch (error) { // Do nothing } diff --git a/tests/integration/app_3001/tests.ts b/tests/integration/app_3001/tests.ts index 6849939..431687e 100644 --- a/tests/integration/app_3001/tests.ts +++ b/tests/integration/app_3001/tests.ts @@ -1,5 +1,5 @@ import { Packet, Server } from "../../../mod.ts"; -import { Rhum, Drash, connectWebSocket } from "../../deps.ts"; +import { Rhum, Drash } from "../../deps.ts"; //////////////////////////////////////////////////////////////////////////////// // SERVER SETUP //////////////////////////////////////////////////////////////// @@ -11,7 +11,7 @@ class Resource extends Drash.Http.Resource { public async POST() { const data = this.request.getBodyParam("data"); if (data) { - const socketClient = await connectWebSocket( + const socketClient = new WebSocket( `wss://${socketServer.hostname}:${socketServer.port}`, ); await socketClient.send(JSON.stringify(data));