From cdf38bd8db86e24ac649bc45d580c15d090fbf12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Mon, 11 May 2026 20:05:47 +0200 Subject: [PATCH] catalog-backend: fix syncSearchRows test to use real call path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the raw Knex onConflict().merge() insert in the 'overwrites original_value on conflict' test with a direct UPDATE to corrupt the stored original_value, followed by a second syncSearchRows call. This tests the actual application code path (ON CONFLICT DO UPDATE inside syncSearchRows) rather than embedding the conflict logic in the test itself. Signed-off-by: Fredrik Adelöw Co-authored-by: Cursor --- .../stitcher/syncSearchRows.test.ts | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/plugins/catalog-backend/src/database/operations/stitcher/syncSearchRows.test.ts b/plugins/catalog-backend/src/database/operations/stitcher/syncSearchRows.test.ts index 9cc2af8206..6981af177b 100644 --- a/plugins/catalog-backend/src/database/operations/stitcher/syncSearchRows.test.ts +++ b/plugins/catalog-backend/src/database/operations/stitcher/syncSearchRows.test.ts @@ -245,21 +245,24 @@ describe.each(databases.eachSupportedId())('syncSearchRows, %p', databaseId => { ); }); - it('overwrites original_value on conflict via ON CONFLICT DO UPDATE', async () => { + it('restores original_value when re-syncing after it was corrupted', async () => { await syncSearchRows(knex, 'e1', [row('a', 'x', 'X')]); - // Simulate a concurrent stitcher inserting the same (entity_id, key, value) - // with a different original_value casing. Unlike DO NOTHING, DO UPDATE - // requires an explicit conflict target — the column list is not optional. - await knex('search') - .insert({ entity_id: 'e1', key: 'a', value: 'x', original_value: 'x' }) - .onConflict(['entity_id', 'key', 'value']) - .merge(['original_value']); + // Corrupt the stored original_value (simulates stale or wrong data left + // by a previous stitcher run) without changing the key or value. + await knex('search') + .where({ entity_id: 'e1', key: 'a', value: 'x' }) + .update({ original_value: 'corrupted' }); + + // Re-syncing the same desired rows should overwrite original_value back to + // 'X' via the ON CONFLICT DO UPDATE SET original_value = EXCLUDED.original_value + // clause inside syncSearchRows. + await syncSearchRows(knex, 'e1', [row('a', 'x', 'X')]); const rows = await getSearchRows(); expect(rows).toHaveLength(1); expect(rows[0]).toEqual( - expect.objectContaining({ key: 'a', value: 'x', original_value: 'x' }), + expect.objectContaining({ key: 'a', value: 'x', original_value: 'X' }), ); });