206 lines
7.1 KiB
JavaScript
206 lines
7.1 KiB
JavaScript
import 'qrcode/qrcode-reader.js'
|
|
import { expect, test, vi} from 'vitest'
|
|
import ZXingBrowser from 'qrcode/zxing-browser.min.js'
|
|
import nacl from 'qrcode/nacl.min.js'
|
|
|
|
const okCodeData =
|
|
'SVF.WB899RLB0%7NFKM.IWSBLTVZ65OQKD59REJ+ I/IDL960%HL%F 5EVVK397HQGIUK3OAPOP0RF/X' +
|
|
'L1FIKJG08J5 LE.G9%EPEDUF7M.C%47SW64DC4W5NF6$CC1S64VCBW53ECQZCGPCSG6C%6YZC:DC-96N' +
|
|
'E1AECPED-EDLFF QEGEC9VE634L%6 47%47C%6446D36K/EXVDAVCRWEV2C0/DUF7:967461R67:6OA7' +
|
|
'Y$5DE1HEC1WE..DF$DUF7/B8-ED:JCSTDR.C4LE1WE..DF$DUF771904E93DKOEXVDKPCF/DV CP9EIE' +
|
|
'C*ZCT34ZA8.Q6$Q6HB8A0'
|
|
|
|
const invalidCodeData = 'https://georges-abitbol.fr'
|
|
|
|
const invalidSignatureData =
|
|
'ELT7PRQKJ097ZM1TA5$EJC%NOMVL5D5QNEZUR.Q5JESA5D+GO*I16IAYJO:D4ZGU GTVIM%DHI88%CGD' +
|
|
'0W6LBKOWSKLRC$ R9%EPEDUF7OB7GPC 57Y47BX5-A6+/61S6$57CW5/Q6+TCRW6GA7 57QF6H*6C56N' +
|
|
'E1AECPED-EDLFF QEGEC9VE634L%6 47%47C%6446D36K/EXVDAVCRWEV2C0/DUF7:96646L%6946OA7' +
|
|
'Y$5DE1HEC1WE..DF$DUF70A8R.C4LE1WE..DF$DUF7VF8XVDKPCF/DV CP9EIEC*ZCO34A0'
|
|
|
|
|
|
const qrcodeReaderTest = test.extend({
|
|
mock: async ({ task }, use) => {
|
|
let resolveResult = undefined
|
|
let resultPromise = new Promise((resolve) => resolveResult = resolve)
|
|
let resolveResultHandled = undefined
|
|
const terminate = Symbol()
|
|
|
|
class MockBrowserQRCodeReader {
|
|
async decodeFromVideoDevice(device, element, callback) {
|
|
while(true) {
|
|
const result = await resultPromise
|
|
|
|
if(result === terminate) {
|
|
return
|
|
}
|
|
|
|
resultPromise = new Promise((resolve) => resolveResult = resolve)
|
|
|
|
callback({ text: result })
|
|
|
|
resolveResultHandled()
|
|
}
|
|
}
|
|
}
|
|
|
|
window.nacl = nacl
|
|
navigator.mediaDevices = true
|
|
const savedZXingBrowser = window.ZXingBrowser
|
|
window.ZXingBrowser = { BrowserQRCodeReader : MockBrowserQRCodeReader }
|
|
|
|
const reader = document.createElement('qrcode-reader')
|
|
|
|
reader.setAttribute('verify-key', 'f81af42f9f9422d2393859d40994a42cdb2ef68507f056292ac96d1de1f1af83')
|
|
document.append(reader)
|
|
|
|
await use({
|
|
reader,
|
|
scan: async (text) => {
|
|
const resultHandled = new Promise((resolve) => resolveResultHandled = resolve)
|
|
resolveResult(text)
|
|
await resultHandled
|
|
}
|
|
})
|
|
vi.useFakeTimers()
|
|
|
|
reader.remove()
|
|
|
|
vi.useRealTimers ()
|
|
|
|
resolveResult(terminate)
|
|
window.ZXingBrowser = savedZXingBrowser
|
|
navigator.mediaDevices = undefined
|
|
window.nacl = undefined
|
|
}
|
|
})
|
|
|
|
test('qrcode reader shows a warning message if not supported on platform', async ({mock}) => {
|
|
const reader = document.createElement('qrcode-reader')
|
|
reader.setAttribute('verify-key', 'f81af42f9f9422d2393859d40994a42cdb2ef68507f056292ac96d1de1f1af83')
|
|
document.append(reader)
|
|
|
|
expect(reader.innerText).toBe('not_supported')
|
|
})
|
|
|
|
qrcodeReaderTest('qrcode reader shows valid qrcode informations', async ({mock}) => {
|
|
const { reader, scan } = mock
|
|
|
|
vi.setSystemTime(new Date(2023, 11, 1))
|
|
await scan(okCodeData)
|
|
|
|
const popup = reader.querySelector('.qrcode-reader--popup')
|
|
const title = popup.querySelector('.qrcode-reader--popup-title')
|
|
|
|
expect(popup.classList.contains('closed')).toBe(false)
|
|
expect(popup.classList.contains('error')).toBe(false)
|
|
expect(title.innerText).toBe('valid')
|
|
|
|
const validity = popup.querySelector('.qrcode-reader--validity')
|
|
|
|
expect(validity.innerText).toMatch(/from :\s*31\/10\/2023 23:00:00\s*to :\s*01\/12\/2023 22:59:59/)
|
|
|
|
const labels = popup.querySelectorAll('.qrcode-reader--data-item-label')
|
|
|
|
expect(labels.length).toBe(3)
|
|
expect(labels[0].innerText).toMatch('last_name')
|
|
expect(labels[1].innerText).toMatch('first_name')
|
|
expect(labels[2].innerText).toMatch('license_plate')
|
|
|
|
const values = popup.querySelectorAll('.qrcode-reader--data-item-value')
|
|
|
|
expect(values.length).toBe(3)
|
|
expect(values[0].innerText).toMatch('Abitbol')
|
|
expect(values[1].innerText).toMatch('Georges')
|
|
expect(values[2].innerText).toMatch('HA-424-AH')
|
|
|
|
const closeButton = reader.querySelector('.qrcode-reader--close-popup-button')
|
|
closeButton.dispatchEvent(new Event('click'))
|
|
|
|
expect(popup.classList.contains('closed')).toBe(true)
|
|
})
|
|
|
|
qrcodeReaderTest('qrcode reader shows error on not yet valid or expired qrcodes', async ({mock}) => {
|
|
const { reader, scan } = mock
|
|
vi.setSystemTime(new Date(2023, 9, 31)) // monthes start at 0 index, wtf javascript
|
|
|
|
await scan(okCodeData)
|
|
|
|
const popup = reader.querySelector('.qrcode-reader--popup')
|
|
const title = popup.querySelector('.qrcode-reader--popup-title')
|
|
|
|
expect(popup.classList.contains('closed')).toBe(false)
|
|
expect(popup.classList.contains('error')).toBe(true)
|
|
expect(title.innerText).toBe('not_yet_valid')
|
|
|
|
vi.setSystemTime(new Date(2023, 11, 2)) // monthes start at 0 index, wtf javascript
|
|
await scan(okCodeData)
|
|
|
|
expect(popup.classList.contains('closed')).toBe(false)
|
|
expect(popup.classList.contains('error')).toBe(true)
|
|
expect(title.innerText).toBe('expired')
|
|
})
|
|
|
|
qrcodeReaderTest('qrcode reader shows error on invalid qrcode', async ({mock}) => {
|
|
const { reader, scan } = mock
|
|
|
|
await scan(invalidCodeData)
|
|
|
|
const popup = reader.querySelector('.qrcode-reader--popup')
|
|
const title = reader.querySelector('.qrcode-reader--popup-title')
|
|
const content = reader.querySelector('.qrcode-reader--popup-content')
|
|
|
|
expect(popup.classList.contains('closed')).toBe(false)
|
|
expect(popup.classList.contains('error')).toBe(true)
|
|
expect(title.innerText).toBe('invalid_title')
|
|
expect(content.innerText).toBe('invalid_qrcode')
|
|
|
|
const closeButton = reader.querySelector('.qrcode-reader--close-popup-button')
|
|
closeButton.dispatchEvent(new Event('click'))
|
|
|
|
expect(popup.classList.contains('closed')).toBe(true)
|
|
})
|
|
|
|
qrcodeReaderTest('qrcode reader shows error on invalid signature', async ({mock}) => {
|
|
const { reader, scan } = mock
|
|
|
|
await scan(invalidSignatureData)
|
|
|
|
const popup = reader.querySelector('.qrcode-reader--popup')
|
|
const title = reader.querySelector('.qrcode-reader--popup-title')
|
|
const content = reader.querySelector('.qrcode-reader--popup-content')
|
|
|
|
expect(popup.classList.contains('closed')).toBe(false)
|
|
expect(popup.classList.contains('error')).toBe(true)
|
|
expect(title.innerText).toBe('invalid_title')
|
|
expect(content.innerText).toBe('invalid_signature')
|
|
|
|
const closeButton = reader.querySelector('.qrcode-reader--close-popup-button')
|
|
closeButton.dispatchEvent(new Event('click'))
|
|
|
|
expect(popup.classList.contains('closed')).toBe(true)
|
|
})
|
|
|
|
qrcodeReaderTest('qrcode reader can toggle fullscreen', async ({mock}) => {
|
|
const { reader } = mock
|
|
const fullscreenButton = reader.querySelector('.qrcode-reader--fullscreen-button')
|
|
|
|
reader.requestFullscreen = vi.fn()
|
|
document.exitFullscreen = vi.fn()
|
|
|
|
fullscreenButton.dispatchEvent(new Event('click'))
|
|
|
|
expect(reader.requestFullscreen).toHaveBeenCalled()
|
|
expect(document.exitFullscreen).not.toHaveBeenCalled()
|
|
expect(reader.classList.contains('fullscreen')).toBe(true)
|
|
|
|
vi.clearAllMocks()
|
|
document.fullscreenElement = reader
|
|
|
|
fullscreenButton.dispatchEvent(new Event('click'))
|
|
|
|
expect(reader.requestFullscreen).not.toHaveBeenCalled()
|
|
expect(document.exitFullscreen).toHaveBeenCalled()
|
|
expect(reader.classList.contains('fullscreen')).toBe(false)
|
|
})
|