CoolFace
Datasetpublic

basant307/AI_Governance_Project

sourceHugging Faceapache-2.0updated 2mo agoView on Hugging Face
0likes48downloads
bootstrap.test.ts263 linesDownload Raw Back to computer-use
1/**2 * @license3 * Copyright 2025 Qwen Team4 * SPDX-License-Identifier: Apache-2.05 */6 7import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';8import { mkdtempSync, rmSync } from 'node:fs';9import { tmpdir } from 'node:os';10import { join } from 'node:path';11import {12  runBootstrap,13  parsePermissionsStatus,14  type BootstrapDeps,15  type StatusDaemon,16} from './bootstrap.js';17 18const KEY = 'cua-driver-rs@0.5.2';19 20function makeFakeClient() {21  const start = vi.fn(async () => {});22  const stop = vi.fn(async () => {});23  return {24    isStarted: vi.fn(() => start.mock.calls.length > stop.mock.calls.length),25    start,26    stop,27    callTool: vi.fn(),28  };29}30 31describe('runBootstrap', () => {32  let tmpHome: string;33  let daemon: StatusDaemon & { kill: ReturnType<typeof vi.fn> };34  let deps: BootstrapDeps;35 36  beforeEach(() => {37    tmpHome = mkdtempSync(join(tmpdir(), 'qwen-cu-bs-'));38    daemon = { kill: vi.fn() };39    deps = {40      homeDir: tmpHome,41      approvalKey: KEY,42      platform: 'darwin',43      promptInstallApproval: vi.fn(async () => true),44      install: vi.fn(async () => '/fake/cua-driver'),45      startStatusDaemon: vi.fn(() => daemon),46      probePermissions: vi.fn(async () => 'ok' as const),47      openPermissionPane: vi.fn(),48      pollIntervalMs: 1,49      pollTimeoutMs: 1000,50    };51  });52 53  afterEach(() => {54    rmSync(tmpHome, { recursive: true, force: true });55  });56 57  it('starts the proxy directly when already granted (no panes opened)', async () => {58    const { saveInstallState } = await import('./install-state.js');59    await saveInstallState(tmpHome, {60      approvedPackageSpec: KEY,61      approvedAtIso: '2026-06-12T10:00:00Z',62    });63 64    const client = makeFakeClient();65    await runBootstrap(66      client as never,67      { signal: new AbortController().signal },68      deps,69    );70 71    expect(deps.install).toHaveBeenCalledOnce();72    expect(deps.openPermissionPane).not.toHaveBeenCalled();73    expect(daemon.kill).toHaveBeenCalled(); // status daemon torn down74    expect(client.start).toHaveBeenCalledOnce();75  });76 77  it('prompts for install approval on first call', async () => {78    const client = makeFakeClient();79    await runBootstrap(80      client as never,81      { signal: new AbortController().signal },82      deps,83    );84    expect(deps.promptInstallApproval).toHaveBeenCalledOnce();85    expect(client.start).toHaveBeenCalledOnce();86  });87 88  it('throws and does NOT download when user declines install', async () => {89    deps.promptInstallApproval = vi.fn(async () => false);90    const client = makeFakeClient();91    await expect(92      runBootstrap(93        client as never,94        { signal: new AbortController().signal },95        deps,96      ),97    ).rejects.toThrow(/declined/i);98    expect(deps.install).not.toHaveBeenCalled();99    expect(client.start).not.toHaveBeenCalled();100  });101 102  it('auto-approves the install (no prompt) and persists state when autoApproveInstall is set', async () => {103    // review #1 (⑤): an auto-approve mode or an always-allow-ruled call passes104    // autoApproveInstall. The gate must skip promptInstallApproval, persist the105    // install state (so later cold calls also skip the gate), and proceed —106    // this is what closes the DEFAULT-mode "install declined" dead-end.107    const { isPackageSpecApproved } = await import('./install-state.js');108    const client = makeFakeClient();109    await runBootstrap(110      client as never,111      { signal: new AbortController().signal, autoApproveInstall: true },112      deps,113    );114    expect(deps.promptInstallApproval).not.toHaveBeenCalled();115    expect(await isPackageSpecApproved(tmpHome, KEY)).toBe(true);116    expect(deps.install).toHaveBeenCalledOnce();117    expect(client.start).toHaveBeenCalledOnce();118  });119 120  it('guides one permission at a time: Accessibility pane, then Screen Recording pane', async () => {121    const { saveInstallState } = await import('./install-state.js');122    await saveInstallState(tmpHome, {123      approvedPackageSpec: KEY,124      approvedAtIso: '2026-06-12T10:00:00Z',125    });126 127    // accessibility missing → screen recording missing → ok128    let n = 0;129    deps.probePermissions = vi.fn(async () => {130      n++;131      if (n === 1) return 'accessibility' as const;132      if (n === 2) return 'screenRecording' as const;133      return 'ok' as const;134    });135 136    const client = makeFakeClient();137    await runBootstrap(138      client as never,139      { signal: new AbortController().signal },140      deps,141    );142 143    const panes = (deps.openPermissionPane as ReturnType<typeof vi.fn>).mock144      .calls;145    expect(panes).toEqual([['accessibility'], ['screenRecording']]); // in order, one each146    expect(client.start).toHaveBeenCalledOnce();147  });148 149  it('relaunches the status daemon when status reads unknown (e.g. SR restart)', async () => {150    const { saveInstallState } = await import('./install-state.js');151    await saveInstallState(tmpHome, {152      approvedPackageSpec: KEY,153      approvedAtIso: '2026-06-12T10:00:00Z',154    });155 156    let n = 0;157    deps.probePermissions = vi.fn(async () => {158      n++;159      if (n === 1) return 'unknown' as const; // daemon coming up / restarted160      if (n === 2) return 'accessibility' as const;161      return 'ok' as const;162    });163 164    const client = makeFakeClient();165    await runBootstrap(166      client as never,167      { signal: new AbortController().signal },168      deps,169    );170 171    // initial launch + one relaunch after 'unknown'.172    expect(deps.startStatusDaemon).toHaveBeenCalledTimes(2);173    expect(client.start).toHaveBeenCalledOnce();174  });175 176  it('times out (and tears down the daemon) if permissions never arrive', async () => {177    const { saveInstallState } = await import('./install-state.js');178    await saveInstallState(tmpHome, {179      approvedPackageSpec: KEY,180      approvedAtIso: '2026-06-12T10:00:00Z',181    });182    deps.probePermissions = vi.fn(async () => 'accessibility' as const);183    deps.pollTimeoutMs = 30;184 185    const client = makeFakeClient();186    await expect(187      runBootstrap(188        client as never,189        { signal: new AbortController().signal },190        deps,191      ),192    ).rejects.toThrow(/timed out/i);193    expect(daemon.kill).toHaveBeenCalled();194    expect(client.start).not.toHaveBeenCalled();195  });196 197  it('skips the permission flow on non-darwin platforms', async () => {198    const { saveInstallState } = await import('./install-state.js');199    await saveInstallState(tmpHome, {200      approvedPackageSpec: KEY,201      approvedAtIso: '2026-06-12T10:00:00Z',202    });203    deps.platform = 'linux';204 205    const client = makeFakeClient();206    await runBootstrap(207      client as never,208      { signal: new AbortController().signal },209      deps,210    );211    expect(deps.startStatusDaemon).not.toHaveBeenCalled();212    expect(deps.probePermissions).not.toHaveBeenCalled();213    expect(client.start).toHaveBeenCalledOnce();214  });215 216  it('does nothing extra when the client is already started (warm)', async () => {217    const { saveInstallState } = await import('./install-state.js');218    await saveInstallState(tmpHome, {219      approvedPackageSpec: KEY,220      approvedAtIso: '2026-06-12T10:00:00Z',221    });222    const client = {223      isStarted: vi.fn(() => true),224      start: vi.fn(async () => {}),225      stop: vi.fn(async () => {}),226      callTool: vi.fn(),227    };228    await runBootstrap(229      client as never,230      { signal: new AbortController().signal },231      deps,232    );233    expect(client.start).not.toHaveBeenCalled();234    expect(deps.startStatusDaemon).not.toHaveBeenCalled();235    // The warm-client short-circuit must precede the install step: a started236    // client implies the binary is present, so the downloader must NOT run237    // (otherwise unit tests trigger a real ~20MB download). (review round 1)238    expect(deps.install).not.toHaveBeenCalled();239  });240});241 242describe('parsePermissionsStatus', () => {243  it("returns 'ok' when both grants are true", () => {244    expect(245      parsePermissionsStatus('{"accessibility":true,"screen_recording":true}'),246    ).toBe('ok');247  });248  it("returns 'accessibility' when accessibility is false", () => {249    expect(250      parsePermissionsStatus('{"accessibility":false,"screen_recording":true}'),251    ).toBe('accessibility');252  });253  it("returns 'screenRecording' when only screen recording is false", () => {254    expect(255      parsePermissionsStatus('{"accessibility":true,"screen_recording":false}'),256    ).toBe('screenRecording');257  });258  it("returns 'unknown' for daemon-less / unparseable payloads", () => {259    expect(parsePermissionsStatus('{"status":"unknown"}')).toBe('unknown');260    expect(parsePermissionsStatus('not json')).toBe('unknown');261  });262});263 
basant307/AI_Governance_Project · CoolFace