feat(ci): add husky pre-commit hook and fix puppeteer-core chrome detection
This commit is contained in:
1
.husky/pre-commit
Normal file
1
.husky/pre-commit
Normal file
@@ -0,0 +1 @@
|
|||||||
|
npm test
|
||||||
@@ -23,11 +23,13 @@
|
|||||||
"companion:dev": "npm run dev --workspace=@gridpilot/companion",
|
"companion:dev": "npm run dev --workspace=@gridpilot/companion",
|
||||||
"companion:build": "npm run build --workspace=@gridpilot/companion",
|
"companion:build": "npm run build --workspace=@gridpilot/companion",
|
||||||
"companion:start": "npm run start --workspace=@gridpilot/companion",
|
"companion:start": "npm run start --workspace=@gridpilot/companion",
|
||||||
"chrome:debug": "open -a 'Google Chrome' --args --remote-debugging-port=9222 --user-data-dir=/tmp/chrome-debug"
|
"chrome:debug": "open -a 'Google Chrome' --args --remote-debugging-port=9222 --user-data-dir=/tmp/chrome-debug",
|
||||||
|
"prepare": "husky"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@cucumber/cucumber": "^11.0.1",
|
"@cucumber/cucumber": "^11.0.1",
|
||||||
"@vitest/ui": "^2.1.8",
|
"@vitest/ui": "^2.1.8",
|
||||||
|
"husky": "^9.1.7",
|
||||||
"puppeteer": "^24.31.0",
|
"puppeteer": "^24.31.0",
|
||||||
"typescript": "^5.7.2",
|
"typescript": "^5.7.2",
|
||||||
"vitest": "^2.1.8"
|
"vitest": "^2.1.8"
|
||||||
|
|||||||
@@ -124,11 +124,19 @@ export class BrowserDevToolsAdapter implements IBrowserAutomation {
|
|||||||
'--no-sandbox',
|
'--no-sandbox',
|
||||||
];
|
];
|
||||||
|
|
||||||
this.browser = await puppeteer.launch({
|
const launchOptions: Parameters<typeof puppeteer.launch>[0] = {
|
||||||
headless: this.config.headless,
|
headless: this.config.headless,
|
||||||
executablePath: this.config.executablePath || undefined,
|
|
||||||
args: launchArgs,
|
args: launchArgs,
|
||||||
});
|
};
|
||||||
|
|
||||||
|
// Use explicit executablePath if provided, otherwise use channel to auto-detect Chrome
|
||||||
|
if (this.config.executablePath) {
|
||||||
|
launchOptions.executablePath = this.config.executablePath;
|
||||||
|
} else {
|
||||||
|
launchOptions.channel = 'chrome';
|
||||||
|
}
|
||||||
|
|
||||||
|
this.browser = await puppeteer.launch(launchOptions);
|
||||||
|
|
||||||
const pages = await this.browser.pages();
|
const pages = await this.browser.pages();
|
||||||
this.page = pages[0] || await this.browser.newPage();
|
this.page = pages[0] || await this.browser.newPage();
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
||||||
import { BrowserDevToolsAdapter, DevToolsConfig } from '../../../src/infrastructure/adapters/automation/BrowserDevToolsAdapter';
|
import { BrowserDevToolsAdapter, DevToolsConfig } from '../../../packages/infrastructure/adapters/automation/BrowserDevToolsAdapter';
|
||||||
import { StepId } from '../../../src/packages/domain/value-objects/StepId';
|
import { StepId } from '../../../packages/domain/value-objects/StepId';
|
||||||
import {
|
import {
|
||||||
IRacingSelectorMap,
|
IRacingSelectorMap,
|
||||||
getStepSelectors,
|
getStepSelectors,
|
||||||
getStepName,
|
getStepName,
|
||||||
isModalStep,
|
isModalStep,
|
||||||
} from '../../../src/infrastructure/adapters/automation/selectors/IRacingSelectorMap';
|
} from '../../../packages/infrastructure/adapters/automation/selectors/IRacingSelectorMap';
|
||||||
|
|
||||||
// Mock puppeteer-core
|
// Mock puppeteer-core
|
||||||
vi.mock('puppeteer-core', () => {
|
vi.mock('puppeteer-core', () => {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { describe, it, expect, beforeEach } from 'vitest';
|
import { describe, it, expect, beforeEach } from 'vitest';
|
||||||
import { InMemorySessionRepository } from '../../../src/infrastructure/repositories/InMemorySessionRepository';
|
import { InMemorySessionRepository } from '../../../packages/infrastructure/repositories/InMemorySessionRepository';
|
||||||
import { AutomationSession } from '../../../src/packages/domain/entities/AutomationSession';
|
import { AutomationSession } from '../../../packages/domain/entities/AutomationSession';
|
||||||
import { StepId } from '../../../src/packages/domain/value-objects/StepId';
|
import { StepId } from '../../../packages/domain/value-objects/StepId';
|
||||||
|
|
||||||
describe('InMemorySessionRepository Integration Tests', () => {
|
describe('InMemorySessionRepository Integration Tests', () => {
|
||||||
let repository: InMemorySessionRepository;
|
let repository: InMemorySessionRepository;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
||||||
import { MockBrowserAutomationAdapter } from '../../../src/infrastructure/adapters/automation/MockBrowserAutomationAdapter';
|
import { MockBrowserAutomationAdapter } from '../../../packages/infrastructure/adapters/automation/MockBrowserAutomationAdapter';
|
||||||
import { StepId } from '../../../src/packages/domain/value-objects/StepId';
|
import { StepId } from '../../../packages/domain/value-objects/StepId';
|
||||||
|
|
||||||
describe('MockBrowserAutomationAdapter Integration Tests', () => {
|
describe('MockBrowserAutomationAdapter Integration Tests', () => {
|
||||||
let adapter: MockBrowserAutomationAdapter;
|
let adapter: MockBrowserAutomationAdapter;
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { describe, it, expect, vi, beforeEach, Mock } from 'vitest';
|
import { describe, it, expect, vi, beforeEach, Mock } from 'vitest';
|
||||||
import { StartAutomationSessionUseCase } from '../../../../src/packages/application/use-cases/StartAutomationSessionUseCase';
|
import { StartAutomationSessionUseCase } from '../../../../packages/application/use-cases/StartAutomationSessionUseCase';
|
||||||
import { IAutomationEngine } from '../../../../src/packages/application/ports/IAutomationEngine';
|
import { IAutomationEngine } from '../../../../packages/application/ports/IAutomationEngine';
|
||||||
import { IBrowserAutomation } from '../../../../src/packages/application/ports/IBrowserAutomation';
|
import { IBrowserAutomation } from '../../../../packages/application/ports/IBrowserAutomation';
|
||||||
import { ISessionRepository } from '../../../../src/packages/application/ports/ISessionRepository';
|
import { ISessionRepository } from '../../../../packages/application/ports/ISessionRepository';
|
||||||
import { AutomationSession } from '../../../../src/packages/domain/entities/AutomationSession';
|
import { AutomationSession } from '../../../../packages/domain/entities/AutomationSession';
|
||||||
|
|
||||||
describe('StartAutomationSessionUseCase', () => {
|
describe('StartAutomationSessionUseCase', () => {
|
||||||
let mockAutomationEngine: {
|
let mockAutomationEngine: {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { describe, it, expect } from 'vitest';
|
import { describe, it, expect } from 'vitest';
|
||||||
import { AutomationSession } from '../../../../src/packages/domain/entities/AutomationSession';
|
import { AutomationSession } from '../../../../packages/domain/entities/AutomationSession';
|
||||||
import { StepId } from '../../../../src/packages/domain/value-objects/StepId';
|
import { StepId } from '../../../../packages/domain/value-objects/StepId';
|
||||||
import { SessionState } from '../../../../src/packages/domain/value-objects/SessionState';
|
import { SessionState } from '../../../../packages/domain/value-objects/SessionState';
|
||||||
|
|
||||||
describe('AutomationSession Entity', () => {
|
describe('AutomationSession Entity', () => {
|
||||||
describe('create', () => {
|
describe('create', () => {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { describe, it, expect } from 'vitest';
|
import { describe, it, expect } from 'vitest';
|
||||||
import { StepTransitionValidator } from '../../../../src/packages/domain/services/StepTransitionValidator';
|
import { StepTransitionValidator } from '../../../../packages/domain/services/StepTransitionValidator';
|
||||||
import { StepId } from '../../../../src/packages/domain/value-objects/StepId';
|
import { StepId } from '../../../../packages/domain/value-objects/StepId';
|
||||||
import { SessionState } from '../../../../src/packages/domain/value-objects/SessionState';
|
import { SessionState } from '../../../../packages/domain/value-objects/SessionState';
|
||||||
|
|
||||||
describe('StepTransitionValidator Service', () => {
|
describe('StepTransitionValidator Service', () => {
|
||||||
describe('canTransition', () => {
|
describe('canTransition', () => {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { describe, it, expect } from 'vitest';
|
import { describe, it, expect } from 'vitest';
|
||||||
import { SessionState } from '../../../../src/packages/domain/value-objects/SessionState';
|
import { SessionState } from '../../../../packages/domain/value-objects/SessionState';
|
||||||
|
|
||||||
describe('SessionState Value Object', () => {
|
describe('SessionState Value Object', () => {
|
||||||
describe('create', () => {
|
describe('create', () => {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { describe, it, expect } from 'vitest';
|
import { describe, it, expect } from 'vitest';
|
||||||
import { StepId } from '../../../../src/packages/domain/value-objects/StepId';
|
import { StepId } from '../../../../packages/domain/value-objects/StepId';
|
||||||
|
|
||||||
describe('StepId Value Object', () => {
|
describe('StepId Value Object', () => {
|
||||||
describe('create', () => {
|
describe('create', () => {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
||||||
import { loadAutomationConfig, AutomationMode } from '../../../src/infrastructure/config/AutomationConfig';
|
import { loadAutomationConfig, AutomationMode } from '../../../packages/infrastructure/config/AutomationConfig';
|
||||||
|
|
||||||
describe('AutomationConfig', () => {
|
describe('AutomationConfig', () => {
|
||||||
const originalEnv = process.env;
|
const originalEnv = process.env;
|
||||||
@@ -16,12 +16,12 @@ describe('AutomationConfig', () => {
|
|||||||
|
|
||||||
describe('loadAutomationConfig', () => {
|
describe('loadAutomationConfig', () => {
|
||||||
describe('default configuration', () => {
|
describe('default configuration', () => {
|
||||||
it('should return mock mode when AUTOMATION_MODE is not set', () => {
|
it('should return dev mode when AUTOMATION_MODE is not set', () => {
|
||||||
delete process.env.AUTOMATION_MODE;
|
delete process.env.AUTOMATION_MODE;
|
||||||
|
|
||||||
const config = loadAutomationConfig();
|
const config = loadAutomationConfig();
|
||||||
|
|
||||||
expect(config.mode).toBe('mock');
|
expect(config.mode).toBe('dev');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return default devTools configuration', () => {
|
it('should return default devTools configuration', () => {
|
||||||
@@ -161,12 +161,12 @@ describe('AutomationConfig', () => {
|
|||||||
expect(config.nutJs?.confidence).toBe(0.9);
|
expect(config.nutJs?.confidence).toBe(0.9);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should fallback to mock mode for invalid AUTOMATION_MODE', () => {
|
it('should fallback to dev mode for invalid AUTOMATION_MODE', () => {
|
||||||
process.env.AUTOMATION_MODE = 'invalid-mode';
|
process.env.AUTOMATION_MODE = 'invalid-mode';
|
||||||
|
|
||||||
const config = loadAutomationConfig();
|
const config = loadAutomationConfig();
|
||||||
|
|
||||||
expect(config.mode).toBe('mock');
|
expect(config.mode).toBe('dev');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user