Procházet zdrojové kódy

test(app): add JOB_EXPIRED case and clarify duplicate-reuse arrange

Address review comments from @miya on #11195:

- Clarify in the first test that the initial status is irrelevant
  because notifyExportResultAndCleanUp overwrites it; the real
  duplicate-reuse path enters with status=completed.
- Add a third action coverage for JOB_EXPIRED. It is equivalent to
  FAILED under the current branch (action === COMPLETED), but pinning
  it guards against a future split silently backfilling completedAt
  on expired jobs.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
tomoyuki-t před 2 týdny
rodič
revize
91b519e67b

+ 29 - 1
apps/app/src/features/page-bulk-export/server/service/page-bulk-export-job-cron/notify-export-result-and-clean-up.integ.ts

@@ -48,7 +48,10 @@ describe('PageBulkExportJobCronService.notifyExportResultAndCleanUp', () => {
   });
 
   test('should set completedAt when a job is completed without it (duplicate-reuse path)', async () => {
-    // arrange: mimic the reuse path — completed-bound job without completedAt
+    // arrange: the only precondition the bug requires is "completedAt is null on entry";
+    // the initial status is irrelevant because notifyExportResultAndCleanUp overwrites it
+    // from the action argument. (Real duplicate-reuse path enters with status=completed,
+    // simplified to status=exporting here.)
     const job = await PageBulkExportJob.create({
       user: new mongoose.Types.ObjectId(),
       page: new mongoose.Types.ObjectId(),
@@ -113,4 +116,29 @@ describe('PageBulkExportJobCronService.notifyExportResultAndCleanUp', () => {
     expect(updated?.status).toBe(PageBulkExportJobStatus.failed);
     expect(updated?.completedAt).toBeUndefined();
   });
+
+  // JOB_EXPIRED is a third action that flows through the same choke point.
+  // Under the current branch (`action === COMPLETED`) it is equivalent to
+  // FAILED, but pinning it ensures a future split between the two does not
+  // silently start backfilling completedAt on expired jobs.
+  test('should not set completedAt when the job expired', async () => {
+    // arrange
+    const job = await PageBulkExportJob.create({
+      user: new mongoose.Types.ObjectId(),
+      page: new mongoose.Types.ObjectId(),
+      format: PageBulkExportFormat.md,
+      status: PageBulkExportJobStatus.exporting,
+    });
+
+    // act
+    await pageBulkExportJobCronService?.notifyExportResultAndCleanUp(
+      SupportedAction.ACTION_PAGE_BULK_EXPORT_JOB_EXPIRED,
+      job,
+    );
+
+    // assert
+    const updated = await PageBulkExportJob.findById(job._id);
+    expect(updated?.status).toBe(PageBulkExportJobStatus.failed);
+    expect(updated?.completedAt).toBeUndefined();
+  });
 });