@xiboplayer/sw 0.9.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.
@@ -0,0 +1,439 @@
1
+ # Service Worker Test Plan - 2026-02-07
2
+
3
+ ## Overview
4
+
5
+ Test plan to verify the Service Worker bug fixes for widget resource handling.
6
+
7
+ **Target URL**: https://displays.superpantalles.com/player/pwa/
8
+
9
+ ---
10
+
11
+ ## Test 1: Fresh Boot (No Cache)
12
+
13
+ **Objective**: Verify Service Worker handles initial widget resource requests correctly.
14
+
15
+ **Steps**:
16
+ 1. Open Chrome DevTools (F12)
17
+ 2. Go to Application > Storage > Clear site data
18
+ 3. Close DevTools
19
+ 4. Navigate to https://displays.superpantalles.com/player/pwa/
20
+ 5. Open DevTools Console
21
+ 6. Wait for layout to load
22
+
23
+ **Expected Results**:
24
+ ```
25
+ [SW] Loading standalone Service Worker: 2026-02-06-standalone
26
+ [PWA] Service Worker registered
27
+ [PWA] Pre-fetching widget dependency: bundle.min.js
28
+ [PWA] Pre-fetching widget dependency: fonts.css
29
+ [SW] Fetching widget resource from CMS: bundle.min.js
30
+ [SW] Widget resource not available (404): bundle.min.js - NOT caching
31
+ [SW] Fetching widget resource from CMS: fonts.css
32
+ [SW] Widget resource not available (404): fonts.css - NOT caching
33
+ ```
34
+
35
+ **Success Criteria**:
36
+ - ✅ No `NS_ERROR_CORRUPTED_CONTENT` errors
37
+ - ✅ Service Worker logs are visible with `[SW]` prefix
38
+ - ✅ 404 responses are NOT cached
39
+ - ✅ Layout renders (even if widgets fail to load)
40
+
41
+ ---
42
+
43
+ ## Test 2: Second Load (With Cache)
44
+
45
+ **Objective**: Verify Service Worker serves cached resources correctly.
46
+
47
+ **Steps**:
48
+ 1. Complete Test 1
49
+ 2. Wait for Service Worker to download widget resources (if available)
50
+ 3. Refresh page (Ctrl+R)
51
+ 4. Check console
52
+
53
+ **Expected Results**:
54
+ ```
55
+ [SW] Loading standalone Service Worker: 2026-02-06-standalone
56
+ [PWA] Service Worker registered
57
+ [SW] Serving widget resource from cache: bundle.min.js
58
+ [SW] Serving widget resource from cache: fonts.css
59
+ ```
60
+
61
+ **Success Criteria**:
62
+ - ✅ Widget resources served from cache (if available)
63
+ - ✅ No network requests for cached resources
64
+ - ✅ No `NS_ERROR_CORRUPTED_CONTENT` errors
65
+ - ✅ Layout renders correctly
66
+
67
+ ---
68
+
69
+ ## Test 3: Service Worker Update
70
+
71
+ **Objective**: Verify Service Worker can be updated without breaking cache.
72
+
73
+ **Steps**:
74
+ 1. Complete Test 2
75
+ 2. In DevTools, go to Application > Service Workers
76
+ 3. Click "Update" button
77
+ 4. Refresh page
78
+ 5. Check console
79
+
80
+ **Expected Results**:
81
+ ```
82
+ [SW] Loading standalone Service Worker: 2026-02-06-standalone
83
+ [SW] Installing...
84
+ [SW] Activating...
85
+ [SW] Standalone Service Worker ready
86
+ ```
87
+
88
+ **Success Criteria**:
89
+ - ✅ Service Worker updates successfully
90
+ - ✅ Cache remains valid
91
+ - ✅ No errors during update
92
+ - ✅ Layout continues to render
93
+
94
+ ---
95
+
96
+ ## Test 4: Widget Resource Download
97
+
98
+ **Objective**: Verify Service Worker downloads widget resources in background.
99
+
100
+ **Steps**:
101
+ 1. Complete Test 1
102
+ 2. Check Network tab for widget resource requests
103
+ 3. Wait 30 seconds
104
+ 4. Check Service Worker download progress
105
+ 5. Refresh page
106
+ 6. Verify cached resources are served
107
+
108
+ **Expected Results**:
109
+ ```
110
+ [SW Message] Enqueueing 13 files for download
111
+ [SW Queue] Enqueued: bundle.min.js (1 pending, 0 active)
112
+ [SW Queue] Starting download: bundle.min.js (1/4 active)
113
+ [SW Download] Starting: https://...bundle.min.js
114
+ [SW Download] File size: 0.5 MB
115
+ [SW Download] Cached: /cache/widget-resource/bundle.min.js (512345 bytes)
116
+ ```
117
+
118
+ **Success Criteria**:
119
+ - ✅ Widget resources are enqueued for download
120
+ - ✅ Downloads complete successfully
121
+ - ✅ Resources are cached
122
+ - ✅ Subsequent loads serve from cache
123
+
124
+ ---
125
+
126
+ ## Test 5: Error Handling
127
+
128
+ **Objective**: Verify Service Worker handles network errors gracefully.
129
+
130
+ **Steps**:
131
+ 1. Open DevTools > Network
132
+ 2. Enable "Offline" mode
133
+ 3. Navigate to https://displays.superpantalles.com/player/pwa/
134
+ 4. Check console
135
+
136
+ **Expected Results**:
137
+ ```
138
+ [SW] Fetching widget resource from CMS: bundle.min.js
139
+ [SW] Failed to fetch widget resource: bundle.min.js TypeError: Failed to fetch
140
+ Failed to fetch widget resource (502)
141
+ ```
142
+
143
+ **Success Criteria**:
144
+ - ✅ Service Worker returns proper 502 error
145
+ - ✅ No `NS_ERROR_CORRUPTED_CONTENT` errors
146
+ - ✅ Error is logged clearly
147
+ - ✅ Player continues to function (using cached data)
148
+
149
+ ---
150
+
151
+ ## Test 6: Cache Invalidation
152
+
153
+ **Objective**: Verify Service Worker respects cache invalidation.
154
+
155
+ **Steps**:
156
+ 1. Complete Test 2 (with cached resources)
157
+ 2. Open DevTools Console
158
+ 3. Run: `navigator.serviceWorker.controller.postMessage({ type: 'CLEAR_CACHE' })`
159
+ 4. Wait for response
160
+ 5. Refresh page
161
+ 6. Check that resources are re-fetched
162
+
163
+ **Expected Results**:
164
+ ```
165
+ [SW Message] Received: CLEAR_CACHE
166
+ [SW Message] Clearing cache
167
+ [Cache] Cleared 13 cached files
168
+ ```
169
+
170
+ **Success Criteria**:
171
+ - ✅ Cache is cleared successfully
172
+ - ✅ Resources are re-fetched on next load
173
+ - ✅ No errors during cache clear
174
+ - ✅ Player continues to function
175
+
176
+ ---
177
+
178
+ ## Test 7: Concurrent Requests
179
+
180
+ **Objective**: Verify Service Worker handles multiple simultaneous requests.
181
+
182
+ **Steps**:
183
+ 1. Complete Test 1
184
+ 2. Open 3 browser tabs to https://displays.superpantalles.com/player/pwa/
185
+ 3. Load all tabs simultaneously
186
+ 4. Check console in each tab
187
+
188
+ **Expected Results**:
189
+ ```
190
+ Tab 1:
191
+ [SW] Fetching widget resource from CMS: bundle.min.js
192
+ [SW] Caching widget resource: bundle.min.js
193
+
194
+ Tab 2:
195
+ [SW] Serving widget resource from cache: bundle.min.js
196
+
197
+ Tab 3:
198
+ [SW] Serving widget resource from cache: bundle.min.js
199
+ ```
200
+
201
+ **Success Criteria**:
202
+ - ✅ Only one network request per resource
203
+ - ✅ All tabs receive the same resource
204
+ - ✅ No race conditions or corruption
205
+ - ✅ All tabs render correctly
206
+
207
+ ---
208
+
209
+ ## Test 8: Large File Handling
210
+
211
+ **Objective**: Verify Service Worker handles large files (>100MB) with parallel chunks.
212
+
213
+ **Steps**:
214
+ 1. Upload a large video file (>100MB) to Xibo CMS
215
+ 2. Add to layout
216
+ 3. Load player
217
+ 4. Check console for chunk download logs
218
+
219
+ **Expected Results**:
220
+ ```
221
+ [SW Download] Starting: https://...video.mp4
222
+ [SW Download] File size: 250.0 MB
223
+ [SW Download] Downloading 5 chunks in parallel
224
+ [SW Download] Chunk 1 / 5 (20.0%)
225
+ [SW Download] Chunk 2 / 5 (40.0%)
226
+ [SW Download] Chunk 3 / 5 (60.0%)
227
+ [SW Download] Chunk 4 / 5 (80.0%)
228
+ [SW Download] Chunk 5 / 5 (100.0%)
229
+ [SW Download] Cached: /cache/media/123 (262144000 bytes)
230
+ ```
231
+
232
+ **Success Criteria**:
233
+ - ✅ File is downloaded in parallel chunks
234
+ - ✅ Progress is logged
235
+ - ✅ File is cached successfully
236
+ - ✅ Video plays correctly
237
+
238
+ ---
239
+
240
+ ## Regression Tests
241
+
242
+ ### Regression 1: XMDS Media Requests
243
+
244
+ **Objective**: Verify XMDS media requests still work (not broken by widget resource fix).
245
+
246
+ **Expected**: XMDS media requests (type=M, type=L) are served from cache or passed through to CMS.
247
+
248
+ ### Regression 2: Widget HTML Requests
249
+
250
+ **Objective**: Verify widget HTML requests still work.
251
+
252
+ **Expected**: Widget HTML is served from `/cache/widget/{layoutId}/{regionId}/{widgetId}`.
253
+
254
+ ### Regression 3: Static File Caching
255
+
256
+ **Objective**: Verify static files (index.html, manifest.json) are cached.
257
+
258
+ **Expected**: Static files are served from `STATIC_CACHE` on subsequent loads.
259
+
260
+ ---
261
+
262
+ ## Known Issues (Expected Behavior)
263
+
264
+ ### Issue 1: displayId Mismatch
265
+
266
+ Widget HTML may contain URLs with different displayId than current display. This is a CMS issue, not a Service Worker issue.
267
+
268
+ **Example**:
269
+ ```
270
+ Widget rendered for displayId=1
271
+ Widget HTML contains: <script src="...?displayId=80&...">
272
+ ```
273
+
274
+ **Impact**: Widget resource 404s if displayId doesn't match
275
+
276
+ **Workaround**: Service Worker should NOT cache 404s (fixed in this release)
277
+
278
+ ### Issue 2: Widget Resources Not Available
279
+
280
+ Some widget types may not have widget resources (bundle.min.js, fonts) uploaded to CMS.
281
+
282
+ **Example**:
283
+ ```
284
+ Clock widget: No bundle.min.js needed
285
+ Embedded widget: Has bundle.min.js
286
+ ```
287
+
288
+ **Impact**: 404 responses are expected for some widgets
289
+
290
+ **Workaround**: Service Worker logs warning but doesn't fail (fixed in this release)
291
+
292
+ ---
293
+
294
+ ## Performance Benchmarks
295
+
296
+ ### Benchmark 1: Fresh Load Time
297
+
298
+ **Metric**: Time from navigation to layout render
299
+
300
+ **Target**: < 5 seconds (without widget resources)
301
+
302
+ ### Benchmark 2: Cached Load Time
303
+
304
+ **Metric**: Time from navigation to layout render (with cache)
305
+
306
+ **Target**: < 2 seconds
307
+
308
+ ### Benchmark 3: Download Throughput
309
+
310
+ **Metric**: MB/s for large file downloads
311
+
312
+ **Target**: > 10 MB/s (depends on network)
313
+
314
+ ### Benchmark 4: Cache Hit Rate
315
+
316
+ **Metric**: % of requests served from cache
317
+
318
+ **Target**: > 90% (after initial load)
319
+
320
+ ---
321
+
322
+ ## Bug Verification
323
+
324
+ ### Bug 1: NS_ERROR_CORRUPTED_CONTENT
325
+
326
+ **Status**: FIXED ✅
327
+
328
+ **Verification**:
329
+ 1. Load player with widget resources
330
+ 2. Check console for errors
331
+ 3. Verify no `NS_ERROR_CORRUPTED_CONTENT`
332
+
333
+ ### Bug 2: Cached 404 Responses
334
+
335
+ **Status**: FIXED ✅
336
+
337
+ **Verification**:
338
+ 1. Load player with unavailable widget resource
339
+ 2. Check Service Worker cache (DevTools > Application > Cache Storage)
340
+ 3. Verify 404 response is NOT in cache
341
+
342
+ ### Bug 3: Response Stream Corruption
343
+
344
+ **Status**: FIXED ✅
345
+
346
+ **Verification**:
347
+ 1. Load player multiple times
348
+ 2. Check that responses are consistent
349
+ 3. Verify no corruption errors
350
+
351
+ ---
352
+
353
+ ## Automated Testing (Future)
354
+
355
+ ### Playwright Tests
356
+
357
+ ```javascript
358
+ test('Widget resources load without corruption', async ({ page }) => {
359
+ await page.goto('https://displays.superpantalles.com/player/pwa/');
360
+
361
+ const errors = [];
362
+ page.on('console', msg => {
363
+ if (msg.text().includes('NS_ERROR')) {
364
+ errors.push(msg.text());
365
+ }
366
+ });
367
+
368
+ await page.waitForSelector('#layout-container', { timeout: 10000 });
369
+
370
+ expect(errors).toHaveLength(0);
371
+ });
372
+
373
+ test('Service Worker caches successful responses', async ({ page, context }) => {
374
+ await page.goto('https://displays.superpantalles.com/player/pwa/');
375
+
376
+ const sw = await context.serviceWorkers()[0];
377
+ const cache = await sw.evaluate(() => {
378
+ return caches.open('xibo-static-v1').then(cache => cache.keys());
379
+ });
380
+
381
+ const widgetResources = cache.filter(req =>
382
+ req.url.includes('fileType=bundle') ||
383
+ req.url.includes('fileType=fontCss')
384
+ );
385
+
386
+ // Should only cache successful responses, not 404s
387
+ for (const req of widgetResources) {
388
+ const resp = await sw.evaluate(url => {
389
+ return caches.match(url).then(r => r.status);
390
+ }, req.url);
391
+ expect(resp).toBe(200);
392
+ }
393
+ });
394
+ ```
395
+
396
+ ---
397
+
398
+ ## Deployment Checklist
399
+
400
+ - [x] Code changes committed to `feature/standalone-service-worker`
401
+ - [x] Service Worker version updated: `2026-02-06-standalone`
402
+ - [x] Deployment tested on h1.superpantalles.com
403
+ - [x] Documentation updated (this file + SW_BUGFIXES_2026-02-07.md)
404
+ - [ ] Manual testing completed (all 8 tests)
405
+ - [ ] Regression tests passed
406
+ - [ ] Performance benchmarks measured
407
+ - [ ] Bug verification completed
408
+ - [ ] Production deployment approved
409
+ - [ ] Monitoring enabled
410
+
411
+ ---
412
+
413
+ ## Rollback Plan
414
+
415
+ If issues are found after deployment:
416
+
417
+ 1. Revert to previous Service Worker version:
418
+ ```bash
419
+ git checkout HEAD~1 platforms/pwa/public/sw.js
420
+ cp platforms/pwa/public/sw.js platforms/pwa/dist/sw.js
421
+ ansible-playbook playbooks/services/deploy-pwa.yml -l h1.superpantalles.com
422
+ ```
423
+
424
+ 2. Clear Service Worker cache on clients:
425
+ - Users: Clear browser data
426
+ - Admins: Force Service Worker update via DevTools
427
+
428
+ 3. Investigate issues and create hotfix
429
+
430
+ ---
431
+
432
+ ## Contact
433
+
434
+ **Author**: Claude (AI Assistant)
435
+ **Date**: 2026-02-07
436
+ **Branch**: feature/standalone-service-worker
437
+ **Deployed**: h1.superpantalles.com
438
+
439
+ For questions or issues, check console logs with `[SW]` prefix.
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "@xiboplayer/sw",
3
+ "version": "0.9.0",
4
+ "description": "Service Worker toolkit for chunk streaming and offline caching",
5
+ "type": "module",
6
+ "main": "./src/index.js",
7
+ "exports": {
8
+ ".": "./src/index.js",
9
+ "./worker": "./src/worker.js"
10
+ },
11
+ "scripts": {
12
+ "test": "vitest run",
13
+ "test:watch": "vitest",
14
+ "test:coverage": "vitest run --coverage"
15
+ },
16
+ "dependencies": {},
17
+ "devDependencies": {
18
+ "vitest": "^2.0.0"
19
+ },
20
+ "keywords": [
21
+ "xibo",
22
+ "digital-signage",
23
+ "service-worker",
24
+ "offline",
25
+ "cache"
26
+ ],
27
+ "author": "Pau Aliagas <linuxnow@gmail.com>",
28
+ "license": "AGPL-3.0-or-later",
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "git+https://github.com/xibo/xibo-players.git",
32
+ "directory": "packages/sw"
33
+ }
34
+ }
package/src/index.js ADDED
@@ -0,0 +1,23 @@
1
+ // @xiboplayer/sw - Service Worker toolkit
2
+ export async function registerServiceWorker(swUrl, options = {}) {
3
+ if (!('serviceWorker' in navigator)) {
4
+ console.warn('Service Workers not supported');
5
+ return null;
6
+ }
7
+
8
+ try {
9
+ const registration = await navigator.serviceWorker.register(swUrl, options);
10
+ console.log('Service Worker registered:', registration);
11
+ return registration;
12
+ } catch (error) {
13
+ console.error('Service Worker registration failed:', error);
14
+ throw error;
15
+ }
16
+ }
17
+
18
+ export async function unregisterServiceWorker() {
19
+ if (!('serviceWorker' in navigator)) return false;
20
+
21
+ const registration = await navigator.serviceWorker.ready;
22
+ return await registration.unregister();
23
+ }
package/src/worker.js ADDED
@@ -0,0 +1,12 @@
1
+ // @xiboplayer/sw/worker - Service Worker implementation helpers
2
+ // To be used inside Service Worker context
3
+
4
+ export function setupChunkStreaming() {
5
+ // Chunk streaming setup for Service Workers
6
+ console.log('Service Worker chunk streaming setup');
7
+ }
8
+
9
+ export function handleChunkRequest(request) {
10
+ // Handle chunk-based requests
11
+ return fetch(request);
12
+ }