FactuGES_ERP/apps/server/src/lib/modules/module-loader.test.ts
David d57b71c200 refactor: standardize import statements and formatting across components
- Updated import statements in `textarea.tsx`, `toggle.tsx`, and `tooltip.tsx` for consistency.
- Added missing semicolons and adjusted formatting in `use-mobile.ts` and `use-mobile.tsx`.
- Cleaned up `package.json` and `root.json` files by removing unnecessary line breaks.
- Simplified `turbo.json` by consolidating array formatting for better readability.
2026-09-10 13:26:33 +02:00

170 lines
4.1 KiB
TypeScript

import assert from "node:assert/strict";
import test from "node:test";
import {
AsyncLocalStorageOperationContextStore,
type IModuleServer,
type ModuleParams,
SequelizeTransactionContext,
} from "@erp/core/api";
import { Audit } from "@repo/rdx-audit";
import { Result } from "@repo/rdx-utils";
import { resetModelsRegistry } from "./model-loader";
import { initModules, registerModule, resetModuleRegistry, startModules } from "./module-loader";
import { listServices, resetServiceRegistry } from "./service-registry";
type FakeDatabase = {
sync: () => Promise<void>;
models: Record<string, unknown>;
};
function buildModuleParams(): ModuleParams & {
config: { database: { syncMode: string } };
database: FakeDatabase;
logger: Console;
} {
return {
getService: () => {
throw new Error("Base params getService should not be called directly in tests.");
},
config: {
database: {
syncMode: "none",
},
},
warmup: { timeoutMs: 10_000, strict: false },
databaseSyncMode: "none",
database: {
sync: async () => undefined,
models: {},
},
logger: console,
operationContext: new AsyncLocalStorageOperationContextStore(),
transactionContext: new SequelizeTransactionContext(),
audit: new Audit({
source: { type: "test", id: "module-loader" },
contextProvider: { get: () => null },
store: { append: async () => Result.ok() },
}),
};
}
function resetModuleTestState(): void {
resetServiceRegistry();
resetModuleRegistry();
resetModelsRegistry();
}
test("module-loader permite dependencias externas declaradas", async (t) => {
resetModuleTestState();
t.after(resetModuleTestState);
let receivedService = "";
const catalogsModule: IModuleServer = {
name: "catalogs",
version: "1.0.0",
setup: () => ({
services: {
general: {
name: "catalogs-service",
},
},
}),
};
const companiesModule: IModuleServer = {
name: "companies",
version: "1.0.0",
dependencies: ["catalogs"],
start: ({ getService }) => {
const service = getService<{ name: string }>("catalogs:general");
receivedService = service.name;
},
};
registerModule(catalogsModule);
registerModule(companiesModule);
await initModules(buildModuleParams());
await startModules(buildModuleParams());
assert.equal(receivedService, "catalogs-service");
assert.deepEqual(listServices().sort(), ["catalogs:general"]);
});
test("module-loader falla cuando una dependencia usada no está declarada", async (t) => {
resetModuleTestState();
t.after(resetModuleTestState);
registerModule({
name: "catalogs",
version: "1.0.0",
setup: () => ({
services: {
general: {
name: "catalogs-service",
},
},
}),
});
registerModule({
name: "companies",
version: "1.0.0",
start: ({ getService }) => {
getService("catalogs:general");
},
});
await assert.rejects(async () => {
await initModules(buildModuleParams());
await startModules(buildModuleParams());
}, /without declaring dependency on "catalogs"/i);
});
test("module-loader sigue detectando ciclos reales entre módulos", async (t) => {
resetModuleTestState();
t.after(resetModuleTestState);
registerModule({
name: "companies",
version: "1.0.0",
dependencies: ["catalogs"],
});
registerModule({
name: "catalogs",
version: "1.0.0",
dependencies: ["companies"],
});
await assert.rejects(() => initModules(buildModuleParams()), /cyclic dependency detected/i);
});
test("module-loader rechaza la autoreferencia explícita por nombre de módulo", async (t) => {
resetModuleTestState();
t.after(resetModuleTestState);
registerModule({
name: "companies",
version: "1.0.0",
setup: () => ({
services: {
general: {
name: "companies-service",
},
},
}),
start: ({ getService }) => {
getService("companies:general");
},
});
await assert.rejects(async () => {
await initModules(buildModuleParams());
await startModules(buildModuleParams());
}, /without declaring dependency on "companies"/i);
});