Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion tests/browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,17 @@ async function launch() {

// On interroge le point d'entrée HTTP de DevTools plutôt que de lire stderr :
// Edge n'y annonce rien, contrairement à Chrome.
const urlWs = await attendreDevTools(port, 20000);
//
// ⚠ 60 s, et pas 20. Sur la CI Windows du 2026-08-17, Edge n'a pas répondu
// dans les 20 s : `launch()` a rendu `null`, le `before` de `ui.test.js` a
// levé, et les 46 tests d'interface sont passés en « cancelled » — 0 échec,
// mais le job rouge quand même. Le même runner les avait fait passer deux
// fois le jour même : c'est la charge de la machine, pas un refus de démarrer.
//
// Attendre plus longtemps ne coûte RIEN quand tout va bien — la boucle sort
// dès que DevTools répond, en général sous la seconde. Ça ne coûte que dans
// le cas déjà perdu, où le navigateur ne démarrera jamais.
const urlWs = await attendreDevTools(port, 60000);
if (!urlWs) {
try { child.kill(); } catch (e) {}
try { fs.rmSync(profil, { recursive: true, force: true }); } catch (e) {}
Expand Down
66 changes: 54 additions & 12 deletions tests/champ3d.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -611,23 +611,52 @@ describe('Champ 3D', () => {
{ id: 'o3', p3: [2, 0, 2], dir3: [1, 0, 0], len3: 1 },
] });

/** Ordre d'allumage des barres, relevé sur le flux OSC. */
const ordreVu = async () => {
/**
* Ordre d'allumage des barres, relevé sur le flux OSC.
*
* ⚠ On attend que les 4 barres se soient allumées, on ne PARIE PAS sur une
* durée. La version d'avant coupait à 560 ms pour 4 pas de 120 ms, soit
* 80 ms de marge : la CI Windows du 2026-08-17 a relevé
* ["bar1","bar2","bar3"] — le bon ordre, tronqué d'un cran, parce que le
* quatrième pas n'était pas encore arrivé sur un runner chargé. Un test qui
* mesure une grandeur qui évolue doit être long devant le bruit de charge.
*
* Attendre la CONDITION plutôt qu'une durée rend le relevé indépendant de
* la vitesse de la machine, sans allonger le test sur une machine rapide :
* il sort dès que le compte y est. Le plafond le garde borné si rien ne
* vient — et un relevé incomplet fera échouer l'assertion, comme il doit.
*
* Attendre plus longtemps ne peut RIEN fausser ici : chaque barre n'est
* retenue qu'à son PREMIER allumage, donc les cycles suivants du chase sont
* ignorés. C'est ce qui rend cet élargissement sûr, là où élargir une
* fenêtre au hasard ne l'est pas.
*/
const ordreVu = async (attendu = 4) => {
await h.post('/api/blackout');
await sleep(80);
h.clearOsc();
await h.post('/api/resync');
await h.post('/api/start');
await sleep(560); // ~4 pas de 120 ms
await h.post('/api/stop');
const vus = [];
const precedent = {};
for (const m of h.osc()) {
const mm = /^\/fixtures\/(bar\d+)\/luminosity$/.exec(m.address);
if (!mm) continue;
if (m.args[0] > 0.5 && !(precedent[mm[1]] > 0.5) && !vus.includes(mm[1])) vus.push(mm[1]);
precedent[mm[1]] = m.args[0];
/** Relit tout le flux depuis le dernier `clearOsc()` — idempotent. */
const relever = () => {
const vus = [];
const precedent = {};
for (const m of h.osc()) {
const mm = /^\/fixtures\/(bar\d+)\/luminosity$/.exec(m.address);
if (!mm) continue;
if (m.args[0] > 0.5 && !(precedent[mm[1]] > 0.5) && !vus.includes(mm[1])) vus.push(mm[1]);
precedent[mm[1]] = m.args[0];
}
return vus;
};
let vus = [];
// Plafond à 3 s : largement au-dessus des ~480 ms nominales, et le test
// reste borné si le chase ne démarre pas du tout.
for (let i = 0; i < 60 && vus.length < attendu; i++) {
await sleep(50);
vus = relever();
}
await h.post('/api/stop');
return vus;
};

Expand Down Expand Up @@ -1008,8 +1037,21 @@ describe('Champ 3D', () => {
await base({ engine: 'field', field: 'bruit', axAz, axEl: 0,
stepMs: 10000, group: 8, speed: 0.05, width: 2 });
await h.post('/api/start');
// ⚠ Laisser le champ s'ÉTABLIR avant de mesurer, et prendre assez de
// relevés pour que la statistique converge. Sur la CI Windows du
// 2026-08-17, ce test a rendu 0,1087 contre 0,2149 — or 0,2149 est la
// valeur nominale des DEUX azimuts. Ce n'est donc pas l'axe qui a bougé :
// c'est un écart-type écrasé par des relevés plats, pris avant le premier
// tick sur une machine chargée. Un relevé plat sur dix suffit à diviser la
// dispersion par deux.
//
// On ne touche PAS au seuil de 15 % : il a été resserré depuis 50 % sur
// mesure, précisément parce que 50 % laissait passer le défaut que ce test
// interdit. Élargir la tolérance annulerait ce travail — c'est la mesure
// qu'on fiabilise, pas l'exigence qu'on relâche.
await sleep(150);
const vals = [];
for (let i = 0; i < 10; i++) {
for (let i = 0; i < 20; i++) {
const st = await h.state();
for (const v of (st.levels || [])) if (typeof v === 'number') vals.push(v);
await sleep(70);
Expand Down
7 changes: 6 additions & 1 deletion tests/ui.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,12 @@ describe('Interface dans un vrai navigateur', { skip: AUCUN_NAVIGATEUR &&
h = await start();
await h.post('/api/fixtures', { fixtures: fixtures(6) });
nav = await launch();
if (!nav) throw new Error('le navigateur n’a pas démarré');
// ⚠ Ce message est tout ce qu'on aura pour diagnostiquer : quand ce `before`
// lève, les 46 tests d'en dessous s'annoncent « cancelled » sans dire
// pourquoi. Dire le délai attendu évite de rechercher la cause à l'aveugle,
// comme il a fallu le faire le 2026-08-17.
if (!nav) throw new Error(
'le navigateur n’a pas démarré : DevTools n’a pas répondu en 60 s');
await nav.goto('http://127.0.0.1:' + h.port + '/');
});
after(async () => {
Expand Down
Loading