1import { AtomRegistry } from "effect/reactivity";
2import * as AsyncResult from "effect/reactivity/AsyncResult";
3import { afterAll, afterEach, describe, expect, it, vi } from "vite-plus/test";
4
5import { npmReleasePublishedAtom } from "./npmRelease";
6
7const version = "0.0.46-nightly.20261012.3021";
8
9// FetchHttpClient reads globalThis.fetch once and keeps it, so every test shares this mock.
10const fetchMock = vi.fn<typeof fetch>();
11vi.stubGlobal("fetch", fetchMock);
12
13async function settledCheck() {
14 const atom = npmReleasePublishedAtom(version);
15 const registry = AtomRegistry.make();
16 const unmount = registry.mount(atom);
17 try {
18 await vi.waitFor(() => {
19 const result = registry.get(atom);
20 expect(AsyncResult.isInitial(result) || result.waiting).toBe(false);
21 });
22 return registry.get(atom);
23 } finally {
24 unmount();
25 registry.dispose();
26 }
27}
28
29describe("npmReleasePublishedAtom", () => {
30 afterEach(() => {
31 fetchMock.mockReset();
32 });
33
34 afterAll(() => {
35 vi.unstubAllGlobals();
36 });
37
38 it("checks npm without tracing headers, so the browser skips the preflight npm rejects", async () => {
39 fetchMock.mockImplementation(async () => Response.json({ version }));
40
41 const result = await settledCheck();
42
43 expect(fetchMock).toHaveBeenCalledTimes(1);
44 const request = new Request(fetchMock.mock.calls[0]?.[0] ?? "", fetchMock.mock.calls[0]?.[1]);
45 expect(request.url).toBe(`https://registry.npmjs.org/t3/${version}`);
46 expect(request.headers.get("traceparent")).toBeNull();
47 expect(request.headers.get("b3")).toBeNull();
48 expect(AsyncResult.getOrElse(result, () => false)).toBe(true);
49 });
50
51 it("reports a version npm does not have as unpublished", async () => {
52 fetchMock.mockImplementation(async () => new Response(null, { status: 404 }));
53
54 const result = await settledCheck();
55
56 expect(AsyncResult.isSuccess(result)).toBe(true);
57 expect(AsyncResult.getOrElse(result, () => true)).toBe(false);
58 });
59
60 it("leaves a failed first check unknown, which callers read as unpublished", async () => {
61 fetchMock.mockRejectedValue(new TypeError("Failed to fetch"));
62
63 const result = await settledCheck();
64
65 expect(AsyncResult.isFailure(result)).toBe(true);
66 expect(AsyncResult.getOrElse(result, () => false)).toBe(false);
67 });
68});