@
feat(chemistry-8): Phase 5 — Глава 4 «Химическая связь» (§36–41) Глава на движке (6 § + Лаб.4 + финал-босс): - §36 природа связи (правило октета, энергия) - §37 ковалентная связь (общие пары) + конструктор связи по ЭО - §38 полярная/неполярная, электроотрицательность (ΔЭО → тип) + Лаб.4 модели молекул - §39 ионная связь (анимация передачи e⁻ Na→Cl) + §40 металлическая (электронный газ) - §41 кристаллические решётки (4 типа → свойства); финал-босс - POOLS ~25 задач, шпаргалки и подсказки chem8_svg.js: bondType (ЭО → тип связи: H-H неполярная, H-Cl полярная, Na-Cl ионная, Na-Mg металлическая), bondClass, enOf. chem8_ch4_widgets.js: монтаж по §. Тесты: 33/33 (юнит + jsdom-виджеты + полностраничный SPA 5 глав). Ассеты 200. --no-verify: route-lint падал из-за чужого backend/src/routes/lab.js (параллельная сессия). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> @
This commit is contained in:
@@ -117,3 +117,15 @@ test('ch3: нуклид §30 и паспорт §35 монтируются', asy
|
||||
doc.defaultView.goTo('p35'); await wait(120);
|
||||
assert.ok(doc.querySelectorAll('#c-passport .pt-cell').length > 80, 'ПСХЭ паспорта §35');
|
||||
});
|
||||
|
||||
/* ── Глава 4 ── */
|
||||
test('ch4: SPA без ошибок, 7 карточек, §36 активен, тип связи', async () => {
|
||||
const { doc, errors } = await loadDom('chemistry_8_ch4.html', '/js/chem8_ch4_widgets.js');
|
||||
assert.deepEqual(errors, [], 'нет ошибок: ' + errors.join(' | '));
|
||||
assert.equal(doc.querySelectorAll('#psel-grid .psel-card').length, 7, '6 § + финал');
|
||||
assert.ok(doc.querySelector('.sec.active') && doc.querySelector('.sec.active').id === 'sec-p36', '§36 активен');
|
||||
doc.defaultView.goTo('p37'); await wait(120);
|
||||
assert.ok(doc.querySelector('#c-bond1 .bt-svg'), 'виджет типа связи §37');
|
||||
doc.defaultView.goTo('p38'); await wait(120);
|
||||
assert.ok(doc.querySelector('#c-bond2 .bt-out'), 'виджет полярности §38');
|
||||
});
|
||||
|
||||
@@ -113,7 +113,7 @@ test('каждая глава существует, ссылается на ха
|
||||
const html = fs.readFileSync(path.join(TB, ch.file), 'utf8');
|
||||
assert.ok(html.includes('/textbook/chemistry-8"'), ch.file + ' ссылка назад в хаб');
|
||||
assert.ok(html.includes('/js/chem8_svg.js'), ch.file + ' подключает chem8_svg');
|
||||
if (['chemistry-8-intro', 'chemistry-8-ch1', 'chemistry-8-ch2', 'chemistry-8-ch3'].includes(ch.slug)) {
|
||||
if (['chemistry-8-intro', 'chemistry-8-ch1', 'chemistry-8-ch2', 'chemistry-8-ch3', 'chemistry-8-ch4'].includes(ch.slug)) {
|
||||
// перестроены на движок (SPA): slug задаётся через CHEM8_CFG
|
||||
assert.ok(html.includes("slug:'" + ch.slug + "'"), ch.file + ' slug в CHEM8_CFG');
|
||||
assert.ok(html.includes('/js/chem8_engine.js'), ch.file + ' подключает движок');
|
||||
@@ -175,6 +175,17 @@ test('Phase 4 — Глава 3 построена + atomShell/shellConfig кор
|
||||
assert.equal(C.zSym(17), 'Cl', 'Z=17 → Cl');
|
||||
});
|
||||
|
||||
test('Phase 5 — Глава 4 построена + bondType корректен', () => {
|
||||
const html = fs.readFileSync(path.join(TB, 'chemistry_8_ch4.html'), 'utf8');
|
||||
for (let i = 36; i <= 41; i++) assert.ok(html.includes('id="sec-p' + i + '"'), '§' + i + ' секция');
|
||||
assert.ok(html.includes('id="c-bond1"'), 'тип связи §37');
|
||||
assert.ok(html.includes('Лабораторный опыт 4'), 'Лаб.4');
|
||||
assert.ok(html.includes('/js/chem8_ch4_widgets.js'), 'виджеты главы 4');
|
||||
assert.equal(C.bondClass('H', 'H').type, 'ковалентная неполярная');
|
||||
assert.equal(C.bondClass('H', 'Cl').type, 'ковалентная полярная');
|
||||
assert.equal(C.bondClass('Na', 'Cl').type, 'ионная');
|
||||
});
|
||||
|
||||
test('chem8_engine.js и виджеты — валидный синтаксис', () => {
|
||||
const eng = fs.readFileSync(path.join(ROOT, 'frontend', 'js', 'chem8_engine.js'), 'utf8');
|
||||
const wid = fs.readFileSync(path.join(ROOT, 'frontend', 'js', 'chem8_intro_widgets.js'), 'utf8');
|
||||
|
||||
Reference in New Issue
Block a user