- Introduced `.prettierrc.json` to enforce consistent code formatting across the project. - Updated unit and e2e test files to address formatting issues, improve readability, and ensure alignment with the new Prettier configuration.
165 lines
5.9 KiB
JavaScript
165 lines
5.9 KiB
JavaScript
import { readFileSync } from "node:fs";
|
|
import { join } from "node:path";
|
|
import { describe, expect, it } from "vitest";
|
|
|
|
const root = process.cwd();
|
|
|
|
const normalizeSource = (source) => source.replace(/\r\n/g, "\n");
|
|
const readSource = (relativePath) => normalizeSource(readFileSync(join(root, relativePath), "utf8"));
|
|
|
|
const sessionUserSource = readSource("src/components/session/token/SessionUser.vue");
|
|
const superUserObjectSource = readSource("src/components/session/token/superUserObject.vue");
|
|
|
|
const extractBlock = (source, startToken, endToken) => {
|
|
const startIndex = source.indexOf(startToken);
|
|
if (startIndex === -1) {
|
|
throw new Error(`Unable to find start token: ${startToken}`);
|
|
}
|
|
|
|
const contentStartIndex = startIndex + startToken.length;
|
|
const endIndex = source.indexOf(endToken, contentStartIndex);
|
|
if (endIndex === -1) {
|
|
throw new Error(`Unable to find end token: ${endToken}`);
|
|
}
|
|
|
|
return source.slice(contentStartIndex, endIndex);
|
|
};
|
|
|
|
const parseDirectBindings = (sourceBlock) => {
|
|
const bindings = new Map();
|
|
const pattern = /^\s*([A-Za-z0-9_]+)\s*:\s*([A-Za-z0-9_]+)\s*,\s*$/gm;
|
|
|
|
for (const match of sourceBlock.matchAll(pattern)) {
|
|
bindings.set(match[1], match[2]);
|
|
}
|
|
|
|
return bindings;
|
|
};
|
|
|
|
const parseGetterBindings = (sourceBlock) => {
|
|
const bindings = new Map();
|
|
const pattern = /^\s*get\s+([A-Za-z0-9_]+)\s*\(\)\s*{\s*return\s+([A-Za-z0-9_]+);\s*},?\s*$/gm;
|
|
|
|
for (const match of sourceBlock.matchAll(pattern)) {
|
|
bindings.set(match[1], match[2]);
|
|
}
|
|
|
|
return bindings;
|
|
};
|
|
|
|
const expectedSessionObjectBindings = {
|
|
categories: "Categories",
|
|
products: "Products",
|
|
product_options: "ProductOptions",
|
|
departments: "Departments",
|
|
department_categories: "DepartmentCategories",
|
|
economic_departments: "EconomicDepartments",
|
|
economic_products: "EconomicProducts",
|
|
roles: "Roles",
|
|
permissions: "Permissions",
|
|
collectedOrderInvoices: "CollectedOrderInvoices",
|
|
department_daily_reports: "DepartmentDailyReports",
|
|
goals: "Goals",
|
|
notifications: "Notifications",
|
|
orders: "Orders",
|
|
forms: "Forms",
|
|
bookings: "Bookings",
|
|
Branding: "Branding",
|
|
vehicles: "Vehicles",
|
|
department_notification_sms: "DepartmentNotificationSms",
|
|
department_time_bookings_opening_hours: "DepartmentTimeBookingsOpeningHours",
|
|
department_time_bookings_types: "DepartmentTimeBookingsTypes",
|
|
department_time_bookings_entries: "DepartmentTimeBookingsEntries",
|
|
department_variables: "DepartmentVariables",
|
|
xlvask_vehicle_types: "XLVaskVehicleTypes",
|
|
openai: "OpenAI",
|
|
department_lanes: "DepartmentLanes",
|
|
department_gates: "DepartmentGates",
|
|
department_relays: "DepartmentRelays",
|
|
order_bookings: "OrderBookings",
|
|
module_action_logs: "ModuleActionLogs",
|
|
self_serve_questions: "SelfServeQuestions",
|
|
self_serve_tasks: "SelfServeTasks",
|
|
self_serve_conditions: "SelfServeConditions",
|
|
self_serve_vehicle_conditions: "SelfServeVehicleConditions",
|
|
self_serve_condition_rules: "SelfServeConditionRules",
|
|
self_serve_machine_types: "SelfServeMachineTypes",
|
|
subuser_grants: "SubuserGrants",
|
|
global: "ObjectsGlobal",
|
|
};
|
|
|
|
const expectedSuperUserModuleBindings = {
|
|
economic: "Economic",
|
|
reCAPTCHA: "reCAPTCHA",
|
|
email: "Email",
|
|
backups: "Backups",
|
|
motorapi: "MotorAPI",
|
|
stripe: "Stripe",
|
|
fxratesapi: "FXRatesAPI",
|
|
weatherapi: "WeatherAPI",
|
|
gatewayapi: "GatewayAPI",
|
|
xlvask: "XLVask",
|
|
entra: "Entra",
|
|
limble: "Limble",
|
|
ocrspace: "OcrSpace",
|
|
openai: "OpenAI",
|
|
licenseplaterecognizer: "LicensePlateRecognizer",
|
|
virkdata: "VirkData",
|
|
shelly: "Shelly",
|
|
selfserve: "SelfServe",
|
|
bird: "Bird",
|
|
};
|
|
|
|
const superUserModulesBlock = extractBlock(superUserObjectSource, "modules: {", "\n },\n /** Intimidate a user */");
|
|
const superUserSystemBlock = extractBlock(superUserObjectSource, "system: {", "\n },\n modules: {");
|
|
|
|
const sessionObjectsContentBlock = extractBlock(
|
|
sessionUserSource,
|
|
"objects: {",
|
|
"\n },\n /** The user's token and authentication status */"
|
|
);
|
|
|
|
describe("session token initialization regression contract", () => {
|
|
it("keeps department id lookup decoupled from router module initialization", () => {
|
|
expect(sessionUserSource).not.toContain('import router from "@/router.js";');
|
|
expect(sessionUserSource).not.toContain("router.currentRoute.value.params.departmentId");
|
|
expect(sessionUserSource).toContain("const path = window.location.pathname || '';");
|
|
expect(sessionUserSource).toContain("const match = path.match(/^\\/admin\\/(\\d+)(?:\\/|$)/);");
|
|
expect(sessionUserSource).toContain("const departmentId = Number.parseInt(match[1], 10);");
|
|
expect(sessionUserSource).toContain(
|
|
"return Number.isInteger(departmentId) && departmentId > 0 ? departmentId : undefined;"
|
|
);
|
|
});
|
|
|
|
it("keeps SessionUser.objects eagerly bound for all shared object modules", () => {
|
|
const directBindings = parseDirectBindings(sessionObjectsContentBlock);
|
|
const getterBindings = parseGetterBindings(sessionObjectsContentBlock);
|
|
|
|
expect(getterBindings.size).toBe(0);
|
|
|
|
for (const [key, expectedBinding] of Object.entries(expectedSessionObjectBindings)) {
|
|
expect(directBindings.get(key)).toBe(expectedBinding);
|
|
}
|
|
});
|
|
});
|
|
|
|
describe("superuser module initialization regression contract", () => {
|
|
it("keeps superuser system binding lazy to avoid circular-import TDZ errors", () => {
|
|
const systemBindings = parseGetterBindings(superUserSystemBlock);
|
|
expect(systemBindings.get("database")).toBe("DatabaseSystemObject");
|
|
});
|
|
|
|
it("keeps all superuser module bindings lazy at object construction time", () => {
|
|
const moduleGetterBindings = parseGetterBindings(superUserModulesBlock);
|
|
const moduleDirectBindings = parseDirectBindings(superUserModulesBlock);
|
|
|
|
expect(moduleDirectBindings.size).toBe(0);
|
|
|
|
for (const [key, expectedBinding] of Object.entries(expectedSuperUserModuleBindings)) {
|
|
expect(moduleGetterBindings.get(key)).toBe(expectedBinding);
|
|
}
|
|
|
|
expect(superUserObjectSource).toContain("get cron() { return Cron; }");
|
|
});
|
|
});
|