@dash0/sdk-web 0.18.3 → 0.18.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,282 @@
1
+ import { expect, describe, it, vi, beforeEach, afterEach } from "vitest";
2
+ import { now, nowNanos, toNanosTs, getTimeOrigin, domHRTimestampToNanos } from "./time";
3
+ import * as globals from "./globals";
4
+
5
+ describe("now", () => {
6
+ it("returns the current time in milliseconds", () => {
7
+ const before = new Date().getTime();
8
+ const result = now();
9
+ const after = new Date().getTime();
10
+
11
+ expect(result).toBeGreaterThanOrEqual(before);
12
+ expect(result).toBeLessThanOrEqual(after);
13
+ });
14
+ });
15
+
16
+ describe("toNanosTs", () => {
17
+ it("converts milliseconds to nanoseconds as string", () => {
18
+ const ms = 1609459200000; // 2021-01-01 00:00:00 UTC
19
+ const result = toNanosTs(ms);
20
+ expect(result).toBe("1609459200000000000");
21
+ });
22
+
23
+ it("converts Date object to nanoseconds as string", () => {
24
+ const date = new Date(1609459200000);
25
+ const result = toNanosTs(date);
26
+ expect(result).toBe("1609459200000000000");
27
+ });
28
+
29
+ it("handles zero timestamp", () => {
30
+ const result = toNanosTs(0);
31
+ expect(result).toBe("0000000");
32
+ });
33
+
34
+ it("preserves precision", () => {
35
+ const ms = 1234567890123;
36
+ const result = toNanosTs(ms);
37
+ expect(result).toBe("1234567890123000000");
38
+ });
39
+ });
40
+
41
+ describe("getTimeOrigin", () => {
42
+ afterEach(() => {
43
+ vi.restoreAllMocks();
44
+ });
45
+
46
+ it("returns timeOrigin when available", () => {
47
+ const mockPerf = {
48
+ timeOrigin: 1609459200000,
49
+ now: vi.fn(),
50
+ };
51
+ vi.spyOn(globals, "perf", "get").mockReturnValue(mockPerf as any);
52
+
53
+ const result = getTimeOrigin();
54
+ expect(result).toBe(1609459200000);
55
+ });
56
+
57
+ it("falls back to timing.fetchStart when timeOrigin is not a number", () => {
58
+ const mockPerf = {
59
+ timing: {
60
+ fetchStart: 1609459200000,
61
+ },
62
+ now: vi.fn(),
63
+ };
64
+ vi.spyOn(globals, "perf", "get").mockReturnValue(mockPerf as any);
65
+
66
+ const result = getTimeOrigin();
67
+ expect(result).toBe(1609459200000);
68
+ });
69
+
70
+ it("returns undefined when perf is not available", () => {
71
+ vi.spyOn(globals, "perf", "get").mockReturnValue(undefined);
72
+
73
+ const result = getTimeOrigin();
74
+ expect(result).toBeUndefined();
75
+ });
76
+
77
+ it("returns undefined when both timeOrigin and fetchStart are unavailable", () => {
78
+ const mockPerf = {
79
+ now: vi.fn(),
80
+ };
81
+ vi.spyOn(globals, "perf", "get").mockReturnValue(mockPerf as any);
82
+
83
+ const result = getTimeOrigin();
84
+ expect(result).toBeUndefined();
85
+ });
86
+ });
87
+
88
+ describe("nowNanos", () => {
89
+ let dateNowSpy: any;
90
+
91
+ beforeEach(() => {
92
+ dateNowSpy = vi.spyOn(Date.prototype, "getTime");
93
+ });
94
+
95
+ afterEach(() => {
96
+ vi.restoreAllMocks();
97
+ });
98
+
99
+ it("uses performance time when available and not drifted", () => {
100
+ const timeOrigin = 1609459200000;
101
+ const perfNow = 5000; // 5 seconds after time origin
102
+ const expectedTime = timeOrigin + perfNow; // 1609459205000
103
+
104
+ const mockPerf = {
105
+ timeOrigin,
106
+ now: vi.fn().mockReturnValue(perfNow),
107
+ };
108
+ vi.spyOn(globals, "perf", "get").mockReturnValue(mockPerf as any);
109
+ dateNowSpy.mockReturnValue(expectedTime);
110
+
111
+ const result = nowNanos();
112
+ const expected = String(expectedTime * 1000000);
113
+ expect(result).toBe(expected);
114
+ });
115
+
116
+ it("falls back to Date when drift is exactly 60000ms (60 seconds)", () => {
117
+ const timeOrigin = 1609459200000;
118
+ const perfNow = 5000;
119
+ const perfTime = timeOrigin + perfNow; // 1609459205000
120
+ const dateTime = perfTime + 60000; // 60000ms drift
121
+
122
+ const mockPerf = {
123
+ timeOrigin,
124
+ now: vi.fn().mockReturnValue(perfNow),
125
+ };
126
+ vi.spyOn(globals, "perf", "get").mockReturnValue(mockPerf as any);
127
+ dateNowSpy.mockReturnValue(dateTime);
128
+
129
+ const result = nowNanos();
130
+ const expected = String(dateTime) + "000000";
131
+ expect(result).toBe(expected);
132
+ });
133
+
134
+ it("falls back to Date when drift exceeds 60000ms (positive)", () => {
135
+ const timeOrigin = 1609459200000;
136
+ const perfNow = 5000;
137
+ const perfTime = timeOrigin + perfNow;
138
+ const dateTime = perfTime + 65000; // 65000ms drift (browser slept)
139
+
140
+ const mockPerf = {
141
+ timeOrigin,
142
+ now: vi.fn().mockReturnValue(perfNow),
143
+ };
144
+ vi.spyOn(globals, "perf", "get").mockReturnValue(mockPerf as any);
145
+ dateNowSpy.mockReturnValue(dateTime);
146
+
147
+ const result = nowNanos();
148
+ const expected = String(dateTime) + "000000";
149
+ expect(result).toBe(expected);
150
+ });
151
+
152
+ it("falls back to Date when drift exceeds 60000ms (negative)", () => {
153
+ const timeOrigin = 1609459200000;
154
+ const perfNow = 5000;
155
+ const perfTime = timeOrigin + perfNow;
156
+ const dateTime = perfTime - 65000; // -65000ms drift (clock adjustment)
157
+
158
+ const mockPerf = {
159
+ timeOrigin,
160
+ now: vi.fn().mockReturnValue(perfNow),
161
+ };
162
+ vi.spyOn(globals, "perf", "get").mockReturnValue(mockPerf as any);
163
+ dateNowSpy.mockReturnValue(dateTime);
164
+
165
+ const result = nowNanos();
166
+ const expected = String(dateTime) + "000000";
167
+ expect(result).toBe(expected);
168
+ });
169
+
170
+ it("uses performance time when drift is just under 60000ms (59999ms)", () => {
171
+ const timeOrigin = 1609459200000;
172
+ const perfNow = 5000;
173
+ const perfTime = timeOrigin + perfNow;
174
+ const dateTime = perfTime + 59999; // 59999ms drift (still acceptable)
175
+
176
+ const mockPerf = {
177
+ timeOrigin,
178
+ now: vi.fn().mockReturnValue(perfNow),
179
+ };
180
+ vi.spyOn(globals, "perf", "get").mockReturnValue(mockPerf as any);
181
+ dateNowSpy.mockReturnValue(dateTime);
182
+
183
+ const result = nowNanos();
184
+ const expected = String(perfTime * 1000000);
185
+ expect(result).toBe(expected);
186
+ });
187
+
188
+ it("uses performance time when drift is just under -60000ms (-59999ms)", () => {
189
+ const timeOrigin = 1609459200000;
190
+ const perfNow = 5000;
191
+ const perfTime = timeOrigin + perfNow;
192
+ const dateTime = perfTime - 59999; // -59999ms drift (still acceptable)
193
+
194
+ const mockPerf = {
195
+ timeOrigin,
196
+ now: vi.fn().mockReturnValue(perfNow),
197
+ };
198
+ vi.spyOn(globals, "perf", "get").mockReturnValue(mockPerf as any);
199
+ dateNowSpy.mockReturnValue(dateTime);
200
+
201
+ const result = nowNanos();
202
+ const expected = String(perfTime * 1000000);
203
+ expect(result).toBe(expected);
204
+ });
205
+
206
+ it("falls back to Date when timeOrigin is not available", () => {
207
+ vi.spyOn(globals, "perf", "get").mockReturnValue(undefined);
208
+ const dateTime = 1609459205000;
209
+ dateNowSpy.mockReturnValue(dateTime);
210
+
211
+ const result = nowNanos();
212
+ const expected = String(dateTime) + "000000";
213
+ expect(result).toBe(expected);
214
+ });
215
+
216
+ it("falls back to Date when timeOrigin is not a number", () => {
217
+ const mockPerf = {
218
+ timeOrigin: undefined,
219
+ now: vi.fn().mockReturnValue(5000),
220
+ timing: {}, // no fetchStart either
221
+ };
222
+ vi.spyOn(globals, "perf", "get").mockReturnValue(mockPerf as any);
223
+ const dateTime = 1609459205000;
224
+ dateNowSpy.mockReturnValue(dateTime);
225
+
226
+ const result = nowNanos();
227
+ const expected = String(dateTime) + "000000";
228
+ expect(result).toBe(expected);
229
+ });
230
+ });
231
+
232
+ describe("domHRTimestampToNanos", () => {
233
+ afterEach(() => {
234
+ vi.restoreAllMocks();
235
+ });
236
+
237
+ it("converts DOM high resolution timestamp to nanoseconds", () => {
238
+ const timeOrigin = 1609459200000;
239
+ const hrTimestamp = 5000.123; // 5.000123 seconds after time origin
240
+
241
+ const mockPerf = {
242
+ timeOrigin,
243
+ now: vi.fn(),
244
+ };
245
+ vi.spyOn(globals, "perf", "get").mockReturnValue(mockPerf as any);
246
+
247
+ const result = domHRTimestampToNanos(hrTimestamp);
248
+ const expectedMs = timeOrigin + hrTimestamp;
249
+ const expectedNanos = String(Math.round(expectedMs * 1000000));
250
+ expect(result).toBe(expectedNanos);
251
+ });
252
+
253
+ it("rounds to nearest nanosecond", () => {
254
+ const timeOrigin = 1000;
255
+ const hrTimestamp = 0.0000001; // Very small fraction
256
+
257
+ const mockPerf = {
258
+ timeOrigin,
259
+ now: vi.fn(),
260
+ };
261
+ vi.spyOn(globals, "perf", "get").mockReturnValue(mockPerf as any);
262
+
263
+ const result = domHRTimestampToNanos(hrTimestamp);
264
+ const expectedMs = timeOrigin + hrTimestamp;
265
+ const expectedNanos = String(Math.round(expectedMs * 1000000));
266
+ expect(result).toBe(expectedNanos);
267
+ });
268
+
269
+ it("handles zero timestamp", () => {
270
+ const timeOrigin = 1609459200000;
271
+
272
+ const mockPerf = {
273
+ timeOrigin,
274
+ now: vi.fn(),
275
+ };
276
+ vi.spyOn(globals, "perf", "get").mockReturnValue(mockPerf as any);
277
+
278
+ const result = domHRTimestampToNanos(0);
279
+ const expectedNanos = String(Math.round(timeOrigin * 1000000));
280
+ expect(result).toBe(expectedNanos);
281
+ });
282
+ });