/**
 * Architecture Agent Test — SF-02
 *
 * 验证场景：
 * 1. 电商小程序 → 技术选型（小程序 + 支付 + 物流）
 * 2. 企业 OA → 审批/考勤架构
 * 3. 教育平台 → 课程系统架构
 * 4. 笔记应用 → 轻量架构
 * 5. 宠物管理 → 完整架构生成
 * 6. 空/invalid PRD → 错误处理
 * 7. 通用 PRD → 降级处理
 * 8. 架构图生成
 * 9. 数据库设计
 * 10. API 设计
 * 11. 目录结构
 * 12. 模块分解
 * 13. 数据流
 * 14. CLI 端到端
 * 15. 集成 SF-01
 */

import { describe, it, before } from "node:test";
import assert from "node:assert/strict";
import { resolve } from "node:path";
import { fileURLToPath } from "node:url";
import { existsSync, rmSync, readFileSync } from "node:fs";

const __dirname = resolve(fileURLToPath(new URL(".", import.meta.url)));
const WORKSPACE = resolve(__dirname, "..");
const FIXTURES_DIR = resolve(WORKSPACE, "test/fixtures/architecture-agent");

const ECO_PRJ = resolve(FIXTURES_DIR, "ecommerce-prd.json");
const ENT_PRJ = resolve(FIXTURES_DIR, "enterprise-prd.json");
const EDU_PRJ = resolve(FIXTURES_DIR, "education-prd.json");
const NOTE_PRJ = resolve(FIXTURES_DIR, "note-prd.json");
const EMPTY_PRJ = resolve(FIXTURES_DIR, "empty-prd.json");
const GENERIC_PRJ = resolve(FIXTURES_DIR, "generic-prd.json");

let generateArchitecture, resolveTechStack, generateArchDiagram;
let generateDataFlows, decomposeModules, generateDatabaseSchema;
let designAPI, generateDirectoryStructure;
let loadPRD, writeArchitecture;

before(async () => {
  const mod = await import("../scripts/architecture-agent.mjs");
  generateArchitecture = mod.generateArchitecture;
  resolveTechStack = mod.resolveTechStack;
  generateArchDiagram = mod.generateArchDiagram;
  generateDataFlows = mod.generateDataFlows;
  decomposeModules = mod.decomposeModules;
  generateDatabaseSchema = mod.generateDatabaseSchema;
  designAPI = mod.designAPI;
  generateDirectoryStructure = mod.generateDirectoryStructure;
  loadPRD = mod.loadPRD;
  writeArchitecture = mod.writeArchitecture;
});

// ═══════════════════════════════════════════════════════
// 1 — 电商小程序架构
// ═══════════════════════════════════════════════════════
describe("1 — 电商小程序架构", () => {
  it("技术选型为小程序栈", () => {
    const { data } = loadPRD(ECO_PRJ);
    const arch = generateArchitecture(data);

    assert.ok(arch.techStack.frontend.includes("uni-app") || arch.techStack.frontend.includes("小程序"));
    assert.ok(arch.techStack.considerations.some(c => c.includes("支付")));
    assert.ok(arch.techStack.considerations.some(c => c.includes("物流")));
  });

  it("包含订单和物流表", () => {
    const { data } = loadPRD(ECO_PRJ);
    const arch = generateArchitecture(data);

    const tableNames = arch.databaseSchema.map(t => t.table);
    assert.ok(tableNames.includes("orders"));
    assert.ok(tableNames.includes("logistics"));
    assert.ok(tableNames.includes("products"));
    assert.ok(tableNames.includes("users"));
  });

  it("订单表有明细关联", () => {
    const { data } = loadPRD(ECO_PRJ);
    const arch = generateArchitecture(data);

    const orderItems = arch.databaseSchema.find(t => t.table === "order_items");
    assert.ok(orderItems);
    assert.ok(orderItems.fields.some(f => f.name === "order_id"));
    assert.ok(orderItems.fields.some(f => f.name === "product_id"));
  });

  it("API 按资源分组", () => {
    const { data } = loadPRD(ECO_PRJ);
    const arch = generateArchitecture(data);

    const resources = arch.apiDesign.map(g => g.resource);
    assert.ok(resources.includes("products"));
    assert.ok(resources.includes("orders"));
  });
});

