'use strict'; /* * jsdom-смоук виджетов chem8_svg.js: реальная отрисовка в DOM, ввод, проверка. * Ловит рантайм-ошибки DOM-манипуляций, которые не видны в чистых юнит-тестах. */ const test = require('node:test'); const assert = require('node:assert'); const fs = require('node:fs'); const path = require('node:path'); const { JSDOM } = require('jsdom'); const SRC = fs.readFileSync( path.join(__dirname, '..', '..', 'frontend', 'js', 'chem8_svg.js'), 'utf8'); function mkDom() { const dom = new JSDOM('
'); // выполняем модуль так, что его `window` === jsdom-окно new Function('window', SRC)(dom.window); return { dom, C: dom.window.Chem8, doc: dom.window.document }; } function fire(el, type) { el.dispatchEvent(new el.ownerDocument.defaultView.Event(type, { bubbles: true })); } test('moleTriangle монтируется и считает m = n·M', () => { const { C, doc } = mkDom(); const api = C.moleTriangle(doc.getElementById('m'), {}); assert.ok(api && api.el, 'виджет смонтирован'); const inputs = doc.querySelectorAll('#m input[data-k]'); assert.equal(inputs.length, 3, '3 поля'); const byKey = {}; inputs.forEach(i => { byKey[i.getAttribute('data-k')] = i; }); // вводим n=2, затем M=18 → ожидаем m=36 byKey.n.value = '2'; fire(byKey.n, 'input'); byKey.M.value = '18'; fire(byKey.M, 'input'); const out = doc.querySelector('#m [data-out]'); assert.ok(/36/.test(out.textContent), 'm = 36 вычислено: ' + out.textContent); }); test('equationBalancer: неверные коэффициенты → дисбаланс, верные → баланс', () => { const { C, doc } = mkDom(); const api = C.equationBalancer(doc.getElementById('b'), { skeleton: 'H2 + O2 -> H2O', solution: [2, 1, 2] }); assert.ok(api && api.check, 'виджет смонтирован'); // по умолчанию все коэффициенты = 1 → не сбалансировано assert.equal(api.check(), false, '1·H2 + 1·O2 -> 1·H2O не сбалансировано'); const out = doc.querySelector('#b [data-out]'); assert.ok(out.className.includes('bad'), 'подсветка дисбаланса'); // применяем решение через кнопку doc.querySelector('#b [data-solve]').dispatchEvent( new doc.defaultView.Event('click', { bubbles: true })); assert.ok(out.className.includes('ok'), 'после решения — сбалансировано: ' + out.className); }); test('equationBalancer считает атомы для сложной реакции', () => { const { C, doc } = mkDom(); const api = C.equationBalancer(doc.getElementById('b'), { skeleton: 'Al + HCl -> AlCl3 + H2', solution: [2, 6, 2, 3] }); const coefs = doc.querySelectorAll('#b .ceqb-coef'); [2, 6, 2, 3].forEach((v, i) => { coefs[i].value = String(v); }); assert.equal(api.check(), true, '2Al + 6HCl -> 2AlCl3 + 3H2 сбалансировано'); });