288 lines
8.5 KiB
JavaScript
288 lines
8.5 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
/**
|
|
* Builder-specific Tests for Pake CLI
|
|
*
|
|
* These tests verify platform-specific builder logic and file naming patterns
|
|
* Based on analysis of bin/builders/ implementation
|
|
*/
|
|
|
|
import { execSync } from 'child_process';
|
|
import path from 'path';
|
|
import config, { TEST_URLS, TEST_NAMES } from './test.config.js';
|
|
import ora from 'ora';
|
|
|
|
class BuilderTestRunner {
|
|
constructor() {
|
|
this.tests = [];
|
|
this.results = [];
|
|
}
|
|
|
|
addTest(name, testFn, description = '') {
|
|
this.tests.push({ name, testFn, description });
|
|
}
|
|
|
|
async runAll() {
|
|
console.log('🏗️ Builder-specific Tests');
|
|
console.log('==========================\n');
|
|
|
|
for (const [index, test] of this.tests.entries()) {
|
|
const spinner = ora(`Running ${test.name}...`).start();
|
|
|
|
try {
|
|
const result = await test.testFn();
|
|
if (result) {
|
|
spinner.succeed(`${index + 1}. ${test.name}: PASS`);
|
|
this.results.push({ name: test.name, passed: true });
|
|
} else {
|
|
spinner.fail(`${index + 1}. ${test.name}: FAIL`);
|
|
this.results.push({ name: test.name, passed: false });
|
|
}
|
|
} catch (error) {
|
|
spinner.fail(`${index + 1}. ${test.name}: ERROR - ${error.message.slice(0, 50)}...`);
|
|
this.results.push({ name: test.name, passed: false, error: error.message });
|
|
}
|
|
}
|
|
|
|
this.displayResults();
|
|
}
|
|
|
|
displayResults() {
|
|
const passed = this.results.filter(r => r.passed).length;
|
|
const total = this.results.length;
|
|
|
|
console.log(`\n📊 Builder Test Results: ${passed}/${total} passed\n`);
|
|
|
|
if (passed === total) {
|
|
console.log('🎉 All builder tests passed!');
|
|
} else {
|
|
console.log('❌ Some builder tests failed');
|
|
this.results.filter(r => !r.passed).forEach(result => {
|
|
console.log(` - ${result.name}${result.error ? `: ${result.error}` : ''}`);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
const runner = new BuilderTestRunner();
|
|
|
|
// Platform-specific file naming tests
|
|
runner.addTest(
|
|
'Mac Builder File Naming Pattern',
|
|
() => {
|
|
try {
|
|
// Test macOS file naming: name_version_arch.dmg
|
|
const mockName = 'TestApp';
|
|
const mockVersion = '1.0.0';
|
|
const arch = process.arch === 'arm64' ? 'aarch64' : process.arch;
|
|
|
|
// Expected pattern: TestApp_1.0.0_aarch64.dmg (for M1) or TestApp_1.0.0_x64.dmg (for Intel)
|
|
const expectedPattern = `${mockName}_${mockVersion}_${arch}`;
|
|
const universalPattern = `${mockName}_${mockVersion}_universal`;
|
|
|
|
// Test that naming pattern is consistent
|
|
return expectedPattern.includes(mockName) &&
|
|
expectedPattern.includes(mockVersion) &&
|
|
(expectedPattern.includes(arch) || universalPattern.includes('universal'));
|
|
} catch (error) {
|
|
return false;
|
|
}
|
|
},
|
|
'Should generate correct macOS file naming pattern'
|
|
);
|
|
|
|
runner.addTest(
|
|
'Windows Builder File Naming Pattern',
|
|
() => {
|
|
try {
|
|
// Test Windows file naming: name_version_arch_language.msi
|
|
const mockName = 'TestApp';
|
|
const mockVersion = '1.0.0';
|
|
const arch = process.arch;
|
|
const language = 'en-US'; // default language
|
|
|
|
// Expected pattern: TestApp_1.0.0_x64_en-US.msi
|
|
const expectedPattern = `${mockName}_${mockVersion}_${arch}_${language}`;
|
|
|
|
return expectedPattern.includes(mockName) &&
|
|
expectedPattern.includes(mockVersion) &&
|
|
expectedPattern.includes(arch) &&
|
|
expectedPattern.includes(language);
|
|
} catch (error) {
|
|
return false;
|
|
}
|
|
},
|
|
'Should generate correct Windows file naming pattern'
|
|
);
|
|
|
|
runner.addTest(
|
|
'Linux Builder File Naming Pattern',
|
|
() => {
|
|
try {
|
|
// Test Linux file naming variations
|
|
const mockName = 'testapp';
|
|
const mockVersion = '1.0.0';
|
|
let arch = process.arch === 'x64' ? 'amd64' : process.arch;
|
|
|
|
// Test different target formats
|
|
const debPattern = `${mockName}_${mockVersion}_${arch}`; // .deb
|
|
const rpmPattern = `${mockName}-${mockVersion}-1.${arch === 'arm64' ? 'aarch64' : arch}`; // .rpm
|
|
const appImagePattern = `${mockName}_${mockVersion}_${arch === 'arm64' ? 'aarch64' : arch}`; // .AppImage
|
|
|
|
return debPattern.includes(mockName) &&
|
|
rpmPattern.includes(mockName) &&
|
|
appImagePattern.includes(mockName);
|
|
} catch (error) {
|
|
return false;
|
|
}
|
|
},
|
|
'Should generate correct Linux file naming patterns for different targets'
|
|
);
|
|
|
|
runner.addTest(
|
|
'Architecture Detection Logic',
|
|
() => {
|
|
try {
|
|
// Test architecture mapping logic
|
|
const currentArch = process.arch;
|
|
|
|
// Mac: arm64 -> aarch64, others keep same
|
|
const macArch = currentArch === 'arm64' ? 'aarch64' : currentArch;
|
|
|
|
// Linux: x64 -> amd64 for deb, arm64 -> aarch64 for rpm/appimage
|
|
const linuxArch = currentArch === 'x64' ? 'amd64' : currentArch;
|
|
|
|
// Windows: keeps process.arch as-is
|
|
const winArch = currentArch;
|
|
|
|
return typeof macArch === 'string' &&
|
|
typeof linuxArch === 'string' &&
|
|
typeof winArch === 'string';
|
|
} catch (error) {
|
|
return false;
|
|
}
|
|
},
|
|
'Should correctly detect and map system architecture'
|
|
);
|
|
|
|
runner.addTest(
|
|
'Multi-arch Build Detection',
|
|
() => {
|
|
try {
|
|
// Test universal binary logic for macOS
|
|
const platform = process.platform;
|
|
|
|
if (platform === 'darwin') {
|
|
// macOS should support multi-arch with --multi-arch flag
|
|
const supportsMultiArch = true;
|
|
const universalSuffix = 'universal';
|
|
|
|
return supportsMultiArch && universalSuffix === 'universal';
|
|
} else {
|
|
// Other platforms don't support multi-arch
|
|
return true;
|
|
}
|
|
} catch (error) {
|
|
return false;
|
|
}
|
|
},
|
|
'Should handle multi-architecture builds correctly'
|
|
);
|
|
|
|
runner.addTest(
|
|
'Target Format Validation',
|
|
() => {
|
|
try {
|
|
// Test valid target formats per platform
|
|
const platform = process.platform;
|
|
const validTargets = {
|
|
'darwin': ['dmg'],
|
|
'win32': ['msi'],
|
|
'linux': ['deb', 'appimage', 'rpm']
|
|
};
|
|
|
|
const platformTargets = validTargets[platform];
|
|
return Array.isArray(platformTargets) && platformTargets.length > 0;
|
|
} catch (error) {
|
|
return false;
|
|
}
|
|
},
|
|
'Should validate target formats per platform'
|
|
);
|
|
|
|
runner.addTest(
|
|
'Build Path Generation',
|
|
() => {
|
|
try {
|
|
// Test build path logic: debug vs release
|
|
const debugPath = 'src-tauri/target/debug/bundle/';
|
|
const releasePath = 'src-tauri/target/release/bundle/';
|
|
const universalPath = 'src-tauri/target/universal-apple-darwin/release/bundle';
|
|
|
|
// Paths should be consistent
|
|
return debugPath.includes('debug') &&
|
|
releasePath.includes('release') &&
|
|
universalPath.includes('universal');
|
|
} catch (error) {
|
|
return false;
|
|
}
|
|
},
|
|
'Should generate correct build paths for different modes'
|
|
);
|
|
|
|
runner.addTest(
|
|
'File Extension Mapping',
|
|
() => {
|
|
try {
|
|
// Test file extension mapping logic
|
|
const platform = process.platform;
|
|
const extensionMap = {
|
|
'darwin': 'dmg',
|
|
'win32': 'msi',
|
|
'linux': 'deb' // default, can be appimage or rpm
|
|
};
|
|
|
|
const expectedExt = extensionMap[platform];
|
|
|
|
// Special case for Linux AppImage (capital A)
|
|
const appImageExt = 'AppImage';
|
|
|
|
return typeof expectedExt === 'string' &&
|
|
(expectedExt.length > 0 || appImageExt === 'AppImage');
|
|
} catch (error) {
|
|
return false;
|
|
}
|
|
},
|
|
'Should map file extensions correctly per platform'
|
|
);
|
|
|
|
runner.addTest(
|
|
'Name Sanitization Logic',
|
|
() => {
|
|
try {
|
|
// Test name sanitization for file systems
|
|
const testNames = [
|
|
'Simple App', // Should handle spaces
|
|
'App-With_Symbols', // Should handle hyphens and underscores
|
|
'CamelCaseApp', // Should handle case variations
|
|
'App123', // Should handle numbers
|
|
];
|
|
|
|
// Test that names can be processed (basic validation)
|
|
return testNames.every(name => {
|
|
const processed = name.toLowerCase().replace(/\s+/g, '');
|
|
return processed.length > 0;
|
|
});
|
|
} catch (error) {
|
|
return false;
|
|
}
|
|
},
|
|
'Should sanitize app names for filesystem compatibility'
|
|
);
|
|
|
|
// Run builder tests if this file is executed directly
|
|
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
runner.runAll().catch(console.error);
|
|
}
|
|
|
|
export default runner; |