- Add E2ESchemaDatabaseConfig interface for database configuration validation. - Implement assertE2ESchemaDatabaseConfig function to enforce schema requirements. - Create prepareE2ESchema function to handle schema preparation and initialization. - Develop E2E lifecycle management functions to provision, prepare, and run tests. - Introduce Docker Compose setup for E2E database environment. - Add Playwright configuration for E2E testing. - Implement various test cases to validate E2E schema preparation and lifecycle. - Create utility functions for environment variable management and database assertions. - Establish smoke tests to verify initial data setup and integrity.
195 lines
5.3 KiB
TypeScript
195 lines
5.3 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import test from "node:test";
|
|
|
|
import { runE2ELifecycle } from "./e2e-lifecycle.ts";
|
|
|
|
test("prepara antes de ejecutar el hijo y limpia tras éxito", async () => {
|
|
const events: string[] = [];
|
|
const result = await runE2ELifecycle({
|
|
provision: async () => ({
|
|
environment: { DB_NAME: "e2e" },
|
|
destroy: async () => events.push("cleanup"),
|
|
}),
|
|
prepare: async () => {
|
|
events.push("prepare");
|
|
},
|
|
bootstrap: async () => {
|
|
events.push("bootstrap");
|
|
},
|
|
runChild: async (env) => {
|
|
events.push(env.DB_NAME);
|
|
return 0;
|
|
},
|
|
});
|
|
assert.equal(result, 0);
|
|
assert.deepEqual(events, ["prepare", "bootstrap", "e2e", "cleanup"]);
|
|
});
|
|
|
|
test("limpia tras código de salida no cero y conserva su código", async () => {
|
|
let cleaned = false;
|
|
const result = await runE2ELifecycle({
|
|
provision: async () => ({
|
|
environment: {},
|
|
destroy: async () => {
|
|
cleaned = true;
|
|
},
|
|
}),
|
|
prepare: async () => undefined,
|
|
bootstrap: async () => undefined,
|
|
runChild: async () => 3,
|
|
});
|
|
assert.equal(result, 3);
|
|
assert.equal(cleaned, true);
|
|
});
|
|
|
|
test("no intenta limpiar si falla el provisionado", async () => {
|
|
await assert.rejects(
|
|
() =>
|
|
runE2ELifecycle({
|
|
provision: async () => {
|
|
throw new Error("provision");
|
|
},
|
|
prepare: async () => undefined,
|
|
bootstrap: async () => undefined,
|
|
runChild: async () => 0,
|
|
}),
|
|
/provision/
|
|
);
|
|
});
|
|
|
|
test("un fallo de cleanup no oculta una excepción del hijo", async () => {
|
|
await assert.rejects(
|
|
() =>
|
|
runE2ELifecycle({
|
|
provision: async () => ({
|
|
environment: {},
|
|
destroy: async () => {
|
|
throw new Error("cleanup");
|
|
},
|
|
}),
|
|
prepare: async () => undefined,
|
|
bootstrap: async () => undefined,
|
|
runChild: async () => {
|
|
throw new Error("child");
|
|
},
|
|
}),
|
|
(error: unknown) =>
|
|
error instanceof AggregateError &&
|
|
error.errors.some((value) => value instanceof Error && value.message === "child") &&
|
|
error.errors.some((value) => value instanceof Error && value.message === "cleanup")
|
|
);
|
|
});
|
|
|
|
test("un fallo de cleanup tras éxito hace fallar el lifecycle", async () => {
|
|
await assert.rejects(
|
|
() =>
|
|
runE2ELifecycle({
|
|
provision: async () => ({
|
|
environment: {},
|
|
destroy: async () => {
|
|
throw new Error("cleanup");
|
|
},
|
|
}),
|
|
prepare: async () => undefined,
|
|
bootstrap: async () => undefined,
|
|
runChild: async () => 0,
|
|
}),
|
|
/cleanup/
|
|
);
|
|
});
|
|
|
|
test("un fallo de preparación impide el hijo y mantiene cleanup", async () => {
|
|
const events: string[] = [];
|
|
|
|
await assert.rejects(
|
|
() =>
|
|
runE2ELifecycle({
|
|
provision: async () => ({
|
|
environment: {},
|
|
destroy: async () => {
|
|
events.push("cleanup");
|
|
},
|
|
}),
|
|
prepare: async () => {
|
|
events.push("prepare");
|
|
throw new Error("prepare");
|
|
},
|
|
bootstrap: async () => undefined,
|
|
runChild: async () => {
|
|
events.push("child");
|
|
return 0;
|
|
},
|
|
}),
|
|
/prepare/
|
|
);
|
|
|
|
assert.deepEqual(events, ["prepare", "cleanup"]);
|
|
});
|
|
|
|
test("preserva el fallo de preparación y el de cleanup", async () => {
|
|
await assert.rejects(
|
|
() =>
|
|
runE2ELifecycle({
|
|
provision: async () => ({
|
|
environment: {},
|
|
destroy: async () => {
|
|
throw new Error("cleanup");
|
|
},
|
|
}),
|
|
prepare: async () => {
|
|
throw new Error("prepare");
|
|
},
|
|
bootstrap: async () => undefined,
|
|
runChild: async () => 0,
|
|
}),
|
|
(error: unknown) =>
|
|
error instanceof AggregateError &&
|
|
error.errors.some((value) => value instanceof Error && value.message === "prepare") &&
|
|
error.errors.some((value) => value instanceof Error && value.message === "cleanup")
|
|
);
|
|
});
|
|
|
|
test("un fallo de bootstrap impide el hijo y mantiene cleanup", async () => {
|
|
const events: string[] = [];
|
|
await assert.rejects(
|
|
() =>
|
|
runE2ELifecycle({
|
|
provision: async () => ({ environment: {}, destroy: async () => events.push("cleanup") }),
|
|
prepare: async () => events.push("prepare"),
|
|
bootstrap: async () => {
|
|
events.push("bootstrap");
|
|
throw new Error("bootstrap");
|
|
},
|
|
runChild: async () => {
|
|
events.push("child");
|
|
return 0;
|
|
},
|
|
}),
|
|
/bootstrap/
|
|
);
|
|
assert.deepEqual(events, ["prepare", "bootstrap", "cleanup"]);
|
|
});
|
|
|
|
test("preserva el fallo de bootstrap y el de cleanup", async () => {
|
|
await assert.rejects(
|
|
() =>
|
|
runE2ELifecycle({
|
|
provision: async () => ({
|
|
environment: {},
|
|
destroy: async () => {
|
|
throw new Error("cleanup");
|
|
},
|
|
}),
|
|
prepare: async () => undefined,
|
|
bootstrap: async () => {
|
|
throw new Error("bootstrap");
|
|
},
|
|
runChild: async () => 0,
|
|
}),
|
|
(error: unknown) =>
|
|
error instanceof AggregateError &&
|
|
error.errors.some((value) => value instanceof Error && value.message === "bootstrap") &&
|
|
error.errors.some((value) => value instanceof Error && value.message === "cleanup")
|
|
);
|
|
});
|