From f767e35e0683dfec5481719d0455f8cb3a312adb Mon Sep 17 00:00:00 2001 From: Eva Date: Mon, 13 Jul 2026 18:27:59 +0700 Subject: [PATCH] test(incremental): surface node deletion failures --- .../lbug-delete-nodes-for-files.test.ts | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/gitnexus/test/integration/lbug-delete-nodes-for-files.test.ts b/gitnexus/test/integration/lbug-delete-nodes-for-files.test.ts index 124bd64749..54d2ef42c9 100644 --- a/gitnexus/test/integration/lbug-delete-nodes-for-files.test.ts +++ b/gitnexus/test/integration/lbug-delete-nodes-for-files.test.ts @@ -237,3 +237,29 @@ withTestLbugDB('delete-nodes-missing-embedding-table', () => { }, 120_000); }); }); + +/** + * Error propagation contract for #37: zero matched rows are a valid no-op, + * but a native/schema failure while deleting a required node table must + * reject the whole writeback. A dedicated database keeps the intentional + * schema damage isolated from the successful-delete coverage above. + */ +withTestLbugDB('delete-nodes-required-table-failure', () => { + describe('deleteNodesForFiles native deletion failures (#37)', () => { + it('surfaces a required node-table failure instead of reporting success', async () => { + const { deleteNodesForFiles, executeQuery } = + await import('../../src/core/lbug/lbug-adapter.js'); + + await executeQuery( + `CREATE (:Function {id: 'Function:src/a.ts:fnA:1', name: 'fnA', filePath: 'src/a.ts', startLine: 1, endLine: 3, isExported: true, content: '', description: ''})`, + ); + + // File is not part of the embedding join. Removing the property used + // by its delete predicate therefore reaches the actual node-table + // loop before LadybugDB raises the binder failure. + await executeQuery('ALTER TABLE File DROP filePath'); + + await expect(deleteNodesForFiles(['src/a.ts'])).rejects.toThrow(/File|filePath|property/i); + }, 120_000); + }); +});