Files
hera-web/scripts/elementIcon.test.cjs

75 lines
4.0 KiB
JavaScript

const test = require('node:test')
const assert = require('node:assert/strict')
const fs = require('node:fs')
const path = require('node:path')
const vm = require('node:vm')
const ts = require('typescript')
const root = path.resolve(__dirname, '..')
const cache = new Map()
function load(file) {
if (cache.has(file)) return cache.get(file)
const exports = {}
cache.set(file, exports)
const code = ts.transpileModule(fs.readFileSync(file, 'utf8'), {
compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2019, jsx: ts.JsxEmit.ReactJSX }
}).outputText
vm.runInNewContext(code, { exports, require: id => {
if (id.endsWith('.scss')) return {}
if (id === '@tarojs/components') return { View: 'view', Text: 'text' }
if (id.startsWith('.')) return load(path.resolve(path.dirname(file), `${id}.ts`))
return require(id)
} })
return exports
}
const { getDayMasterIcon } = load(path.join(root, 'src/utils/elementIcon.ts'))
const { calculateFiveElements, analyzePillars } = load(path.join(root, 'src/utils/fiveElements.ts'))
const { FiveElementIcon } = load(path.join(root, 'src/components/FiveElementIcon.tsx'))
test('十天干的日主对应五种元素图标,不按最高占比或喜用选择', () => {
const days = ['甲子', '乙丑', '丙寅', '丁卯', '戊辰', '己巳', '庚午', '辛未', '壬申', '癸酉']
const expected = ['wood', 'wood', 'fire', 'fire', 'earth', 'earth', 'metal', 'metal', 'water', 'water']
days.forEach((day, index) => {
const report = analyzePillars(['甲寅', '乙卯', day, '壬子'])
const icon = getDayMasterIcon(report)
assert.equal(icon.kind, expected[index])
assert.equal(icon.label, report.masterElement)
assert.match(icon.color, /^#[0-9a-f]{6}$/)
const component = FiveElementIcon({ report })
assert.equal(component.props.className, `five-element-icon five-element-${expected[index]}`)
assert.equal(component.props['aria-label'], `日主五行:${report.masterElement}`)
})
const report = analyzePillars(['甲寅', '乙卯', '庚申', '甲寅'])
assert.equal([...report.scores].sort((a, b) => b.value - a.value)[0].name, '木')
assert.equal(getDayMasterIcon(report).kind, 'metal')
})
test('真实生日变动同步切换日主图标,数据缺失或非法不默认显示水', () => {
const kinds = new Set()
for (let day = 10; day < 20; day++) {
const report = calculateFiveElements(`1998-06-${day}`, '辰时')
kinds.add(getDayMasterIcon(report).kind)
}
assert.equal(kinds.size, 5)
const first = getDayMasterIcon(calculateFiveElements('1998-06-18', '辰时'))
const changed = getDayMasterIcon(calculateFiveElements('1998-06-20', '辰时'))
assert.notEqual(first.kind, changed.kind)
for (const report of [null, undefined, { masterElement: '未知' }, calculateFiveElements('', '')]) {
assert.equal(getDayMasterIcon(report).kind, 'unknown')
}
assert.equal(FiveElementIcon({ report: null }).props['aria-label'], '完善出生信息后显示日主五行')
})
test('我的元素复用当前报告,个人头像保持独立,图标样式不污染水滴默认头像', () => {
const page = fs.readFileSync(path.join(root, 'src/pages/my/index.tsx'), 'utf8')
assert.match(page, /<FiveElementIcon report=\{elementReport\} \/>/)
assert.match(page, /calculateFiveElements\(profile.birthday, profile.birthHour\)/)
assert.match(page, /\[profile\?\.birthday, profile\?\.birthHour\]/)
assert.match(page, /<UserAvatar src=\{profile.avatarUrl\}[^>]+fallback=\{<WaterMascot \/>\}/)
assert.doesNotMatch(page, /<WaterMascot compact/)
const sass = require(require.resolve('sass', { paths: [require.resolve('@tarojs/webpack5-runner')] }))
const postcss = require(require.resolve('postcss', { paths: [require.resolve('@tarojs/webpack5-runner')] }))
const css = sass.renderSync({ file: path.join(root, 'src/components/FiveElementIcon.scss') }).css.toString()
postcss.parse(css).walkRules(rule => rule.selectors.forEach(selector => assert.match(selector, /^\.five-element-/)))
assert.doesNotMatch(css, /\.water-mascot/)
})