// ═══════════════════════════════════════════════════════
// 2 — 企业 OA 架构
// ═══════════════════════════════════════════════════════
describe("2 — 企业 OA 架构", () => {
  it("包含审批流核心表", () => {
    const { data } = loadPRD(ENT_PRJ);
    const arch = generateArchitecture(data);

    const tableNames = arch.databaseSchema.map(t => t.table);
    assert.ok(tableNames.includes("approvals"));
    assert.ok(tableNames.includes("approval_steps"));
    assert.ok(tableNames.includes("attendance"));
    assert.ok(tableNames.includes("departments"));
  });

  it("审批步骤有步骤序号", () => {
    const { data } = loadPRD(ENT_PRJ);
    const arch = generateArchitecture(data);

    const steps = arch.databaseSchema.find(t => t.table === "approval_steps");
    assert.ok(steps.fields.some(f => f.name === "step_order"));
    assert.ok(steps.fields.some(f => f.name === "status"));
    assert.ok(steps.fields.some(f => f.name === "approver_id"));
  });

  it("模块包含审批和考勤", () => {
    const { data } = loadPRD(ENT_PRJ);
    const arch = generateArchitecture(data);

    const modNames = arch.modules.map(m => m.name);
    assert.ok(modNames.some(n => n.includes("approval")));
    assert.ok(modNames.some(n => n.includes("attendance")));
  });

  it("部门表支持自引用", () => {
    const { data } = loadPRD(ENT_PRJ);
    const arch = generateArchitecture(data);

    const dept = arch.databaseSchema.find(t => t.table === "departments");
    const parentField = dept.fields.find(f => f.name === "parent_id");
    assert.ok(parentField.constraints.includes("自引用") || parentField.constraints.includes("departments.id"));
  });
});

// ═══════════════════════════════════════════════════════
// 3 — 教育平台架构
// ═══════════════════════════════════════════════════════
describe("3 — 教育平台架构", () => {
  it("包含课程和学习进度表", () => {
    const { data } = loadPRD(EDU_PRJ);
    const arch = generateArchitecture(data);

    const tableNames = arch.databaseSchema.map(t => t.table);
    assert.ok(tableNames.includes("courses"));
    assert.ok(tableNames.includes("lessons"));
    assert.ok(tableNames.includes("exercises"));
    assert.ok(tableNames.includes("user_progress"));
  });

  it("课时表有排序字段", () => {
    const { data } = loadPRD(EDU_PRJ);
    const arch = generateArchitecture(data);

    const lessons = arch.databaseSchema.find(t => t.table === "lessons");
    assert.ok(lessons.fields.some(f => f.name === "sort_order"));
    assert.ok(lessons.fields.some(f => f.name === "video_url"));
  });

  it("API 包含 courses 和 progress", () => {
    const { data } = loadPRD(EDU_PRJ);
    const arch = generateArchitecture(data);

    const resources = arch.apiDesign.map(g => g.resource);
    assert.ok(resources.includes("courses"));
    assert.ok(resources.includes("progress"));
  });
});

// ═══════════════════════════════════════════════════════
// 4 — 笔记应用架构
// ═══════════════════════════════════════════════════════
describe("4 — 笔记应用架构", () => {
  it("包含全文搜索索引", () => {
    const { data } = loadPRD(NOTE_PRJ);
    const arch = generateArchitecture(data);

    const notes = arch.databaseSchema.find(t => t.table === "notes");
    const ftsIdx = notes.indexes?.find(i => i.includes("fts") || i.includes("GIN"));
    assert.ok(ftsIdx, `Expected FTS index, got: ${JSON.stringify(notes.indexes)}`);
  });

  it("标签多对多关联", () => {
    const { data } = loadPRD(NOTE_PRJ);
    const arch = generateArchitecture(data);

    assert.ok(arch.databaseSchema.some(t => t.table === "tags"));
    assert.ok(arch.databaseSchema.some(t => t.table === "note_tags"));
  });

  it("笔记表支持 Markdown", () => {
    const { data } = loadPRD(NOTE_PRJ);
    const arch = generateArchitecture(data);

    const notes = arch.databaseSchema.find(t => t.table === "notes");
    assert.ok(notes.fields.some(f => f.name === "is_markdown"));
  });
});

