FERS 1.0.0
The Flexible Extensible Radar Simulator
Loading...
Searching...
No Matches
simulationProgress.test.ts
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-only
2// Copyright (c) 2026-present FERS Contributors (see AUTHORS.md).
3
4import { describe, expect, test } from 'bun:test';
5import type { SimulationProgressState } from '@/stores/simulationProgressStore';
6import {
7 addSimulationProgressEvent,
8 getSimulationProgressPercent,
9 normalizeCompletedProgressSnapshot,
10} from './simulationProgress';
11
12const trackProgress = (events: SimulationProgressState[]) => {
13 const tracked: Record<string, SimulationProgressState> = {};
14
15 for (const event of events) {
16 Object.assign(tracked, addSimulationProgressEvent(tracked, event));
17 }
18
19 return tracked;
20};
21
22describe('simulation progress normalization', () => {
23 test('keeps CW receiver phases on one stable row', () => {
24 const tracked = trackProgress([
25 {
26 message: 'Finalizing CW Receiver CWRadar',
27 current: 0,
28 total: 100,
29 },
30 {
31 message: 'Rendering Interference for CWRadar',
32 current: 25,
33 total: 100,
34 },
35 {
36 message: 'Applying Noise for CWRadar',
37 current: 50,
38 total: 100,
39 },
40 {
41 message: 'Writing HDF5 for CWRadar',
42 current: 75,
43 total: 100,
44 },
45 {
46 message: 'Finalized CWRadar',
47 current: 100,
48 total: 100,
49 },
50 ]);
51
52 expect(Object.keys(tracked)).toEqual(['receiver:CWRadar']);
53 expect(tracked['receiver:CWRadar']).toEqual({
54 message: 'Finalized CWRadar',
55 current: 100,
56 total: 100,
57 details: [
58 {
59 id: 'cw-finalizing',
60 message: 'Finalizing CW Receiver CWRadar',
61 current: 0,
62 total: 100,
63 },
64 {
65 id: 'cw-rendering-interference',
66 message: 'Rendering Interference for CWRadar',
67 current: 25,
68 total: 100,
69 },
70 {
71 id: 'cw-applying-noise',
72 message: 'Applying Noise for CWRadar',
73 current: 50,
74 total: 100,
75 },
76 {
77 id: 'cw-writing-hdf5',
78 message: 'Writing HDF5 for CWRadar',
79 current: 75,
80 total: 100,
81 },
82 {
83 id: 'cw-finalized',
84 message: 'Finalized CWRadar',
85 current: 100,
86 total: 100,
87 },
88 ],
89 });
90 });
91
92 test('keeps pulsed export chunks and completion on one stable row', () => {
93 const tracked = trackProgress([
94 {
95 message: 'Exporting PulsedRadar: Chunk 9928',
96 current: 9928,
97 total: 0,
98 },
99 {
100 message: 'Finished Exporting PulsedRadar',
101 current: 100,
102 total: 100,
103 },
104 ]);
105
106 expect(Object.keys(tracked)).toEqual(['receiver:PulsedRadar']);
107 expect(tracked['receiver:PulsedRadar']).toEqual({
108 message: 'Finished Exporting PulsedRadar',
109 current: 100,
110 total: 100,
111 details: [
112 {
113 id: 'export-chunk',
114 message: 'Exporting PulsedRadar: Chunk 9928',
115 current: 9928,
116 total: 0,
117 },
118 {
119 id: 'export-finished',
120 message: 'Finished Exporting PulsedRadar',
121 current: 100,
122 total: 100,
123 },
124 ],
125 });
126 });
127
128 test('keeps only the latest chunk detail for high-volume export updates', () => {
129 const tracked = trackProgress([
130 {
131 message: 'Exporting PulsedRadar: Chunk 10',
132 current: 10,
133 total: 0,
134 },
135 {
136 message: 'Exporting PulsedRadar: Chunk 9928',
137 current: 9928,
138 total: 0,
139 },
140 ]);
141
142 expect(tracked['receiver:PulsedRadar'].details).toEqual([
143 {
144 id: 'export-chunk',
145 message: 'Exporting PulsedRadar: Chunk 9928',
146 current: 9928,
147 total: 0,
148 },
149 ]);
150 });
151
152 test('keeps main simulation messages out of the detail list', () => {
153 const tracked = trackProgress([
154 {
155 message: 'Simulating... 1.00s / 10.00s',
156 current: 10,
157 total: 100,
158 },
159 {
160 message: 'Main simulation finished. Waiting for data export...',
161 current: 100,
162 total: 100,
163 },
164 {
165 message: 'Simulation complete',
166 current: 100,
167 total: 100,
168 },
169 ]);
170
171 expect(Object.keys(tracked)).toEqual(['main']);
172 expect(tracked.main).toEqual({
173 message: 'Simulation complete',
174 current: 100,
175 total: 100,
176 details: [
177 {
178 id: 'main-progress',
179 message: 'Simulating... 1.00s / 10.00s',
180 current: 10,
181 total: 100,
182 },
183 {
184 id: 'main-export-wait',
185 message:
186 'Main simulation finished. Waiting for data export...',
187 current: 100,
188 total: 100,
189 },
190 {
191 id: 'main-complete',
192 message: 'Simulation complete',
193 current: 100,
194 total: 100,
195 },
196 ],
197 });
198 });
199
200 test('marks known stale receiver and export rows complete after success', () => {
201 const completed = normalizeCompletedProgressSnapshot({
202 CW: {
203 message: 'Finalizing CW Receiver CWRadar',
204 current: 0,
205 total: 100,
206 },
207 HDF5: {
208 message: 'Writing HDF5 for CWRadar',
209 current: 75,
210 total: 100,
211 },
212 PulsedRadar: {
213 message: 'Exporting PulsedRadar: Chunk 9928',
214 current: 9928,
215 total: 0,
216 },
217 main: {
218 message: 'Main simulation finished. Waiting for data export...',
219 current: 100,
220 total: 100,
221 },
222 });
223
224 expect(completed).toEqual({
225 'receiver:CWRadar': {
226 message: 'Finalized CWRadar',
227 current: 100,
228 total: 100,
229 details: [
230 {
231 id: 'cw-finalizing',
232 message: 'Finalizing CW Receiver CWRadar',
233 current: 0,
234 total: 100,
235 },
236 {
237 id: 'cw-writing-hdf5',
238 message: 'Writing HDF5 for CWRadar',
239 current: 75,
240 total: 100,
241 },
242 {
243 id: 'cw-finalized',
244 message: 'Finalized CWRadar',
245 current: 100,
246 total: 100,
247 },
248 ],
249 },
250 'receiver:PulsedRadar': {
251 message: 'Finished Exporting PulsedRadar',
252 current: 100,
253 total: 100,
254 details: [
255 {
256 id: 'export-chunk',
257 message: 'Exporting PulsedRadar: Chunk 9928',
258 current: 9928,
259 total: 0,
260 },
261 {
262 id: 'export-finished',
263 message: 'Finished Exporting PulsedRadar',
264 current: 100,
265 total: 100,
266 },
267 ],
268 },
269 main: {
270 message: 'Simulation complete',
271 current: 100,
272 total: 100,
273 details: [
274 {
275 id: 'main-export-wait',
276 message:
277 'Main simulation finished. Waiting for data export...',
278 current: 100,
279 total: 100,
280 },
281 {
282 id: 'main-complete',
283 message: 'Simulation complete',
284 current: 100,
285 total: 100,
286 },
287 ],
288 },
289 });
290 });
291
292 test('clamps determinate progress percentages', () => {
293 expect(
294 getSimulationProgressPercent({
295 message: 'below',
296 current: -10,
297 total: 100,
298 })
299 ).toBe(0);
300 expect(
301 getSimulationProgressPercent({
302 message: 'above',
303 current: 125,
304 total: 100,
305 })
306 ).toBe(100);
307 expect(
308 getSimulationProgressPercent({
309 message: 'chunk',
310 current: 9928,
311 total: 0,
312 })
313 ).toBeNull();
314 });
315});