@@ -1,9 +1,11 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
generateFixtures,
|
||||
constraintCoverageMatrix,
|
||||
modelJson,
|
||||
parseFixtureModel,
|
||||
serializeDataset,
|
||||
topologicalTableOrder,
|
||||
type GeneratedDataset,
|
||||
} from "../../src/fixture/model";
|
||||
|
||||
@@ -175,4 +177,104 @@ describe("fixture model", () => {
|
||||
}),
|
||||
).toThrow(/100,000 field values/u);
|
||||
});
|
||||
|
||||
it("imports and generates composite relational constraints topologically", () => {
|
||||
const sql = `CREATE TABLE tenants (
|
||||
region VARCHAR(8) NOT NULL,
|
||||
tenant_id INTEGER NOT NULL,
|
||||
PRIMARY KEY (region, tenant_id)
|
||||
);
|
||||
CREATE TABLE events (
|
||||
region VARCHAR(8) NOT NULL,
|
||||
tenant_id INTEGER NOT NULL,
|
||||
sequence INTEGER NOT NULL,
|
||||
UNIQUE (region, tenant_id, sequence),
|
||||
FOREIGN KEY (region, tenant_id) REFERENCES tenants(region, tenant_id)
|
||||
);`;
|
||||
const model = parseFixtureModel(sql, "sql").model;
|
||||
expect(model.tables[1]?.constraints).toEqual([
|
||||
{ kind: "unique", fields: ["region", "tenant_id", "sequence"] },
|
||||
{
|
||||
kind: "foreignKey",
|
||||
fields: ["region", "tenant_id"],
|
||||
references: { table: "tenants", fields: ["region", "tenant_id"] },
|
||||
},
|
||||
]);
|
||||
expect(topologicalTableOrder(model)).toEqual(["tenants", "events"]);
|
||||
const dataset = generateFixtures(model, {
|
||||
seed: "composite",
|
||||
rows: 12,
|
||||
boundaryPercent: 10,
|
||||
invalidPercent: 0,
|
||||
providerProfile: "auto",
|
||||
});
|
||||
const targets = new Set(
|
||||
dataset.tables.tenants?.map((row) => `${row.region}:${row.tenant_id}`),
|
||||
);
|
||||
expect(
|
||||
dataset.tables.events?.every((row) =>
|
||||
targets.has(`${row.region}:${row.tenant_id}`),
|
||||
),
|
||||
).toBe(true);
|
||||
expect(dataset.generationOrder).toEqual(["tenants", "events"]);
|
||||
expect(
|
||||
constraintCoverageMatrix(model, dataset).some(
|
||||
(entry) =>
|
||||
entry.table === "events" &&
|
||||
entry.constraint.startsWith("foreignKey(region,tenant_id)"),
|
||||
),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it("accepts scalar table-level primary and foreign-key constraints", () => {
|
||||
const sql = `CREATE TABLE accounts (
|
||||
account_id INTEGER NOT NULL,
|
||||
PRIMARY KEY (account_id)
|
||||
);
|
||||
CREATE TABLE entries (
|
||||
account_id INTEGER NOT NULL,
|
||||
FOREIGN KEY (account_id) REFERENCES accounts(account_id)
|
||||
);`;
|
||||
const model = parseFixtureModel(sql, "sql").model;
|
||||
expect(model.tables[0]?.constraints).toEqual([
|
||||
{ kind: "unique", fields: ["account_id"] },
|
||||
]);
|
||||
expect(model.tables[1]?.constraints).toEqual([
|
||||
{
|
||||
kind: "foreignKey",
|
||||
fields: ["account_id"],
|
||||
references: { table: "accounts", fields: ["account_id"] },
|
||||
},
|
||||
]);
|
||||
const dataset = generateFixtures(model, {
|
||||
seed: "scalar-table-constraints",
|
||||
rows: 8,
|
||||
boundaryPercent: 0,
|
||||
invalidPercent: 0,
|
||||
});
|
||||
const accounts = new Set(
|
||||
dataset.tables.accounts?.map((row) => row.account_id),
|
||||
);
|
||||
expect(
|
||||
dataset.tables.entries?.every((row) => accounts.has(row.account_id)),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it("supports deterministic built-in and custom provider profiles", () => {
|
||||
const model = parseFixtureModel("display_name,host,sku\n", "csv").model;
|
||||
const options = {
|
||||
seed: "providers",
|
||||
rows: 4,
|
||||
boundaryPercent: 0,
|
||||
invalidPercent: 0,
|
||||
providerProfile: "auto",
|
||||
};
|
||||
const generated = generateFixtures(model, options);
|
||||
expect(generated).toEqual(generateFixtures(model, options));
|
||||
expect(generated.tables.records?.[0]).toMatchObject({
|
||||
display_name: expect.stringMatching(/ /u),
|
||||
host: expect.stringMatching(/\.example\.test$/u),
|
||||
sku: "SKU-000001",
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user