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:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user