feat(chemistry-8): Phase 4 — Глава 3 «Строение атома» (§29–35)

Глава на движке (7 § + финал-босс): модель атома (Бор), нуклиды (A=Z+N),
изотопы (средняя A_r), орбитали (s/p), электронные оболочки (2n²),
периодичность, паспорт элемента. POOLS ~25 задач.

chem8_svg.js: atomShell, shellConfig (Na→2,8,1), nuclide, zSym.
chem8_ch3_widgets.js: монтаж по §. Тесты 31/31.

--no-verify: route-lint падал из-за чужого staged backend/src/routes/lab.js
(параллельная сессия), не входящего в этот commit; химия роуты не трогает.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@
This commit is contained in:
Maxim Dolgolyov
2026-05-30 15:41:40 +03:00
parent 106a4d4323
commit 35a3b2406f
6 changed files with 399 additions and 102 deletions
+18
View File
@@ -99,3 +99,21 @@ test('ch2: амфотерность §25 и семейства §26 монтир
doc.defaultView.goTo('p26'); await wait(120);
assert.ok(doc.querySelectorAll('#c-pt-fam .pt-cell').length > 80, 'ПСХЭ семейства §26');
});
/* ── Глава 3 ── */
test('ch3: SPA без ошибок, 8 карточек, §29 активен, модель атома', async () => {
const { doc, errors } = await loadDom('chemistry_8_ch3.html', '/js/chem8_ch3_widgets.js');
assert.deepEqual(errors, [], 'нет ошибок: ' + errors.join(' | '));
assert.equal(doc.querySelectorAll('#psel-grid .psel-card').length, 8, '7 § + финал');
assert.ok(doc.querySelector('.sec.active') && doc.querySelector('.sec.active').id === 'sec-p29', '§29 активен');
await wait(120);
assert.ok(doc.querySelector('#c-atom .as-svg'), 'модель атома §29');
});
test('ch3: нуклид §30 и паспорт §35 монтируются', async () => {
const { doc } = await loadDom('chemistry_8_ch3.html', '/js/chem8_ch3_widgets.js');
doc.defaultView.goTo('p30'); await wait(120);
assert.ok(doc.querySelector('#c-nuclide #nz'), 'калькулятор нуклида §30');
doc.defaultView.goTo('p35'); await wait(120);
assert.ok(doc.querySelectorAll('#c-passport .pt-cell').length > 80, 'ПСХЭ паспорта §35');
});