9013fa0b49
Fire-and-forget POST on Platforms download clicks with tests and configurable tracking URL. Co-authored-by: Cursor <cursoragent@cursor.com>
48 lines
1.4 KiB
TypeScript
48 lines
1.4 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import { afterEach, describe, it, mock } from "node:test";
|
|
|
|
import {
|
|
DEFAULT_LICENSE_TRACKING_BASE,
|
|
resolveTrackDownloadUrl,
|
|
trackDownload,
|
|
} from "./trackDownload";
|
|
|
|
describe("trackDownload", () => {
|
|
afterEach(() => {
|
|
mock.restoreAll();
|
|
});
|
|
|
|
it("builds default tracking URL", () => {
|
|
assert.equal(
|
|
resolveTrackDownloadUrl(DEFAULT_LICENSE_TRACKING_BASE),
|
|
"https://license.ttrpgplayer.ru/v1/track/download",
|
|
);
|
|
});
|
|
|
|
it("normalizes base URL without trailing slash", () => {
|
|
assert.equal(
|
|
resolveTrackDownloadUrl("https://license.example.test"),
|
|
"https://license.example.test/v1/track/download",
|
|
);
|
|
});
|
|
|
|
it("POSTs platform with keepalive and swallows errors", async () => {
|
|
const fetchMock = mock.fn(() => Promise.reject(new Error("network down")));
|
|
globalThis.fetch = fetchMock;
|
|
|
|
trackDownload("macos");
|
|
|
|
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
|
|
assert.equal(fetchMock.mock.calls.length, 1);
|
|
const call = fetchMock.mock.calls[0];
|
|
assert.ok(call);
|
|
const [url, init] = call.arguments as unknown as [string, RequestInit];
|
|
assert.equal(url, "https://license.ttrpgplayer.ru/v1/track/download");
|
|
assert.equal(init.method, "POST");
|
|
assert.equal(init.keepalive, true);
|
|
assert.deepEqual(init.headers, { "Content-Type": "application/json" });
|
|
assert.equal(init.body, JSON.stringify({ platform: "macos" }));
|
|
});
|
|
});
|