// ═══════════════════════════════════════════════════════
// 5 — 完整架构输出
// ═══════════════════════════════════════════════════════
describe("5 — 完整架构输出结构", () => {
  it("架构包含所有必需字段", () => {
    const { data } = loadPRD(ECO_PRJ);
    const arch = generateArchitecture(data);

    const required = [
      "projectName", "domain", "techStack", "architectureDiagram",
      "dataFlows", "modules", "databaseSchema", "apiDesign",
      "directoryStructure", "deployment", "meta",
    ];
    for (const field of required) {
      assert.ok(arch[field] !== undefined, `Missing: ${field}`);
    }
  });

  it("techStack 包含四层", () => {
    const { data } = loadPRD(ECO_PRJ);
    const arch = generateArchitecture(data);

    assert.ok(arch.techStack.frontend);
    assert.ok(arch.techStack.backend);
    assert.ok(arch.techStack.database);
    assert.ok(arch.techStack.deployment);
  });

  it("deployment 包含环境和 CI", () => {
    const { data } = loadPRD(ECO_PRJ);
    const arch = generateArchitecture(data);

    assert.ok(arch.deployment.environments.includes("production"));
    assert.ok(arch.deployment.strategy);
    assert.ok(arch.deployment.ci.includes("GitHub Actions") || arch.deployment.ci.includes("CI"));
  });

  it("meta 包含统计信息", () => {
    const { data } = loadPRD(ECO_PRJ);
    const arch = generateArchitecture(data);

    assert.ok(arch.meta.generatedAt);
    assert.ok(typeof arch.meta.moduleCount === "number");
    assert.ok(typeof arch.meta.tableCount === "number");
    assert.ok(typeof arch.meta.apiEndpointCount === "number");
  });
});

// ═══════════════════════════════════════════════════════
// 6 — 错误处理
// ═══════════════════════════════════════════════════════
describe("6 — 错误处理", () => {
  it("空的 error PRD 返回错误", () => {
    const { data } = loadPRD(EMPTY_PRJ);
    const arch = generateArchitecture(data);

    assert.equal(arch.error, "INVALID_PRD");
    assert.ok(arch.message);
  });

  it("null 输入返回错误", () => {
    const arch = generateArchitecture(null);
    assert.equal(arch.error, "INVALID_PRD");
  });

  it("缺少 projectName 返回错误", () => {
    const arch = generateArchitecture({ features: [] });
    assert.equal(arch.error, "INCOMPLETE_PRD");
  });

  it("缺少 features 返回错误", () => {
    const arch = generateArchitecture({ projectName: "test" });
    assert.equal(arch.error, "INCOMPLETE_PRD");
  });
});

// ═══════════════════════════════════════════════════════
// 7 — 通用 PRD 降级
// ═══════════════════════════════════════════════════════
describe("7 — 通用 PRD 降级", () => {
  it("generic domain 生成合理的架构", () => {
    const { data } = loadPRD(GENERIC_PRJ);
    const arch = generateArchitecture(data);

    assert.equal(arch.domain, "generic");
    assert.ok(arch.techStack.frontend);
    assert.ok(arch.techStack.backend);
    assert.ok(arch.databaseSchema.length >= 1);
    assert.ok(arch.modules.length >= 1);
  });

  it("通用 PRD 有最小表结构", () => {
    const { data } = loadPRD(GENERIC_PRJ);
    const arch = generateArchitecture(data);

    assert.ok(arch.databaseSchema.some(t => t.table === "users"));
    assert.ok(arch.databaseSchema.some(t => t.table === "items"));
  });
});

// ═══════════════════════════════════════════════════════
// 8 — 架构图生成
// ═══════════════════════════════════════════════════════
describe("8 — 架构图生成", () => {
  it("架构图包含项目名", () => {
    const diagram = generateArchDiagram(
      "PetCare",
      { frontend: "React Native", backend: "NestJS", database: "PostgreSQL", deployment: "Docker" },
      ["宠物管理", "健康日程", "用户中心"]
    );

    assert.ok(diagram.includes("PetCare"));
    assert.ok(diagram.includes("System Architecture"));
  });

  it("架构图包含模块列表", () => {
    const diagram = generateArchDiagram(
      "TestApp", { frontend: "React", backend: "Node", database: "PG" },
      ["Auth", "API", "Dashboard"]
    );

    assert.ok(diagram.includes("Auth"));
    assert.ok(diagram.includes("API"));
    assert.ok(diagram.includes("Dashboard"));
  });

  it("架构图是 ASCII 格式", () => {
    const diagram = generateArchDiagram("X", {}, []);
    assert.ok(diagram.includes("┌"));
    assert.ok(diagram.includes("└"));
    assert.ok(diagram.includes("│"));
  });
});

