1import { beforeEach, describe, expect, it } from "vite-plus/test";
2
3import {
4 acquireBrowserSurface,
5 acquireBrowserSurfaceActivity,
6 resolveBrowserSurfacePanelRect,
7 useBrowserSurfaceStore,
8} from "./browserSurfaceStore";
9
10describe("browserSurfaceStore", () => {
11 beforeEach(() => {
12 useBrowserSurfaceStore.setState({ activityByTabId: {}, byTabId: {} });
13 });
14
15 it("keeps concurrent background work active until every lease is released", () => {
16 const first = acquireBrowserSurfaceActivity("background-browser");
17 const second = acquireBrowserSurfaceActivity("background-browser");
18
19 first();
20 expect(useBrowserSurfaceStore.getState().activityByTabId["background-browser"]).toBe(1);
21
22 second();
23 expect(useBrowserSurfaceStore.getState().activityByTabId["background-browser"]).toBeUndefined();
24 });
25
26 it("freezes the source content dimensions for a fitted presentation", () => {
27 const tabId = "fitted-browser-surface";
28 const sourceOwner = Symbol("source");
29 const sourceContent = {
30 x: 10,
31 y: 20,
32 width: 1_280,
33 height: 720,
34 scale: 1,
35 scrollLeft: 0,
36 scrollTop: 0,
37 };
38 useBrowserSurfaceStore.getState().claim(tabId, sourceOwner, false);
39 useBrowserSurfaceStore.getState().presentContent(tabId, sourceContent);
40
41 const fittedLease = acquireBrowserSurface(tabId, true);
42 useBrowserSurfaceStore.getState().presentContent(tabId, {
43 ...sourceContent,
44 width: 360,
45 height: 203,
46 scale: 0.28125,
47 });
48
49 expect(useBrowserSurfaceStore.getState().byTabId[tabId]?.fittedSourceContent).toEqual(
50 sourceContent,
51 );
52 fittedLease.release();
53 });
54
55 it("freezes the first content dimensions when fitting starts before the browser is measured", () => {
56 const tabId = "pending-fitted-browser-surface";
57 const fittedLease = acquireBrowserSurface(tabId, true);
58 const sourceContent = {
59 x: 0,
60 y: 0,
61 width: 1_280,
62 height: 720,
63 scale: 1,
64 scrollLeft: 0,
65 scrollTop: 0,
66 };
67
68 useBrowserSurfaceStore.getState().presentContent(tabId, sourceContent);
69 useBrowserSurfaceStore.getState().presentContent(tabId, {
70 ...sourceContent,
71 width: 320,
72 height: 180,
73 scale: 0.25,
74 });
75
76 expect(useBrowserSurfaceStore.getState().byTabId[tabId]?.fittedSourceContent).toEqual(
77 sourceContent,
78 );
79 fittedLease.release();
80 });
81
82 it("tracks content dimensions for a browser that has never been visible", () => {
83 const tabId = "hidden-browser-surface-content-test";
84 useBrowserSurfaceStore.getState().presentContent(tabId, {
85 x: 0,
86 y: 0,
87 width: 393,
88 height: 852,
89 scale: 1,
90 scrollLeft: 0,
91 scrollTop: 0,
92 });
93
94 expect(useBrowserSurfaceStore.getState().byTabId[tabId]).toMatchObject({
95 rect: null,
96 visible: false,
97 content: { width: 393, height: 852 },
98 });
99 });
100
101 it("keeps a hidden background tab on its own last rect", () => {
102 const staleRect = { x: 0, y: 0, width: 500, height: 700 };
103 const liveRect = { x: 10, y: 20, width: 900, height: 640 };
104 expect(
105 resolveBrowserSurfacePanelRect(
106 {
107 hidden: {
108 rect: staleRect,
109 visible: false,
110 zIndex: 30,
111 content: null,
112 fittedSourceContent: null,
113 fitSourceContent: false,
114 cornerRadius: 0,
115 updatedAt: 1,
116 owner: null,
117 },
118 active: {
119 rect: liveRect,
120 visible: true,
121 zIndex: 30,
122 content: null,
123 fittedSourceContent: null,
124 fitSourceContent: false,
125 cornerRadius: 0,
126 updatedAt: 2,
127 owner: null,
128 },
129 },
130 "hidden",
131 ),
132 ).toEqual(staleRect);
133 });
134
135 it("ignores updates and releases from a stale surface lease", () => {
136 const tabId = "leased-browser-surface";
137 const staleRect = { x: 0, y: 0, width: 500, height: 700 };
138 const liveRect = { x: 10, y: 20, width: 900, height: 640 };
139 const staleLease = acquireBrowserSurface(tabId);
140 staleLease.present(staleRect, true);
141
142 const liveLease = acquireBrowserSurface(tabId);
143 liveLease.present(liveRect, true);
144 expect(staleLease.present(staleRect, true)).toBe(false);
145 staleLease.release();
146
147 expect(useBrowserSurfaceStore.getState().byTabId[tabId]).toMatchObject({
148 rect: liveRect,
149 visible: true,
150 });
151 });
152
153 it("hides a surface when its current lease is released", () => {
154 const tabId = "released-browser-surface";
155 const lease = acquireBrowserSurface(tabId);
156 lease.present({ x: 10, y: 20, width: 900, height: 640 }, true);
157
158 lease.release();
159 lease.present({ x: 0, y: 0, width: 1, height: 1 }, true);
160
161 expect(useBrowserSurfaceStore.getState().byTabId[tabId]).toMatchObject({
162 visible: false,
163 owner: null,
164 });
165 });
166
167 it("keeps the requested layer with the active surface lease", () => {
168 const tabId = "layered-browser-surface";
169 const lease = acquireBrowserSurface(tabId);
170 lease.present({ x: 10, y: 20, width: 320, height: 200 }, true, 12, 48);
171
172 expect(useBrowserSurfaceStore.getState().byTabId[tabId]).toMatchObject({
173 visible: true,
174 zIndex: 48,
175 });
176 });
177
178 it("clears fitted presentation state when its lease is released", () => {
179 const tabId = "released-fitted-browser-surface";
180 const fittedLease = acquireBrowserSurface(tabId, true);
181 useBrowserSurfaceStore.getState().presentContent(tabId, {
182 x: 0,
183 y: 0,
184 width: 1_280,
185 height: 800,
186 scale: 1,
187 scrollLeft: 0,
188 scrollTop: 0,
189 });
190
191 fittedLease.release();
192
193 expect(useBrowserSurfaceStore.getState().byTabId[tabId]).toMatchObject({
194 fittedSourceContent: null,
195 fitSourceContent: false,
196 owner: null,
197 visible: false,
198 });
199 });
200});