chore: add vitest-dom & sw test

This commit is contained in:
ayo 2026-05-24 15:15:51 +02:00
parent 9b4312b49d
commit 9d69a6cc67
3 changed files with 153 additions and 1 deletions

View file

@ -54,7 +54,8 @@
"typescript-eslint": "^8.59.3",
"unified": "^11.0.5",
"vite-plugin-static-copy": "^4.1.0",
"vitest": "^4.1.7"
"vitest": "^4.1.7",
"vitest-dom": "^0.1.1"
},
"lint-staged": {
"*.{js,mjs,astro,ts}": [

View file

@ -111,6 +111,9 @@ importers:
vitest:
specifier: ^4.1.7
version: 4.1.7(@types/node@25.8.0)(vite@7.3.3(@types/node@25.8.0)(jiti@2.7.0)(yaml@2.9.0))
vitest-dom:
specifier: ^0.1.1
version: 0.1.1(vitest@4.1.7(@types/node@25.8.0)(vite@7.3.3(@types/node@25.8.0)(jiti@2.7.0)(yaml@2.9.0)))
packages:
@ -1088,6 +1091,10 @@ packages:
resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==}
engines: {node: '>=18'}
chalk@5.6.2:
resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==}
engines: {node: ^12.17.0 || ^14.13 || >=16.0.0}
character-entities-html4@2.1.0:
resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==}
@ -1196,6 +1203,9 @@ packages:
resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==}
engines: {node: '>= 6'}
css.escape@1.5.1:
resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==}
cssesc@3.0.0:
resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
engines: {node: '>=4'}
@ -1267,6 +1277,9 @@ packages:
resolution: {integrity: sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw==}
engines: {node: '>=0.3.1'}
dom-accessibility-api@0.6.3:
resolution: {integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==}
dom-serializer@2.0.0:
resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==}
@ -1690,6 +1703,10 @@ packages:
resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
engines: {node: '>=0.8.19'}
indent-string@5.0.0:
resolution: {integrity: sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==}
engines: {node: '>=12'}
internal-slot@1.1.0:
resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==}
engines: {node: '>= 0.4'}
@ -1888,6 +1905,9 @@ packages:
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
engines: {node: '>=10'}
lodash-es@4.18.1:
resolution: {integrity: sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==}
log-update@6.1.0:
resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==}
engines: {node: '>=18'}
@ -2288,6 +2308,10 @@ packages:
resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==}
engines: {node: '>= 20.19.0'}
redent@4.0.0:
resolution: {integrity: sha512-tYkDkVVtYkSVhuQ4zBgfvciymHaeuel+zFKXShfDnFP5SyVEP7qo70Rf1jTOTCx3vGNAbnEi/xFkcfQVMIBWag==}
engines: {node: '>=12'}
reflect.getprototypeof@1.0.10:
resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==}
engines: {node: '>= 0.4'}
@ -2523,6 +2547,10 @@ packages:
resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==}
engines: {node: '>=12'}
strip-indent@4.1.1:
resolution: {integrity: sha512-SlyRoSkdh1dYP0PzclLE7r0M9sgbFKKMFXpFRUMNuKhQSbC6VQIGzq3E0qsfvGJaUFJPGv6Ws1NZ/haTAjfbMA==}
engines: {node: '>=12'}
suf-log@2.5.3:
resolution: {integrity: sha512-KvC8OPjzdNOe+xQ4XWJV2whQA0aM1kGVczMQ8+dStAO6KfEB140JEVQ9dE76ONZ0/Ylf67ni4tILPJB41U0eow==}
@ -2804,6 +2832,11 @@ packages:
vite:
optional: true
vitest-dom@0.1.1:
resolution: {integrity: sha512-n/bonR2hcRHCE5hlzG/P0yTXTUXx/gPtsaeUWP86ADfwo/+dHDpnTTV14qY7+kevsUbOZFYECu77MXY7AA0QSA==}
peerDependencies:
vitest: '>=0.31.0'
vitest@4.1.7:
resolution: {integrity: sha512-flYyaFd2CgoCoU+0UKt3pxksgC+S02iTDN0n3LtqaMeXsI9SBcdNujc2k0DeFLzUn/0k538yNjOSdwgCqcrwJA==}
engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0}
@ -3911,6 +3944,8 @@ snapshots:
chai@6.2.2: {}
chalk@5.6.2: {}
character-entities-html4@2.1.0: {}
character-entities-legacy@3.0.0: {}
@ -4028,6 +4063,8 @@ snapshots:
css-what@6.2.2: {}
css.escape@1.5.1: {}
cssesc@3.0.0: {}
csso@5.0.5:
@ -4093,6 +4130,8 @@ snapshots:
diff@8.0.4: {}
dom-accessibility-api@0.6.3: {}
dom-serializer@2.0.0:
dependencies:
domelementtype: 2.3.0
@ -4687,6 +4726,8 @@ snapshots:
imurmurhash@0.1.4: {}
indent-string@5.0.0: {}
internal-slot@1.1.0:
dependencies:
es-errors: 1.3.0
@ -4890,6 +4931,8 @@ snapshots:
dependencies:
p-locate: 5.0.0
lodash-es@4.18.1: {}
log-update@6.1.0:
dependencies:
ansi-escapes: 7.3.0
@ -5474,6 +5517,11 @@ snapshots:
readdirp@5.0.0: {}
redent@4.0.0:
dependencies:
indent-string: 5.0.0
strip-indent: 4.1.1
reflect.getprototypeof@1.0.10:
dependencies:
call-bind: 1.0.9
@ -5862,6 +5910,8 @@ snapshots:
dependencies:
ansi-regex: 6.2.2
strip-indent@4.1.1: {}
suf-log@2.5.3:
dependencies:
s.color: 0.0.15
@ -6113,6 +6163,16 @@ snapshots:
optionalDependencies:
vite: 7.3.3(@types/node@25.8.0)(jiti@2.7.0)(yaml@2.9.0)
vitest-dom@0.1.1(vitest@4.1.7(@types/node@25.8.0)(vite@7.3.3(@types/node@25.8.0)(jiti@2.7.0)(yaml@2.9.0))):
dependencies:
aria-query: 5.3.2
chalk: 5.6.2
css.escape: 1.5.1
dom-accessibility-api: 0.6.3
lodash-es: 4.18.1
redent: 4.0.0
vitest: 4.1.7(@types/node@25.8.0)(vite@7.3.3(@types/node@25.8.0)(jiti@2.7.0)(yaml@2.9.0))
vitest@4.1.7(@types/node@25.8.0)(vite@7.3.3(@types/node@25.8.0)(jiti@2.7.0)(yaml@2.9.0)):
dependencies:
'@vitest/expect': 4.1.7

