@volley/vwr-loader 1.0.5 → 1.1.0
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.
- package/README.md +21 -0
- package/dist/amplitudeFlagFetcher.d.ts +4 -2
- package/dist/amplitudeFlagFetcher.d.ts.map +1 -1
- package/dist/amplitudeFlagFetcher.js +26 -19
- package/dist/amplitudeFlagFetcher.js.map +1 -1
- package/dist/cli.js +213 -0
- package/dist/cli.js.map +1 -0
- package/dist/envDefaults.d.ts +3 -0
- package/dist/envDefaults.d.ts.map +1 -1
- package/dist/envDefaults.js +16 -4
- package/dist/envDefaults.js.map +1 -1
- package/dist/getDeviceId.d.ts +2 -40
- package/dist/getDeviceId.d.ts.map +1 -1
- package/dist/getDeviceId.js +31 -18
- package/dist/getDeviceId.js.map +1 -1
- package/dist/getEnvironment.d.ts +1 -1
- package/dist/getEnvironment.d.ts.map +1 -1
- package/dist/getEnvironment.js +15 -7
- package/dist/getEnvironment.js.map +1 -1
- package/dist/getShellVersion.d.ts +2 -19
- package/dist/getShellVersion.d.ts.map +1 -1
- package/dist/getShellVersion.js +41 -6
- package/dist/getShellVersion.js.map +1 -1
- package/dist/index.html +1 -1
- package/dist/loadVwr.d.ts.map +1 -1
- package/dist/loadVwr.js +8 -6
- package/dist/loadVwr.js.map +1 -1
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/types.d.ts +87 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/dist/vwrConfig.d.ts +2 -0
- package/dist/vwrConfig.d.ts.map +1 -1
- package/dist/vwrConfig.js +148 -119
- package/dist/vwrConfig.js.map +1 -1
- package/package.json +16 -5
- package/src/amplitudeFlagFetcher.test.ts +36 -59
- package/src/amplitudeFlagFetcher.ts +31 -22
- package/src/envDefaults.ts +23 -4
- package/src/getDeviceId.test.ts +89 -27
- package/src/getDeviceId.ts +35 -58
- package/src/getEnvironment.test.ts +479 -0
- package/src/getEnvironment.ts +16 -8
- package/src/getShellVersion.test.ts +123 -4
- package/src/getShellVersion.ts +46 -21
- package/src/loadVwr.ts +13 -6
- package/src/main.ts +3 -1
- package/src/types.ts +88 -0
- package/src/vite-env.d.ts +3 -0
- package/src/vwrConfig.test.ts +2 -2
- package/src/vwrConfig.ts +202 -199
- package/eslint.config.mjs +0 -23
- package/scripts/build.js +0 -2
- package/scripts/build.ts +0 -207
- package/tsconfig.eslint.json +0 -16
- package/tsconfig.json +0 -17
- package/vite.config.ts +0 -24
- package/vitest.config.ts +0 -8
|
@@ -0,0 +1,479 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"
|
|
2
|
+
|
|
3
|
+
import { type Environment, getEnvironment } from "./getEnvironment"
|
|
4
|
+
|
|
5
|
+
describe("getEnvironment", () => {
|
|
6
|
+
const mockLogger = {
|
|
7
|
+
info: vi.fn(),
|
|
8
|
+
warn: vi.fn(),
|
|
9
|
+
error: vi.fn(),
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
beforeEach(() => {
|
|
13
|
+
vi.clearAllMocks()
|
|
14
|
+
mockLogger.info.mockClear()
|
|
15
|
+
mockLogger.warn.mockClear()
|
|
16
|
+
mockLogger.error.mockClear()
|
|
17
|
+
// Clean up window properties
|
|
18
|
+
delete (window as any).Capacitor
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
afterEach(() => {
|
|
22
|
+
vi.restoreAllMocks()
|
|
23
|
+
delete (window as any).Capacitor
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
describe("Fire TV - Native Environment Detection", () => {
|
|
27
|
+
it("should read environment from native BuildConfig for Fire TV", async () => {
|
|
28
|
+
// Setup Capacitor plugin mock
|
|
29
|
+
Object.defineProperty(window, "Capacitor", {
|
|
30
|
+
value: {
|
|
31
|
+
Plugins: {
|
|
32
|
+
DeviceInfo: {
|
|
33
|
+
getNativeShellAppEnvironment: vi
|
|
34
|
+
.fn()
|
|
35
|
+
.mockResolvedValue({
|
|
36
|
+
environment: "development",
|
|
37
|
+
}),
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
writable: true,
|
|
42
|
+
configurable: true,
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
const result = await getEnvironment(
|
|
46
|
+
"FIRE_TV",
|
|
47
|
+
undefined,
|
|
48
|
+
mockLogger
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
expect(result.environment).toBe("dev")
|
|
52
|
+
expect(result.source).toBe("native")
|
|
53
|
+
expect(mockLogger.info).toHaveBeenCalledWith(
|
|
54
|
+
expect.stringContaining(
|
|
55
|
+
'Environment: "dev" (source: native BuildConfig.ENVIRONMENT="development")'
|
|
56
|
+
)
|
|
57
|
+
)
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
it("should map 'production' to 'prod'", async () => {
|
|
61
|
+
Object.defineProperty(window, "Capacitor", {
|
|
62
|
+
value: {
|
|
63
|
+
Plugins: {
|
|
64
|
+
DeviceInfo: {
|
|
65
|
+
getNativeShellAppEnvironment: vi
|
|
66
|
+
.fn()
|
|
67
|
+
.mockResolvedValue({
|
|
68
|
+
environment: "production",
|
|
69
|
+
}),
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
writable: true,
|
|
74
|
+
configurable: true,
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
const result = await getEnvironment(
|
|
78
|
+
"FIRE_TV",
|
|
79
|
+
undefined,
|
|
80
|
+
mockLogger
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
expect(result.environment).toBe("prod")
|
|
84
|
+
expect(result.source).toBe("native")
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
it("should map 'staging' to 'staging'", async () => {
|
|
88
|
+
Object.defineProperty(window, "Capacitor", {
|
|
89
|
+
value: {
|
|
90
|
+
Plugins: {
|
|
91
|
+
DeviceInfo: {
|
|
92
|
+
getNativeShellAppEnvironment: vi
|
|
93
|
+
.fn()
|
|
94
|
+
.mockResolvedValue({
|
|
95
|
+
environment: "staging",
|
|
96
|
+
}),
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
writable: true,
|
|
101
|
+
configurable: true,
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
const result = await getEnvironment(
|
|
105
|
+
"FIRE_TV",
|
|
106
|
+
undefined,
|
|
107
|
+
mockLogger
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
expect(result.environment).toBe("staging")
|
|
111
|
+
expect(result.source).toBe("native")
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
it("should map legacy 'qa' to 'staging'", async () => {
|
|
115
|
+
Object.defineProperty(window, "Capacitor", {
|
|
116
|
+
value: {
|
|
117
|
+
Plugins: {
|
|
118
|
+
DeviceInfo: {
|
|
119
|
+
getNativeShellAppEnvironment: vi
|
|
120
|
+
.fn()
|
|
121
|
+
.mockResolvedValue({
|
|
122
|
+
environment: "qa",
|
|
123
|
+
}),
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
writable: true,
|
|
128
|
+
configurable: true,
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
const result = await getEnvironment(
|
|
132
|
+
"FIRE_TV",
|
|
133
|
+
undefined,
|
|
134
|
+
mockLogger
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
expect(result.environment).toBe("staging")
|
|
138
|
+
expect(result.source).toBe("native")
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
it("should handle native env already in vwr format (dev)", async () => {
|
|
142
|
+
Object.defineProperty(window, "Capacitor", {
|
|
143
|
+
value: {
|
|
144
|
+
Plugins: {
|
|
145
|
+
DeviceInfo: {
|
|
146
|
+
getNativeShellAppEnvironment: vi
|
|
147
|
+
.fn()
|
|
148
|
+
.mockResolvedValue({
|
|
149
|
+
environment: "dev",
|
|
150
|
+
}),
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
writable: true,
|
|
155
|
+
configurable: true,
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
const result = await getEnvironment(
|
|
159
|
+
"FIRE_TV",
|
|
160
|
+
undefined,
|
|
161
|
+
mockLogger
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
expect(result.environment).toBe("dev")
|
|
165
|
+
expect(result.source).toBe("native")
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
it("should fallback to dev when native returns unknown value", async () => {
|
|
169
|
+
Object.defineProperty(window, "Capacitor", {
|
|
170
|
+
value: {
|
|
171
|
+
Plugins: {
|
|
172
|
+
DeviceInfo: {
|
|
173
|
+
getNativeShellAppEnvironment: vi
|
|
174
|
+
.fn()
|
|
175
|
+
.mockResolvedValue({
|
|
176
|
+
environment: "unknown-env",
|
|
177
|
+
}),
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
},
|
|
181
|
+
writable: true,
|
|
182
|
+
configurable: true,
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
const result = await getEnvironment(
|
|
186
|
+
"FIRE_TV",
|
|
187
|
+
undefined,
|
|
188
|
+
mockLogger
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
expect(result.environment).toBe("dev")
|
|
192
|
+
expect(result.source).toBe("native")
|
|
193
|
+
})
|
|
194
|
+
|
|
195
|
+
it("should fallback to build-time when native plugin unavailable", async () => {
|
|
196
|
+
// No Capacitor plugin available
|
|
197
|
+
const result = await getEnvironment(
|
|
198
|
+
"FIRE_TV",
|
|
199
|
+
"staging",
|
|
200
|
+
mockLogger
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
expect(result.environment).toBe("staging")
|
|
204
|
+
expect(result.source).toBe("build-time")
|
|
205
|
+
expect(mockLogger.warn).toHaveBeenCalledWith(
|
|
206
|
+
expect.stringContaining(
|
|
207
|
+
"Failed to read environment from native, falling back to build-time"
|
|
208
|
+
)
|
|
209
|
+
)
|
|
210
|
+
})
|
|
211
|
+
|
|
212
|
+
it("should fallback to build-time when native plugin throws error", async () => {
|
|
213
|
+
Object.defineProperty(window, "Capacitor", {
|
|
214
|
+
value: {
|
|
215
|
+
Plugins: {
|
|
216
|
+
DeviceInfo: {
|
|
217
|
+
getNativeShellAppEnvironment: vi
|
|
218
|
+
.fn()
|
|
219
|
+
.mockRejectedValue(
|
|
220
|
+
new Error("Native plugin error")
|
|
221
|
+
),
|
|
222
|
+
},
|
|
223
|
+
},
|
|
224
|
+
},
|
|
225
|
+
writable: true,
|
|
226
|
+
configurable: true,
|
|
227
|
+
})
|
|
228
|
+
|
|
229
|
+
const result = await getEnvironment("FIRE_TV", "prod", mockLogger)
|
|
230
|
+
|
|
231
|
+
expect(result.environment).toBe("prod")
|
|
232
|
+
expect(result.source).toBe("build-time")
|
|
233
|
+
expect(mockLogger.error).toHaveBeenCalled()
|
|
234
|
+
expect(mockLogger.warn).toHaveBeenCalledWith(
|
|
235
|
+
expect.stringContaining("falling back to build-time")
|
|
236
|
+
)
|
|
237
|
+
})
|
|
238
|
+
|
|
239
|
+
it("should fallback to build-time when native returns empty", async () => {
|
|
240
|
+
Object.defineProperty(window, "Capacitor", {
|
|
241
|
+
value: {
|
|
242
|
+
Plugins: {
|
|
243
|
+
DeviceInfo: {
|
|
244
|
+
getNativeShellAppEnvironment: vi
|
|
245
|
+
.fn()
|
|
246
|
+
.mockResolvedValue({
|
|
247
|
+
environment: "",
|
|
248
|
+
}),
|
|
249
|
+
},
|
|
250
|
+
},
|
|
251
|
+
},
|
|
252
|
+
writable: true,
|
|
253
|
+
configurable: true,
|
|
254
|
+
})
|
|
255
|
+
|
|
256
|
+
const result = await getEnvironment("FIRE_TV", "dev", mockLogger)
|
|
257
|
+
|
|
258
|
+
expect(result.environment).toBe("dev")
|
|
259
|
+
expect(result.source).toBe("build-time")
|
|
260
|
+
expect(mockLogger.error).toHaveBeenCalledWith(
|
|
261
|
+
expect.stringContaining(
|
|
262
|
+
"DeviceInfo.getNativeShellAppEnvironment returned empty"
|
|
263
|
+
)
|
|
264
|
+
)
|
|
265
|
+
})
|
|
266
|
+
|
|
267
|
+
it("should fallback to default when both native and build-time fail", async () => {
|
|
268
|
+
// No Capacitor plugin, no build-time env
|
|
269
|
+
const result = await getEnvironment(
|
|
270
|
+
"FIRE_TV",
|
|
271
|
+
undefined,
|
|
272
|
+
mockLogger
|
|
273
|
+
)
|
|
274
|
+
|
|
275
|
+
expect(result.environment).toBe("dev")
|
|
276
|
+
expect(result.source).toBe("default")
|
|
277
|
+
expect(mockLogger.warn).toHaveBeenCalledWith(
|
|
278
|
+
expect.stringContaining(
|
|
279
|
+
'Environment: "dev" (source: default fallback'
|
|
280
|
+
)
|
|
281
|
+
)
|
|
282
|
+
})
|
|
283
|
+
|
|
284
|
+
it("should be case-insensitive for Fire TV platform", async () => {
|
|
285
|
+
Object.defineProperty(window, "Capacitor", {
|
|
286
|
+
value: {
|
|
287
|
+
Plugins: {
|
|
288
|
+
DeviceInfo: {
|
|
289
|
+
getNativeShellAppEnvironment: vi
|
|
290
|
+
.fn()
|
|
291
|
+
.mockResolvedValue({
|
|
292
|
+
environment: "production",
|
|
293
|
+
}),
|
|
294
|
+
},
|
|
295
|
+
},
|
|
296
|
+
},
|
|
297
|
+
writable: true,
|
|
298
|
+
configurable: true,
|
|
299
|
+
})
|
|
300
|
+
|
|
301
|
+
const result1 = await getEnvironment(
|
|
302
|
+
"fire_tv",
|
|
303
|
+
undefined,
|
|
304
|
+
mockLogger
|
|
305
|
+
)
|
|
306
|
+
const result2 = await getEnvironment(
|
|
307
|
+
"FIRE_TV",
|
|
308
|
+
undefined,
|
|
309
|
+
mockLogger
|
|
310
|
+
)
|
|
311
|
+
|
|
312
|
+
expect(result1.environment).toBe("prod")
|
|
313
|
+
expect(result2.environment).toBe("prod")
|
|
314
|
+
})
|
|
315
|
+
})
|
|
316
|
+
|
|
317
|
+
describe("Non-Fire TV Platforms - Build-time Environment", () => {
|
|
318
|
+
const platforms = ["SAMSUNG_TV", "LG_TV", "MOBILE", "WEB"]
|
|
319
|
+
|
|
320
|
+
platforms.forEach((platform) => {
|
|
321
|
+
describe(`${platform}`, () => {
|
|
322
|
+
it("should use build-time environment when provided", async () => {
|
|
323
|
+
const result = await getEnvironment(
|
|
324
|
+
platform,
|
|
325
|
+
"staging",
|
|
326
|
+
mockLogger
|
|
327
|
+
)
|
|
328
|
+
|
|
329
|
+
expect(result.environment).toBe("staging")
|
|
330
|
+
expect(result.source).toBe("build-time")
|
|
331
|
+
expect(mockLogger.info).toHaveBeenCalledWith(
|
|
332
|
+
expect.stringContaining(
|
|
333
|
+
'Environment: "staging" (source: build-time CLI injection)'
|
|
334
|
+
)
|
|
335
|
+
)
|
|
336
|
+
})
|
|
337
|
+
|
|
338
|
+
it("should use build-time 'prod' environment", async () => {
|
|
339
|
+
const result = await getEnvironment(
|
|
340
|
+
platform,
|
|
341
|
+
"prod",
|
|
342
|
+
mockLogger
|
|
343
|
+
)
|
|
344
|
+
|
|
345
|
+
expect(result.environment).toBe("prod")
|
|
346
|
+
expect(result.source).toBe("build-time")
|
|
347
|
+
})
|
|
348
|
+
|
|
349
|
+
it("should use build-time 'dev' environment", async () => {
|
|
350
|
+
const result = await getEnvironment(
|
|
351
|
+
platform,
|
|
352
|
+
"dev",
|
|
353
|
+
mockLogger
|
|
354
|
+
)
|
|
355
|
+
|
|
356
|
+
expect(result.environment).toBe("dev")
|
|
357
|
+
expect(result.source).toBe("build-time")
|
|
358
|
+
})
|
|
359
|
+
|
|
360
|
+
it("should use build-time 'local' environment", async () => {
|
|
361
|
+
const result = await getEnvironment(
|
|
362
|
+
platform,
|
|
363
|
+
"local",
|
|
364
|
+
mockLogger
|
|
365
|
+
)
|
|
366
|
+
|
|
367
|
+
expect(result.environment).toBe("local")
|
|
368
|
+
expect(result.source).toBe("build-time")
|
|
369
|
+
})
|
|
370
|
+
|
|
371
|
+
it("should fallback to default when build-time not provided", async () => {
|
|
372
|
+
const result = await getEnvironment(
|
|
373
|
+
platform,
|
|
374
|
+
undefined,
|
|
375
|
+
mockLogger
|
|
376
|
+
)
|
|
377
|
+
|
|
378
|
+
expect(result.environment).toBe("dev")
|
|
379
|
+
expect(result.source).toBe("default")
|
|
380
|
+
expect(mockLogger.warn).toHaveBeenCalledWith(
|
|
381
|
+
expect.stringContaining(
|
|
382
|
+
'Environment: "dev" (source: default fallback'
|
|
383
|
+
)
|
|
384
|
+
)
|
|
385
|
+
})
|
|
386
|
+
|
|
387
|
+
it("should fallback to default when build-time is invalid", async () => {
|
|
388
|
+
const result = await getEnvironment(
|
|
389
|
+
platform,
|
|
390
|
+
"invalid-env",
|
|
391
|
+
mockLogger
|
|
392
|
+
)
|
|
393
|
+
|
|
394
|
+
expect(result.environment).toBe("dev")
|
|
395
|
+
expect(result.source).toBe("default")
|
|
396
|
+
})
|
|
397
|
+
})
|
|
398
|
+
})
|
|
399
|
+
})
|
|
400
|
+
|
|
401
|
+
describe("Environment Validation", () => {
|
|
402
|
+
it("should accept valid environments", async () => {
|
|
403
|
+
const validEnvs: Environment[] = ["local", "dev", "staging", "prod"]
|
|
404
|
+
|
|
405
|
+
for (const env of validEnvs) {
|
|
406
|
+
const result = await getEnvironment("WEB", env, mockLogger)
|
|
407
|
+
expect(result.environment).toBe(env)
|
|
408
|
+
expect(result.source).toBe("build-time")
|
|
409
|
+
}
|
|
410
|
+
})
|
|
411
|
+
|
|
412
|
+
it("should reject invalid environments", async () => {
|
|
413
|
+
const invalidEnvs = [
|
|
414
|
+
"development",
|
|
415
|
+
"production",
|
|
416
|
+
"qa",
|
|
417
|
+
"test",
|
|
418
|
+
"",
|
|
419
|
+
"random",
|
|
420
|
+
]
|
|
421
|
+
|
|
422
|
+
for (const env of invalidEnvs) {
|
|
423
|
+
const result = await getEnvironment("WEB", env, mockLogger)
|
|
424
|
+
expect(result.environment).toBe("dev")
|
|
425
|
+
expect(result.source).toBe("default")
|
|
426
|
+
}
|
|
427
|
+
})
|
|
428
|
+
})
|
|
429
|
+
|
|
430
|
+
describe("Logging", () => {
|
|
431
|
+
it("should log native environment source", async () => {
|
|
432
|
+
Object.defineProperty(window, "Capacitor", {
|
|
433
|
+
value: {
|
|
434
|
+
Plugins: {
|
|
435
|
+
DeviceInfo: {
|
|
436
|
+
getNativeShellAppEnvironment: vi
|
|
437
|
+
.fn()
|
|
438
|
+
.mockResolvedValue({
|
|
439
|
+
environment: "production",
|
|
440
|
+
}),
|
|
441
|
+
},
|
|
442
|
+
},
|
|
443
|
+
},
|
|
444
|
+
writable: true,
|
|
445
|
+
configurable: true,
|
|
446
|
+
})
|
|
447
|
+
|
|
448
|
+
await getEnvironment("FIRE_TV", undefined, mockLogger)
|
|
449
|
+
|
|
450
|
+
expect(mockLogger.info).toHaveBeenCalledWith(
|
|
451
|
+
'[Shell] Environment: "prod" (source: native BuildConfig.ENVIRONMENT="production")'
|
|
452
|
+
)
|
|
453
|
+
})
|
|
454
|
+
|
|
455
|
+
it("should log build-time environment source", async () => {
|
|
456
|
+
await getEnvironment("SAMSUNG_TV", "staging", mockLogger)
|
|
457
|
+
|
|
458
|
+
expect(mockLogger.info).toHaveBeenCalledWith(
|
|
459
|
+
'[Shell] Environment: "staging" (source: build-time CLI injection)'
|
|
460
|
+
)
|
|
461
|
+
})
|
|
462
|
+
|
|
463
|
+
it("should warn when falling back to default", async () => {
|
|
464
|
+
await getEnvironment("LG_TV", undefined, mockLogger)
|
|
465
|
+
|
|
466
|
+
expect(mockLogger.warn).toHaveBeenCalledWith(
|
|
467
|
+
'[Shell] Environment: "dev" (source: default fallback - no native or build-time env found)'
|
|
468
|
+
)
|
|
469
|
+
})
|
|
470
|
+
|
|
471
|
+
it("should warn when native fails and falls back", async () => {
|
|
472
|
+
await getEnvironment("FIRE_TV", "prod", mockLogger)
|
|
473
|
+
|
|
474
|
+
expect(mockLogger.warn).toHaveBeenCalledWith(
|
|
475
|
+
"[Shell] Failed to read environment from native, falling back to build-time"
|
|
476
|
+
)
|
|
477
|
+
})
|
|
478
|
+
})
|
|
479
|
+
})
|
package/src/getEnvironment.ts
CHANGED
|
@@ -19,7 +19,7 @@ export interface EnvironmentResult {
|
|
|
19
19
|
* This ensures production APKs cannot accidentally run dev VWR,
|
|
20
20
|
* since the native Android build variant determines the environment.
|
|
21
21
|
*
|
|
22
|
-
* @param platform - Platform identifier ('FIRE_TV', 'SAMSUNG_TV', 'LG_TV', '
|
|
22
|
+
* @param platform - Platform identifier ('FIRE_TV', 'SAMSUNG_TV', 'LG_TV', 'ANDROID_MOBILE', 'IOS_MOBILE', 'WEB')
|
|
23
23
|
* @param buildTimeEnv - Optional build-time injected environment (from CLI)
|
|
24
24
|
* @param logger - Optional logger for reporting
|
|
25
25
|
* @returns Environment result with source information for logging
|
|
@@ -48,13 +48,16 @@ export async function getEnvironment(
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
// Build-time injection (CLI --env flag)
|
|
51
|
-
if (buildTimeEnv
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
51
|
+
if (buildTimeEnv) {
|
|
52
|
+
const normalizedBuildTimeEnv = buildTimeEnv.toLowerCase()
|
|
53
|
+
if (isValidEnvironment(normalizedBuildTimeEnv)) {
|
|
54
|
+
logger.info(
|
|
55
|
+
`[Shell] Environment: "${normalizedBuildTimeEnv}" (source: build-time CLI injection)`
|
|
56
|
+
)
|
|
57
|
+
return {
|
|
58
|
+
environment: normalizedBuildTimeEnv as Environment,
|
|
59
|
+
source: "build-time",
|
|
60
|
+
}
|
|
58
61
|
}
|
|
59
62
|
}
|
|
60
63
|
|
|
@@ -110,12 +113,17 @@ async function getFireTVEnvironment(logger: Logger): Promise<string | null> {
|
|
|
110
113
|
* - "dev"
|
|
111
114
|
* - "staging"
|
|
112
115
|
* - "prod"
|
|
116
|
+
*
|
|
117
|
+
* Note: Legacy "qa" values are mapped to "staging".
|
|
113
118
|
*/
|
|
114
119
|
function mapNativeEnvironment(nativeEnv: string): Environment {
|
|
115
120
|
const normalized = nativeEnv.toLowerCase()
|
|
116
121
|
switch (normalized) {
|
|
117
122
|
case "development":
|
|
118
123
|
return "dev"
|
|
124
|
+
case "qa":
|
|
125
|
+
// Legacy: map qa to staging
|
|
126
|
+
return "staging"
|
|
119
127
|
case "staging":
|
|
120
128
|
return "staging"
|
|
121
129
|
case "production":
|
|
@@ -220,11 +220,130 @@ describe("getShellVersion", () => {
|
|
|
220
220
|
})
|
|
221
221
|
})
|
|
222
222
|
|
|
223
|
-
describe("Mobile", () => {
|
|
224
|
-
|
|
225
|
-
|
|
223
|
+
describe("Mobile (iOS)", () => {
|
|
224
|
+
afterEach(() => {
|
|
225
|
+
delete (window as any).iosAppContext
|
|
226
|
+
})
|
|
227
|
+
|
|
228
|
+
it("returns version from iosAppContext.appVersion", async () => {
|
|
229
|
+
;(window as any).iosAppContext = {
|
|
230
|
+
appVersion: "2.1.0",
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
const version = await getShellVersion("IOS_MOBILE")
|
|
234
|
+
|
|
235
|
+
expect(version).toBe("2.1.0")
|
|
236
|
+
})
|
|
237
|
+
|
|
238
|
+
it("returns unknown when iosAppContext is not available", async () => {
|
|
239
|
+
const consoleWarnSpy = vi
|
|
240
|
+
.spyOn(console, "warn")
|
|
241
|
+
.mockImplementation(() => {})
|
|
242
|
+
|
|
243
|
+
const version = await getShellVersion("IOS_MOBILE")
|
|
244
|
+
|
|
245
|
+
expect(version).toBe("unknown")
|
|
246
|
+
|
|
247
|
+
consoleWarnSpy.mockRestore()
|
|
248
|
+
})
|
|
249
|
+
|
|
250
|
+
it("returns unknown when appVersion is empty", async () => {
|
|
251
|
+
const consoleWarnSpy = vi
|
|
252
|
+
.spyOn(console, "warn")
|
|
253
|
+
.mockImplementation(() => {})
|
|
254
|
+
|
|
255
|
+
;(window as any).iosAppContext = {
|
|
256
|
+
appVersion: " ",
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
const version = await getShellVersion("IOS_MOBILE")
|
|
260
|
+
|
|
261
|
+
expect(version).toBe("unknown")
|
|
262
|
+
|
|
263
|
+
consoleWarnSpy.mockRestore()
|
|
264
|
+
})
|
|
265
|
+
|
|
266
|
+
it("is case insensitive", async () => {
|
|
267
|
+
;(window as any).iosAppContext = {
|
|
268
|
+
appVersion: "2.2.0",
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
const version = await getShellVersion("ios_mobile")
|
|
272
|
+
|
|
273
|
+
expect(version).toBe("2.2.0")
|
|
274
|
+
})
|
|
275
|
+
})
|
|
276
|
+
|
|
277
|
+
describe("Mobile (Android)", () => {
|
|
278
|
+
afterEach(() => {
|
|
279
|
+
delete (window as any).androidAppContext
|
|
280
|
+
})
|
|
281
|
+
|
|
282
|
+
it("returns version from androidAppContext.appVersion", async () => {
|
|
283
|
+
;(window as any).androidAppContext = {
|
|
284
|
+
appVersion: "3.1.0",
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
const version = await getShellVersion("ANDROID_MOBILE")
|
|
288
|
+
|
|
289
|
+
expect(version).toBe("3.1.0")
|
|
290
|
+
})
|
|
291
|
+
|
|
292
|
+
it("returns unknown when androidAppContext is not available", async () => {
|
|
293
|
+
const consoleWarnSpy = vi
|
|
294
|
+
.spyOn(console, "warn")
|
|
295
|
+
.mockImplementation(() => {})
|
|
296
|
+
|
|
297
|
+
const version = await getShellVersion("ANDROID_MOBILE")
|
|
298
|
+
|
|
299
|
+
expect(version).toBe("unknown")
|
|
300
|
+
|
|
301
|
+
consoleWarnSpy.mockRestore()
|
|
302
|
+
})
|
|
303
|
+
|
|
304
|
+
it("returns unknown when appVersion is empty", async () => {
|
|
305
|
+
const consoleWarnSpy = vi
|
|
306
|
+
.spyOn(console, "warn")
|
|
307
|
+
.mockImplementation(() => {})
|
|
308
|
+
|
|
309
|
+
;(window as any).androidAppContext = {
|
|
310
|
+
appVersion: "",
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
const version = await getShellVersion("ANDROID_MOBILE")
|
|
226
314
|
|
|
227
315
|
expect(version).toBe("unknown")
|
|
316
|
+
|
|
317
|
+
consoleWarnSpy.mockRestore()
|
|
318
|
+
})
|
|
319
|
+
|
|
320
|
+
it("is case insensitive", async () => {
|
|
321
|
+
;(window as any).androidAppContext = {
|
|
322
|
+
appVersion: "3.2.0",
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
const version = await getShellVersion("android_mobile")
|
|
326
|
+
|
|
327
|
+
expect(version).toBe("3.2.0")
|
|
328
|
+
})
|
|
329
|
+
|
|
330
|
+
it("prefers iOS context when both are available", async () => {
|
|
331
|
+
;(window as any).iosAppContext = {
|
|
332
|
+
appVersion: "1.0.0-ios",
|
|
333
|
+
}
|
|
334
|
+
;(window as any).androidAppContext = {
|
|
335
|
+
appVersion: "1.0.0-android",
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// When calling with IOS_MOBILE, should get iOS version
|
|
339
|
+
const iosVersion = await getShellVersion("IOS_MOBILE")
|
|
340
|
+
expect(iosVersion).toBe("1.0.0-ios")
|
|
341
|
+
|
|
342
|
+
// When calling with ANDROID_MOBILE, should still check iOS first (matching SDK behavior)
|
|
343
|
+
const androidVersion = await getShellVersion("ANDROID_MOBILE")
|
|
344
|
+
expect(androidVersion).toBe("1.0.0-ios")
|
|
345
|
+
|
|
346
|
+
delete (window as any).iosAppContext
|
|
228
347
|
})
|
|
229
348
|
})
|
|
230
349
|
|
|
@@ -268,7 +387,7 @@ describe("getShellVersion", () => {
|
|
|
268
387
|
expect(version).toBe("unknown")
|
|
269
388
|
expect(consoleWarnSpy).toHaveBeenCalledWith(
|
|
270
389
|
"[Shell] Failed to get shell version:",
|
|
271
|
-
expect.any(Error)
|
|
390
|
+
{ error: expect.any(Error) }
|
|
272
391
|
)
|
|
273
392
|
|
|
274
393
|
consoleWarnSpy.mockRestore()
|