113 lines
4.5 KiB
JavaScript
113 lines
4.5 KiB
JavaScript
/**
|
||||
|
|
* date 时分秒回归测试(2026-10-05 加)。
|
|||
|
|
*
|
|||
|
|
* node test/date-time.mjs
|
|||
|
|
*
|
|||
|
|
* 背景:编辑器的日期框只有年月日,写出来的 front matter 是 `date: 2026-10-05`。
|
|||
|
|
* 同一天发两篇 → 两篇 date 一模一样 → 前台(Hugo 按 Date 排)和后台列表
|
|||
|
|
* (posts.mjs 的 listPosts 按 date 排)都只能拿标题当兜底比较,于是 21:30 发的
|
|||
|
|
* 新文章排在了 11:34 发的旧文章**后面**(真实事故:首页第 2 位)。
|
|||
|
|
*
|
|||
|
|
* 这里在一个一次性临时仓库里跑,不碰真仓库。断言 5 件事:
|
|||
|
|
* ① 新建时 date 只给「天」→ 落盘必须带时分秒 + 北京时区偏移
|
|||
|
|
* ② 同一天连发两篇 → 时间戳必须不同,列表里新的在前
|
|||
|
|
* ③「时间正好 00:00:00」的写法也按「只到天」处理,同样补时刻
|
|||
|
|
* ④ 保存时不改日子 → 原有的时分秒一个字符都不能动
|
|||
|
|
* ⑤ 保存时真的换了日子 → date 换成新日子 + 新时刻
|
|||
|
|
*/
|
|||
|
|
import fs from 'node:fs';
|
|||
|
|
import os from 'node:os';
|
|||
|
|
import path from 'node:path';
|
|||
|
|
import { makePosts } from '../src/posts.mjs';
|
|||
|
|
|
|||
|
|
const TMP = fs.mkdtempSync(path.join(os.tmpdir(), 'editor-date-'));
|
|||
|
|
const contentDir = path.join(TMP, 'content', 'posts');
|
|||
|
|
fs.mkdirSync(contentDir, { recursive: true });
|
|||
|
|
|
|||
|
|
const api = makePosts({
|
|||
|
|
contentDir,
|
|||
|
|
trashDir: path.join(TMP, 'trash'),
|
|||
|
|
defaultAuthor: '测试',
|
|||
|
|
repoRoot: TMP,
|
|||
|
|
blogBase: '',
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
const admin = { uid: 1, name: '测试', role: 'admin' };
|
|||
|
|
let pass = 0;
|
|||
|
|
let fail = 0;
|
|||
|
|
|
|||
|
|
function check(name, ok, extra = '') {
|
|||
|
|
if (ok) {
|
|||
|
|
pass++;
|
|||
|
|
console.log(' ✓ ' + name + (extra ? ' ' + extra : ''));
|
|||
|
|
} else {
|
|||
|
|
fail++;
|
|||
|
|
console.log(' ✗ ' + name + (extra ? ' ' + extra : ''));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/** 读回落盘的 date 值(序列化会把带 ':' 的值加单引号,剥掉) */
|
|||
|
|
function dateOf(dirName) {
|
|||
|
|
const raw = fs.readFileSync(path.join(contentDir, '2026', dirName, 'index.md'), 'utf8');
|
|||
|
|
const v = ((/^date:\s*(.+)$/m.exec(raw) || [])[1] || '').trim();
|
|||
|
|
return /^'.*'$/.test(v) ? v.slice(1, -1) : v;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const CN = /^2026-10-0[57]T\d{2}:\d{2}:\d{2}\+08:00$/;
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
// ---- ① 只给「天」----
|
|||
|
|
const a = api.createPost(
|
|||
|
|
{ frontMatter: { title: '同日甲', date: '2026-10-05', slug: '20261005090000' }, content: '甲' },
|
|||
|
|
admin
|
|||
|
|
);
|
|||
|
|
const da = dateOf(a.dirName);
|
|||
|
|
check('① 新建:date 补上了时分秒', CN.test(da), da);
|
|||
|
|
|
|||
|
|
// ---- ② 同一天再发一篇(隔 1 秒,保证时刻严格更大)----
|
|||
|
|
await new Promise((r) => setTimeout(r, 1100));
|
|||
|
|
const b = api.createPost(
|
|||
|
|
{ frontMatter: { title: '同日乙', date: '2026-10-05', slug: '20261005103000' }, content: '乙' },
|
|||
|
|
admin
|
|||
|
|
);
|
|||
|
|
const db = dateOf(b.dirName);
|
|||
|
|
check('② 第二篇也有时分秒', CN.test(db), db);
|
|||
|
|
check('② 两篇时间戳不再相同', da !== db, da + ' vs ' + db);
|
|||
|
|
|
|||
|
|
const order = api.listPosts({ perPage: 50 }, admin).posts.map((p) => p.title);
|
|||
|
|
check('② 列表里新的排在前面', order[0] === '同日乙' && order[1] === '同日甲', JSON.stringify(order));
|
|||
|
|
|
|||
|
|
// ---- ③ 时刻正好 00:00:00 的老写法 ----
|
|||
|
|
const c = api.createPost(
|
|||
|
|
{
|
|||
|
|
frontMatter: { title: '零点写法', date: '2026-10-06T00:00:00.000Z', slug: '20261006000000' },
|
|||
|
|
content: '丙',
|
|||
|
|
},
|
|||
|
|
admin
|
|||
|
|
);
|
|||
|
|
check('③ 00:00:00 也按「只到天」补时刻', /^2026-10-06T\d{2}:\d{2}:\d{2}\+08:00$/.test(dateOf(c.dirName)), dateOf(c.dirName));
|
|||
|
|
|
|||
|
|
// ---- ④ 保存时不改日子(编辑器只会回传 2026-10-05)----
|
|||
|
|
api.savePost(b.dirName, { content: '乙(改了正文)', frontMatter: { date: '2026-10-05' } }, admin);
|
|||
|
|
check('④ 不改日子 → 时分秒保留', dateOf(b.dirName) === db, dateOf(b.dirName));
|
|||
|
|
|
|||
|
|
// ---- ⑤ 真的换了日子 ----
|
|||
|
|
api.savePost(b.dirName, { frontMatter: { date: '2026-10-07' } }, admin);
|
|||
|
|
check('⑤ 改日子 → 新日子 + 时刻', /^2026-10-07T\d{2}:\d{2}:\d{2}\+08:00$/.test(dateOf(b.dirName)), dateOf(b.dirName));
|
|||
|
|
|
|||
|
|
// ---- ⑥ 明确给了时刻的(含手工指定的历史时间)不能被覆盖 ----
|
|||
|
|
const d = api.createPost(
|
|||
|
|
{
|
|||
|
|
frontMatter: { title: '指定时刻', date: '2026-10-05T08:15:30+08:00', slug: '20261005081530' },
|
|||
|
|
content: '丁',
|
|||
|
|
},
|
|||
|
|
admin
|
|||
|
|
);
|
|||
|
|
check('⑥ 明确给了时刻则原样保留', dateOf(d.dirName) === '2026-10-05T08:15:30+08:00', dateOf(d.dirName));
|
|||
|
|
} finally {
|
|||
|
|
fs.rmSync(TMP, { recursive: true, force: true, maxRetries: 3 });
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
console.log('\n================================');
|
|||
|
|
console.log('通过 ' + pass + ' / 失败 ' + fail);
|
|||
|
|
process.exit(fail ? 1 : 0);
|