91
tests/sw.test.js Normal file
View file

@ -0,0 +1,91 @@
import { describe, it, expect, vi, beforeEach } from 'vitest'
import { install } from 'vitest-dom'
// Install DOM environment for vitest
install()
// Mock the service worker globals
global.caches = {
keys: vi.fn(),
delete: vi.fn(),
open: vi.fn(),
match: vi.fn(),
}
// Mock the global self object
global.self = {
skipWaiting: vi.fn(),
addEventListener: vi.fn(),
}
// Mock the fetch function
global.fetch = vi.fn()
// Import the service worker module
// Note: We need to use dynamic import to avoid module loading issues
let swModule
beforeEach(async () => {
// Clear all mocks
vi.clearAllMocks()
// Mock the module
swModule = await import('../src/sw.mjs')
})
describe('Service Worker', () => {
describe('cleanOldCaches', () => {
it('should delete old caches', async () => {
const cacheName = 'app-v000'
const oldCacheName = 'app-v001'
global.caches.keys.mockResolvedValue([cacheName, oldCacheName])
global.caches.delete.mockResolvedValue(true)
await swModule.cleanOldCaches()
expect(global.caches.delete).toHaveBeenCalledWith(oldCacheName)
})
})
describe('addResourcesToCache', () => {
it('should add resources to cache', async () => {
const resources = ['/index.html', '/style.css']
const cache = { addAll: vi.fn() }
global.caches.open.mockResolvedValue(cache)
await swModule.addResourcesToCache(resources)
expect(cache.addAll).toHaveBeenCalledWith(resources)
})
})
describe('networkFirst', () => {
it('should return network response when available', async () => {
const request = new Request('/test')
const networkResponse = new Response('network content')
global.fetch.mockResolvedValue(networkResponse)
global.caches.open.mockResolvedValue({ put: vi.fn() })
const result = await swModule.networkFirst({ request })
expect(result).toEqual(networkResponse)
})
it('should return cached response when network fails', async () => {
const request = new Request('/test')
const cachedResponse = new Response('cached content')
global.fetch.mockRejectedValue(new Error('Network error'))
global.caches.open.mockResolvedValue({
match: vi.fn().mockResolvedValue(cachedResponse),
})
const result = await swModule.networkFirst({ request })
expect(result).toEqual(cachedResponse)
})
})
})