wip
This commit is contained in:
113
tests/smoke/electron-build.smoke.test.ts
Normal file
113
tests/smoke/electron-build.smoke.test.ts
Normal file
@@ -0,0 +1,113 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
import { execSync } from 'child_process';
|
||||
|
||||
/**
|
||||
* Electron Build Smoke Test
|
||||
*
|
||||
* Purpose: Detect browser context errors during Electron build
|
||||
*
|
||||
* This test catches bundling issues where Node.js modules are imported
|
||||
* in the renderer process, causing runtime errors.
|
||||
*
|
||||
* RED Phase: This test MUST FAIL due to externalized modules
|
||||
*/
|
||||
|
||||
test.describe('Electron Build Smoke Tests', () => {
|
||||
test('should build Electron app without browser context errors', () => {
|
||||
// When: Building the Electron companion app
|
||||
let buildOutput: string;
|
||||
|
||||
try {
|
||||
buildOutput = execSync('npm run companion:build', {
|
||||
cwd: process.cwd(),
|
||||
encoding: 'utf-8',
|
||||
stdio: 'pipe',
|
||||
});
|
||||
} catch (error: any) {
|
||||
buildOutput = error.stdout + error.stderr;
|
||||
}
|
||||
|
||||
// Then: Build should not contain externalized module warnings
|
||||
const foundErrors: string[] = [];
|
||||
|
||||
// Split output into lines and check each line
|
||||
const lines = buildOutput.split('\n');
|
||||
lines.forEach(line => {
|
||||
if (line.includes('has been externalized for browser compatibility')) {
|
||||
foundErrors.push(line.trim());
|
||||
}
|
||||
if (line.includes('Cannot access') && line.includes('in client code')) {
|
||||
foundErrors.push(line.trim());
|
||||
}
|
||||
});
|
||||
|
||||
// This WILL FAIL in RED phase due to electron/fs/path being externalized
|
||||
expect(
|
||||
foundErrors.length,
|
||||
`Browser context errors detected during build:\n\n${foundErrors.map((e, i) => `${i + 1}. ${e}`).join('\n')}\n\n` +
|
||||
`These indicate Node.js modules (electron, fs, path) are being imported in renderer code.\n` +
|
||||
`This will cause runtime errors when the app launches.`
|
||||
).toBe(0);
|
||||
});
|
||||
|
||||
test('should not import Node.js modules in renderer source code', () => {
|
||||
// Given: Renderer source code
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const rendererPath = path.join(
|
||||
process.cwd(),
|
||||
'apps/companion/renderer'
|
||||
);
|
||||
|
||||
// When: Checking renderer source for forbidden imports
|
||||
const forbiddenPatterns = [
|
||||
{ pattern: /from\s+['"]electron['"]/, name: 'electron' },
|
||||
{ pattern: /require\(['"]electron['"]\)/, name: 'electron' },
|
||||
{ pattern: /from\s+['"]fs['"]/, name: 'fs' },
|
||||
{ pattern: /require\(['"]fs['"]\)/, name: 'fs' },
|
||||
{ pattern: /from\s+['"]path['"]/, name: 'path' },
|
||||
{ pattern: /require\(['"]path['"]\)/, name: 'path' },
|
||||
];
|
||||
|
||||
const violations: Array<{ file: string; line: number; import: string; module: string }> = [];
|
||||
|
||||
function scanDirectory(dir: string) {
|
||||
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
||||
|
||||
entries.forEach((entry: any) => {
|
||||
const fullPath = path.join(dir, entry.name);
|
||||
|
||||
if (entry.isDirectory()) {
|
||||
scanDirectory(fullPath);
|
||||
} else if (entry.name.endsWith('.tsx') || entry.name.endsWith('.ts')) {
|
||||
const content = fs.readFileSync(fullPath, 'utf-8');
|
||||
const lines = content.split('\n');
|
||||
|
||||
lines.forEach((line, index) => {
|
||||
forbiddenPatterns.forEach(({ pattern, name }) => {
|
||||
if (pattern.test(line)) {
|
||||
violations.push({
|
||||
file: path.relative(process.cwd(), fullPath),
|
||||
line: index + 1,
|
||||
import: line.trim(),
|
||||
module: name,
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
scanDirectory(rendererPath);
|
||||
|
||||
// Then: No Node.js modules should be imported in renderer
|
||||
expect(
|
||||
violations.length,
|
||||
`Found Node.js module imports in renderer source code:\n\n${
|
||||
violations.map(v => `${v.file}:${v.line}\n Module: ${v.module}\n Code: ${v.import}`).join('\n\n')
|
||||
}\n\nRenderer code must use the preload script or IPC to access Node.js APIs.`
|
||||
).toBe(0);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user