98 lines
5.2 KiB
JavaScript
98 lines
5.2 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 exports_ = {}
|
|
vm.runInNewContext(ts.transpileModule(fs.readFileSync(path.join(__dirname, '../src/utils/birthdayCalendar.ts'), 'utf8'), {
|
|
compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2019 }
|
|
}).outputText, { exports: exports_, require })
|
|
const { solarToLunarBirthday, lunarBirthdayToSolar, lunarBirthdayModel, changeLunarBirthdayColumn, formatLunarBirthday } = exports_
|
|
const max = '2026-10-18'
|
|
|
|
test('阳历农历准确往返,闰月单列而不是重复普通月份', () => {
|
|
for (const solar of ['1900-01-01', '1998-06-18', '2000-02-05', '2023-03-22', '2024-02-29', max]) {
|
|
assert.equal(lunarBirthdayToSolar(solarToLunarBirthday(solar)), solar)
|
|
}
|
|
const leap = solarToLunarBirthday('2023-03-22')
|
|
assert.equal(leap.year, 2023); assert.equal(leap.month, -2); assert.equal(leap.day, 1)
|
|
assert.match(formatLunarBirthday('2023-03-22'), /闰二月初一/)
|
|
const model = lunarBirthdayModel(leap, max)
|
|
assert.ok(model.months.some(month => month.value === 2))
|
|
assert.ok(model.months.some(month => month.value === -2 && month.label === '闰二月'))
|
|
})
|
|
|
|
test('小月天数、无闰月年份联动纠正,不生成无效生日', () => {
|
|
const original = lunarBirthdayModel({ year: 2023, month: 2, day: 30 }, max)
|
|
const leapIndex = original.months.findIndex(month => month.value === -2)
|
|
const leap = changeLunarBirthdayColumn(original, 1, leapIndex, max)
|
|
assert.equal(leap.month, -2); assert.equal(leap.day, 29)
|
|
const leapModel = lunarBirthdayModel(leap, max)
|
|
const next = changeLunarBirthdayColumn(leapModel, 0, leapModel.years.indexOf(2024), max)
|
|
assert.equal(next.month, 2)
|
|
assert.ok(lunarBirthdayToSolar(next))
|
|
assert.equal(lunarBirthdayToSolar({ year: 2023, month: -2, day: 30 }), null)
|
|
assert.equal(lunarBirthdayToSolar({ year: 2024, month: -2, day: 1 }), null)
|
|
})
|
|
|
|
test('边界年月日只包含1900至今天,农历跨年仍正确', () => {
|
|
for (const solar of ['1900-01-01', max]) {
|
|
const model = lunarBirthdayModel(solarToLunarBirthday(solar), max)
|
|
for (const month of model.months) for (const day of month.days) {
|
|
const candidate = lunarBirthdayToSolar({ year: model.selection.year, month: month.value, day })
|
|
assert.ok(candidate >= '1900-01-01' && candidate <= max)
|
|
}
|
|
}
|
|
const current = lunarBirthdayModel({ year: 2026, month: 12, day: 30 }, max)
|
|
assert.ok(lunarBirthdayToSolar(current.selection) <= max)
|
|
assert.equal(solarToLunarBirthday('2026-02-30'), null)
|
|
assert.equal(solarToLunarBirthday('2026-2-1'), null)
|
|
})
|
|
|
|
test('同一生日两种输入不改变生肖与日主计算日期', () => {
|
|
for (const solar of ['2000-02-04', '2000-02-05', '2023-03-22']) {
|
|
const lunar = solarToLunarBirthday(solar)
|
|
const input = lunarBirthdayModel(lunar, max)
|
|
assert.equal(lunarBirthdayToSolar(input.selection), solar)
|
|
}
|
|
})
|
|
|
|
test('微信头像选择仅接收系统结果,不会再次调用媒体选择', () => {
|
|
const source = fs.readFileSync(path.join(__dirname, '../src/pages/profile-edit/index.tsx'), 'utf8')
|
|
assert.equal((source.match(/\? 'chooseAvatar' : undefined/g) || []).length, 1)
|
|
const callback = source.match(/const handleWechatAvatar = [\s\S]*?\n }/)[0]
|
|
assert.match(callback, /useAvatar\(event.detail.avatarUrl\)/)
|
|
assert.doesNotMatch(callback, /chooseMedia|chooseFrom|chooseImage/)
|
|
assert.doesNotMatch(source, /微信头像选择|wechat-avatar-action/)
|
|
})
|
|
|
|
test('日期控件回显农历偏好,切换历法不修改实际生日或触发保存', () => {
|
|
const component = {}
|
|
const file = fs.readFileSync(path.join(__dirname, '../src/components/BirthdayPicker.tsx'), 'utf8')
|
|
vm.runInNewContext(ts.transpileModule(file, { compilerOptions: { module: ts.ModuleKind.CommonJS,
|
|
target: ts.ScriptTarget.ES2019, jsx: ts.JsxEmit.ReactJSX } }).outputText, { exports: component, require: id => {
|
|
if (id === 'react') return { useState: initial => [initial(), () => {}], useEffect: () => {}, useMemo: fn => fn() }
|
|
if (id.endsWith('/birthdayCalendar')) return exports_
|
|
if (id === '@tarojs/components') return { View: 'View', Text: 'Text', Button: 'Button', Picker: 'Picker' }
|
|
return require(id)
|
|
} })
|
|
const modes = [], dates = []
|
|
const tree = component.BirthdayPicker({ value: '2023-03-22', calendar: 'lunar', onChange: value => dates.push(value), onCalendarChange: mode => modes.push(mode) })
|
|
const collect = node => {
|
|
if (!node || typeof node !== 'object') return []
|
|
if (Array.isArray(node)) return node.flatMap(collect)
|
|
return [node, ...collect(node.props?.children)]
|
|
}
|
|
const nodes = collect(tree)
|
|
const lunar = nodes.find(node => node.props?.['aria-label'] === '选择农历')
|
|
assert.match(lunar.props.className, /active/)
|
|
nodes.find(node => node.props?.['aria-label'] === '选择阳历').props.onClick()
|
|
assert.deepEqual(modes, ['solar']); assert.deepEqual(dates, [])
|
|
const picker = nodes.find(node => node.type === 'Picker')
|
|
assert.equal(picker.props.mode, 'multiSelector')
|
|
assert.ok(picker.props.range[1].includes('闰二月'))
|
|
picker.props.onCancel()
|
|
assert.deepEqual(dates, [])
|
|
})
|