test(api): pin earliest-uploadedAt + uploadEnabled-agnostic pre-check; fix comment

评审硬化三项(checkUploadDuplicates 后续,不 amend):
- e2e 补「同 bytes 多条可见命中取最早 uploadedAt」:两条同 bytes 不同
  uploadedAt 的种子行,断言回显更早值。
- e2e 补「uploadEnabled=false 预检仍 200 且照常命中」:钉住只读预览刻意
  不校验开关的偏差——防止未来一致性重构把检查加回来,破坏 App 关册时的
  降级体验(init 入队时仍有 409 兜底)。
- 修正 uploads.service checkDuplicates 的 null-uploadedAt 注释:原「谓词
  命中与否不受影响」不准确,改为「仅直改库等理论形状(bytes>0 且
  uploadedAt=null)下预检可能漏报而 init 仍会 409」。

uploads e2e 30/30 ✅ · api typecheck ✅

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
浅念
2026-09-28 19:06:47 +08:00
parent 805f77be76
commit 64e1be09d3
2 changed files with 42 additions and 2 deletions
+2 -2
View File
@@ -594,8 +594,8 @@ export class UploadsService {
const earliest = new Map<number, Date>();
for (const row of rows) {
// bytes>0 的行只会经 complete 落定(同事务写 uploadedAt);null 仅理论
// 形状(直改库等),跳过不参与映射——谓词命中与否不受影响(uploadedAt
// 只是回显元数据)。
// 形状(直改库等,bytes>0 且 uploadedAt=null),跳过不参与映射——该形状
// 下预检可能漏报而 init 仍会 409(偏差仅限于此理论形状,正常写路径不可达)。
if (row.uploadedAt === null) {
continue;
}
+40
View File
@@ -1117,6 +1117,46 @@ describe('uploads duplicates check (e2e)', () => {
expect(res.body.duplicates).toEqual([]);
});
it('同 bytes 多条可见命中取最早 uploadedAt(force 允许的重复行)', async () => {
const bytes = 555_555;
await seedPhoto(memberAId, bytes, {
uploadedAt: new Date('2026-09-25T08:00:00.000Z'),
});
await seedPhoto(memberAId, bytes, {
uploadedAt: new Date('2026-09-10T08:00:00.000Z'), // 更早,应回显此值
});
const res = await check(memberAToken, {
albumId,
items: [item('e.jpg', bytes)],
});
expect(res.status).toBe(200);
expect(res.body.duplicates).toEqual([
{ index: 0, bytes, uploadedAt: '2026-09-10T08:00:00.000Z' },
]);
});
it('uploadEnabled=false:预检仍 200 且照常命中(只读预览刻意不校验开关;init 入队时仍 409 兜底)', async () => {
await prisma.albums.update({
where: { id: albumId },
data: { uploadEnabled: false },
});
try {
const res = await check(memberAToken, {
albumId,
items: [item('a.jpg', BYTES_A)],
});
expect(res.status).toBe(200);
expect(res.body.duplicates).toEqual([
{ index: 0, bytes: BYTES_A, uploadedAt: UPLOADED_AT_A },
]);
} finally {
await prisma.albums.update({
where: { id: albumId },
data: { uploadEnabled: true },
});
}
});
it('非成员 → 404 ALBUM_NOT_FOUND(防枚举,同 init)', async () => {
const res = await check(outsiderToken, {
albumId,