/
Starolat
/
DeepDive
Обзор
Документация
Войти
/
Starolat
/
DeepDive
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
tests/js-data-engine-phase4.node-test.js
357 строк
10 KB
Starolat Sergei
Фаза 6: полное удаление SQL.js и переход на JS Data Engine
28 июн 2026, 10:02
28 июн 2026, 10:02
ff2000f
Код
Авторство
О чём код?
// @ts-check /** * @fileoverview Phase 4 JS Data Engine integration tests * Run: node tests/js-data-engine-phase4.node-test.js * @version 1.0.0 * * Проверяет: * - DataService маршрутизирует getActivities/getWBS/getCodeTypes/getCodeValues * в DataServiceJsAdapter (JS Data Engine). * - DataServiceJsAdapter корректно фильтрует activities (scheduleType, weekRange, filters). * - SummaryDataService для progress/sCurve/bar-chart не использует SQL temp tables. */ import assert from "assert"; import { fileURLToPath } from "url"; import path from "path"; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); // fzstd expects global.self in Node.js if (typeof global !== "undefined") { global.self = global; } // Legacy USE_JS_DATA_ENGINE flag removed; DataService always uses JS Data Engine. if (typeof global.window === "undefined") { global.window = {}; } global.window.ENV = {}; // SummaryDataService constructor attaches document listeners. if (typeof global.document === "undefined") { global.document = { addEventListener: () => {}, removeEventListener: () => {}, dispatchEvent: () => true, }; } const { default: dataIndexer } = await import("../js/services/DataIndexer.js"); const { default: dataServiceJsAdapter } = await import("../js/services/DataServiceJsAdapter.js"); const { default: dataService } = await import("../js/services/DataService.js"); const { default: summaryDataService } = await import("../js/services/SummaryDataService.js"); let passed = 0; let failed = 0; async function test(name, fn) { try { await fn(); passed++; console.log(` ✓ ${name}`); } catch (err) { failed++; console.error(` ✗ ${name}`); console.error(` ${err.message}`); if (err.stack) { console.error( err.stack .split("\n") .slice(1, 3) .map((s) => ` ${s}`) .join("\n"), ); } } } console.log("\nJS Data Engine Phase 4 Tests\n"); // ============================================================================= // Helpers // ============================================================================= function createApiData() { return { projects: [ { projectId: 1, shortName: "TEST", name: "Test Project", startDate: "2024-01-01", endDate: "2024-12-31", status: "Active", dataDate: "2024-03-10", }, ], activities: [ { id: 1, projectId: 1, wbsId: 10, activityCode: "A001", taskName: "Activity One", taskType: "Task", duration: 10, totalFloat: 2, freeFloat: 0, startDate: "2024-03-01", endDate: "2024-03-15", }, { id: 2, projectId: 1, wbsId: 11, activityCode: "A002", taskName: "Activity Two", taskType: "Task", duration: 5, totalFloat: 0, freeFloat: 0, startDate: "2024-04-01", endDate: "2024-04-05", }, ], codeTypes: [ { typeId: 100, name: "Location", maxLength: 20, scope: "AS_Global", }, ], codeValues: [ { valueId: 1000, typeId: 100, shortName: "ZONE_A", description: "Zone A (North)", color: "#FF6B6B", sortOrder: 1, }, ], codeAssignments: [ { activityId: 1, codeTypeId: 100, codeValueId: 1000, }, ], wbs: [ { wbsId: 10, projectId: 1, parentId: null, wbsShortName: "WBS1", wbsName: "Work Package 1", seqNum: 0, }, { wbsId: 11, projectId: 1, parentId: 10, wbsShortName: "WBS1.1", wbsName: "Sub Package", seqNum: 1, }, ], resources: [ { resourceId: 100, shortName: "WORKER", name: "Worker", type: "labor", unitId: 1, isActive: "Y", }, { resourceId: 101, shortName: "CEMENT", name: "Cement", type: "material", unitId: 2, isActive: "Y", }, ], resourceAssignments: [ { assignmentId: 1000, activityId: 1, resourceId: 100, resourceType: "labor", targetUnits: 80, actualUnits: 40, remainingUnits: 40, }, { assignmentId: 1001, activityId: 2, resourceId: 100, resourceType: "labor", targetUnits: 20, actualUnits: 10, remainingUnits: 10, }, ], resourceAssignmentSpread: [ { ResourceAssignmentObjectId: 1000, Period: [ { StartDate: "2024-03-04", EndDate: "2024-03-10", ActualUnits: 20, RemainingUnits: 20, PlannedUnits: 40, }, { StartDate: "2024-03-11", EndDate: "2024-03-17", ActualUnits: 20, RemainingUnits: 20, PlannedUnits: 40, }, ], }, { ResourceAssignmentObjectId: 1001, Period: [ { StartDate: "2024-04-01", EndDate: "2024-04-07", ActualUnits: 10, RemainingUnits: 10, PlannedUnits: 20, }, ], }, ], }; } // ============================================================================= // Tests // ============================================================================= await test("DataService initializes JS Data Engine without SQL.js", async () => { await dataService.initialize({}); assert.strictEqual(dataService.isInitialized, true); }); let dbId; await test("DataIndexer builds indexes from API", async () => { dbId = await dataIndexer.buildIndexesFromAPI(createApiData(), "Phase4-Test", { scheduleType: "current", }); assert.ok(dbId, "databaseId returned"); const indexes = dataIndexer.getIndexes(dbId); assert.ok(indexes, "indexes exist"); assert.strictEqual(indexes.activitiesById.size, 2, "2 activities indexed"); }); await test("DataServiceJsAdapter.getActivities returns all activities", async () => { const activities = await dataServiceJsAdapter.getActivities(dbId, [], { scheduleType: "both", }); assert.strictEqual(activities.length, 2); assert.ok(activities.find((a) => a.activityCode === "A001")); assert.ok(activities.find((a) => a.activityCode === "A002")); }); await test("DataServiceJsAdapter.getActivities filters by scheduleType", async () => { const current = await dataServiceJsAdapter.getActivities(dbId, [], { scheduleType: "current", }); assert.strictEqual(current.length, 2); const target = await dataServiceJsAdapter.getActivities(dbId, [], { scheduleType: "target", }); assert.strictEqual(target.length, 0); }); await test("DataServiceJsAdapter.getActivities filters by weekRange", async () => { // Activity A001 has spread in weeks around 2024-03-04 and 2024-03-11. // Activity A002 has spread in week 2024-04-01. const weekIndexService = (await import("../js/services/WeekIndexService.js")) .weekIndexService; const startIdx = weekIndexService.getWeekIndex("2024-03-04"); const endIdx = weekIndexService.getWeekIndex("2024-03-17"); const activities = await dataServiceJsAdapter.getActivities(dbId, [], { scheduleType: "current", weekRange: { startIdx, endIdx }, }); assert.strictEqual(activities.length, 1); assert.strictEqual(activities[0].activityCode, "A001"); }); await test("DataServiceJsAdapter.getActivities filters by Filter[]", async () => { const activities = await dataServiceJsAdapter.getActivities(dbId, [ { field: "activityCode", condition: "equals", value: "A002" }, ]); assert.strictEqual(activities.length, 1); assert.strictEqual(activities[0].activityCode, "A002"); }); await test("DataService.getActivities routes to JS adapter", async () => { const activities = await dataService.getActivities([], dbId, { scheduleType: "current", }); assert.strictEqual(activities.length, 2); }); await test("DataService.getWBS routes to JS adapter", async () => { const wbs = await dataService.getWBS(dbId, { scheduleType: "current" }); assert.strictEqual(wbs.length, 2); assert.ok(wbs.find((w) => w.code === "WBS1")); assert.ok(wbs.find((w) => w.code === "WBS1.1")); }); await test("DataService.getCodeTypes routes to JS adapter", async () => { const types = await dataService.getCodeTypes(dbId, { scheduleType: "current", }); assert.strictEqual(types.length, 1); assert.strictEqual(types[0].name, "Location"); }); await test("DataService.getCodeValues routes to JS adapter", async () => { const values = await dataService.getCodeValues(100, dbId, { scheduleType: "current", }); assert.strictEqual(values.length, 1); assert.strictEqual(values[0].shortName, "ZONE_A"); }); await test("DataService.getMaterialResources routes to JS adapter", async () => { const resources = await dataService.getMaterialResources(dbId); assert.strictEqual(resources.length, 1); assert.strictEqual(resources[0].type, "material"); }); await test("SummaryDataService.buildWidgetData(progress) uses JS Engine", async () => { const data = await summaryDataService.buildWidgetData("progress", dbId, {}); assert.ok(data, "progress data returned"); assert.strictEqual(typeof data.totalPlan, "number"); assert.strictEqual(typeof data.totalFact, "number"); }); await test("SummaryDataService.buildWidgetData(bar-chart) uses JS Engine", async () => { const data = await summaryDataService.buildWidgetData("bar-chart", dbId, {}); assert.ok(data, "bar-chart data returned"); assert.ok(Array.isArray(data.categories)); }); await test("SummaryDataService.buildWidgetData(sCurve) uses JS Engine", async () => { const data = await summaryDataService.buildWidgetData("sCurve", dbId, {}); assert.ok(data, "sCurve data returned"); assert.ok(Array.isArray(data.baseline)); }); console.log(`\nPassed: ${passed}, Failed: ${failed}\n`); process.exit(failed > 0 ? 1 : 0);