mods-consumers.test.ts 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
  2. import { existsSync } from "node:fs";
  3. import { tmpdir } from "node:os";
  4. import { dirname, join } from "node:path";
  5. import { describe, expect, it } from "vitest";
  6. import { compileBundle } from "@nengine/pack";
  7. import { createEditEngine } from "../src/edit-engine.js";
  8. import { runEditorPack } from "../src/pack.js";
  9. import { writeProjectYaml } from "../src/project-yaml.js";
  10. const MOD_A = [
  11. "export default {",
  12. ' manifest: { id: "a-mod", version: "1.0.0" },',
  13. " hooks: { onDayStart() {} },",
  14. "};",
  15. "",
  16. ].join("\n");
  17. const MOD_B = [
  18. "export default {",
  19. ' manifest: { id: "b-mod", version: "1.0.0" },',
  20. " hooks: { onDayStart() {} },",
  21. "};",
  22. "",
  23. ].join("\n");
  24. const FIXTURE_FILES: Record<string, string> = {
  25. "content/time.yaml": [
  26. "id: default",
  27. "dayLengthTicks: 240",
  28. "seasons:",
  29. " - { name: spring, dayCount: 14 }",
  30. "start: { day: 1, season: spring }",
  31. "",
  32. ].join("\n"),
  33. "content/maps/farm.yaml": [
  34. "id: farm",
  35. "width: 8",
  36. "height: 8",
  37. "tilesetRef: farm-tiles",
  38. "spawn: { x: 1, y: 1 }",
  39. "layers:",
  40. " - name: ground",
  41. " data:",
  42. ...mapRows(),
  43. "",
  44. ].join("\n"),
  45. "mods/a-mod/index.mjs": MOD_A,
  46. "mods/b-mod/index.mjs": MOD_B,
  47. };
  48. function mapRows(): string[] {
  49. const rows: string[] = [];
  50. for (let y = 0; y < 8; y++) {
  51. const row: string[] = [];
  52. for (let x = 0; x < 8; x++) row.push("grass");
  53. rows.push(` - [${row.join(", ")}]`);
  54. }
  55. return rows;
  56. }
  57. async function fixtureDir(): Promise<string> {
  58. const dir = await mkdtemp(join(tmpdir(), "editor-mods-consumers-"));
  59. for (const [rel, content] of Object.entries(FIXTURE_FILES)) {
  60. const target = join(dir, rel);
  61. await mkdir(dirname(target), { recursive: true });
  62. await writeFile(target, content, "utf8");
  63. }
  64. return dir;
  65. }
  66. async function rmRecursive(dir: string): Promise<void> {
  67. await rm(dir, { recursive: true, force: true });
  68. }
  69. function packOptions(): Parameters<typeof runEditorPack>[1] {
  70. return { name: "Mods Farm", icon: "", desktop: false, installer: false, mods: true, splitAssets: false, outDir: "" };
  71. }
  72. describe("F1 consumer wiring", () => {
  73. it("createEditEngine applies the enabledMods filter (undefined = all)", async () => {
  74. const dir = await fixtureDir();
  75. try {
  76. const filtered = createEditEngine(dir, ["a-mod"]);
  77. await filtered.start();
  78. try {
  79. expect(filtered.mods.map((m) => m.id)).toEqual(["a-mod"]);
  80. } finally {
  81. await filtered.stop();
  82. }
  83. const all = createEditEngine(dir);
  84. await all.start();
  85. try {
  86. expect(all.mods.map((m) => m.id).sort()).toEqual(["a-mod", "b-mod"]);
  87. } finally {
  88. await all.stop();
  89. }
  90. } finally {
  91. await rmRecursive(dir);
  92. }
  93. });
  94. it("compileBundle with an enabledMods list packages only the enabled mods", async () => {
  95. const dir = await fixtureDir();
  96. try {
  97. const filtered = await compileBundle(join(dir, "content"), join(dir, "mods"), false, ["b-mod"]);
  98. expect(Object.keys(filtered.mods ?? {})).toEqual(["b-mod"]);
  99. const all = await compileBundle(join(dir, "content"), join(dir, "mods"));
  100. expect(Object.keys(all.mods ?? {}).sort()).toEqual(["a-mod", "b-mod"]);
  101. } finally {
  102. await rmRecursive(dir);
  103. }
  104. });
  105. it("runEditorPack honors project.yaml mods.enabled (main parity)", async () => {
  106. const dir = await fixtureDir();
  107. try {
  108. await writeProjectYaml(dir, { mods: { enabled: ["a-mod"] } });
  109. const result = await runEditorPack(dir, packOptions(), existsSync(join(dir, "mods")));
  110. expect(result.ok).toBe(true);
  111. if (!result.ok) return;
  112. expect(result.stats.modCount).toBe(1);
  113. const bundle = JSON.parse(
  114. await (await import("node:fs/promises")).readFile(join(result.outDir, "bundle.json"), "utf8"),
  115. );
  116. expect(Object.keys(bundle.mods ?? {})).toEqual(["a-mod"]);
  117. } finally {
  118. await rmRecursive(dir);
  119. }
  120. });
  121. });