test(boardwalk): cover the build id, the reload banner and the chunk reload guard (quick-261028-rqb)
This commit is contained in:
99
admin/tests/app/chunkReload.test.ts
Normal file
99
admin/tests/app/chunkReload.test.ts
Normal file
@@ -0,0 +1,99 @@
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import {
|
||||
CHUNK_RELOAD_KEY,
|
||||
CHUNK_RELOAD_WINDOW,
|
||||
installChunkReloadGuard,
|
||||
shouldReload,
|
||||
} from '../../src/app/chunkReload'
|
||||
|
||||
/** An in-memory Storage. */
|
||||
function memoryStorage(): Storage {
|
||||
const items = new Map<string, string>()
|
||||
return {
|
||||
get length() {
|
||||
return items.size
|
||||
},
|
||||
clear: () => items.clear(),
|
||||
getItem: (key) => items.get(key) ?? null,
|
||||
key: (index) => [...items.keys()][index] ?? null,
|
||||
removeItem: (key) => void items.delete(key),
|
||||
setItem: (key, value) => void items.set(key, String(value)),
|
||||
}
|
||||
}
|
||||
|
||||
describe('shouldReload', () => {
|
||||
it('reloads once and records the time', () => {
|
||||
const storage = memoryStorage()
|
||||
expect(shouldReload(storage, 1000)).toBe(true)
|
||||
expect(storage.getItem(CHUNK_RELOAD_KEY)).toBe('1000')
|
||||
})
|
||||
|
||||
it('declines a second reload within the window and allows one after it', () => {
|
||||
const storage = memoryStorage()
|
||||
expect(shouldReload(storage, 1000)).toBe(true)
|
||||
expect(shouldReload(storage, 1000 + CHUNK_RELOAD_WINDOW - 1)).toBe(false)
|
||||
expect(shouldReload(storage, 1000 + CHUNK_RELOAD_WINDOW)).toBe(true)
|
||||
expect(storage.getItem(CHUNK_RELOAD_KEY)).toBe(String(1000 + CHUNK_RELOAD_WINDOW))
|
||||
})
|
||||
|
||||
it('reloads over a stored value that is not a timestamp', () => {
|
||||
const storage = memoryStorage()
|
||||
storage.setItem(CHUNK_RELOAD_KEY, 'garbage')
|
||||
expect(shouldReload(storage, 1000)).toBe(true)
|
||||
})
|
||||
|
||||
it('never reloads without storage', () => {
|
||||
expect(shouldReload(null, 1000)).toBe(false)
|
||||
})
|
||||
|
||||
it('never reloads when storage throws', () => {
|
||||
const reading = memoryStorage()
|
||||
reading.getItem = () => {
|
||||
throw new Error('denied')
|
||||
}
|
||||
expect(shouldReload(reading, 1000)).toBe(false)
|
||||
const writing = memoryStorage()
|
||||
writing.setItem = () => {
|
||||
throw new Error('quota')
|
||||
}
|
||||
expect(shouldReload(writing, 1000)).toBe(false)
|
||||
})
|
||||
|
||||
it('keys the flag under summer-admin.* with a 60 second window', () => {
|
||||
expect(CHUNK_RELOAD_KEY).toBe('summer-admin.chunk-reload')
|
||||
expect(CHUNK_RELOAD_WINDOW).toBe(60_000)
|
||||
})
|
||||
})
|
||||
|
||||
describe('installChunkReloadGuard', () => {
|
||||
it('reloads once on vite:preloadError and leaves the event to the importer', () => {
|
||||
const target = new EventTarget()
|
||||
const storage = memoryStorage()
|
||||
const reload = vi.fn()
|
||||
let clock = 5000
|
||||
const uninstall = installChunkReloadGuard({ target, storage: () => storage, reload, now: () => clock })
|
||||
|
||||
const first = new Event('vite:preloadError', { cancelable: true })
|
||||
target.dispatchEvent(first)
|
||||
expect(reload).toHaveBeenCalledTimes(1)
|
||||
expect(first.defaultPrevented).toBe(false)
|
||||
|
||||
clock += 1000
|
||||
target.dispatchEvent(new Event('vite:preloadError', { cancelable: true }))
|
||||
expect(reload).toHaveBeenCalledTimes(1)
|
||||
|
||||
uninstall()
|
||||
clock += CHUNK_RELOAD_WINDOW
|
||||
target.dispatchEvent(new Event('vite:preloadError', { cancelable: true }))
|
||||
expect(reload).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
it('does not reload when no storage is available', () => {
|
||||
const target = new EventTarget()
|
||||
const reload = vi.fn()
|
||||
const uninstall = installChunkReloadGuard({ target, storage: () => null, reload })
|
||||
target.dispatchEvent(new Event('vite:preloadError'))
|
||||
expect(reload).not.toHaveBeenCalled()
|
||||
uninstall()
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user