@volley/vwr-loader 1.4.0 → 1.6.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 +1 -1
- package/dist/cli.js +41 -6
- package/dist/cli.js.map +1 -1
- package/dist/main.js +11 -11
- package/dist/main.js.map +1 -1
- package/dist/{datadog.d.ts → vwr/src/datadog.d.ts} +7 -3
- package/dist/vwr/src/datadog.d.ts.map +1 -0
- package/dist/{datadog.js → vwr/src/datadog.js} +6 -5
- package/dist/vwr/src/datadog.js.map +1 -0
- package/dist/{envDefaults.d.ts → vwr/src/envDefaults.d.ts} +1 -0
- package/dist/vwr/src/envDefaults.d.ts.map +1 -0
- package/dist/{envDefaults.js → vwr/src/envDefaults.js} +30 -3
- package/dist/vwr/src/envDefaults.js.map +1 -0
- package/dist/vwr/src/logger.d.ts +15 -0
- package/dist/vwr/src/logger.d.ts.map +1 -0
- package/dist/{logger.js → vwr/src/logger.js} +30 -46
- package/dist/vwr/src/logger.js.map +1 -0
- package/dist/vwr/src/native/device-info/getDeviceId.d.ts +13 -0
- package/dist/vwr/src/native/device-info/getDeviceId.d.ts.map +1 -0
- package/dist/vwr/src/native/device-info/getDeviceId.js +137 -0
- package/dist/vwr/src/native/device-info/getDeviceId.js.map +1 -0
- package/dist/{vwrConfig.d.ts → vwr/src/vwrConfig.d.ts} +5 -0
- package/dist/vwr/src/vwrConfig.d.ts.map +1 -0
- package/dist/{vwrConfig.js → vwr/src/vwrConfig.js} +13 -5
- package/dist/vwr/src/vwrConfig.js.map +1 -0
- package/dist/vwr-loader/src/__mocks__/@datadog/browser-logs.d.ts.map +1 -0
- package/dist/vwr-loader/src/__mocks__/@datadog/browser-logs.js.map +1 -0
- package/dist/vwr-loader/src/__mocks__/@datadog/browser-rum.d.ts.map +1 -0
- package/dist/vwr-loader/src/__mocks__/@datadog/browser-rum.js.map +1 -0
- package/dist/vwr-loader/src/__mocks__/vwrModule.d.ts +2 -0
- package/dist/vwr-loader/src/__mocks__/vwrModule.d.ts.map +1 -0
- package/dist/vwr-loader/src/__mocks__/vwrModule.js +3 -0
- package/dist/vwr-loader/src/__mocks__/vwrModule.js.map +1 -0
- package/dist/vwr-loader/src/amplitudeFlagFetcher.d.ts.map +1 -0
- package/dist/vwr-loader/src/amplitudeFlagFetcher.js.map +1 -0
- package/dist/vwr-loader/src/errors/InitializationError.d.ts.map +1 -0
- package/dist/vwr-loader/src/errors/InitializationError.js.map +1 -0
- package/dist/vwr-loader/src/errors/ensureError.d.ts.map +1 -0
- package/dist/vwr-loader/src/errors/ensureError.js.map +1 -0
- package/dist/vwr-loader/src/errors/index.d.ts.map +1 -0
- package/dist/vwr-loader/src/errors/index.js.map +1 -0
- package/dist/{exitHandler.d.ts → vwr-loader/src/exitHandler.d.ts} +14 -0
- package/dist/vwr-loader/src/exitHandler.d.ts.map +1 -0
- package/dist/{exitHandler.js → vwr-loader/src/exitHandler.js} +82 -1
- package/dist/vwr-loader/src/exitHandler.js.map +1 -0
- package/dist/vwr-loader/src/getEnvironment.d.ts.map +1 -0
- package/dist/vwr-loader/src/getEnvironment.js.map +1 -0
- package/dist/vwr-loader/src/getShellVersion.d.ts.map +1 -0
- package/dist/vwr-loader/src/getShellVersion.js.map +1 -0
- package/dist/vwr-loader/src/index.d.ts +8 -0
- package/dist/vwr-loader/src/index.d.ts.map +1 -0
- package/dist/vwr-loader/src/index.js +6 -0
- package/dist/vwr-loader/src/index.js.map +1 -0
- package/dist/vwr-loader/src/loadVwr.d.ts.map +1 -0
- package/dist/{loadVwr.js → vwr-loader/src/loadVwr.js} +29 -6
- package/dist/vwr-loader/src/loadVwr.js.map +1 -0
- package/dist/vwr-loader/src/logger.d.ts +4 -0
- package/dist/vwr-loader/src/logger.d.ts.map +1 -0
- package/dist/vwr-loader/src/logger.js +10 -0
- package/dist/vwr-loader/src/logger.js.map +1 -0
- package/dist/vwr-loader/src/main.d.ts +2 -0
- package/dist/vwr-loader/src/main.d.ts.map +1 -0
- package/dist/vwr-loader/src/main.js +96 -0
- package/dist/vwr-loader/src/main.js.map +1 -0
- package/dist/vwr-loader/src/polyfills.d.ts.map +1 -0
- package/dist/vwr-loader/src/polyfills.js.map +1 -0
- package/dist/{test-setup.d.ts.map → vwr-loader/src/test-setup.d.ts.map} +1 -1
- package/dist/vwr-loader/src/test-setup.js.map +1 -0
- package/package.json +10 -8
- package/src/__mocks__/vwrModule.ts +3 -0
- package/src/exitHandler.test.ts +241 -3
- package/src/exitHandler.ts +109 -1
- package/src/getShellVersion.ts +2 -1
- package/src/index.ts +3 -3
- package/src/loadVwr.test.ts +170 -10
- package/src/loadVwr.ts +39 -12
- package/src/logger.ts +5 -115
- package/src/main.ts +16 -8
- package/src/vite-env.d.ts +1 -0
- package/dist/__mocks__/@datadog/browser-logs.d.ts.map +0 -1
- package/dist/__mocks__/@datadog/browser-logs.js.map +0 -1
- package/dist/__mocks__/@datadog/browser-rum.d.ts.map +0 -1
- package/dist/__mocks__/@datadog/browser-rum.js.map +0 -1
- package/dist/amplitudeFlagFetcher.d.ts.map +0 -1
- package/dist/amplitudeFlagFetcher.js.map +0 -1
- package/dist/datadog.d.ts.map +0 -1
- package/dist/datadog.js.map +0 -1
- package/dist/envDefaults.d.ts.map +0 -1
- package/dist/envDefaults.js.map +0 -1
- package/dist/errors/InitializationError.d.ts.map +0 -1
- package/dist/errors/InitializationError.js.map +0 -1
- package/dist/errors/ensureError.d.ts.map +0 -1
- package/dist/errors/ensureError.js.map +0 -1
- package/dist/errors/index.d.ts.map +0 -1
- package/dist/errors/index.js.map +0 -1
- package/dist/exitHandler.d.ts.map +0 -1
- package/dist/exitHandler.js.map +0 -1
- package/dist/getDeviceId.d.ts +0 -26
- package/dist/getDeviceId.d.ts.map +0 -1
- package/dist/getDeviceId.js +0 -209
- package/dist/getDeviceId.js.map +0 -1
- package/dist/getEnvironment.d.ts.map +0 -1
- package/dist/getEnvironment.js.map +0 -1
- package/dist/getShellVersion.d.ts.map +0 -1
- package/dist/getShellVersion.js.map +0 -1
- package/dist/index.d.ts +0 -8
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -6
- package/dist/index.js.map +0 -1
- package/dist/loadVwr.d.ts.map +0 -1
- package/dist/loadVwr.js.map +0 -1
- package/dist/logger.d.ts +0 -12
- package/dist/logger.d.ts.map +0 -1
- package/dist/logger.js.map +0 -1
- package/dist/polyfills.d.ts.map +0 -1
- package/dist/polyfills.js.map +0 -1
- package/dist/test-setup.js.map +0 -1
- package/dist/types.d.ts +0 -91
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -5
- package/dist/types.js.map +0 -1
- package/dist/vwrConfig.d.ts.map +0 -1
- package/dist/vwrConfig.js.map +0 -1
- package/src/datadog.ts +0 -55
- package/src/envDefaults.ts +0 -93
- package/src/getDeviceId.test.ts +0 -298
- package/src/getDeviceId.ts +0 -224
- package/src/types.ts +0 -92
- package/src/vwrConfig.test.ts +0 -386
- package/src/vwrConfig.ts +0 -374
- /package/dist/{__mocks__ → vwr-loader/src/__mocks__}/@datadog/browser-logs.d.ts +0 -0
- /package/dist/{__mocks__ → vwr-loader/src/__mocks__}/@datadog/browser-logs.js +0 -0
- /package/dist/{__mocks__ → vwr-loader/src/__mocks__}/@datadog/browser-rum.d.ts +0 -0
- /package/dist/{__mocks__ → vwr-loader/src/__mocks__}/@datadog/browser-rum.js +0 -0
- /package/dist/{amplitudeFlagFetcher.d.ts → vwr-loader/src/amplitudeFlagFetcher.d.ts} +0 -0
- /package/dist/{amplitudeFlagFetcher.js → vwr-loader/src/amplitudeFlagFetcher.js} +0 -0
- /package/dist/{errors → vwr-loader/src/errors}/InitializationError.d.ts +0 -0
- /package/dist/{errors → vwr-loader/src/errors}/InitializationError.js +0 -0
- /package/dist/{errors → vwr-loader/src/errors}/ensureError.d.ts +0 -0
- /package/dist/{errors → vwr-loader/src/errors}/ensureError.js +0 -0
- /package/dist/{errors → vwr-loader/src/errors}/index.d.ts +0 -0
- /package/dist/{errors → vwr-loader/src/errors}/index.js +0 -0
- /package/dist/{getEnvironment.d.ts → vwr-loader/src/getEnvironment.d.ts} +0 -0
- /package/dist/{getEnvironment.js → vwr-loader/src/getEnvironment.js} +0 -0
- /package/dist/{getShellVersion.d.ts → vwr-loader/src/getShellVersion.d.ts} +0 -0
- /package/dist/{getShellVersion.js → vwr-loader/src/getShellVersion.js} +0 -0
- /package/dist/{loadVwr.d.ts → vwr-loader/src/loadVwr.d.ts} +0 -0
- /package/dist/{polyfills.d.ts → vwr-loader/src/polyfills.d.ts} +0 -0
- /package/dist/{polyfills.js → vwr-loader/src/polyfills.js} +0 -0
- /package/dist/{test-setup.d.ts → vwr-loader/src/test-setup.d.ts} +0 -0
- /package/dist/{test-setup.js → vwr-loader/src/test-setup.js} +0 -0
package/src/exitHandler.test.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
exitIfBackNavigation,
|
|
5
|
+
setupFireTVBackButtonHandler,
|
|
6
|
+
setupLGBackButtonHandler,
|
|
7
|
+
} from "./exitHandler"
|
|
8
|
+
import { logger } from "./logger"
|
|
4
9
|
|
|
5
10
|
describe("exitHandler", () => {
|
|
6
11
|
beforeEach(() => {
|
|
@@ -81,14 +86,247 @@ describe("exitHandler", () => {
|
|
|
81
86
|
expect(() => exitIfBackNavigation("SAMSUNG_TV")).not.toThrow()
|
|
82
87
|
})
|
|
83
88
|
|
|
84
|
-
it("should
|
|
89
|
+
it("should exit Fire TV app when back_forward detected", () => {
|
|
85
90
|
vi.spyOn(performance, "getEntriesByType").mockReturnValue([
|
|
86
91
|
{ type: "back_forward" } as PerformanceNavigationTiming,
|
|
87
92
|
])
|
|
88
93
|
|
|
89
|
-
|
|
94
|
+
const mockExitApp = vi.fn().mockResolvedValue(undefined)
|
|
95
|
+
window.Capacitor = {
|
|
96
|
+
Plugins: {
|
|
97
|
+
AppLifecycle: { exitApp: mockExitApp },
|
|
98
|
+
},
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
exitIfBackNavigation("FIRE_TV")
|
|
102
|
+
|
|
103
|
+
expect(mockExitApp).toHaveBeenCalled()
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
it("should handle Fire TV without Capacitor gracefully", () => {
|
|
107
|
+
vi.spyOn(performance, "getEntriesByType").mockReturnValue([
|
|
108
|
+
{ type: "back_forward" } as PerformanceNavigationTiming,
|
|
109
|
+
])
|
|
110
|
+
|
|
111
|
+
window.Capacitor = undefined
|
|
112
|
+
|
|
90
113
|
expect(() => exitIfBackNavigation("FIRE_TV")).not.toThrow()
|
|
91
114
|
})
|
|
115
|
+
|
|
116
|
+
it("should log when Fire TV exit promise rejects", async () => {
|
|
117
|
+
vi.spyOn(performance, "getEntriesByType").mockReturnValue([
|
|
118
|
+
{ type: "back_forward" } as PerformanceNavigationTiming,
|
|
119
|
+
])
|
|
120
|
+
|
|
121
|
+
const mockExitApp = vi
|
|
122
|
+
.fn()
|
|
123
|
+
.mockRejectedValue(new Error("exit failed"))
|
|
124
|
+
const loggerErrorSpy = vi.spyOn(logger, "error")
|
|
125
|
+
|
|
126
|
+
window.Capacitor = {
|
|
127
|
+
Plugins: {
|
|
128
|
+
AppLifecycle: { exitApp: mockExitApp },
|
|
129
|
+
},
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
exitIfBackNavigation("FIRE_TV")
|
|
133
|
+
|
|
134
|
+
await vi.waitFor(() => {
|
|
135
|
+
expect(loggerErrorSpy).toHaveBeenCalledWith(
|
|
136
|
+
{ error: expect.any(Error) },
|
|
137
|
+
"[Shell] Failed to exit Fire TV app"
|
|
138
|
+
)
|
|
139
|
+
})
|
|
140
|
+
})
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
describe("setupFireTVBackButtonHandler", () => {
|
|
144
|
+
const ANDROID_BACK_KEYCODE = 4
|
|
145
|
+
type KeyDownListener = (event: { keyCode: number }) => void
|
|
146
|
+
|
|
147
|
+
it("should call Capacitor AppLifecycle.exitApp when InputHandler emits back keyDown", async () => {
|
|
148
|
+
const mockExitApp = vi.fn().mockResolvedValue(undefined)
|
|
149
|
+
const mockRemoveListener = vi.fn().mockResolvedValue(undefined)
|
|
150
|
+
let capturedListener: KeyDownListener | null = null
|
|
151
|
+
const mockAddListener = vi
|
|
152
|
+
.fn()
|
|
153
|
+
.mockImplementation(
|
|
154
|
+
async (eventName: string, listener: KeyDownListener) => {
|
|
155
|
+
if (eventName === "keyDown") {
|
|
156
|
+
capturedListener = listener
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return {
|
|
160
|
+
remove: mockRemoveListener,
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
window.Capacitor = {
|
|
166
|
+
Plugins: {
|
|
167
|
+
AppLifecycle: { exitApp: mockExitApp },
|
|
168
|
+
InputHandler: {
|
|
169
|
+
addListener: mockAddListener,
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const cleanup = setupFireTVBackButtonHandler()
|
|
175
|
+
|
|
176
|
+
await vi.waitFor(() => {
|
|
177
|
+
expect(mockAddListener).toHaveBeenCalledWith(
|
|
178
|
+
"keyDown",
|
|
179
|
+
expect.any(Function)
|
|
180
|
+
)
|
|
181
|
+
})
|
|
182
|
+
|
|
183
|
+
capturedListener?.({ keyCode: ANDROID_BACK_KEYCODE })
|
|
184
|
+
|
|
185
|
+
expect(mockExitApp).toHaveBeenCalled()
|
|
186
|
+
|
|
187
|
+
cleanup()
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
it("should handle missing Capacitor gracefully", () => {
|
|
191
|
+
window.Capacitor = undefined
|
|
192
|
+
|
|
193
|
+
const cleanup = setupFireTVBackButtonHandler()
|
|
194
|
+
|
|
195
|
+
expect(() => cleanup()).not.toThrow()
|
|
196
|
+
cleanup()
|
|
197
|
+
})
|
|
198
|
+
|
|
199
|
+
it("should not trigger when InputHandler emits non-back keyDown", async () => {
|
|
200
|
+
const mockExitApp = vi.fn().mockResolvedValue(undefined)
|
|
201
|
+
let capturedListener: KeyDownListener | null = null
|
|
202
|
+
const mockAddListener = vi
|
|
203
|
+
.fn()
|
|
204
|
+
.mockImplementation(
|
|
205
|
+
async (eventName: string, listener: KeyDownListener) => {
|
|
206
|
+
if (eventName === "keyDown") {
|
|
207
|
+
capturedListener = listener
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
return {
|
|
211
|
+
remove: vi.fn().mockResolvedValue(undefined),
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
window.Capacitor = {
|
|
217
|
+
Plugins: {
|
|
218
|
+
AppLifecycle: { exitApp: mockExitApp },
|
|
219
|
+
InputHandler: {
|
|
220
|
+
addListener: mockAddListener,
|
|
221
|
+
},
|
|
222
|
+
},
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const cleanup = setupFireTVBackButtonHandler()
|
|
226
|
+
|
|
227
|
+
await vi.waitFor(() => {
|
|
228
|
+
expect(mockAddListener).toHaveBeenCalledWith(
|
|
229
|
+
"keyDown",
|
|
230
|
+
expect.any(Function)
|
|
231
|
+
)
|
|
232
|
+
})
|
|
233
|
+
|
|
234
|
+
capturedListener?.({ keyCode: 13 })
|
|
235
|
+
|
|
236
|
+
expect(mockExitApp).not.toHaveBeenCalled()
|
|
237
|
+
|
|
238
|
+
cleanup()
|
|
239
|
+
})
|
|
240
|
+
|
|
241
|
+
it("should remove InputHandler listener when cleanup is called", async () => {
|
|
242
|
+
const mockExitApp = vi.fn().mockResolvedValue(undefined)
|
|
243
|
+
const mockRemoveListener = vi.fn().mockResolvedValue(undefined)
|
|
244
|
+
const mockAddListener = vi.fn().mockResolvedValue({
|
|
245
|
+
remove: mockRemoveListener,
|
|
246
|
+
})
|
|
247
|
+
|
|
248
|
+
window.Capacitor = {
|
|
249
|
+
Plugins: {
|
|
250
|
+
AppLifecycle: { exitApp: mockExitApp },
|
|
251
|
+
InputHandler: {
|
|
252
|
+
addListener: mockAddListener,
|
|
253
|
+
},
|
|
254
|
+
},
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
const cleanup = setupFireTVBackButtonHandler()
|
|
258
|
+
|
|
259
|
+
await vi.waitFor(() => {
|
|
260
|
+
expect(mockAddListener).toHaveBeenCalledWith(
|
|
261
|
+
"keyDown",
|
|
262
|
+
expect.any(Function)
|
|
263
|
+
)
|
|
264
|
+
})
|
|
265
|
+
|
|
266
|
+
cleanup()
|
|
267
|
+
|
|
268
|
+
await vi.waitFor(() => {
|
|
269
|
+
expect(mockRemoveListener).toHaveBeenCalled()
|
|
270
|
+
})
|
|
271
|
+
})
|
|
272
|
+
|
|
273
|
+
it("should support InputHandler addListener returning a sync handle", async () => {
|
|
274
|
+
const mockExitApp = vi.fn().mockResolvedValue(undefined)
|
|
275
|
+
const mockRemoveListener = vi.fn().mockResolvedValue(undefined)
|
|
276
|
+
let capturedListener: KeyDownListener | null = null
|
|
277
|
+
const mockAddListener = vi
|
|
278
|
+
.fn()
|
|
279
|
+
.mockImplementation(
|
|
280
|
+
(eventName: string, listener: KeyDownListener) => {
|
|
281
|
+
if (eventName === "keyDown") {
|
|
282
|
+
capturedListener = listener
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
return {
|
|
286
|
+
remove: mockRemoveListener,
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
)
|
|
290
|
+
|
|
291
|
+
window.Capacitor = {
|
|
292
|
+
Plugins: {
|
|
293
|
+
AppLifecycle: { exitApp: mockExitApp },
|
|
294
|
+
InputHandler: {
|
|
295
|
+
addListener: mockAddListener,
|
|
296
|
+
},
|
|
297
|
+
},
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
const cleanup = setupFireTVBackButtonHandler()
|
|
301
|
+
|
|
302
|
+
expect(mockAddListener).toHaveBeenCalledWith(
|
|
303
|
+
"keyDown",
|
|
304
|
+
expect.any(Function)
|
|
305
|
+
)
|
|
306
|
+
|
|
307
|
+
capturedListener?.({ keyCode: ANDROID_BACK_KEYCODE })
|
|
308
|
+
expect(mockExitApp).toHaveBeenCalled()
|
|
309
|
+
|
|
310
|
+
cleanup()
|
|
311
|
+
|
|
312
|
+
await vi.waitFor(() => {
|
|
313
|
+
expect(mockRemoveListener).toHaveBeenCalled()
|
|
314
|
+
})
|
|
315
|
+
})
|
|
316
|
+
|
|
317
|
+
it("should handle missing InputHandler plugin gracefully", () => {
|
|
318
|
+
const mockExitApp = vi.fn().mockResolvedValue(undefined)
|
|
319
|
+
window.Capacitor = {
|
|
320
|
+
Plugins: {
|
|
321
|
+
AppLifecycle: { exitApp: mockExitApp },
|
|
322
|
+
},
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
const cleanup = setupFireTVBackButtonHandler()
|
|
326
|
+
|
|
327
|
+
expect(mockExitApp).not.toHaveBeenCalled()
|
|
328
|
+
expect(() => cleanup()).not.toThrow()
|
|
329
|
+
})
|
|
92
330
|
})
|
|
93
331
|
|
|
94
332
|
describe("setupLGBackButtonHandler", () => {
|
package/src/exitHandler.ts
CHANGED
|
@@ -10,6 +10,9 @@ import { logger } from "./logger"
|
|
|
10
10
|
/** LG webOS back button keycode */
|
|
11
11
|
const LG_BACK_KEYCODE = 461
|
|
12
12
|
|
|
13
|
+
/** Android back button keycode (used by Fire TV InputHandler plugin) */
|
|
14
|
+
const ANDROID_BACK_KEYCODE = 4
|
|
15
|
+
|
|
13
16
|
/**
|
|
14
17
|
* Exit the app if the page was loaded via back/forward navigation.
|
|
15
18
|
*
|
|
@@ -80,6 +83,86 @@ export function setupLGBackButtonHandler(): () => void {
|
|
|
80
83
|
}
|
|
81
84
|
}
|
|
82
85
|
|
|
86
|
+
/**
|
|
87
|
+
* Set up Fire TV back button (keycode 4) handler.
|
|
88
|
+
*
|
|
89
|
+
* On Fire TV, the native shell intercepts the back button at the Activity
|
|
90
|
+
* level and forwards it to JavaScript via the InputHandler Capacitor plugin.
|
|
91
|
+
* During the vwr-loader loading phase, we subscribe directly to InputHandler
|
|
92
|
+
* keyDown events and call Capacitor AppLifecycle.exitApp().
|
|
93
|
+
*
|
|
94
|
+
* Once VWR loads successfully, call the returned cleanup function - VWR
|
|
95
|
+
* will take over back button handling.
|
|
96
|
+
*
|
|
97
|
+
* @returns Cleanup function to remove the listener
|
|
98
|
+
*/
|
|
99
|
+
export function setupFireTVBackButtonHandler(): () => void {
|
|
100
|
+
const inputHandler = window.Capacitor?.Plugins?.InputHandler
|
|
101
|
+
|
|
102
|
+
if (!inputHandler?.addListener) {
|
|
103
|
+
logger.warn("[Shell] Capacitor InputHandler plugin not available")
|
|
104
|
+
return () => {
|
|
105
|
+
logger.info("[Shell] Fire TV back button handler removed")
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
let listenerHandle: { remove: () => Promise<void> | void } | null = null
|
|
110
|
+
let isCleanedUp = false
|
|
111
|
+
|
|
112
|
+
const listenerRegistration = Promise.resolve(
|
|
113
|
+
inputHandler.addListener("keyDown", (event: { keyCode: number }) => {
|
|
114
|
+
if (event.keyCode === ANDROID_BACK_KEYCODE) {
|
|
115
|
+
logger.info("[Shell] Fire TV back button pressed, exiting app")
|
|
116
|
+
exitFireTVApp()
|
|
117
|
+
}
|
|
118
|
+
})
|
|
119
|
+
)
|
|
120
|
+
.then((handle: { remove: () => Promise<void> | void }) => {
|
|
121
|
+
listenerHandle = handle
|
|
122
|
+
|
|
123
|
+
if (isCleanedUp) {
|
|
124
|
+
return Promise.resolve(handle.remove()).catch(
|
|
125
|
+
(error: unknown) => {
|
|
126
|
+
logger.error(
|
|
127
|
+
{ error },
|
|
128
|
+
"[Shell] Failed to remove Fire TV back button handler"
|
|
129
|
+
)
|
|
130
|
+
}
|
|
131
|
+
)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return undefined
|
|
135
|
+
})
|
|
136
|
+
.catch((error: unknown) => {
|
|
137
|
+
logger.error(
|
|
138
|
+
{ error },
|
|
139
|
+
"[Shell] Failed to register Fire TV back button handler"
|
|
140
|
+
)
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
logger.info("[Shell] Fire TV back button handler registered")
|
|
144
|
+
|
|
145
|
+
return () => {
|
|
146
|
+
isCleanedUp = true
|
|
147
|
+
|
|
148
|
+
if (listenerHandle) {
|
|
149
|
+
void Promise.resolve(listenerHandle.remove()).catch(
|
|
150
|
+
(error: unknown) => {
|
|
151
|
+
logger.error(
|
|
152
|
+
{ error },
|
|
153
|
+
"[Shell] Failed to remove Fire TV back button handler"
|
|
154
|
+
)
|
|
155
|
+
}
|
|
156
|
+
)
|
|
157
|
+
listenerHandle = null
|
|
158
|
+
} else {
|
|
159
|
+
void listenerRegistration
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
logger.info("[Shell] Fire TV back button handler removed")
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
83
166
|
/**
|
|
84
167
|
* Exit the app using platform-specific methods.
|
|
85
168
|
*
|
|
@@ -93,7 +176,10 @@ function exitApp(platform: Platform): void {
|
|
|
93
176
|
case "LG_TV":
|
|
94
177
|
exitLGAppViaBackNavigation()
|
|
95
178
|
break
|
|
96
|
-
|
|
179
|
+
case "FIRE_TV":
|
|
180
|
+
exitFireTVApp()
|
|
181
|
+
break
|
|
182
|
+
// Mobile apps handle exit at the native layer
|
|
97
183
|
// Web doesn't have a meaningful "exit" concept
|
|
98
184
|
default:
|
|
99
185
|
logger.info({ platform }, "[Shell] No platform-specific exit")
|
|
@@ -123,3 +209,25 @@ function exitLGAppViaBackNavigation(): void {
|
|
|
123
209
|
logger.error({ error }, "[Shell] Failed to exit LG app")
|
|
124
210
|
}
|
|
125
211
|
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Exit Fire TV app via Capacitor AppLifecycle plugin.
|
|
215
|
+
*/
|
|
216
|
+
function exitFireTVApp(): void {
|
|
217
|
+
try {
|
|
218
|
+
if (window.Capacitor?.Plugins?.AppLifecycle?.exitApp) {
|
|
219
|
+
void window.Capacitor.Plugins.AppLifecycle.exitApp().catch(
|
|
220
|
+
(error: unknown) => {
|
|
221
|
+
logger.error(
|
|
222
|
+
{ error },
|
|
223
|
+
"[Shell] Failed to exit Fire TV app"
|
|
224
|
+
)
|
|
225
|
+
}
|
|
226
|
+
)
|
|
227
|
+
} else {
|
|
228
|
+
logger.warn("[Shell] Capacitor AppLifecycle plugin not available")
|
|
229
|
+
}
|
|
230
|
+
} catch (error) {
|
|
231
|
+
logger.error({ error }, "[Shell] Failed to exit Fire TV app")
|
|
232
|
+
}
|
|
233
|
+
}
|
package/src/getShellVersion.ts
CHANGED
package/src/index.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
export { getDeviceId } from "../../vwr/src/native/device-info/getDeviceId"
|
|
2
|
+
export type { VWRConfig, VWRConfigRequest } from "../../vwr/src/vwrConfig"
|
|
3
|
+
export { getVWRConfig } from "../../vwr/src/vwrConfig"
|
|
1
4
|
export type { AmplitudeConfig, FlagResult } from "./amplitudeFlagFetcher"
|
|
2
5
|
export { fetchAmplitudeFlags } from "./amplitudeFlagFetcher"
|
|
3
|
-
export { getDeviceId } from "./getDeviceId"
|
|
4
6
|
export { getShellVersion } from "./getShellVersion"
|
|
5
7
|
export { loadVwr } from "./loadVwr"
|
|
6
|
-
export type { VWRConfig, VWRConfigRequest } from "./vwrConfig"
|
|
7
|
-
export { getVWRConfig } from "./vwrConfig"
|
package/src/loadVwr.test.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"
|
|
2
2
|
|
|
3
3
|
// Mock all dependencies before importing loadVwr
|
|
4
|
-
vi.mock("
|
|
4
|
+
vi.mock("../../vwr/src/native/device-info/getDeviceId", () => ({
|
|
5
5
|
getDeviceId: vi.fn(),
|
|
6
6
|
}))
|
|
7
7
|
|
|
@@ -19,7 +19,7 @@ vi.mock("./amplitudeFlagFetcher", () => ({
|
|
|
19
19
|
},
|
|
20
20
|
}))
|
|
21
21
|
|
|
22
|
-
vi.mock("
|
|
22
|
+
vi.mock("../../vwr/src/vwrConfig", () => ({
|
|
23
23
|
getVWRConfig: vi.fn(),
|
|
24
24
|
validateConfig: vi.fn(),
|
|
25
25
|
}))
|
|
@@ -29,11 +29,14 @@ vi.mock("./getEnvironment", () => ({
|
|
|
29
29
|
}))
|
|
30
30
|
|
|
31
31
|
// Import mocked modules
|
|
32
|
+
|
|
33
|
+
import type { DatadogRum } from "@datadog/browser-rum"
|
|
34
|
+
|
|
35
|
+
import { getDeviceId } from "../../vwr/src/native/device-info/getDeviceId"
|
|
36
|
+
import { getVWRConfig, validateConfig } from "../../vwr/src/vwrConfig"
|
|
32
37
|
import { fetchAmplitudeFlags } from "./amplitudeFlagFetcher"
|
|
33
|
-
import { getDeviceId } from "./getDeviceId"
|
|
34
38
|
import { getEnvironment } from "./getEnvironment"
|
|
35
39
|
import { getShellVersion } from "./getShellVersion"
|
|
36
|
-
import { getVWRConfig, validateConfig } from "./vwrConfig"
|
|
37
40
|
|
|
38
41
|
const mockGetDeviceId = vi.mocked(getDeviceId)
|
|
39
42
|
const mockGetShellVersion = vi.mocked(getShellVersion)
|
|
@@ -43,12 +46,18 @@ const mockGetVWRConfig = vi.mocked(getVWRConfig)
|
|
|
43
46
|
const mockValidateConfig = vi.mocked(validateConfig)
|
|
44
47
|
|
|
45
48
|
// Mock RUM object for tests
|
|
46
|
-
const createMockRum = () =>
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
const createMockRum = () =>
|
|
50
|
+
({
|
|
51
|
+
addAction: vi.fn(),
|
|
52
|
+
addError: vi.fn(),
|
|
53
|
+
addTiming: vi.fn(),
|
|
54
|
+
setGlobalContextProperty: vi.fn(),
|
|
55
|
+
}) as unknown as DatadogRum & {
|
|
56
|
+
addAction: ReturnType<typeof vi.fn>
|
|
57
|
+
addError: ReturnType<typeof vi.fn>
|
|
58
|
+
addTiming: ReturnType<typeof vi.fn>
|
|
59
|
+
setGlobalContextProperty: ReturnType<typeof vi.fn>
|
|
60
|
+
}
|
|
52
61
|
|
|
53
62
|
describe("loadVwr", () => {
|
|
54
63
|
beforeEach(() => {
|
|
@@ -71,6 +80,7 @@ describe("loadVwr", () => {
|
|
|
71
80
|
platformApiUrl: "https://platform.example.com",
|
|
72
81
|
platformAuthApiUrl: "https://auth.example.com",
|
|
73
82
|
trustedDomains: ["https://hub.example.com"],
|
|
83
|
+
trustedShellOrigins: [],
|
|
74
84
|
},
|
|
75
85
|
source: "environment",
|
|
76
86
|
attempts: [],
|
|
@@ -321,6 +331,7 @@ describe("loadVwr", () => {
|
|
|
321
331
|
platformApiUrl: "https://platform.example.com",
|
|
322
332
|
platformAuthApiUrl: "https://auth.example.com",
|
|
323
333
|
trustedDomains: ["https://hub.example.com"],
|
|
334
|
+
trustedShellOrigins: [],
|
|
324
335
|
},
|
|
325
336
|
source: "device",
|
|
326
337
|
attempts: [
|
|
@@ -391,4 +402,153 @@ describe("loadVwr", () => {
|
|
|
391
402
|
)
|
|
392
403
|
})
|
|
393
404
|
})
|
|
405
|
+
|
|
406
|
+
describe("configSource display string", () => {
|
|
407
|
+
const mockVwrModulePath = "./__mocks__/vwrModule"
|
|
408
|
+
|
|
409
|
+
const setupWithConfigSource = (
|
|
410
|
+
source:
|
|
411
|
+
| "device"
|
|
412
|
+
| "shellVersion"
|
|
413
|
+
| "environment"
|
|
414
|
+
| "defaults"
|
|
415
|
+
| "local"
|
|
416
|
+
) => {
|
|
417
|
+
mockGetVWRConfig.mockResolvedValue({
|
|
418
|
+
config: {
|
|
419
|
+
vwrUrl: mockVwrModulePath,
|
|
420
|
+
hubUrl: "https://hub.example.com",
|
|
421
|
+
launchUrl: undefined,
|
|
422
|
+
platformApiUrl: "https://platform.example.com",
|
|
423
|
+
platformAuthApiUrl: "https://auth.example.com",
|
|
424
|
+
trustedDomains: ["https://hub.example.com"],
|
|
425
|
+
trustedShellOrigins: [],
|
|
426
|
+
},
|
|
427
|
+
source,
|
|
428
|
+
attempts: [],
|
|
429
|
+
total_duration_ms: 100,
|
|
430
|
+
})
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
beforeEach(async () => {
|
|
434
|
+
vi.stubEnv("VITE_ENVIRONMENT", "dev")
|
|
435
|
+
vi.stubEnv("VITE_PLATFORM", "FIRE_TV")
|
|
436
|
+
vi.stubEnv("VITE_CONFIG_URL", "https://config.example.com")
|
|
437
|
+
vi.stubEnv("VITE_CONFIG_FILE", "config.json")
|
|
438
|
+
|
|
439
|
+
// Reset the mock init function between tests
|
|
440
|
+
const vwrModule = await import("./__mocks__/vwrModule")
|
|
441
|
+
vwrModule.init.mockReset()
|
|
442
|
+
})
|
|
443
|
+
|
|
444
|
+
it('passes "device (<deviceId>)" for device config source', async () => {
|
|
445
|
+
setupWithConfigSource("device")
|
|
446
|
+
|
|
447
|
+
const { loadVwr } = await import("./loadVwr")
|
|
448
|
+
const mockRum = createMockRum()
|
|
449
|
+
|
|
450
|
+
try {
|
|
451
|
+
await loadVwr(mockRum)
|
|
452
|
+
} catch {
|
|
453
|
+
// May fail after init
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
const vwrModule = await import("./__mocks__/vwrModule")
|
|
457
|
+
expect(vwrModule.init).toHaveBeenCalledWith(
|
|
458
|
+
expect.objectContaining({
|
|
459
|
+
configSource: "device (test-device-id)",
|
|
460
|
+
}),
|
|
461
|
+
expect.anything(),
|
|
462
|
+
expect.anything()
|
|
463
|
+
)
|
|
464
|
+
})
|
|
465
|
+
|
|
466
|
+
it('passes "environment (<env>)" for environment config source', async () => {
|
|
467
|
+
setupWithConfigSource("environment")
|
|
468
|
+
|
|
469
|
+
const { loadVwr } = await import("./loadVwr")
|
|
470
|
+
const mockRum = createMockRum()
|
|
471
|
+
|
|
472
|
+
try {
|
|
473
|
+
await loadVwr(mockRum)
|
|
474
|
+
} catch {
|
|
475
|
+
// May fail after init
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
const vwrModule = await import("./__mocks__/vwrModule")
|
|
479
|
+
expect(vwrModule.init).toHaveBeenCalledWith(
|
|
480
|
+
expect.objectContaining({
|
|
481
|
+
configSource: "environment (dev)",
|
|
482
|
+
}),
|
|
483
|
+
expect.anything(),
|
|
484
|
+
expect.anything()
|
|
485
|
+
)
|
|
486
|
+
})
|
|
487
|
+
|
|
488
|
+
it('passes "shell-version (<env>/<platform>/<version>)" for shellVersion config source', async () => {
|
|
489
|
+
setupWithConfigSource("shellVersion")
|
|
490
|
+
|
|
491
|
+
const { loadVwr } = await import("./loadVwr")
|
|
492
|
+
const mockRum = createMockRum()
|
|
493
|
+
|
|
494
|
+
try {
|
|
495
|
+
await loadVwr(mockRum)
|
|
496
|
+
} catch {
|
|
497
|
+
// May fail after init
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
const vwrModule = await import("./__mocks__/vwrModule")
|
|
501
|
+
expect(vwrModule.init).toHaveBeenCalledWith(
|
|
502
|
+
expect.objectContaining({
|
|
503
|
+
configSource: "shell-version (dev/FIRE_TV/1.0.0)",
|
|
504
|
+
}),
|
|
505
|
+
expect.anything(),
|
|
506
|
+
expect.anything()
|
|
507
|
+
)
|
|
508
|
+
})
|
|
509
|
+
|
|
510
|
+
it('passes "local" for local config source', async () => {
|
|
511
|
+
setupWithConfigSource("local")
|
|
512
|
+
|
|
513
|
+
const { loadVwr } = await import("./loadVwr")
|
|
514
|
+
const mockRum = createMockRum()
|
|
515
|
+
|
|
516
|
+
try {
|
|
517
|
+
await loadVwr(mockRum)
|
|
518
|
+
} catch {
|
|
519
|
+
// May fail after init
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
const vwrModule = await import("./__mocks__/vwrModule")
|
|
523
|
+
expect(vwrModule.init).toHaveBeenCalledWith(
|
|
524
|
+
expect.objectContaining({
|
|
525
|
+
configSource: "local",
|
|
526
|
+
}),
|
|
527
|
+
expect.anything(),
|
|
528
|
+
expect.anything()
|
|
529
|
+
)
|
|
530
|
+
})
|
|
531
|
+
|
|
532
|
+
it('passes "defaults" for defaults config source', async () => {
|
|
533
|
+
setupWithConfigSource("defaults")
|
|
534
|
+
|
|
535
|
+
const { loadVwr } = await import("./loadVwr")
|
|
536
|
+
const mockRum = createMockRum()
|
|
537
|
+
|
|
538
|
+
try {
|
|
539
|
+
await loadVwr(mockRum)
|
|
540
|
+
} catch {
|
|
541
|
+
// May fail after init
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
const vwrModule = await import("./__mocks__/vwrModule")
|
|
545
|
+
expect(vwrModule.init).toHaveBeenCalledWith(
|
|
546
|
+
expect.objectContaining({
|
|
547
|
+
configSource: "defaults",
|
|
548
|
+
}),
|
|
549
|
+
expect.anything(),
|
|
550
|
+
expect.anything()
|
|
551
|
+
)
|
|
552
|
+
})
|
|
553
|
+
})
|
|
394
554
|
})
|