desktopBoot.test.ts 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. // @vitest-environment node
  2. import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
  3. import { mkdtempSync, rmSync } from 'node:fs'
  4. import { tmpdir } from 'node:os'
  5. import { join } from 'node:path'
  6. const native = vi.hoisted(() => ({ loaded: true, calls: [] as string[][] }))
  7. vi.mock('node:child_process', () => ({ execFileSync: (command: string, args: string[]) => {
  8. native.calls.push([command, ...args])
  9. if (args[0] === 'print' && !native.loaded) throw new Error('not loaded')
  10. if (args[0] === 'bootout') native.loaded = false
  11. if (args[0] === 'bootstrap') native.loaded = true
  12. return ''
  13. } }))
  14. import { LaunchAgentService } from '../../bin/lib/service-update.mjs'
  15. let home: string
  16. beforeEach(() => { home = mkdtempSync(join(tmpdir(), 'yaoyao-launchagent-boot-')); native.loaded = true; native.calls = [] })
  17. afterEach(() => { rmSync(home, { recursive: true, force: true }) })
  18. function fixture(pid?: number) {
  19. const driver = new LaunchAgentService({ home, releaseRoot: join(home, 'releases'), label: 'fixture', environment: { HERMES_YAOYAO_DEFER_HERMES: '1' } })
  20. driver.pid = () => pid
  21. driver.prepareBoot = vi.fn((defer: boolean) => defer && !pid)
  22. driver.writePlist = vi.fn()
  23. return driver
  24. }
  25. const operations = () => native.calls.map(([, operation]) => operation)
  26. describe.skipIf(process.platform === 'win32')('desktop LaunchAgent boot', () => {
  27. it('reloads a stopped but loaded job before starting it with the new deferred environment', async () => {
  28. const driver = fixture()
  29. await driver.boot()
  30. expect(driver.prepareBoot).toHaveBeenCalledWith(true)
  31. expect(operations()).toEqual(['print', 'bootout', 'bootstrap'])
  32. })
  33. it('keeps an already running service registered and preserves its active authorization', async () => {
  34. const driver = fixture(1234)
  35. await driver.boot()
  36. expect(operations()).toEqual(['print', 'kickstart'])
  37. })
  38. it('restores the previous loaded job without clearing its recovered authorization', async () => {
  39. const driver = fixture()
  40. await driver.restore({ plist: { Label: 'fixture' }, wasRunning: true })
  41. expect(driver.prepareBoot).toHaveBeenCalledWith(false)
  42. expect(operations()).toEqual(['print', 'kickstart'])
  43. })
  44. it('bootstraps a new registration directly', async () => {
  45. native.loaded = false
  46. await fixture().boot()
  47. expect(operations()).toEqual(['print', 'bootstrap'])
  48. })
  49. it('does not unload a service that starts while preparation is finishing', async () => {
  50. const driver = fixture()
  51. driver.prepareBoot = vi.fn(() => { driver.pid = () => 1234; return true })
  52. await driver.boot()
  53. expect(operations()).toEqual(['print', 'kickstart'])
  54. })
  55. })