chore: initialize from frontend template 4dc033c
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
|
||||
import {
|
||||
createBrowserUploadCancellationChannel,
|
||||
type UploadCancellationBroadcastFacade,
|
||||
} from "../../src/adapters/browser-transfer/resumable-upload/upload-cancellation-channel.ts";
|
||||
|
||||
type MessageListener = (
|
||||
event: Readonly<{ data: unknown }>,
|
||||
) => void;
|
||||
|
||||
function createBroadcastHarness() {
|
||||
const listeners: Array<Set<MessageListener>> = [];
|
||||
const closes: Array<ReturnType<typeof vi.fn>> = [];
|
||||
|
||||
function createChannel(): UploadCancellationBroadcastFacade {
|
||||
const ownIndex = listeners.length;
|
||||
const ownListeners = new Set<MessageListener>();
|
||||
const close = vi.fn();
|
||||
listeners.push(ownListeners);
|
||||
closes.push(close);
|
||||
return {
|
||||
postMessage(message) {
|
||||
for (const [index, peerListeners] of listeners.entries()) {
|
||||
if (index === ownIndex) continue;
|
||||
for (const listener of [...peerListeners]) {
|
||||
listener({ data: structuredClone(message) });
|
||||
}
|
||||
}
|
||||
},
|
||||
addEventListener(_type, listener) {
|
||||
ownListeners.add(listener);
|
||||
},
|
||||
removeEventListener(_type, listener) {
|
||||
ownListeners.delete(listener);
|
||||
},
|
||||
close,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
createChannel,
|
||||
emit(index: number, data: unknown) {
|
||||
for (const listener of [...(listeners[index] ?? [])]) {
|
||||
listener({ data });
|
||||
}
|
||||
},
|
||||
listenerCount(index: number) {
|
||||
return listeners[index]?.size ?? 0;
|
||||
},
|
||||
closes,
|
||||
};
|
||||
}
|
||||
|
||||
describe("browser upload cancellation channel", () => {
|
||||
it("delivers only the closed v1 wire message to another context", () => {
|
||||
const harness = createBroadcastHarness();
|
||||
const first = createBrowserUploadCancellationChannel({
|
||||
channelName: "product-upload-cancel-v1",
|
||||
createChannel: harness.createChannel,
|
||||
});
|
||||
const second = createBrowserUploadCancellationChannel({
|
||||
channelName: "product-upload-cancel-v1",
|
||||
createChannel: harness.createChannel,
|
||||
});
|
||||
expect(first).toBeDefined();
|
||||
expect(second).toBeDefined();
|
||||
if (!first || !second) return;
|
||||
|
||||
const received = vi.fn();
|
||||
const release = second.subscribe(received);
|
||||
expect(first.publish("upload_key_cross_context")).toBe(true);
|
||||
expect(received).toHaveBeenCalledOnce();
|
||||
expect(received).toHaveBeenCalledWith(
|
||||
"upload_key_cross_context",
|
||||
);
|
||||
|
||||
for (const malformed of [
|
||||
null,
|
||||
{
|
||||
protocol: "RESUMABLE_UPLOAD_CANCEL_V0",
|
||||
uploadKey: "upload_key_cross_context",
|
||||
},
|
||||
{
|
||||
protocol: "RESUMABLE_UPLOAD_CANCEL_V1",
|
||||
uploadKey: "short",
|
||||
},
|
||||
{
|
||||
protocol: "RESUMABLE_UPLOAD_CANCEL_V1",
|
||||
uploadKey: "upload_key_cross_context",
|
||||
extra: true,
|
||||
},
|
||||
]) {
|
||||
harness.emit(1, malformed);
|
||||
}
|
||||
expect(received).toHaveBeenCalledTimes(1);
|
||||
|
||||
release();
|
||||
second.close();
|
||||
expect(harness.listenerCount(1)).toBe(0);
|
||||
expect(harness.closes[1]).toHaveBeenCalledOnce();
|
||||
expect(second.publish("upload_key_cross_context")).toBe(false);
|
||||
first.close();
|
||||
});
|
||||
|
||||
it("fails closed when the host is unsupported and rejects invalid namespaces", () => {
|
||||
expect(
|
||||
createBrowserUploadCancellationChannel({ host: {} }),
|
||||
).toBeUndefined();
|
||||
expect(() =>
|
||||
createBrowserUploadCancellationChannel({
|
||||
channelName: "invalid channel name",
|
||||
host: {},
|
||||
}),
|
||||
).toThrow(/channel name/u);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user