// ═══════════════════════════════════════════════════════
// 9 — 数据库设计
// ═══════════════════════════════════════════════════════
describe("9 — 数据库设计", () => {
  it("所有表都有 fields 数组", () => {
    const domains = ["pet", "ecommerce", "education", "enterprise", "fitness", "note", "generic"];
    for (const domain of domains) {
      const tables = generateDatabaseSchema(
        [{ name: "测试功能", description: "测试", priority: "P0" }],
        [{ method: "GET", path: "/api/test", description: "test" }],
        domain
      );
      for (const table of tables) {
        assert.ok(table.table, `${domain}: table has name`);
        assert.ok(Array.isArray(table.fields), `${domain}.${table.table}: fields is array`);
        assert.ok(table.fields.length > 0, `${domain}.${table.table}: fields not empty`);
      }
    }
  });

  it("所有域都有 users 表", () => {
    const domains = ["pet", "ecommerce", "education", "enterprise"];
    for (const domain of domains) {
      const tables = generateDatabaseSchema([], [], domain);
      assert.ok(tables.some(t => t.table === "users"), `${domain}: missing users table`);
    }
  });

  it("表字段包含类型和约束", () => {
    const tables = generateDatabaseSchema(
      [{ name: "测试", description: "", priority: "P0" }],
      [{ method: "GET", path: "/api/test", description: "" }],
      "pet"
    );
    for (const table of tables) {
      for (const field of table.fields) {
        assert.ok(field.name);
        assert.ok(field.type);
        // constraints may be null/empty for some fields
      }
    }
  });
});

// ═══════════════════════════════════════════════════════
// 10 — API 设计
// ═══════════════════════════════════════════════════════
describe("10 — API 设计", () => {
  it("按资源分组 API", () => {
    const apis = [
      { method: "GET", path: "/api/pets", description: "列表" },
      { method: "POST", path: "/api/pets", description: "创建" },
      { method: "GET", path: "/api/schedules", description: "日程" },
    ];
    const design = designAPI(apis);

    assert.equal(design.length, 2);
    const resources = design.map(g => g.resource);
    assert.ok(resources.includes("pets"));
    assert.ok(resources.includes("schedules"));
  });

  it("每个资源组有 basePath", () => {
    const apis = [{ method: "GET", path: "/api/orders", description: "订单" }];
    const design = designAPI(apis);

    assert.equal(design[0].basePath, "/api/orders");
    assert.equal(design[0].endpoints.length, 1);
  });

  it("endpoint 包含 method 和 path", () => {
    const apis = [
      { method: "POST", path: "/api/pets", description: "创建宠物" },
      { method: "GET", path: "/api/pets/:id", description: "获取宠物" },
    ];
    const design = designAPI(apis);

    const group = design.find(g => g.resource === "pets");
    assert.equal(group.endpoints.length, 2);
    assert.ok(group.endpoints.some(e => e.method === "POST"));
    assert.ok(group.endpoints.some(e => e.path.includes(":id")));
  });
});

// ═══════════════════════════════════════════════════════
// 11 — 目录结构
// ═══════════════════════════════════════════════════════
describe("11 — 目录结构生成", () => {
  it("包含 apps 和 server 目录", () => {
    const dirs = generateDirectoryStructure("PetCare", "pet", [
      { name: "pet", label: "宠物管理", features: ["宠物档案"] },
    ]);

    const text = dirs.join("\n");
    assert.ok(text.includes("apps/"));
    assert.ok(text.includes("server/"));
  });

  it("包含 docker-compose 和 CI 配置", () => {
    const dirs = generateDirectoryStructure("TestApp", "generic", []);
    const text = dirs.join("\n");

    assert.ok(text.includes("docker-compose.yml"));
    assert.ok(text.includes(".github/workflows"));
    assert.ok(text.includes("ci.yml"));
  });

  it("模块目录包含 controller/service/module", () => {
    const dirs = generateDirectoryStructure("PetCare", "pet", [
      { name: "pets", label: "宠物管理", features: [] },
    ]);
    const text = dirs.join("\n");

    assert.ok(text.includes("pets.controller.ts"));
    assert.ok(text.includes("pets.service.ts"));
    assert.ok(text.includes("pets.module.ts"));
  });

  it("包含 Prisma schema", () => {
    const dirs = generateDirectoryStructure("App", "generic", []);
    const text = dirs.join("\n");

    assert.ok(text.includes("schema.prisma"));
  });
});

