80 lines
2.6 KiB
TypeScript
80 lines
2.6 KiB
TypeScript
|
|
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);
|
||
|
|
});
|
||
|
|
});
|