const test = require('node:test') const assert = require('node:assert/strict') const fs = require('node:fs') const path = require('node:path') const Module = require('node:module') const ts = require('typescript') const filename = path.resolve(__dirname, '../src/utils/fiveElements.ts') const compiled = ts.transpileModule(fs.readFileSync(filename, 'utf8'), { compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2017 } }).outputText const loaded = new Module(filename, module) loaded.filename = filename loaded.paths = Module._nodeModulePaths(path.dirname(filename)) loaded._compile(compiled, filename) const { analyzePillars, calculateFiveElements } = loaded.exports test('同一日主在强弱不同的四柱下,扶抑方向应反转', () => { const strong = analyzePillars(['甲寅', '乙卯', '甲寅', '乙卯']) const weak = analyzePillars(['丙午', '丁巳', '甲申', '戊戌']) assert.equal(strong.dayMaster, weak.dayMaster) assert.equal(strong.strength, '偏强') assert.equal(weak.strength, '偏弱') assert.equal(strong.favorable, '火土金') assert.equal(weak.favorable, '水木') assert.equal(strong.analysis.season.supported, true) assert.equal(weak.analysis.roots.supported, false) }) test('地支藏干中的同类根必须计入,得势不包含日干自身', () => { const report = analyzePillars(['丙午', '丁巳', '甲辰', '戊戌']) assert.equal(report.analysis.roots.supported, true) // 辰藏乙,不能只看辰土。 assert.ok(report.analysis.roots.score > 0) const noSupport = analyzePillars(['丙午', '丁巳', '甲申', '戊戌']) assert.ok(noSupport.analysis.support.score < 20) }) test('有效日期和时辰改变后重新排盘,不受昵称或后端报告影响', () => { const first = calculateFiveElements('1998-06-18', '辰时') assert.deepEqual(first.pillars, ['戊寅', '戊午', '丙申', '壬辰']) const changedDate = calculateFiveElements('1998-12-18', '辰时') const changedHour = calculateFiveElements('1998-06-18', '戌时') assert.notDeepEqual(first.scores, changedDate.scores) assert.notDeepEqual(first.pillars, changedHour.pillars) assert.notDeepEqual(first.scores, changedHour.scores) assert.deepEqual(first, calculateFiveElements('1998-06-18', '7')) }) test('百分比总和为100,强弱有界,喜忌互斥,平衡不强行指定喜忌', () => { let balanced = false for (let month = 1; month <= 12; month++) { for (const hour of ['子时', '辰时', '午时', '酉时']) { const report = calculateFiveElements(`2000-${String(month).padStart(2, '0')}-15`, hour) assert.equal(report.scores.reduce((sum, score) => sum + score.value, 0), 100) assert.ok(report.scores.every((score) => Number.isInteger(score.value) && score.value >= 0 && score.value <= 100)) assert.ok(report.strengthScore >= 0 && report.strengthScore <= 100) assert.ok(![...report.favorable].some((element) => report.unfavorable.includes(element))) if (report.strength === '相对平衡') { balanced = true assert.equal(report.favorable, '') assert.equal(report.unfavorable, '') } } } assert.equal(balanced, true) }) test('不把无效生日、缺失时辰或越界时辰转换成虚构报告', () => { for (const [date, hour] of [ ['', '辰时'], ['2025-02-29', '辰时'], ['2024-02-30', '辰时'], ['2024-13-01', '辰时'], ['2000-01-01', ''], ['2000-01-01', '24'], ['2000-01-01', '-1'], ['2000-01-01', '辰时xxx'] ]) assert.equal(calculateFiveElements(date, hour), null) assert.ok(calculateFiveElements('2024-02-29', '子时')) assert.throws(() => analyzePillars(['甲子', '无效', '甲子', '甲子'])) }) test('节气前后切换月柱;子时换日采用历法库第二流派', () => { const before = calculateFiveElements('2024-02-03', '午时') const after = calculateFiveElements('2024-02-05', '午时') assert.notEqual(before.pillars[1], after.pillars[1]) const early = calculateFiveElements('2024-06-18', '0') const late = calculateFiveElements('2024-06-18', '23') assert.equal(early.dayMaster, late.dayMaster) })