| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061 |
- // @vitest-environment node
- import { afterEach, beforeEach, expect, it, vi } from 'vitest'
- import { mkdtempSync, readFileSync, rmSync } from 'node:fs'
- import { tmpdir } from 'node:os'
- import { join } from 'node:path'
- import { DesktopHostCore } from '../../desktop/environment-host.mjs'
- import { authorizeCurrentComputer } from '../../desktop/computer-authorization.mjs'
- import { dialog } from 'electron'
- vi.mock('electron', () => ({
- app: { isPackaged: false }, BrowserWindow: class {}, session: {},
- desktopCapturer: {}, shell: {},
- dialog: { showMessageBox: vi.fn() },
- screen: { on: vi.fn(), removeListener: vi.fn() },
- powerMonitor: { on: vi.fn(), removeListener: vi.fn() },
- systemPreferences: { isTrustedAccessibilityClient: () => true, getMediaAccessStatus: () => 'granted' },
- }))
- let home: string, core: any
- const owner = 'a'.repeat(64)
- beforeEach(() => {
- home = mkdtempSync(join(tmpdir(), 'native-authorization-'))
- core = new DesktopHostCore({ root: home, dataRoot: home })
- core.platform = { computer: true }
- vi.mocked(dialog.showMessageBox).mockResolvedValue({ response: 1, checkboxChecked: false })
- })
- afterEach(async () => { await core.close(); rmSync(home, { recursive: true, force: true }); vi.clearAllMocks() })
- const request = (scope = 'full', isCurrent = () => true, context = { owner, account: '当前账号' }) => {
- const fetchImpl = vi.fn().mockResolvedValue({ ok: true, json: async () => context })
- return { fetchImpl, promise: authorizeCurrentComputer({ scope, core, origin: 'https://example.test', cookies: [{ name: 'session', value: 'test' }], fetchImpl, isCurrent }) }
- }
- it('grants only the current native core after reading the authenticated account context', async () => {
- const { promise, fetchImpl } = request()
- await expect(promise).resolves.toEqual({ ok: true })
- expect(core.approvedFull.has(owner)).toBe(true)
- expect(core.approved.size).toBe(0)
- expect(JSON.parse(readFileSync(join(home, 'computer-permissions.json'), 'utf8'))).toEqual({ screen: [], full: [owner] })
- expect(fetchImpl.mock.calls[0][0].pathname).toBe('/api/app/desktop-environment/authorization')
- expect(fetchImpl.mock.calls[0][1]).toMatchObject({ method: 'GET', redirect: 'error' })
- })
- it('rejects server-dispatched authorization without showing a dialog', async () => {
- await expect(core.execute({ operation: 'authorize', scope: 'full', owner, deadline: Date.now() + 10000 })).rejects.toThrow('当前设备')
- expect(dialog.showMessageBox).not.toHaveBeenCalled()
- expect(core.approvedFull.size).toBe(0)
- })
- it('does not grant if the client connection changes while confirmation is open', async () => {
- let current = true
- vi.mocked(dialog.showMessageBox).mockImplementation(async () => { current = false; return { response: 1, checkboxChecked: false } })
- await expect(request('full', () => current).promise).rejects.toThrow('已取消')
- expect(core.approvedFull.size).toBe(0)
- })
- it('rejects an all-devices scope before fetching or confirming', async () => {
- const { promise, fetchImpl } = request('all')
- await expect(promise).rejects.toThrow('授权范围无效')
- expect(fetchImpl).not.toHaveBeenCalled()
- expect(dialog.showMessageBox).not.toHaveBeenCalled()
- })
- it('leaves grants unchanged when confirmation is cancelled', async () => {
- vi.mocked(dialog.showMessageBox).mockResolvedValue({ response: 0, checkboxChecked: false })
- await expect(request().promise).rejects.toThrow('已取消')
- expect(core.approvedFull.size).toBe(0)
- })
|