// ═══════════════════════════════════════════════════════
// 12 — 模块分解
// ═══════════════════════════════════════════════════════
describe("12 — 模块分解", () => {
  it("按关键词分组合并功能", () => {
    const features = [
      { name: "用户管理", description: "", priority: "P0" },
      { name: "权限控制", description: "", priority: "P0" },
      { name: "设置中心", description: "", priority: "P1" },
    ];
    const modules = decomposeModules(features, "generic");

    // "用户管理" → auth, "权限控制" → auth (matches "权限"), "设置中心" → settings (matches "设置")
    assert.ok(modules.some(m => m.name === "auth"));
    assert.ok(modules.some(m => m.name === "settings"));
  });

  it("未知功能各自独立模块", () => {
    const features = [
      { name: "量子计算", description: "", priority: "P0" },
    ];
    const modules = decomposeModules(features, "generic");

    assert.ok(modules.some(m => m.name === "量子计算"));
  });

  it("电商域添加订单和商品模块", () => {
    const features = [{ name: "商品浏览", description: "", priority: "P0" }];
    const modules = decomposeModules(features, "ecommerce");

    const names = modules.map(m => m.name);
    assert.ok(names.includes("product"));
    assert.ok(names.includes("order"));
  });

  it("企业域添加审批/考勤/部门模块", () => {
    const features = [
      { name: "审批流程", description: "", priority: "P0" },
      { name: "考勤打卡", description: "", priority: "P0" },
      { name: "部门管理", description: "", priority: "P0" },
    ];
    const modules = decomposeModules(features, "enterprise");

    const names = modules.map(m => m.name);
    assert.ok(names.includes("approval"));
    assert.ok(names.includes("attendance"));
    assert.ok(names.includes("department"));
  });

  it("每个模块有 responsibilities", () => {
    const { data } = loadPRD(ECO_PRJ);
    const arch = generateArchitecture(data);

    for (const mod of arch.modules) {
      assert.ok(mod.name);
      assert.ok(mod.label);
      assert.ok(Array.isArray(mod.features));
      assert.ok(Array.isArray(mod.responsibilities));
      assert.ok(mod.responsibilities.length > 0);
    }
  });
});

// ═══════════════════════════════════════════════════════
// 13 — 数据流
// ═══════════════════════════════════════════════════════
describe("13 — 数据流生成", () => {
  it("为页面生成数据流", () => {
    const { data } = loadPRD(ECO_PRJ);
    const flows = generateDataFlows(data.pages, data.apiRequirements);

    assert.ok(flows.length > 0);
    for (const flow of flows) {
      assert.ok(flow.page);
      assert.ok(flow.route);
      assert.ok(flow.description);
      assert.ok(Array.isArray(flow.dataFlow));
      assert.ok(flow.direction.includes("Database"));
    }
  });

  it("API 为空时回退到通用数据流", () => {
    const flows = generateDataFlows(
      [{ name: "首页", route: "/home", description: "首页" }],
      [{ method: "GET", path: "/api/health", description: "健康检查" }]
    );

    assert.ok(flows.length > 0);
  });
});

