forkoff 1.0.11 → 1.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/dist/__tests__/cli-commands.test.d.ts +6 -0
  2. package/dist/__tests__/cli-commands.test.d.ts.map +1 -0
  3. package/dist/__tests__/cli-commands.test.js +213 -0
  4. package/dist/__tests__/cli-commands.test.js.map +1 -0
  5. package/dist/__tests__/startup.test.d.ts +11 -0
  6. package/dist/__tests__/startup.test.d.ts.map +1 -0
  7. package/dist/__tests__/startup.test.js +233 -0
  8. package/dist/__tests__/startup.test.js.map +1 -0
  9. package/dist/__tests__/tools/claude-process.test.js +221 -15
  10. package/dist/__tests__/tools/claude-process.test.js.map +1 -1
  11. package/dist/__tests__/tools/permission-hook.test.d.ts +17 -0
  12. package/dist/__tests__/tools/permission-hook.test.d.ts.map +1 -0
  13. package/dist/__tests__/tools/permission-hook.test.js +616 -0
  14. package/dist/__tests__/tools/permission-hook.test.js.map +1 -0
  15. package/dist/__tests__/tools/permission-ipc.test.d.ts +11 -0
  16. package/dist/__tests__/tools/permission-ipc.test.d.ts.map +1 -0
  17. package/dist/__tests__/tools/permission-ipc.test.js +612 -0
  18. package/dist/__tests__/tools/permission-ipc.test.js.map +1 -0
  19. package/dist/index.d.ts +2 -1
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +1010 -898
  22. package/dist/index.js.map +1 -1
  23. package/dist/startup.d.ts.map +1 -1
  24. package/dist/startup.js +40 -5
  25. package/dist/startup.js.map +1 -1
  26. package/dist/tools/__tests__/claude-sessions.test.d.ts +2 -0
  27. package/dist/tools/__tests__/claude-sessions.test.d.ts.map +1 -0
  28. package/dist/tools/__tests__/claude-sessions.test.js +306 -0
  29. package/dist/tools/__tests__/claude-sessions.test.js.map +1 -0
  30. package/dist/tools/claude-process.d.ts +81 -4
  31. package/dist/tools/claude-process.d.ts.map +1 -1
  32. package/dist/tools/claude-process.js +332 -20
  33. package/dist/tools/claude-process.js.map +1 -1
  34. package/dist/tools/claude-sessions.d.ts +5 -0
  35. package/dist/tools/claude-sessions.d.ts.map +1 -1
  36. package/dist/tools/claude-sessions.js +16 -2
  37. package/dist/tools/claude-sessions.js.map +1 -1
  38. package/dist/tools/index.d.ts +1 -0
  39. package/dist/tools/index.d.ts.map +1 -1
  40. package/dist/tools/index.js +3 -1
  41. package/dist/tools/index.js.map +1 -1
  42. package/dist/tools/permission-hook.d.ts +41 -0
  43. package/dist/tools/permission-hook.d.ts.map +1 -0
  44. package/dist/tools/permission-hook.js +312 -0
  45. package/dist/tools/permission-hook.js.map +1 -0
  46. package/dist/tools/permission-ipc.d.ts +109 -0
  47. package/dist/tools/permission-ipc.d.ts.map +1 -0
  48. package/dist/tools/permission-ipc.js +295 -0
  49. package/dist/tools/permission-ipc.js.map +1 -0
  50. package/dist/websocket.d.ts +14 -0
  51. package/dist/websocket.d.ts.map +1 -1
  52. package/dist/websocket.js +34 -4
  53. package/dist/websocket.js.map +1 -1
  54. package/jest.config.js +3 -0
  55. package/package.json +1 -1
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Tests for CLI commands: help, unknown command, version
3
+ * Uses createProgram() exported from index.ts
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=cli-commands.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-commands.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/cli-commands.test.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
@@ -0,0 +1,213 @@
1
+ "use strict";
2
+ /**
3
+ * Tests for CLI commands: help, unknown command, version
4
+ * Uses createProgram() exported from index.ts
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ // Mock all heavy dependencies so importing index.ts doesn't trigger real connections
8
+ jest.mock('../config', () => ({
9
+ config: {
10
+ deviceId: null,
11
+ deviceName: 'test',
12
+ apiUrl: 'http://localhost:3000',
13
+ wsUrl: 'ws://localhost:3000',
14
+ pairingCode: null,
15
+ pairedAt: null,
16
+ userId: null,
17
+ isPaired: false,
18
+ startupEnabled: null,
19
+ startupBinaryPath: null,
20
+ getPath: () => '/tmp/config.json',
21
+ reset: jest.fn(),
22
+ },
23
+ }));
24
+ jest.mock('../api', () => ({
25
+ api: {
26
+ healthCheck: jest.fn(),
27
+ registerDevice: jest.fn(),
28
+ refreshPairingCode: jest.fn(),
29
+ checkPairingStatus: jest.fn(),
30
+ reportConnectedTools: jest.fn(),
31
+ },
32
+ }));
33
+ jest.mock('../websocket', () => ({
34
+ wsClient: {
35
+ connect: jest.fn(),
36
+ disconnect: jest.fn(),
37
+ isConnected: false,
38
+ on: jest.fn(),
39
+ sendTerminalOutput: jest.fn(),
40
+ sendTerminalCwd: jest.fn(),
41
+ sendClaudeSessionUpdate: jest.fn(),
42
+ sendClaudeSessions: jest.fn(),
43
+ sendToolStatusUpdate: jest.fn(),
44
+ sendDirectoryListResponse: jest.fn(),
45
+ sendReadFileResponse: jest.fn(),
46
+ sendTranscriptHistory: jest.fn(),
47
+ sendTranscriptUpdate: jest.fn(),
48
+ sendClaudeApprovalRequest: jest.fn(),
49
+ sendToolActivity: jest.fn(),
50
+ sendPermissionPrompt: jest.fn(),
51
+ sendClaudeSessionEvent: jest.fn(),
52
+ sendRpcResponse: jest.fn(),
53
+ sendPendingPermissionsSync: jest.fn(),
54
+ sendThinkingContent: jest.fn(),
55
+ sendTokenUsage: jest.fn(),
56
+ sendTaskProgress: jest.fn(),
57
+ },
58
+ }));
59
+ jest.mock('../terminal', () => ({
60
+ terminalManager: {
61
+ on: jest.fn(),
62
+ createSession: jest.fn(),
63
+ executeCommand: jest.fn(),
64
+ },
65
+ }));
66
+ jest.mock('../approval', () => ({
67
+ approvalManager: {
68
+ on: jest.fn(),
69
+ handleApprovalResponse: jest.fn(),
70
+ },
71
+ }));
72
+ jest.mock('../tools', () => ({
73
+ toolDetector: { detectAll: jest.fn(), watchToolStatus: jest.fn() },
74
+ claudeHooksManager: { canConfigure: jest.fn(), installHooks: jest.fn(), uninstallHooks: jest.fn(), isHookConfigured: jest.fn() },
75
+ claudeSessionDetector: {
76
+ isClaudeInstalled: jest.fn().mockReturnValue(false),
77
+ scanSessions: jest.fn().mockReturnValue([]),
78
+ getSessions: jest.fn().mockReturnValue([]),
79
+ startWatching: jest.fn(),
80
+ stopWatching: jest.fn(),
81
+ seedKnownSessions: jest.fn(),
82
+ on: jest.fn(),
83
+ },
84
+ claudeProcessManager: {
85
+ isClaudeSession: jest.fn(),
86
+ sendInput: jest.fn(),
87
+ registerSession: jest.fn(),
88
+ markTakenOver: jest.fn(),
89
+ isTakenOver: jest.fn(),
90
+ startSession: jest.fn(),
91
+ startAndSendMessage: jest.fn(),
92
+ handleApprovalResponse: jest.fn(),
93
+ handlePermissionResponse: jest.fn(),
94
+ updatePermissionRules: jest.fn(),
95
+ clearAllTakenOver: jest.fn(),
96
+ autoAllowAllPendingPrompts: jest.fn(),
97
+ cleanupAllPermissionState: jest.fn(),
98
+ getAllPendingPrompts: jest.fn().mockReturnValue([]),
99
+ on: jest.fn(),
100
+ },
101
+ PermissionIpcManager: {
102
+ cleanupStaleTempFiles: jest.fn(),
103
+ },
104
+ }));
105
+ jest.mock('../transcript-streamer', () => ({
106
+ transcriptStreamer: {
107
+ fetchHistory: jest.fn(),
108
+ subscribeToUpdates: jest.fn(),
109
+ unsubscribeFromUpdates: jest.fn(),
110
+ cleanup: jest.fn(),
111
+ on: jest.fn(),
112
+ },
113
+ }));
114
+ jest.mock('../logger', () => ({
115
+ setQuiet: jest.fn(),
116
+ createSpinner: jest.fn(() => ({
117
+ start: jest.fn().mockReturnThis(),
118
+ stop: jest.fn(),
119
+ succeed: jest.fn(),
120
+ fail: jest.fn(),
121
+ info: jest.fn(),
122
+ warn: jest.fn(),
123
+ text: '',
124
+ })),
125
+ }));
126
+ jest.mock('chalk', () => {
127
+ const handler = {
128
+ get: () => new Proxy((s) => s, handler),
129
+ apply: (_target, _thisArg, args) => args[0],
130
+ };
131
+ return new Proxy((s) => s, handler);
132
+ });
133
+ jest.mock('qrcode-terminal', () => ({
134
+ generate: jest.fn(),
135
+ }));
136
+ jest.mock('../startup', () => ({
137
+ enableStartup: jest.fn(),
138
+ disableStartup: jest.fn(),
139
+ isStartupRegistered: jest.fn().mockReturnValue(false),
140
+ getBinaryPath: jest.fn().mockReturnValue('/usr/local/bin/forkoff'),
141
+ }));
142
+ const index_1 = require("../index");
143
+ describe('CLI commands', () => {
144
+ let consoleLogSpy;
145
+ let consoleErrorSpy;
146
+ beforeEach(() => {
147
+ consoleLogSpy = jest.spyOn(console, 'log').mockImplementation();
148
+ consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation();
149
+ process.exitCode = undefined;
150
+ });
151
+ afterEach(() => {
152
+ consoleLogSpy.mockRestore();
153
+ consoleErrorSpy.mockRestore();
154
+ process.exitCode = undefined;
155
+ });
156
+ describe('help command', () => {
157
+ it('outputs available commands', async () => {
158
+ const program = (0, index_1.createProgram)();
159
+ // Prevent commander from calling process.exit on help
160
+ program.exitOverride();
161
+ let helpOutput = '';
162
+ program.configureOutput({
163
+ writeOut: (str) => { helpOutput += str; },
164
+ writeErr: (str) => { helpOutput += str; },
165
+ });
166
+ try {
167
+ await program.parseAsync(['node', 'forkoff', 'help']);
168
+ }
169
+ catch {
170
+ // Commander throws on exitOverride
171
+ }
172
+ // The help action calls program.outputHelp(), check console.log calls
173
+ const allOutput = helpOutput + consoleLogSpy.mock.calls.map((c) => c.join(' ')).join('\n');
174
+ expect(allOutput).toContain('pair');
175
+ expect(allOutput).toContain('connect');
176
+ expect(allOutput).toContain('disconnect');
177
+ expect(allOutput).toContain('status');
178
+ expect(allOutput).toContain('startup');
179
+ expect(allOutput).toContain('config');
180
+ expect(allOutput).toContain('tools');
181
+ expect(allOutput).toContain('help');
182
+ });
183
+ });
184
+ describe('--version flag', () => {
185
+ it('shows version from package.json', async () => {
186
+ const program = (0, index_1.createProgram)();
187
+ program.exitOverride();
188
+ let versionOutput = '';
189
+ program.configureOutput({
190
+ writeOut: (str) => { versionOutput += str; },
191
+ writeErr: (str) => { versionOutput += str; },
192
+ });
193
+ try {
194
+ await program.parseAsync(['node', 'forkoff', '--version']);
195
+ }
196
+ catch {
197
+ // Commander throws on exitOverride
198
+ }
199
+ const pkg = require('../../package.json');
200
+ expect(versionOutput).toContain(pkg.version);
201
+ });
202
+ });
203
+ describe('unknown command', () => {
204
+ it('sets process.exitCode = 1 and shows error message', async () => {
205
+ const program = (0, index_1.createProgram)();
206
+ await program.parseAsync(['node', 'forkoff', 'gibberish']);
207
+ expect(process.exitCode).toBe(1);
208
+ const errorOutput = consoleErrorSpy.mock.calls.map((c) => c.join(' ')).join('\n');
209
+ expect(errorOutput).toContain('Unknown command: gibberish');
210
+ });
211
+ });
212
+ });
213
+ //# sourceMappingURL=cli-commands.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-commands.test.js","sourceRoot":"","sources":["../../src/__tests__/cli-commands.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Tests for startup module
3
+ * Covers:
4
+ * - Bug 1: Windows .bat wrapper for schtasks (avoids nested quoting)
5
+ * - Bug 2: macOS plist uses explicit node path (nvm/fnm compatibility)
6
+ * - disableStartup cleans up .bat file on Windows
7
+ * - isStartupRegistered checks schtasks (win32) / plist existence (darwin)
8
+ * - getBinaryPath: cached, which/where, fallback to process.argv[1]
9
+ */
10
+ export {};
11
+ //# sourceMappingURL=startup.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"startup.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/startup.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
@@ -0,0 +1,233 @@
1
+ "use strict";
2
+ /**
3
+ * Tests for startup module
4
+ * Covers:
5
+ * - Bug 1: Windows .bat wrapper for schtasks (avoids nested quoting)
6
+ * - Bug 2: macOS plist uses explicit node path (nvm/fnm compatibility)
7
+ * - disableStartup cleans up .bat file on Windows
8
+ * - isStartupRegistered checks schtasks (win32) / plist existence (darwin)
9
+ * - getBinaryPath: cached, which/where, fallback to process.argv[1]
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ const mockExecSync = jest.fn();
13
+ jest.mock('child_process', () => ({
14
+ execSync: mockExecSync,
15
+ }));
16
+ const mockExistsSync = jest.fn();
17
+ const mockWriteFileSync = jest.fn();
18
+ const mockUnlinkSync = jest.fn();
19
+ const mockMkdirSync = jest.fn();
20
+ jest.mock('fs', () => ({
21
+ existsSync: mockExistsSync,
22
+ writeFileSync: mockWriteFileSync,
23
+ unlinkSync: mockUnlinkSync,
24
+ mkdirSync: mockMkdirSync,
25
+ }));
26
+ const mockConfig = {
27
+ startupBinaryPath: null,
28
+ startupEnabled: null,
29
+ };
30
+ jest.mock('../config', () => ({
31
+ config: mockConfig,
32
+ }));
33
+ const startup_1 = require("../startup");
34
+ describe('startup', () => {
35
+ const originalPlatform = process.platform;
36
+ const originalExecPath = process.execPath;
37
+ const originalArgv = [...process.argv];
38
+ function setPlatform(platform) {
39
+ Object.defineProperty(process, 'platform', { value: platform, configurable: true });
40
+ }
41
+ beforeEach(() => {
42
+ // resetAllMocks clears calls AND implementations (unlike clearAllMocks)
43
+ jest.resetAllMocks();
44
+ mockConfig.startupBinaryPath = null;
45
+ mockConfig.startupEnabled = null;
46
+ mockExistsSync.mockReturnValue(false);
47
+ });
48
+ afterEach(() => {
49
+ Object.defineProperty(process, 'platform', { value: originalPlatform, configurable: true });
50
+ Object.defineProperty(process, 'execPath', { value: originalExecPath, configurable: true });
51
+ process.argv = [...originalArgv];
52
+ });
53
+ describe('getBinaryPath', () => {
54
+ it('returns cached path when it exists on disk', () => {
55
+ mockConfig.startupBinaryPath = '/usr/local/bin/forkoff';
56
+ mockExistsSync.mockReturnValue(true);
57
+ expect((0, startup_1.getBinaryPath)()).toBe('/usr/local/bin/forkoff');
58
+ expect(mockExecSync).not.toHaveBeenCalled();
59
+ });
60
+ it('finds via which on darwin', () => {
61
+ setPlatform('darwin');
62
+ mockConfig.startupBinaryPath = null;
63
+ mockExecSync.mockReturnValue('/usr/local/bin/forkoff\n');
64
+ // startupBinaryPath is null → short-circuit, existsSync NOT called for cache.
65
+ // First existsSync call is for the which result → return true.
66
+ mockExistsSync.mockReturnValueOnce(true);
67
+ expect((0, startup_1.getBinaryPath)()).toBe('/usr/local/bin/forkoff');
68
+ expect(mockExecSync).toHaveBeenCalledWith('which forkoff', { encoding: 'utf-8' });
69
+ expect(mockConfig.startupBinaryPath).toBe('/usr/local/bin/forkoff');
70
+ });
71
+ it('finds via where on win32', () => {
72
+ setPlatform('win32');
73
+ mockConfig.startupBinaryPath = null;
74
+ mockExecSync.mockReturnValue('C:\\Program Files\\nodejs\\forkoff\r\n');
75
+ mockExistsSync.mockReturnValueOnce(true);
76
+ expect((0, startup_1.getBinaryPath)()).toBe('C:\\Program Files\\nodejs\\forkoff');
77
+ expect(mockExecSync).toHaveBeenCalledWith('where forkoff', { encoding: 'utf-8' });
78
+ });
79
+ it('falls back to process.argv[1] when which/where fails', () => {
80
+ setPlatform('darwin');
81
+ mockConfig.startupBinaryPath = null;
82
+ mockExecSync.mockImplementation(() => { throw new Error('not found'); });
83
+ process.argv = ['node', '/home/user/.nvm/versions/node/bin/forkoff'];
84
+ expect((0, startup_1.getBinaryPath)()).toBe('/home/user/.nvm/versions/node/bin/forkoff');
85
+ expect(mockConfig.startupBinaryPath).toBe('/home/user/.nvm/versions/node/bin/forkoff');
86
+ });
87
+ it('throws when no binary can be found', () => {
88
+ mockConfig.startupBinaryPath = null;
89
+ mockExecSync.mockImplementation(() => { throw new Error('not found'); });
90
+ process.argv = ['node']; // No argv[1]
91
+ expect(() => (0, startup_1.getBinaryPath)()).toThrow('Could not determine forkoff binary path');
92
+ });
93
+ });
94
+ describe('isStartupRegistered', () => {
95
+ it('returns true on win32 when schtasks query succeeds', () => {
96
+ setPlatform('win32');
97
+ mockExecSync.mockReturnValue('');
98
+ expect((0, startup_1.isStartupRegistered)()).toBe(true);
99
+ expect(mockExecSync).toHaveBeenCalledWith(expect.stringContaining('schtasks /Query'), { stdio: 'pipe' });
100
+ });
101
+ it('returns false on win32 when schtasks query throws', () => {
102
+ setPlatform('win32');
103
+ mockExecSync.mockImplementation(() => { throw new Error('not found'); });
104
+ expect((0, startup_1.isStartupRegistered)()).toBe(false);
105
+ });
106
+ it('returns true on darwin when plist file exists', () => {
107
+ setPlatform('darwin');
108
+ mockExistsSync.mockReturnValue(true);
109
+ expect((0, startup_1.isStartupRegistered)()).toBe(true);
110
+ });
111
+ it('returns false on darwin when plist file does not exist', () => {
112
+ setPlatform('darwin');
113
+ mockExistsSync.mockReturnValue(false);
114
+ expect((0, startup_1.isStartupRegistered)()).toBe(false);
115
+ });
116
+ it('returns false on unsupported platform', () => {
117
+ setPlatform('linux');
118
+ expect((0, startup_1.isStartupRegistered)()).toBe(false);
119
+ });
120
+ });
121
+ describe('enableStartup (win32)', () => {
122
+ beforeEach(() => {
123
+ setPlatform('win32');
124
+ Object.defineProperty(process, 'execPath', {
125
+ value: 'C:\\Program Files\\nodejs\\node.exe',
126
+ configurable: true,
127
+ });
128
+ mockConfig.startupBinaryPath = 'C:\\Users\\test\\AppData\\Roaming\\npm\\forkoff';
129
+ mockExistsSync.mockReturnValue(true);
130
+ });
131
+ it('writes .bat wrapper with correct content', async () => {
132
+ await (0, startup_1.enableStartup)();
133
+ const batCall = mockWriteFileSync.mock.calls.find((call) => typeof call[0] === 'string' && call[0].endsWith('.bat'));
134
+ expect(batCall).toBeDefined();
135
+ const batContent = batCall[1];
136
+ expect(batContent).toContain('@echo off');
137
+ expect(batContent).toContain('"C:\\Program Files\\nodejs\\node.exe"');
138
+ expect(batContent).toContain('"C:\\Users\\test\\AppData\\Roaming\\npm\\forkoff"');
139
+ expect(batContent).toContain('connect --quiet');
140
+ });
141
+ it('calls schtasks /Create with .bat path', async () => {
142
+ await (0, startup_1.enableStartup)();
143
+ const createCall = mockExecSync.mock.calls.find((call) => typeof call[0] === 'string' && call[0].includes('schtasks /Create'));
144
+ expect(createCall).toBeDefined();
145
+ expect(createCall[0]).toContain('startup.bat');
146
+ expect(createCall[0]).toContain('/SC ONLOGON');
147
+ });
148
+ it('sets config.startupEnabled = true', async () => {
149
+ await (0, startup_1.enableStartup)();
150
+ expect(mockConfig.startupEnabled).toBe(true);
151
+ });
152
+ });
153
+ describe('enableStartup (darwin)', () => {
154
+ beforeEach(() => {
155
+ setPlatform('darwin');
156
+ Object.defineProperty(process, 'execPath', {
157
+ value: '/Users/test/.nvm/versions/node/v20.0.0/bin/node',
158
+ configurable: true,
159
+ });
160
+ mockConfig.startupBinaryPath = '/usr/local/bin/forkoff';
161
+ mockExistsSync.mockReturnValue(true);
162
+ });
163
+ it('writes plist with process.execPath as first ProgramArgument', async () => {
164
+ await (0, startup_1.enableStartup)();
165
+ const plistCall = mockWriteFileSync.mock.calls.find((call) => typeof call[0] === 'string' && call[0].endsWith('.plist'));
166
+ expect(plistCall).toBeDefined();
167
+ const plistContent = plistCall[1];
168
+ const argsMatch = plistContent.match(/<array>([\s\S]*?)<\/array>/);
169
+ expect(argsMatch).toBeDefined();
170
+ const strings = [...argsMatch[1].matchAll(/<string>(.*?)<\/string>/g)].map(m => m[1]);
171
+ expect(strings[0]).toBe('/Users/test/.nvm/versions/node/v20.0.0/bin/node');
172
+ expect(strings[1]).toBe('/usr/local/bin/forkoff');
173
+ expect(strings[2]).toBe('connect');
174
+ expect(strings[3]).toBe('--quiet');
175
+ });
176
+ it('includes node directory in PATH when not in default PATH', async () => {
177
+ await (0, startup_1.enableStartup)();
178
+ const plistCall = mockWriteFileSync.mock.calls.find((call) => typeof call[0] === 'string' && call[0].endsWith('.plist'));
179
+ const plistContent = plistCall[1];
180
+ expect(plistContent).toContain('/Users/test/.nvm/versions/node/v20.0.0/bin:');
181
+ });
182
+ it('calls launchctl load', async () => {
183
+ await (0, startup_1.enableStartup)();
184
+ const loadCall = mockExecSync.mock.calls.find((call) => typeof call[0] === 'string' && call[0].includes('launchctl load'));
185
+ expect(loadCall).toBeDefined();
186
+ });
187
+ it('sets config.startupEnabled = true', async () => {
188
+ await (0, startup_1.enableStartup)();
189
+ expect(mockConfig.startupEnabled).toBe(true);
190
+ });
191
+ });
192
+ describe('disableStartup (win32)', () => {
193
+ beforeEach(() => {
194
+ setPlatform('win32');
195
+ });
196
+ it('calls schtasks /Delete', async () => {
197
+ await (0, startup_1.disableStartup)();
198
+ const deleteCall = mockExecSync.mock.calls.find((call) => typeof call[0] === 'string' && call[0].includes('schtasks /Delete'));
199
+ expect(deleteCall).toBeDefined();
200
+ });
201
+ it('removes .bat file if it exists', async () => {
202
+ mockExistsSync.mockReturnValue(true);
203
+ await (0, startup_1.disableStartup)();
204
+ expect(mockUnlinkSync).toHaveBeenCalledWith(expect.stringContaining('startup.bat'));
205
+ });
206
+ it('sets config.startupEnabled = false', async () => {
207
+ await (0, startup_1.disableStartup)();
208
+ expect(mockConfig.startupEnabled).toBe(false);
209
+ });
210
+ });
211
+ describe('disableStartup (darwin)', () => {
212
+ beforeEach(() => {
213
+ setPlatform('darwin');
214
+ });
215
+ it('calls launchctl unload and removes plist when it exists', async () => {
216
+ mockExistsSync.mockReturnValue(true);
217
+ await (0, startup_1.disableStartup)();
218
+ const unloadCall = mockExecSync.mock.calls.find((call) => typeof call[0] === 'string' && call[0].includes('launchctl unload'));
219
+ expect(unloadCall).toBeDefined();
220
+ expect(mockUnlinkSync).toHaveBeenCalledWith(expect.stringContaining('.plist'));
221
+ });
222
+ it('does nothing when plist does not exist', async () => {
223
+ mockExistsSync.mockReturnValue(false);
224
+ await (0, startup_1.disableStartup)();
225
+ expect(mockUnlinkSync).not.toHaveBeenCalled();
226
+ });
227
+ it('sets config.startupEnabled = false', async () => {
228
+ await (0, startup_1.disableStartup)();
229
+ expect(mockConfig.startupEnabled).toBe(false);
230
+ });
231
+ });
232
+ });
233
+ //# sourceMappingURL=startup.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"startup.test.js","sourceRoot":"","sources":["../../src/__tests__/startup.test.ts"],"names":[],"mappings":"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"}