Skip to content
87 linesCodeBlameRaw
1import assert from "node:assert/strict";
2import { test } from "node:test";
3
4import {
5 MAX_PRODUCTION_IMAGE_BYTES,
6 cardSources,
7 externalTarget,
8 externalVersion,
9 productionImageUrl,
10 readProductionImageUpload,
11 utcDay,
12} from "./production-image.ts";
13
14const PNG = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0, 0, 0, 0];
15const GIF = [...new TextEncoder().encode("GIF89a"), 0, 0, 0, 0, 0, 0];
16
17function form(bytes: number[] | Uint8Array | null, type = "image/png"): FormData {
18 const data = new FormData();
19 if (bytes) data.set("image", new File([Uint8Array.from(bytes)], "shot.png", { type }));
20 return data;
21}
22
23test("an uploaded image is served from the usercontent origin by its hash", () => {
24 assert.equal(productionImageUrl("ab12", "https://g1tusercontent.com"), "https://g1tusercontent.com/production-images/ab12");
25 assert.equal(productionImageUrl("ab12"), "/production-images/ab12");
26});
27
28test("an upload is a PNG, JPEG or WebP of at most 5 MB, read by its bytes", async () => {
29 const ok = await readProductionImageUpload(form(PNG));
30 assert.ok("image" in ok);
31 assert.deepEqual(await readProductionImageUpload(form(null)), { error: "Choose an image to upload." });
32 assert.deepEqual(await readProductionImageUpload(form(GIF, "image/gif")), { error: "Use a PNG, JPEG or WebP image." });
33 // Named a PNG, but it is not one.
34 assert.deepEqual(await readProductionImageUpload(form([1, 2, 3, 4])), { error: "Use a PNG, JPEG or WebP image." });
35 const big = new Uint8Array(MAX_PRODUCTION_IMAGE_BYTES + 1);
36 big.set(PNG);
37 assert.deepEqual(await readProductionImageUpload(form(big)), { error: "Use an image of at most 5 MB." });
38});
39
40const now = Date.parse("2026-10-11T12:00:00Z");
41const elsewhere = { kind: "app", runs: "elsewhere", productionUrl: "https://g1t.sh", productionImage: null };
42const reported = { url: "https://app.example.com", sha: "ABC1234DEF5678ABC1234DEF5678ABC1234DEF56", created_at: "2026-10-11T10:00:00Z" };
43
44test("production elsewhere is taken at its address, versioned by the day", () => {
45 assert.deepEqual(externalTarget(elsewhere, null, now), { url: "https://g1t.sh", commit: "2026-10-11", since: null });
46 assert.equal(utcDay(now), "2026-10-11");
47});
48
49test("a reported production deployment gives the address and the commit", () => {
50 assert.deepEqual(externalTarget(elsewhere, reported, now), {
51 url: "https://app.example.com",
52 commit: reported.sha.toLowerCase(),
53 since: reported.created_at,
54 });
55 // No address of its own: the project's.
56 assert.equal(externalTarget(elsewhere, { ...reported, url: null }, now)?.url, "https://g1t.sh");
57 // An app nobody said runs where, reporting production, runs elsewhere.
58 assert.equal(externalTarget({ ...elsewhere, runs: null, productionUrl: null }, reported, now)?.url, "https://app.example.com");
59});
60
61test("no screenshot when it is not elsewhere, has no address, or shows an upload", () => {
62 assert.equal(externalTarget({ ...elsewhere, runs: "g1t" }, null, now), null);
63 assert.equal(externalTarget({ ...elsewhere, runs: null }, null, now), null);
64 assert.equal(externalTarget({ ...elsewhere, runs: null, kind: "library" }, reported, now), null);
65 assert.equal(externalTarget({ ...elsewhere, productionUrl: null }, null, now), null);
66 assert.equal(externalTarget({ ...elsewhere, productionUrl: "ftp://g1t.sh" }, null, now), null);
67 assert.equal(externalTarget({ ...elsewhere, productionImage: { preferred: true } }, reported, now), null);
68});
69
70test("a version changes with the deploy or the day", () => {
71 assert.equal(externalVersion({ url: "https://g1t.sh", commit: "2026-10-11", since: null }), "2026-10-11-0");
72 assert.equal(
73 externalVersion({ url: "https://g1t.sh", commit: "abc1234", since: "2026-10-11T10:00:00Z" }),
74 `abc1234-${Date.parse("2026-10-11T10:00:00Z")}`,
75 );
76});
77
78test("the card tries the screenshot, then the upload; a preferred upload alone", () => {
79 const upload = { url: "https://g1tusercontent.com/production-images/ab", preferred: false };
80 const shot = { src: "/a/b/production.jpg", kind: "screenshot" };
81 const uploaded = { src: upload.url, kind: "upload" };
82 assert.deepEqual(cardSources("/a/b/production.jpg", upload), [shot, uploaded]);
83 assert.deepEqual(cardSources("/a/b/production.jpg", { ...upload, preferred: true }), [uploaded]);
84 assert.deepEqual(cardSources(null, upload), [uploaded]);
85 assert.deepEqual(cardSources("/a/b/production.jpg", null), [shot]);
86 assert.deepEqual(cardSources(null, null), []);
87});