1import { describe, expect, it } from "vite-plus/test";
2
3import {
4 beginProjectFaviconRequest,
5 createProjectFaviconRequest,
6 hasLoadedProjectFavicon,
7 markProjectFaviconFailed,
8 markProjectFaviconLoaded,
9} from "./projectFaviconRequests";
10
11describe("project favicon requests", () => {
12 it("ignores callbacks from a superseded URL", () => {
13 const cacheKey = "environment-1:/workspace:v1-favicon.svg";
14 const expiredUrl = "https://environment.example/api/assets/expired/v1-favicon.svg";
15 const refreshedUrl = "https://environment.example/api/assets/refreshed/v1-favicon.svg";
16
17 const expiredRequest = createProjectFaviconRequest(cacheKey, expiredUrl);
18 const endExpiredRequest = beginProjectFaviconRequest(expiredRequest);
19 markProjectFaviconLoaded(expiredRequest);
20 const refreshedRequest = createProjectFaviconRequest(cacheKey, refreshedUrl);
21 const endRefreshedRequest = beginProjectFaviconRequest(refreshedRequest);
22
23 expect(markProjectFaviconLoaded(expiredRequest)).toBe(false);
24 expect(markProjectFaviconFailed(expiredRequest)).toBe(false);
25 expect(hasLoadedProjectFavicon(cacheKey)).toBe(true);
26 expect(markProjectFaviconFailed(refreshedRequest)).toBe(true);
27 expect(hasLoadedProjectFavicon(cacheKey)).toBe(false);
28
29 endRefreshedRequest();
30 endExpiredRequest();
31 });
32
33 it("evicts the URL that actually failed", () => {
34 const cacheKey = "environment-1:/workspace:v2-favicon.svg";
35 const faviconUrl = "https://environment.example/api/assets/current/v2-favicon.svg";
36 const request = createProjectFaviconRequest(cacheKey, faviconUrl);
37 const endRequest = beginProjectFaviconRequest(request);
38
39 markProjectFaviconLoaded(request);
40
41 expect(markProjectFaviconFailed(request)).toBe(true);
42 expect(hasLoadedProjectFavicon(cacheKey)).toBe(false);
43
44 endRequest();
45 });
46
47 it("does not supersede a request until the next request begins", () => {
48 const cacheKey = "environment-1:/workspace:v3-favicon.svg";
49 const committedUrl = "https://environment.example/api/assets/current/v3-favicon.svg";
50 const abandonedUrl = "https://environment.example/api/assets/abandoned/v3-favicon.svg";
51 const committedRequest = createProjectFaviconRequest(cacheKey, committedUrl);
52 const endCommittedRequest = beginProjectFaviconRequest(committedRequest);
53
54 createProjectFaviconRequest(cacheKey, abandonedUrl);
55
56 expect(markProjectFaviconLoaded(committedRequest)).toBe(true);
57 expect(hasLoadedProjectFavicon(cacheKey)).toBe(true);
58
59 endCommittedRequest();
60 });
61
62 it("requires a cache key before creating a URL-bearing request", () => {
63 const firstUrl = "https://environment.example/api/assets/first/favicon.svg";
64 const secondUrl = "https://environment.example/api/assets/second/favicon.svg";
65
66 expect(createProjectFaviconRequest(null, firstUrl)).toBeNull();
67 expect(createProjectFaviconRequest(null, secondUrl)).toBeNull();
68 });
69
70 it("restores the remaining active URL when a newer request ends", () => {
71 const cacheKey = "environment-1:/workspace:v4-favicon.svg";
72 const firstRequest = createProjectFaviconRequest(
73 cacheKey,
74 "https://environment.example/api/assets/first/v4-favicon.svg",
75 );
76 const secondRequest = createProjectFaviconRequest(
77 cacheKey,
78 "https://environment.example/api/assets/second/v4-favicon.svg",
79 );
80 const endFirstRequest = beginProjectFaviconRequest(firstRequest);
81 const endSecondRequest = beginProjectFaviconRequest(secondRequest);
82
83 expect(markProjectFaviconLoaded(firstRequest)).toBe(false);
84 endSecondRequest();
85 expect(markProjectFaviconLoaded(firstRequest)).toBe(true);
86 endFirstRequest();
87 expect(markProjectFaviconLoaded(firstRequest)).toBe(false);
88 });
89
90 it("bounds remembered loaded revisions", () => {
91 const firstCacheKey = "environment-1:/workspace:revision-0";
92 let lastCacheKey = firstCacheKey;
93
94 for (let revision = 0; revision < 300; revision++) {
95 lastCacheKey = `environment-1:/workspace:revision-${revision}`;
96 const request = createProjectFaviconRequest(
97 lastCacheKey,
98 `https://environment.example/api/assets/revision-${revision}/favicon.svg`,
99 );
100 const endRequest = beginProjectFaviconRequest(request);
101 markProjectFaviconLoaded(request);
102 endRequest();
103 }
104
105 expect(hasLoadedProjectFavicon(firstCacheKey)).toBe(false);
106 expect(hasLoadedProjectFavicon(lastCacheKey)).toBe(true);
107 });
108});