fix: address Windows smoke review findings (#122)
Co-authored-by: iliya <iliyazelenkog@gmail.com>
This commit is contained in:
parent
9c438e7c84
commit
f08e228a7d
5 changed files with 103 additions and 4 deletions
|
|
@ -173,4 +173,13 @@ async function main() {
|
||||||
fail(`Timed out after ${STARTUP_TIMEOUT_MS}ms waiting for packaged startup`, log);
|
fail(`Timed out after ${STARTUP_TIMEOUT_MS}ms waiting for packaged startup`, log);
|
||||||
}
|
}
|
||||||
|
|
||||||
main().catch((error) => fail(error?.stack || String(error)));
|
if (require.main === module) {
|
||||||
|
main().catch((error) => fail(error?.stack || String(error)));
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
_internal: {
|
||||||
|
terminateChild,
|
||||||
|
waitForProcessClose,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -12,13 +12,13 @@ import type { ClaudeMdContextInjection } from '@renderer/types/contextInjection'
|
||||||
*/
|
*/
|
||||||
export function buildDirectoryTree(
|
export function buildDirectoryTree(
|
||||||
injections: ClaudeMdContextInjection[],
|
injections: ClaudeMdContextInjection[],
|
||||||
projectRoot: string
|
projectRoot?: string
|
||||||
): TreeNode {
|
): TreeNode {
|
||||||
const root: TreeNode = { name: '', path: '', isFile: false, children: new Map() };
|
const root: TreeNode = { name: '', path: '', isFile: false, children: new Map() };
|
||||||
|
|
||||||
for (const injection of injections) {
|
for (const injection of injections) {
|
||||||
const relativePath = projectRoot
|
const relativePath = projectRoot
|
||||||
? getRelativePathWithinPrefix(projectRoot, injection.path) ?? injection.path
|
? (getRelativePathWithinPrefix(projectRoot, injection.path) ?? injection.path)
|
||||||
: injection.path;
|
: injection.path;
|
||||||
|
|
||||||
const parts = relativePath.split(/[\\/]/);
|
const parts = relativePath.split(/[\\/]/);
|
||||||
|
|
|
||||||
|
|
@ -169,6 +169,21 @@ describe('recentProjectOpenHistory', () => {
|
||||||
|
|
||||||
it('ignores blank project paths without throwing', () => {
|
it('ignores blank project paths without throwing', () => {
|
||||||
expect(() => recordRecentProjectOpenPaths([' '], 10_000)).not.toThrow();
|
expect(() => recordRecentProjectOpenPaths([' '], 10_000)).not.toThrow();
|
||||||
expect(getRecentProjectLastOpenedAt(makeProject({ primaryPath: ' ', associatedPaths: [' '] }))).toBe(0);
|
expect(
|
||||||
|
getRecentProjectLastOpenedAt(makeProject({ primaryPath: ' ', associatedPaths: [' '] }))
|
||||||
|
).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('ignores paths that normalize to an empty history key', () => {
|
||||||
|
recordRecentProjectOpenPaths(['///'], 10_000);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
getRecentProjectLastOpenedAt(
|
||||||
|
makeProject({
|
||||||
|
primaryPath: '/',
|
||||||
|
associatedPaths: ['/'],
|
||||||
|
})
|
||||||
|
)
|
||||||
|
).toBe(0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
69
test/main/build/smokePackagedApp.test.ts
Normal file
69
test/main/build/smokePackagedApp.test.ts
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
// @vitest-environment node
|
||||||
|
import { createRequire } from 'node:module';
|
||||||
|
|
||||||
|
import { describe, expect, it, vi } from 'vitest';
|
||||||
|
|
||||||
|
interface SmokePackagedAppInternals {
|
||||||
|
terminateChild(
|
||||||
|
child: { exitCode: number | null; signalCode: string | null; kill: () => void },
|
||||||
|
exitPromise: Promise<unknown>,
|
||||||
|
platform: string
|
||||||
|
): Promise<void>;
|
||||||
|
waitForProcessClose(
|
||||||
|
child: { exitCode: number | null; signalCode: string | null },
|
||||||
|
exitPromise: Promise<unknown>,
|
||||||
|
timeoutMs: number
|
||||||
|
): Promise<boolean>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SmokePackagedAppModule {
|
||||||
|
default?: { _internal?: SmokePackagedAppInternals };
|
||||||
|
_internal?: SmokePackagedAppInternals;
|
||||||
|
}
|
||||||
|
|
||||||
|
const requireFromTest: (id: string) => unknown = createRequire(import.meta.url);
|
||||||
|
const smokePackagedApp = requireFromTest(
|
||||||
|
'../../../scripts/electron-builder/smokePackagedApp.cjs'
|
||||||
|
) as SmokePackagedAppModule;
|
||||||
|
const smokePackagedAppInternals =
|
||||||
|
smokePackagedApp._internal ?? smokePackagedApp.default?._internal;
|
||||||
|
if (!smokePackagedAppInternals) {
|
||||||
|
throw new Error('smokePackagedApp internals were not exported');
|
||||||
|
}
|
||||||
|
const { terminateChild, waitForProcessClose } = smokePackagedAppInternals;
|
||||||
|
|
||||||
|
describe('smokePackagedApp shutdown handling', () => {
|
||||||
|
it('reports successful process closure before the timeout', async () => {
|
||||||
|
let resolveExit!: (value: unknown) => void;
|
||||||
|
const exitPromise = new Promise((resolve) => {
|
||||||
|
resolveExit = resolve;
|
||||||
|
});
|
||||||
|
const child = { exitCode: null, signalCode: null };
|
||||||
|
|
||||||
|
const closed = waitForProcessClose(child, exitPromise, 1_000);
|
||||||
|
resolveExit({ code: 0, signal: null });
|
||||||
|
|
||||||
|
await expect(closed).resolves.toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('reports shutdown timeout instead of treating it as success', async () => {
|
||||||
|
vi.useFakeTimers();
|
||||||
|
try {
|
||||||
|
const exitPromise = new Promise(() => undefined);
|
||||||
|
const child = {
|
||||||
|
exitCode: null,
|
||||||
|
signalCode: null,
|
||||||
|
kill: vi.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const termination = terminateChild(child, exitPromise, 'linux');
|
||||||
|
const rejection = expect(termination).rejects.toThrow('Timed out after 5000ms');
|
||||||
|
await vi.advanceTimersByTimeAsync(5_000);
|
||||||
|
|
||||||
|
await rejection;
|
||||||
|
expect(child.kill).toHaveBeenCalledTimes(1);
|
||||||
|
} finally {
|
||||||
|
vi.useRealTimers();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -44,4 +44,10 @@ describe('buildDirectoryTree Windows paths', () => {
|
||||||
|
|
||||||
expect(root.children.get('C:')?.children.get('Users')).toBeDefined();
|
expect(root.children.get('C:')?.children.get('Users')).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('falls back to absolute injection paths when project root is unavailable', () => {
|
||||||
|
const root = buildDirectoryTree([injection('C:\\Users\\Alice\\Repo\\CLAUDE.md')]);
|
||||||
|
|
||||||
|
expect(root.children.get('C:')?.children.get('Users')).toBeDefined();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue