UNPKG

convex

Version:

Client for the Convex Cloud

100 lines (87 loc) 2.94 kB
import { test, expect } from "vitest"; import { Long } from "../browser/long.js"; import ReactDOM from "react-dom"; import { ConvexReactClient } from "./client.js"; import { ClientMessage, QuerySetModification, ServerMessage, } from "../browser/sync/protocol.js"; import { nodeWebSocket, withInMemoryWebSocket, } from "../browser/sync/client_node_test_helpers.js"; import { anyApi } from "../server/api.js"; const testReactClient = (address: string) => new ConvexReactClient(address, { webSocketConstructor: nodeWebSocket, unsavedChangesWarning: false, }); test("ConvexReactClient ends subscriptions on close", async () => { await withInMemoryWebSocket(async ({ address, receive, send }) => { const client = testReactClient(address); const watch = client.watchQuery(anyApi.myQuery.default, {}); let timesCallbackRan = 0; let timesReactScheduled = 0; watch.onUpdate(() => timesCallbackRan++); expect((await receive()).type).toEqual("Connect"); const modify = expectQuerySetModification(await receive()); expect(modify.modifications).toEqual([ { args: [{}], queryId: 0, type: "Add", udfPath: "myQuery:default", }, ]); expect(timesCallbackRan).toEqual(0); send(transition()); // Monkey-patch to mock out this react-dom function. // Mocking in Jest like `jest.mock('react-dom')` doesn't work with ESM yet. const orig = ReactDOM.unstable_batchedUpdates; try { const scheduledCallback = await new Promise<() => void>((resolve) => { ReactDOM.unstable_batchedUpdates = function mock(cb: any) { timesReactScheduled++; resolve(cb); }; }); expect(timesReactScheduled).toEqual(1); // After the callback has been registered with unstable_batchedUpdates but // before the callback has been run, close the client. const closePromise = client.close(); // Later, React calls the callback. This should do nothing. scheduledCallback(); expect(timesCallbackRan).toEqual(0); // After the internal client has closed, same nothing. await closePromise; scheduledCallback(); expect(timesCallbackRan).toEqual(0); } finally { ReactDOM.unstable_batchedUpdates = orig; } }); }); const expectQuerySetModification = ( message: ClientMessage, ): QuerySetModification => { expect(message.type).toEqual("ModifyQuerySet"); if (message.type !== "ModifyQuerySet") throw new Error("Wrong message!"); return message; }; function transition(): ServerMessage { return { type: "Transition", startVersion: { querySet: 0, identity: 0, ts: Long.fromNumber(0) }, endVersion: { querySet: 1, identity: 0, ts: Long.fromNumber(1) }, modifications: [ { type: "QueryUpdated", queryId: 0, value: 0.0, logLines: [], journal: null, }, ], }; }