fix(macos): hidden autostart dock indicator + 자동실행 mismatch false positive
두 macOS 한정 버그 묶음: 1. autostart --hidden 으로 spawn 시 quickCapture (NSPanel) 만 떠 있어 dock running indicator (점) 가 표출 안 됨 — NSPanel 은 NSApp main window 로 register 안 됨. inboxWindow 를 hidden 상태로 미리 create + ready-to-show 시점에 showInactive → hide trick 으로 NSApp 에 register, 사용자 화면 깜빡임 없이 dock 점 켜짐. 2. SettingsPage 의 자동실행 mismatch 경고가 macOS 에서 false positive. macOS 13+ 의 SMAppService API 가 args 옵션 무시 + unsigned/Electron 앱에 대해 executableWillLaunchAtLogin 을 자주 false 로 반환 → 정상 등록 상태에서도 경고 떠 있음. AutostartDiagnostic 결과에 platform 필드 추가, willLaunch 신호는 win32 에서만 mismatch 판정에 사용. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -42,6 +42,7 @@ describe('AutostartDiagnostic — collectAutostartState', () => {
|
||||
expect(state.withArgs).toEqual({ openAtLogin: true, executableWillLaunchAtLogin: true });
|
||||
expect(state.noArgs).toEqual({ openAtLogin: false, executableWillLaunchAtLogin: true });
|
||||
expect(state.execPath).toBe(process.execPath);
|
||||
expect(state.platform).toBe('darwin');
|
||||
});
|
||||
|
||||
it('passes args=["--hidden"] for the first call, no args for the second', async () => {
|
||||
|
||||
@@ -3,15 +3,17 @@ import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
import '@testing-library/jest-dom/vitest';
|
||||
import { render, screen, fireEvent, waitFor, cleanup } from '@testing-library/react';
|
||||
|
||||
function makeDiag(open: boolean): {
|
||||
function makeDiag(open: boolean, platform: NodeJS.Platform = 'win32'): {
|
||||
withArgs: { openAtLogin: boolean; executableWillLaunchAtLogin: boolean };
|
||||
noArgs: { openAtLogin: boolean; executableWillLaunchAtLogin: boolean };
|
||||
execPath: string;
|
||||
platform: NodeJS.Platform;
|
||||
} {
|
||||
return {
|
||||
withArgs: { openAtLogin: open, executableWillLaunchAtLogin: open },
|
||||
noArgs: { openAtLogin: open, executableWillLaunchAtLogin: open },
|
||||
execPath: '/path/to/exe'
|
||||
execPath: '/path/to/exe',
|
||||
platform
|
||||
};
|
||||
}
|
||||
|
||||
@@ -51,7 +53,8 @@ describe('AutostartSection', () => {
|
||||
diagnostic: {
|
||||
withArgs: { openAtLogin: true, executableWillLaunchAtLogin: true },
|
||||
noArgs: { openAtLogin: false, executableWillLaunchAtLogin: true },
|
||||
execPath: '/path/to/Inkling.exe'
|
||||
execPath: '/path/to/Inkling.exe',
|
||||
platform: 'win32'
|
||||
}
|
||||
});
|
||||
render(<AutostartSection />);
|
||||
@@ -71,6 +74,7 @@ describe('AutostartSection', () => {
|
||||
withArgs: { openAtLogin: true, executableWillLaunchAtLogin: true },
|
||||
noArgs: { openAtLogin: true, executableWillLaunchAtLogin: true },
|
||||
execPath: 'C:\\app.exe',
|
||||
platform: 'win32',
|
||||
registryPath: 'HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\Inkling',
|
||||
registryValue: '"C:\\app.exe" --hidden'
|
||||
}
|
||||
@@ -89,7 +93,8 @@ describe('AutostartSection', () => {
|
||||
diagnostic: {
|
||||
withArgs: { openAtLogin: true, executableWillLaunchAtLogin: true },
|
||||
noArgs: { openAtLogin: true, executableWillLaunchAtLogin: true },
|
||||
execPath: '/p'
|
||||
execPath: '/p',
|
||||
platform: 'win32'
|
||||
}
|
||||
});
|
||||
render(<AutostartSection />);
|
||||
@@ -97,6 +102,38 @@ describe('AutostartSection', () => {
|
||||
expect(screen.queryByText(/⚠️/)).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('macOS: no false-positive mismatch when willLaunch=false (SMAppService 한계)', async () => {
|
||||
const { inboxApi } = await import('../../src/renderer/inbox/api.js');
|
||||
vi.mocked(inboxApi.getAutostart).mockResolvedValueOnce({
|
||||
openAtLogin: true,
|
||||
diagnostic: {
|
||||
withArgs: { openAtLogin: true, executableWillLaunchAtLogin: false },
|
||||
noArgs: { openAtLogin: true, executableWillLaunchAtLogin: false },
|
||||
execPath: '/Applications/Inkling.app',
|
||||
platform: 'darwin'
|
||||
}
|
||||
});
|
||||
render(<AutostartSection />);
|
||||
await screen.findByRole('checkbox');
|
||||
expect(screen.queryByText(/⚠️/)).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Win: mismatch warning when openAtLogin=true but willLaunch=false', async () => {
|
||||
const { inboxApi } = await import('../../src/renderer/inbox/api.js');
|
||||
vi.mocked(inboxApi.getAutostart).mockResolvedValueOnce({
|
||||
openAtLogin: true,
|
||||
diagnostic: {
|
||||
withArgs: { openAtLogin: true, executableWillLaunchAtLogin: false },
|
||||
noArgs: { openAtLogin: true, executableWillLaunchAtLogin: false },
|
||||
execPath: 'C:\\app.exe',
|
||||
platform: 'win32'
|
||||
}
|
||||
});
|
||||
render(<AutostartSection />);
|
||||
await screen.findByRole('checkbox');
|
||||
expect(await screen.findByText(/⚠️/)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('"재등록" button calls setAutostart with current openAtLogin value', async () => {
|
||||
const { inboxApi } = await import('../../src/renderer/inbox/api.js');
|
||||
vi.mocked(inboxApi.getAutostart).mockResolvedValueOnce({
|
||||
@@ -104,7 +141,8 @@ describe('AutostartSection', () => {
|
||||
diagnostic: {
|
||||
withArgs: { openAtLogin: true, executableWillLaunchAtLogin: true },
|
||||
noArgs: { openAtLogin: true, executableWillLaunchAtLogin: true },
|
||||
execPath: '/p'
|
||||
execPath: '/p',
|
||||
platform: 'win32'
|
||||
}
|
||||
});
|
||||
render(<AutostartSection />);
|
||||
|
||||
Reference in New Issue
Block a user