Skip to content

Commit f4266bc

Browse files
committed
chore: add test for schema drift detection
1 parent 3bc62e7 commit f4266bc

1 file changed

Lines changed: 93 additions & 0 deletions

File tree

src/remote/remote.test.ts

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { assertEquals } from "@std/assert/equals";
66
import { ConnectionManager } from "../sync/connection-manager.ts";
77
import { assertArrayIncludes } from "@std/assert";
88
import { PgIdentifier } from "@query-doctor/core";
9+
import { type Op } from "jsondiffpatch/formatters/jsonpatch";
910

1011
const TEST_TARGET_CONTAINER_NAME = "postgres:17";
1112
const TEST_TARGET_CONTAINER_TIMESCALEDB_NAME =
@@ -423,3 +424,95 @@ Deno.test({
423424
}
424425
},
425426
});
427+
428+
Deno.test({
429+
name: "schema loader detects changes after database modification",
430+
sanitizeOps: false,
431+
sanitizeResources: false,
432+
fn: async () => {
433+
const [sourceDb, targetDb] = await Promise.all([
434+
new PostgreSqlContainer("postgres:17")
435+
.withCopyContentToContainer([
436+
{
437+
content: `
438+
create extension pg_stat_statements;
439+
create table testing(a int, b text);
440+
insert into testing values (1, 'test');
441+
create index "testing_b_idx" on testing(b);
442+
select * from testing where a = 1;
443+
`,
444+
target: "/docker-entrypoint-initdb.d/init.sql",
445+
},
446+
])
447+
.withCommand(["-c", "shared_preload_libraries=pg_stat_statements"])
448+
.start(),
449+
testSpawnTarget(),
450+
]);
451+
452+
try {
453+
const target = Connectable.fromString(targetDb.getConnectionUri());
454+
const source = Connectable.fromString(sourceDb.getConnectionUri());
455+
456+
const manager = ConnectionManager.forLocalDatabase();
457+
await using remote = new Remote(target, manager);
458+
459+
const sourcePg = postgres(source.toString());
460+
461+
await remote.syncFrom(source);
462+
await remote.optimizer.finish;
463+
464+
const initialStatus = await remote.getStatus();
465+
const initialDiffsResult = initialStatus.diffs;
466+
assertEquals(
467+
initialDiffsResult.status,
468+
"fulfilled",
469+
"Schema poll should succeed",
470+
);
471+
const initialDiffs = initialDiffsResult.status === "fulfilled"
472+
? initialDiffsResult.value
473+
: [];
474+
assertEquals(
475+
initialDiffs.length,
476+
0,
477+
"Should have no diffs initially after sync",
478+
);
479+
480+
await sourcePg.unsafe(`
481+
alter table testing add column c int;
482+
create index "testing_c_idx" on testing(c);
483+
`);
484+
485+
const statusAfterChange = await remote.getStatus();
486+
const diffsResult = statusAfterChange.diffs;
487+
488+
assertEquals(
489+
diffsResult.status,
490+
"fulfilled",
491+
"Schema poll should succeed",
492+
);
493+
const diffs = diffsResult.status === "fulfilled"
494+
? diffsResult.value
495+
: [];
496+
497+
assertEquals(
498+
diffs.length,
499+
2,
500+
"Should detect 2 schema changes (added column and index)",
501+
);
502+
503+
const addedColumnDiff = diffs.find((diff: Op) =>
504+
typeof diff.path === "string" && diff.path.includes("columns")
505+
);
506+
assertEquals(addedColumnDiff?.op, "add", "Should detect column addition");
507+
508+
const addedIndexDiff = diffs.find((diff: Op) =>
509+
typeof diff.path === "string" && diff.path.includes("indexes")
510+
);
511+
assertEquals(addedIndexDiff?.op, "add", "Should detect index addition");
512+
513+
await sourcePg.end();
514+
} finally {
515+
await Promise.all([sourceDb.stop(), targetDb.stop()]);
516+
}
517+
},
518+
});

0 commit comments

Comments
 (0)