3
.gitignore
vendido
3
.gitignore
vendido
@@ -60,8 +60,7 @@ tmp/
|
|||||||
test_*.i2m
|
test_*.i2m
|
||||||
example_*.i2m
|
example_*.i2m
|
||||||
*_extracted*
|
*_extracted*
|
||||||
*.test.js
|
test/test_*
|
||||||
*.spec.js
|
|
||||||
|
|
||||||
# Example generated files
|
# Example generated files
|
||||||
examples/risitas_with_chiquito.i2m
|
examples/risitas_with_chiquito.i2m
|
||||||
|
|||||||
@@ -5,11 +5,11 @@
|
|||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"types": "index.d.ts",
|
"types": "index.d.ts",
|
||||||
"bin": {
|
"bin": {
|
||||||
"img2mp3": "./bin/cli.js"
|
"img2mp3": "bin/cli.js"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "node src/index.js",
|
"start": "node src/index.js",
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
"test": "node test/basic.test.js",
|
||||||
"prepublishOnly": "npm run test",
|
"prepublishOnly": "npm run test",
|
||||||
"example": "node examples/basic_usage.js"
|
"example": "node examples/basic_usage.js"
|
||||||
},
|
},
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/ale/img2mp3.git"
|
"url": "git+https://github.com/ale/img2mp3.git"
|
||||||
},
|
},
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/ale/img2mp3/issues"
|
"url": "https://github.com/ale/img2mp3/issues"
|
||||||
|
|||||||
181
test/basic.test.js
Archivo normal
181
test/basic.test.js
Archivo normal
@@ -0,0 +1,181 @@
|
|||||||
|
const assert = require('assert');
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
const { IMG2MP3, MP3ImageEncoder, I2MPlayer } = require('../src/index');
|
||||||
|
|
||||||
|
// Test files paths
|
||||||
|
const testImagePath = path.join(__dirname, '..', 'examples', 'risitas.jpg');
|
||||||
|
const testMp3Path = path.join(__dirname, '..', 'examples', 'chiquito-cobarde.mp3');
|
||||||
|
const testOutputPath = path.join(__dirname, 'test_output.i2m');
|
||||||
|
const testExtractedImagePath = path.join(__dirname, 'test_extracted_image.png');
|
||||||
|
const testExtractedMp3Path = path.join(__dirname, 'test_extracted.mp3');
|
||||||
|
|
||||||
|
console.log('🧪 Running IMG2MP3 Test Suite...\n');
|
||||||
|
|
||||||
|
async function runAllTests() {
|
||||||
|
const img2mp3 = new IMG2MP3();
|
||||||
|
let testsPassed = 0;
|
||||||
|
let totalTests = 0;
|
||||||
|
|
||||||
|
function test(name, testFn) {
|
||||||
|
totalTests++;
|
||||||
|
try {
|
||||||
|
return Promise.resolve(testFn()).then(() => {
|
||||||
|
console.log(`✓ ${name}`);
|
||||||
|
testsPassed++;
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`✗ ${name}: ${error.message}`);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Test 1: Class Instantiation
|
||||||
|
await test('IMG2MP3 class instantiation', () => {
|
||||||
|
assert(img2mp3 instanceof IMG2MP3, 'Should create IMG2MP3 instance');
|
||||||
|
});
|
||||||
|
|
||||||
|
await test('MP3ImageEncoder class instantiation', () => {
|
||||||
|
const encoder = new MP3ImageEncoder();
|
||||||
|
assert(encoder instanceof MP3ImageEncoder, 'Should create MP3ImageEncoder instance');
|
||||||
|
});
|
||||||
|
|
||||||
|
await test('I2MPlayer class instantiation', () => {
|
||||||
|
const player = new I2MPlayer();
|
||||||
|
assert(player instanceof I2MPlayer, 'Should create I2MPlayer instance');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Test 2: File Validation
|
||||||
|
await test('Test files existence', () => {
|
||||||
|
assert(fs.existsSync(testImagePath), 'Test image file should exist');
|
||||||
|
assert(fs.existsSync(testMp3Path), 'Test MP3 file should exist');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Test 3: Encoding
|
||||||
|
await test('MP3 encoding into image', async () => {
|
||||||
|
const result = await img2mp3.encode(testImagePath, testMp3Path, testOutputPath);
|
||||||
|
|
||||||
|
assert(result.success === true, 'Encoding should be successful');
|
||||||
|
assert(typeof result.originalImageSize === 'number', 'Should return original image size');
|
||||||
|
assert(typeof result.mp3Size === 'number', 'Should return MP3 size');
|
||||||
|
assert(typeof result.outputSize === 'number', 'Should return output size');
|
||||||
|
assert(typeof result.imageSize === 'string', 'Should return image dimensions');
|
||||||
|
assert(fs.existsSync(testOutputPath), 'Output .i2m file should be created');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Test 4: File Information
|
||||||
|
await test('Get .i2m file information', async () => {
|
||||||
|
const info = await img2mp3.getInfo(testOutputPath);
|
||||||
|
|
||||||
|
assert(info.isValid === true, 'File should be valid');
|
||||||
|
assert(typeof info.mp3Size === 'number', 'Should return MP3 size');
|
||||||
|
assert(typeof info.originalImageSize === 'number', 'Should return original image size');
|
||||||
|
assert(typeof info.containerSize === 'number', 'Should return container size');
|
||||||
|
assert(typeof info.format === 'string', 'Should return format');
|
||||||
|
assert(typeof info.dimensions === 'string', 'Should return dimensions');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Test 5: Invalid file handling
|
||||||
|
await test('Invalid file detection', async () => {
|
||||||
|
const info = await img2mp3.getInfo(testImagePath);
|
||||||
|
assert(info.isValid === false, 'Non-.i2m file should be invalid');
|
||||||
|
assert(typeof info.error === 'string', 'Should return error message');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Test 6: Decoding
|
||||||
|
await test('.i2m file decoding', async () => {
|
||||||
|
const result = await img2mp3.decode(testOutputPath, testExtractedImagePath, testExtractedMp3Path);
|
||||||
|
|
||||||
|
assert(result.success === true, 'Decoding should be successful');
|
||||||
|
assert(typeof result.extractedImageSize === 'number', 'Should return extracted image size');
|
||||||
|
assert(typeof result.extractedMp3Size === 'number', 'Should return extracted MP3 size');
|
||||||
|
assert(fs.existsSync(testExtractedImagePath), 'Extracted image should exist');
|
||||||
|
assert(fs.existsSync(testExtractedMp3Path), 'Extracted MP3 should exist');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Test 7: File integrity
|
||||||
|
await test('File size preservation', () => {
|
||||||
|
const originalImageSize = fs.statSync(testImagePath).size;
|
||||||
|
const originalMp3Size = fs.statSync(testMp3Path).size;
|
||||||
|
const extractedImageSize = fs.statSync(testExtractedImagePath).size;
|
||||||
|
const extractedMp3Size = fs.statSync(testExtractedMp3Path).size;
|
||||||
|
|
||||||
|
assert(originalImageSize === extractedImageSize, 'Image size should be preserved');
|
||||||
|
assert(originalMp3Size === extractedMp3Size, 'MP3 size should be preserved');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Test 8: Player status
|
||||||
|
await test('Player status check', () => {
|
||||||
|
const status = img2mp3.getPlaybackStatus();
|
||||||
|
assert(typeof status.isPlaying === 'boolean', 'Should return playing status');
|
||||||
|
assert(typeof status.hasActiveProcess === 'boolean', 'Should return process status');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Test 9: Stop function
|
||||||
|
await test('Stop playback function', () => {
|
||||||
|
// This should not throw an error even if nothing is playing
|
||||||
|
assert.doesNotThrow(() => {
|
||||||
|
img2mp3.stop();
|
||||||
|
}, 'Stop function should not throw error');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Test 10: Convenience functions
|
||||||
|
await test('Convenience functions export', () => {
|
||||||
|
const { encode, decode, getInfo, play } = require('../src/index');
|
||||||
|
assert(typeof encode === 'function', 'Should export encode function');
|
||||||
|
assert(typeof decode === 'function', 'Should export decode function');
|
||||||
|
assert(typeof getInfo === 'function', 'Should export getInfo function');
|
||||||
|
assert(typeof play === 'function', 'Should export play function');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Test 11: Error handling for non-existent files
|
||||||
|
await test('Error handling for missing files', async () => {
|
||||||
|
try {
|
||||||
|
await img2mp3.encode('nonexistent.jpg', testMp3Path, 'test.i2m');
|
||||||
|
assert.fail('Should have thrown an error for missing image file');
|
||||||
|
} catch (error) {
|
||||||
|
assert(error.message.includes('ENOENT') || error.message.includes('not found'),
|
||||||
|
'Should throw file not found error');
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await img2mp3.encode(testImagePath, 'nonexistent.mp3', 'test.i2m');
|
||||||
|
assert.fail('Should have thrown an error for missing MP3 file');
|
||||||
|
} catch (error) {
|
||||||
|
assert(error.message.includes('ENOENT') || error.message.includes('not found'),
|
||||||
|
'Should throw file not found error');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`\n🎉 All tests passed! (${testsPassed}/${totalTests})`);
|
||||||
|
console.log('✅ IMG2MP3 is ready for publication');
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`\n❌ Test failed: ${error.message}`);
|
||||||
|
console.log(`📊 Tests passed: ${testsPassed}/${totalTests}`);
|
||||||
|
process.exit(1);
|
||||||
|
} finally {
|
||||||
|
// Cleanup test files
|
||||||
|
const filesToClean = [
|
||||||
|
testOutputPath,
|
||||||
|
testExtractedImagePath,
|
||||||
|
testExtractedMp3Path
|
||||||
|
];
|
||||||
|
|
||||||
|
filesToClean.forEach(file => {
|
||||||
|
try {
|
||||||
|
if (fs.existsSync(file)) {
|
||||||
|
fs.unlinkSync(file);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.warn(`Warning: Could not delete ${file}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
img2mp3.cleanup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run all tests
|
||||||
|
runAllTests();
|
||||||
Referencia en una nueva incidencia
Block a user