fix(companion): resolve fixtures path correctly for both dev and built modes
This commit is contained in:
@@ -20,29 +20,30 @@ import type { IFixtureServerService } from '@/packages/infrastructure/adapters/a
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve the fixtures path relative to the monorepo root.
|
* Resolve the fixtures path relative to the monorepo root.
|
||||||
* In Electron, app.getAppPath() returns the path to the app's main directory
|
* Uses __dirname to determine the navigation depth based on whether we're
|
||||||
* (e.g., apps/companion/dist/main in development, or the asar in production).
|
* running from source (dev mode) or built output (dist mode).
|
||||||
* We navigate up to find the monorepo root and then join with the resources path.
|
|
||||||
*
|
*
|
||||||
* Path breakdown from apps/companion/dist/main:
|
* Path breakdown:
|
||||||
* - Level 1: apps/companion/dist (../)
|
* - Dev mode: apps/companion/main → 3 levels to root
|
||||||
* - Level 2: apps/companion (../../)
|
* - Built mode: apps/companion/dist/main → 4 levels to root
|
||||||
* - Level 3: apps (../../../)
|
|
||||||
* - Level 4: gridpilot (monorepo root) (../../../../)
|
|
||||||
*
|
*
|
||||||
* @param configuredPath - The path configured (may be relative or absolute)
|
* @param configuredPath - The path configured (may be relative or absolute)
|
||||||
* @param appPath - The app path from electron (app.getAppPath())
|
* @param dirname - The directory name (__dirname) of the calling module
|
||||||
* @returns Resolved absolute path
|
* @returns Resolved absolute path
|
||||||
*/
|
*/
|
||||||
export function resolveFixturesPath(configuredPath: string, appPath: string): string {
|
export function resolveFixturesPath(configuredPath: string, dirname: string): string {
|
||||||
if (path.isAbsolute(configuredPath)) {
|
if (path.isAbsolute(configuredPath)) {
|
||||||
return configuredPath;
|
return configuredPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
const projectRoot = path.resolve(appPath, '../../../../');
|
// Determine navigation depth based on whether we're in dist/ or source
|
||||||
const resolvedPath = path.join(projectRoot, configuredPath);
|
// Dev mode: apps/companion/main → 3 levels to root
|
||||||
|
// Built mode: apps/companion/dist/main → 4 levels to root
|
||||||
|
const isBuiltMode = dirname.includes(`${path.sep}dist${path.sep}`);
|
||||||
|
const levelsUp = isBuiltMode ? '../../../../' : '../../../';
|
||||||
|
const projectRoot = path.resolve(dirname, levelsUp);
|
||||||
|
|
||||||
return resolvedPath;
|
return path.join(projectRoot, configuredPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BrowserConnectionResult {
|
export interface BrowserConnectionResult {
|
||||||
@@ -196,10 +197,10 @@ export class DIContainer {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve the fixtures path relative to the monorepo root.
|
* Resolve the fixtures path relative to the monorepo root.
|
||||||
* Uses the exported resolveFixturesPath function with app.getAppPath().
|
* Uses the exported resolveFixturesPath function with __dirname.
|
||||||
*/
|
*/
|
||||||
private resolveFixturesPathInternal(configuredPath: string): string {
|
private resolveFixturesPathInternal(configuredPath: string): string {
|
||||||
return resolveFixturesPath(configuredPath, app.getAppPath());
|
return resolveFixturesPath(configuredPath, __dirname);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -226,7 +227,7 @@ export class DIContainer {
|
|||||||
|
|
||||||
this.logger.debug('Fixture server path resolution', {
|
this.logger.debug('Fixture server path resolution', {
|
||||||
configuredPath: config.fixtureServer.fixturesPath,
|
configuredPath: config.fixtureServer.fixturesPath,
|
||||||
appPath: app.getAppPath(),
|
dirname: __dirname,
|
||||||
resolvedPath: fixturesPath
|
resolvedPath: fixturesPath
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -4,63 +4,117 @@ import { resolveFixturesPath } from '@/apps/companion/main/di-container';
|
|||||||
|
|
||||||
describe('DIContainer path resolution', () => {
|
describe('DIContainer path resolution', () => {
|
||||||
describe('resolveFixturesPath', () => {
|
describe('resolveFixturesPath', () => {
|
||||||
it('should resolve fixtures path to monorepo root when app path is apps/companion/dist/main', () => {
|
describe('built mode (with /dist/ in path)', () => {
|
||||||
// Given: The app path as it would be in Electron runtime (apps/companion/dist/main)
|
it('should resolve fixtures path to monorepo root when dirname is apps/companion/dist/main', () => {
|
||||||
const mockAppPath = '/Users/test/Projects/gridpilot/apps/companion/dist/main';
|
// Given: The dirname as it would be in built Electron runtime (apps/companion/dist/main)
|
||||||
const relativePath = './resources/iracing-hosted-sessions';
|
const mockDirname = '/Users/test/Projects/gridpilot/apps/companion/dist/main';
|
||||||
|
const relativePath = './resources/iracing-hosted-sessions';
|
||||||
|
|
||||||
// When: Resolving the fixtures path
|
// When: Resolving the fixtures path
|
||||||
const resolved = resolveFixturesPath(relativePath, mockAppPath);
|
const resolved = resolveFixturesPath(relativePath, mockDirname);
|
||||||
|
|
||||||
// Then: Should resolve to monorepo root (4 levels up from apps/companion/dist/main)
|
// Then: Should resolve to monorepo root (4 levels up from apps/companion/dist/main)
|
||||||
// Level 0: apps/companion/dist/main (app.getAppPath())
|
// Level 0: apps/companion/dist/main (__dirname)
|
||||||
// Level 1: apps/companion/dist (../)
|
// Level 1: apps/companion/dist (../)
|
||||||
// Level 2: apps/companion (../../)
|
// Level 2: apps/companion (../../)
|
||||||
// Level 3: apps (../../../)
|
// Level 3: apps (../../../)
|
||||||
// Level 4: gridpilot (monorepo root) (../../../../) ← CORRECT
|
// Level 4: gridpilot (monorepo root) (../../../../) ← CORRECT
|
||||||
const expectedPath = '/Users/test/Projects/gridpilot/resources/iracing-hosted-sessions';
|
const expectedPath = '/Users/test/Projects/gridpilot/resources/iracing-hosted-sessions';
|
||||||
expect(resolved).toBe(expectedPath);
|
expect(resolved).toBe(expectedPath);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should navigate exactly 4 levels up in built mode', () => {
|
||||||
|
// Given: A path with /dist/ that demonstrates the 4-level navigation
|
||||||
|
const mockDirname = '/level4/level3/dist/level1';
|
||||||
|
const relativePath = './target';
|
||||||
|
|
||||||
|
// When: Resolving the fixtures path
|
||||||
|
const resolved = resolveFixturesPath(relativePath, mockDirname);
|
||||||
|
|
||||||
|
// Then: Should resolve to the path 4 levels up (root /)
|
||||||
|
expect(resolved).toBe('/target');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should work with different relative path formats in built mode', () => {
|
||||||
|
// Given: Various relative path formats
|
||||||
|
const mockDirname = '/Users/test/Projects/gridpilot/apps/companion/dist/main';
|
||||||
|
|
||||||
|
// When/Then: Different relative formats should all work
|
||||||
|
expect(resolveFixturesPath('resources/fixtures', mockDirname))
|
||||||
|
.toBe('/Users/test/Projects/gridpilot/resources/fixtures');
|
||||||
|
|
||||||
|
expect(resolveFixturesPath('./resources/fixtures', mockDirname))
|
||||||
|
.toBe('/Users/test/Projects/gridpilot/resources/fixtures');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return absolute paths unchanged', () => {
|
describe('dev mode (without /dist/ in path)', () => {
|
||||||
// Given: An absolute path
|
it('should resolve fixtures path to monorepo root when dirname is apps/companion/main', () => {
|
||||||
const absolutePath = '/some/absolute/path/to/fixtures';
|
// Given: The dirname as it would be in dev mode (apps/companion/main)
|
||||||
const mockAppPath = '/Users/test/Projects/gridpilot/apps/companion/dist/main';
|
const mockDirname = '/Users/test/Projects/gridpilot/apps/companion/main';
|
||||||
|
const relativePath = './resources/iracing-hosted-sessions';
|
||||||
|
|
||||||
// When: Resolving an absolute path
|
// When: Resolving the fixtures path
|
||||||
const resolved = resolveFixturesPath(absolutePath, mockAppPath);
|
const resolved = resolveFixturesPath(relativePath, mockDirname);
|
||||||
|
|
||||||
// Then: Should return the absolute path unchanged
|
// Then: Should resolve to monorepo root (3 levels up from apps/companion/main)
|
||||||
expect(resolved).toBe(absolutePath);
|
// Level 0: apps/companion/main (__dirname)
|
||||||
|
// Level 1: apps/companion (../)
|
||||||
|
// Level 2: apps (../../)
|
||||||
|
// Level 3: gridpilot (monorepo root) (../../../) ← CORRECT
|
||||||
|
const expectedPath = '/Users/test/Projects/gridpilot/resources/iracing-hosted-sessions';
|
||||||
|
expect(resolved).toBe(expectedPath);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should navigate exactly 3 levels up in dev mode', () => {
|
||||||
|
// Given: A path without /dist/ that demonstrates the 3-level navigation
|
||||||
|
const mockDirname = '/level3/level2/level1';
|
||||||
|
const relativePath = './target';
|
||||||
|
|
||||||
|
// When: Resolving the fixtures path
|
||||||
|
const resolved = resolveFixturesPath(relativePath, mockDirname);
|
||||||
|
|
||||||
|
// Then: Should resolve to the path 3 levels up (root /)
|
||||||
|
expect(resolved).toBe('/target');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should work with different relative path formats in dev mode', () => {
|
||||||
|
// Given: Various relative path formats
|
||||||
|
const mockDirname = '/Users/test/Projects/gridpilot/apps/companion/main';
|
||||||
|
|
||||||
|
// When/Then: Different relative formats should all work
|
||||||
|
expect(resolveFixturesPath('resources/fixtures', mockDirname))
|
||||||
|
.toBe('/Users/test/Projects/gridpilot/resources/fixtures');
|
||||||
|
|
||||||
|
expect(resolveFixturesPath('./resources/fixtures', mockDirname))
|
||||||
|
.toBe('/Users/test/Projects/gridpilot/resources/fixtures');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should navigate exactly 4 levels up from app path', () => {
|
describe('absolute paths', () => {
|
||||||
// Given: A path that demonstrates the 4-level navigation
|
it('should return absolute paths unchanged in built mode', () => {
|
||||||
const mockAppPath = '/level4/level3/level2/level1';
|
// Given: An absolute path
|
||||||
const relativePath = './target';
|
const absolutePath = '/some/absolute/path/to/fixtures';
|
||||||
|
const mockDirname = '/Users/test/Projects/gridpilot/apps/companion/dist/main';
|
||||||
|
|
||||||
// When: Resolving the fixtures path
|
// When: Resolving an absolute path
|
||||||
const resolved = resolveFixturesPath(relativePath, mockAppPath);
|
const resolved = resolveFixturesPath(absolutePath, mockDirname);
|
||||||
|
|
||||||
// Then: Should resolve to the path 4 levels up (root /)
|
// Then: Should return the absolute path unchanged
|
||||||
// Level 0: /level4/level3/level2/level1 (appPath)
|
expect(resolved).toBe(absolutePath);
|
||||||
// Level 1: /level4/level3/level2 (../)
|
});
|
||||||
// Level 2: /level4/level3 (../../)
|
|
||||||
// Level 3: /level4 (../../../)
|
|
||||||
// Level 4: / (../../../../) ← monorepo root equivalent
|
|
||||||
expect(resolved).toBe('/target');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should work with different relative path formats', () => {
|
it('should return absolute paths unchanged in dev mode', () => {
|
||||||
// Given: Various relative path formats
|
// Given: An absolute path
|
||||||
const mockAppPath = '/Users/test/Projects/gridpilot/apps/companion/dist/main';
|
const absolutePath = '/some/absolute/path/to/fixtures';
|
||||||
|
const mockDirname = '/Users/test/Projects/gridpilot/apps/companion/main';
|
||||||
|
|
||||||
// When/Then: Different relative formats should all work
|
// When: Resolving an absolute path
|
||||||
expect(resolveFixturesPath('resources/fixtures', mockAppPath))
|
const resolved = resolveFixturesPath(absolutePath, mockDirname);
|
||||||
.toBe('/Users/test/Projects/gridpilot/resources/fixtures');
|
|
||||||
|
// Then: Should return the absolute path unchanged
|
||||||
expect(resolveFixturesPath('./resources/fixtures', mockAppPath))
|
expect(resolved).toBe(absolutePath);
|
||||||
.toBe('/Users/test/Projects/gridpilot/resources/fixtures');
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
Reference in New Issue
Block a user