test-local-updater.mjs 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738
  1. /** Run the built Desktop coordinator against real Electron downloads without installing software. */
  2. import { spawn } from 'node:child_process'
  3. import { copyFile, mkdir, mkdtemp, readFile, rm } from 'node:fs/promises'
  4. import { tmpdir } from 'node:os'
  5. import { join } from 'node:path'
  6. import { fileURLToPath } from 'node:url'
  7. import electron from 'electron'
  8. if (process.platform !== 'win32') throw new Error('Local NSIS updater qualification requires Windows')
  9. const root = await mkdtemp(join(tmpdir(), 'dsh-local-updater-'))
  10. let timedOut = false
  11. try {
  12. const environment = Object.fromEntries(Object.entries(process.env).filter(([name]) =>
  13. !/KEY|SECRET|TOKEN|PASSWORD|^NODE_OPTIONS$|^ELECTRON_RUN_AS_NODE$/iu.test(name)))
  14. const child = spawn(electron, [fileURLToPath(new URL('../tests/fixtures/local-updater.mjs', import.meta.url))], {
  15. env: { ...environment, DSH_LOCAL_UPDATE_TEST_ROOT: root }, stdio: 'inherit', windowsHide: true,
  16. })
  17. const timeout = setTimeout(() => { timedOut = true; child.kill() }, 120_000)
  18. try {
  19. const result = await new Promise((resolve, reject) => {
  20. child.once('error', reject)
  21. child.once('close', (code, signal) => resolve({ code, signal }))
  22. })
  23. if (timedOut) throw new Error('Local updater qualification exceeded its 120-second deadline')
  24. if (result.signal !== null) throw new Error(`Electron exited on ${result.signal}`)
  25. if (result.code !== 0) throw new Error(`Local updater qualification failed: exit=${result.code}`)
  26. const evidenceRoot = fileURLToPath(new URL('../.desktop-build/qualification/', import.meta.url))
  27. await mkdir(evidenceRoot, { recursive: true })
  28. const evidence = await mkdtemp(join(evidenceRoot, 'local-updater-'))
  29. const report = JSON.parse(await readFile(join(root, 'result.json'), 'utf8'))
  30. await copyFile(join(root, 'result.json'), join(evidence, 'result.json'))
  31. if (report.screenshot.captured) await copyFile(join(root, 'mandatory-update.png'), join(evidence, 'mandatory-update.png'))
  32. for (const name of report.dialogScreenshots) await copyFile(join(root, name), join(evidence, name))
  33. console.log(`Local updater evidence: ${evidence}`)
  34. } finally { clearTimeout(timeout) }
  35. } finally {
  36. await rm(root, { recursive: true, force: true, maxRetries: 5, retryDelay: 200 })
  37. }