✨ Increase comprehensive testing capabilities
This commit is contained in:
288
tests/builder.test.js
Normal file
288
tests/builder.test.js
Normal file
@@ -0,0 +1,288 @@
|
||||
#!/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;
|
||||
Reference in New Issue
Block a user