Submatter/apps/web/components/chat/chat-scope.test.ts

80 lines
2.6 KiB
TypeScript
Raw Normal View History

import { describe, expect, it } from "vitest";
import { createChatScope } from "./chat-utils";
function deferred<T>() {
let resolve!: (value: T) => void;
let reject!: (error: Error) => void;
const promise = new Promise<T>((yes, no) => {
resolve = yes;
reject = no;
});
return { promise, resolve, reject };
}
describe("chat async scope", () => {
it("ignores a send resolved after a channel switch", async () => {
const scope = createChatScope("acme", "first");
const request = deferred<string>();
const result: string[] = [];
const valid = scope.capture();
const completion = request.promise.then((message) => {
if (valid()) result.push(message);
});
scope.select("acme", "second");
request.resolve("first-channel message");
await completion;
expect(result).toEqual([]);
});
it("ignores a late failed send, including a permission error", async () => {
const scope = createChatScope("acme", "first");
const request = deferred<string>();
const result: string[] = [];
const valid = scope.capture();
const completion = request.promise.catch((error: Error) => {
if (valid()) result.push(error.message);
});
scope.select("acme", "second");
request.reject(new Error("FORBIDDEN"));
await completion;
expect(result).toEqual([]);
});
it("ignores a stale mutation result and its subsequent refresh", async () => {
const scope = createChatScope("acme", "first");
const mutation = deferred<string>();
const refresh = deferred<string>();
const result: string[] = [];
const valid = scope.capture();
const completion = mutation.promise.then(async (value) => {
if (!valid()) return;
result.push(value);
const page = await refresh.promise;
if (valid()) result.push(page);
});
mutation.resolve("edited");
await Promise.resolve();
scope.select("acme", "second");
refresh.resolve("old page");
await completion;
expect(result).toEqual(["edited"]);
});
it("invalidates pending work on purge before redirect and cannot remove a new channel's cache", async () => {
const scope = createChatScope("acme", "first");
const cancellation = deferred<void>();
const result: string[] = [];
const valid = scope.capture();
scope.revoke();
result.push("redirect");
const cleanup = cancellation.promise.then(() => {
if (valid()) result.push("remove queries");
});
scope.select("acme", "second");
cancellation.resolve();
await cleanup;
expect(result).toEqual(["redirect"]);
expect(scope.capture()()).toBe(true);
});
});