// ═══════════════════════════════════════════════════════
// 14 — CLI 端到端
// ═══════════════════════════════════════════════════════
describe("14 — CLI 端到端", () => {
  it("--input 模式生成架构", async () => {
    const { execSync } = await import("node:child_process");
    const result = execSync(
      `node scripts/architecture-agent.mjs --input test/fixtures/architecture-agent/ecommerce-prd.json --pretty`,
      { cwd: WORKSPACE, encoding: "utf-8" }
    );
    const parsed = JSON.parse(result);
    assert.equal(parsed.projectName, "ShopApp");
    assert.equal(parsed.domain, "ecommerce");
    assert.ok(parsed.techStack.frontend.includes("uni-app") || parsed.techStack.frontend.includes("小程序"));
  });

  it("--input-text 模式自动调 SF-01", async () => {
    const { execSync } = await import("node:child_process");
    const result = execSync(
      `node scripts/architecture-agent.mjs --input-text "做一个在线教育平台" --pretty`,
      { cwd: WORKSPACE, encoding: "utf-8" }
    );
    const parsed = JSON.parse(result);
    assert.equal(parsed.projectName, "EduPlatform");
    assert.equal(parsed.domain, "education");
  });

  it("--help 显示帮助", async () => {
    const { execSync } = await import("node:child_process");
    const result = execSync(
      `node scripts/architecture-agent.mjs --help`,
      { cwd: WORKSPACE, encoding: "utf-8" }
    );
    assert.ok(result.includes("Usage"));
    assert.ok(result.includes("architecture-agent"));
  });

  it("--output 写入文件", async () => {
    const { execSync } = await import("node:child_process");
    const tmpPath = resolve(WORKSPACE, ".tmp-arch-e2e.json");
    execSync(
      `node scripts/architecture-agent.mjs --input test/fixtures/architecture-agent/note-prd.json --output ${tmpPath} --pretty`,
      { cwd: WORKSPACE, encoding: "utf-8" }
    );
    assert.ok(existsSync(tmpPath));

    const content = JSON.parse(readFileSync(tmpPath, "utf-8"));
    assert.equal(content.projectName, "NoteApp");
    assert.ok(content.architectureDiagram.includes("NoteApp"));

    rmSync(tmpPath);
  });

  it("invalid PRD 返回非零退出码", async () => {
    const { execSync } = await import("node:child_process");
    try {
      execSync(
        `node scripts/architecture-agent.mjs --input test/fixtures/architecture-agent/empty-prd.json`,
        { cwd: WORKSPACE, encoding: "utf-8" }
      );
      assert.fail("Should have thrown");
    } catch (e) {
      assert.ok(e.status !== 0);
    }
  });
});

// ═══════════════════════════════════════════════════════
// 15 — 技术栈解析
// ═══════════════════════════════════════════════════════
describe("15 — 技术栈解析", () => {
  it("wechat-miniapp 平台使用微信栈", () => {
    const prd = {
      techConstraints: { platforms: ["wechat-miniapp"], considerations: [] },
      extraFeatures: [],
    };
    const stack = resolveTechStack(prd);
    assert.ok(stack.frontend.includes("微信"));
  });

  it("iOS 平台推荐 SwiftUI", () => {
    const prd = {
      techConstraints: { platforms: ["ios"], considerations: [] },
      extraFeatures: [],
    };
    const stack = resolveTechStack(prd);
    assert.ok(stack.frontend.includes("SwiftUI"));
  });

  it("mobile+web 推荐跨平台框架", () => {
    const prd = {
      techConstraints: { platforms: ["mobile", "web"], considerations: [] },
      extraFeatures: [],
    };
    const stack = resolveTechStack(prd);
    assert.ok(
      stack.frontend.includes("React Native") ||
      stack.frontend.includes("Flutter")
    );
  });

  it("实时特性添加 WebSocket", () => {
    const prd = {
      techConstraints: { platforms: ["web"], considerations: [] },
      extraFeatures: ["real-time"],
    };
    const stack = resolveTechStack(prd);
    assert.ok(stack.backend.includes("WebSocket") || stack.backend.includes("Socket.io"));
  });

  it("AI 特性添加 AI 服务", () => {
    const prd = {
      techConstraints: { platforms: ["web"], considerations: [] },
      extraFeatures: ["ai-powered"],
    };
    const stack = resolveTechStack(prd);
    assert.ok(stack.backend.includes("AI"));
  });
});

// ═══════════════════════════════════════════════════════
// 16 — File I/O
// ═══════════════════════════════════════════════════════
describe("16 — File I/O", () => {
  it("loadPRD 读取文件", () => {
    const { data } = loadPRD(ECO_PRJ);
    assert.ok(data.projectName);
  });

  it("loadPRD 对不存在文件返回 error", () => {
    const { data, error } = loadPRD("/nonexistent.json");
    assert.equal(data, null);
    assert.ok(error);
  });

  it("writeArchitecture 写入文件", () => {
    const arch = generateArchitecture(JSON.parse(readFileSync(ECO_PRJ, "utf-8")));
    const tmpPath = resolve(WORKSPACE, ".tmp-arch-write-test.json");
    writeArchitecture(arch, tmpPath, true);
    assert.ok(existsSync(tmpPath));
    rmSync(tmpPath);
  });
});
