Files
convertisseur-images/test.html
T

182 lines
7.2 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8" />
<title>Tests — Convertisseur Images</title>
<style>
body { font-family: monospace; padding: 20px; background: #f9f9f9; }
.pass { color: green; margin: 2px 0; }
.fail { color: red; font-weight: bold; margin: 2px 0; }
h2 { margin-top: 20px; border-top: 1px solid #ddd; padding-top: 10px; }
#summary { font-size: 1.2em; font-weight: bold; margin-top: 24px; padding: 12px;
border-radius: 8px; display: inline-block; }
</style>
</head>
<body>
<h1>Tests unitaires</h1>
<div id="results"></div>
<div id="summary"></div>
<script type="module">
let passed = 0, failed = 0;
function assert(description, condition) {
const ok = Boolean(condition);
ok ? passed++ : failed++;
const el = document.createElement('div');
el.className = ok ? 'pass' : 'fail';
el.textContent = `${ok ? '✅' : '❌'} ${description}`;
document.getElementById('results').appendChild(el);
}
function section(title) {
const el = document.createElement('h2');
el.textContent = title;
document.getElementById('results').appendChild(el);
}
// Helper: construit un ImageData-like depuis un tableau 2D de [R,G,B]
function makeImageData(grid) {
const h = grid.length, w = grid[0].length;
const data = new Uint8ClampedArray(w * h * 4);
for (let y = 0; y < h; y++) {
for (let x = 0; x < w; x++) {
const i = (y * w + x) * 4;
const [r, g, b] = grid[y][x];
data[i] = r; data[i+1] = g; data[i+2] = b; data[i+3] = 255;
}
}
return { data, width: w, height: h };
}
// ── heicConverter ──────────────────────────────────────────────
import { convertHeicToJpeg } from './js/heicConverter.js';
section('heicConverter');
try {
await convertHeicToJpeg(null);
assert('convertHeicToJpeg(null) lance TypeError', false);
} catch (e) {
assert('convertHeicToJpeg(null) lance TypeError', e instanceof TypeError);
}
try {
const pngFile = new File([new Uint8Array([137,80,78,71])], 'test.png', { type: 'image/png' });
await convertHeicToJpeg(pngFile);
assert('convertHeicToJpeg avec PNG lance TypeError', false);
} catch (e) {
assert('convertHeicToJpeg avec PNG lance TypeError', e instanceof TypeError);
}
// ── bgRemover — chebyshevDistance ──────────────────────────────
import { chebyshevDistance, createFloodFillMask, applyMaskToImageData } from './js/bgRemover.js';
section('bgRemover — chebyshevDistance');
assert('couleurs identiques → distance 0',
chebyshevDistance([255,255,255], [255,255,255]) === 0);
assert('blanc vs quasi-blanc (diff max=10) → distance 10',
chebyshevDistance([255,255,255], [245,250,252]) === 10);
assert('blanc vs gris 128 → distance 127',
chebyshevDistance([255,255,255], [128,128,128]) === 127);
assert('distance = max des écarts par canal',
chebyshevDistance([200,100,50], [180,90,20]) === 30);
// ── bgRemover — createFloodFillMask ────────────────────────────
section('bgRemover — createFloodFillMask');
const W = [255,255,255], R = [200,50,50], B = [50,50,200];
const img3x3 = makeImageData([
[W, W, W],
[W, R, W],
[W, W, W],
]);
const mask3x3 = createFloodFillMask(img3x3, [255,255,255], 30);
assert('3×3 : 8 pixels blancs de bordure masqués (somme=8)',
Array.from(mask3x3).reduce((a,b) => a+b, 0) === 8);
assert('3×3 : pixel rouge central NON masqué',
mask3x3[1 * 3 + 1] === 0);
const img4x4 = makeImageData([
[W, W, W, W],
[W, B, B, W],
[W, B, B, W],
[W, W, W, W],
]);
const mask4x4 = createFloodFillMask(img4x4, [255,255,255], 30);
assert('4×4 : 12 pixels blancs masqués',
Array.from(mask4x4).reduce((a,b) => a+b, 0) === 12);
assert('4×4 : 4 pixels bleus intérieurs non masqués',
mask4x4[1*4+1] === 0 && mask4x4[1*4+2] === 0 &&
mask4x4[2*4+1] === 0 && mask4x4[2*4+2] === 0);
// ── bgRemover — applyMaskToImageData ───────────────────────────
section('bgRemover — applyMaskToImageData');
const imgApply = makeImageData([
[[200,50,50], [50,50,200]],
[[50,50,200], [50,50,200]],
]);
const maskApply = new Uint8Array([1, 0, 0, 0]);
applyMaskToImageData(imgApply, maskApply, [255,255,255]);
const d = imgApply.data;
assert('pixel masqué → blanc pur',
d[0] === 255 && d[1] === 255 && d[2] === 255);
assert('pixel non masqué → inchangé (bleu)',
d[4] === 50 && d[5] === 50 && d[6] === 200);
// ── imageProcessor — processBatch ──────────────────────────────
import { processBatch } from './js/imageProcessor.js';
section('imageProcessor — processBatch');
const resultsA = [];
await processBatch([1,2,3,4,5], async (item) => { resultsA.push(item * 2); }, 3);
assert('processBatch traite les 5 éléments', resultsA.length === 5);
assert('processBatch retourne les bons résultats',
[2,4,6,8,10].every(v => resultsA.includes(v)));
let concurrent = 0, maxConcurrent = 0;
await processBatch([1,2,3,4,5,6], async () => {
concurrent++;
maxConcurrent = Math.max(maxConcurrent, concurrent);
await new Promise(r => setTimeout(r, 10));
concurrent--;
}, 3);
assert('processBatch ne dépasse jamais 3 en simultané', maxConcurrent <= 3);
// ── zipExporter — downloadAllAsZip ─────────────────────────────
import { downloadAllAsZip } from './js/zipExporter.js';
section('zipExporter — downloadAllAsZip');
let capturedHref = null;
const origAppend = document.body.appendChild.bind(document.body);
const origRemove = document.body.removeChild.bind(document.body);
document.body.appendChild = (el) => {
if (el.tagName === 'A') { capturedHref = el.href; el.click = () => {}; return el; }
return origAppend(el);
};
document.body.removeChild = (el) => { try { origRemove(el); } catch {} };
await downloadAllAsZip([
{ name: '12345.jpg', blob: new Blob(['data1'], { type: 'image/jpeg' }) },
{ name: '67890.jpg', blob: new Blob(['data2'], { type: 'image/jpeg' }) },
]);
document.body.appendChild = origAppend;
document.body.removeChild = origRemove;
assert('downloadAllAsZip génère une URL blob:',
capturedHref !== null && capturedHref.startsWith('blob:'));
// ── Résumé ─────────────────────────────────────────────────────
const summary = document.getElementById('summary');
summary.textContent = `${passed} passé(s), ${failed} échoué(s)`;
summary.style.background = failed === 0 ? '#dcfce7' : '#fee2e2';
summary.style.color = failed === 0 ? '#166534' : '#991b1b';
</script>
</body>
</html>