Skip to content

Commit 8c3a1b4

Browse files
dmealingclaude
andcommitted
test(migrate-ts): e2e reversible drop-column migration (up DROP / down ADD)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 6a8ee12 commit 8c3a1b4

1 file changed

Lines changed: 35 additions & 0 deletions

File tree

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { describe, test, expect } from "bun:test";
2+
import { MetaDataLoader, InMemoryStringSource } from "@metaobjectsdev/metadata";
3+
import type { MetaData } from "@metaobjectsdev/metadata";
4+
import { buildExpectedSchema } from "../../src/expected-schema.js";
5+
import { diff } from "../../src/diff/index.js";
6+
import { emit } from "../../src/emit/index.js";
7+
8+
async function load(json: string): Promise<MetaData> {
9+
return (await new MetaDataLoader().load([new InMemoryStringSource(json)])).root;
10+
}
11+
const ENTITY = (fields: string) => JSON.stringify({
12+
"metadata.root": { children: [{
13+
"object.entity": { name: "User", children: [
14+
{ "field.long": { name: "id" } },
15+
...JSON.parse(fields),
16+
{ "source.rdb": { name: "src", "@table": "users" } },
17+
{ "identity.primary": { name: "pk", "@fields": ["id"], "@generation": "increment" } },
18+
] },
19+
}] },
20+
});
21+
22+
describe("e2e: dropping a field yields a reversible migration", () => {
23+
test("up drops the column; down re-adds it with the recorded type", async () => {
24+
// snapshot (prior) has `email`; new metadata removes it
25+
const prior = buildExpectedSchema(await load(ENTITY('[{"field.string":{"name":"email"}}]')), { dialect: "postgres" });
26+
const next = buildExpectedSchema(await load(ENTITY('[]')), { dialect: "postgres" });
27+
const r = await diff({ expected: next, actual: prior, allow: { dropColumn: true } });
28+
const { up, down } = emit(r.changes, { dialect: "postgres" });
29+
expect(up).toContain(`DROP COLUMN "email"`);
30+
expect(down).toContain(`ADD COLUMN "email"`);
31+
expect(down).toMatch(/column data is not restored/i);
32+
// down is no longer a bare TODO stub
33+
expect(down).not.toMatch(/TODO: re-add dropped column/i);
34+
});
35+
});

0 commit comments

Comments
 (0)