plugin-add.test.ts 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. import { expect, spyOn, test } from "bun:test"
  2. import fs from "fs/promises"
  3. import path from "path"
  4. import { pathToFileURL } from "url"
  5. import { tmpdir } from "../../fixture/fixture"
  6. import { createTuiPluginApi } from "../../fixture/tui-plugin"
  7. import { createTuiResolvedConfig } from "../../fixture/tui-runtime"
  8. import { TuiConfig } from "../../../src/config/tui"
  9. const { TuiPluginRuntime } = await import("../../../src/plugin/tui/runtime")
  10. test("adds tui plugin at runtime from spec", async () => {
  11. await using tmp = await tmpdir({
  12. init: async (dir) => {
  13. const file = path.join(dir, "add-plugin.ts")
  14. const spec = pathToFileURL(file).href
  15. const marker = path.join(dir, "add.txt")
  16. await Bun.write(
  17. file,
  18. `export default {
  19. id: "demo.add",
  20. tui: async () => {
  21. await Bun.write(${JSON.stringify(marker)}, "called")
  22. },
  23. }
  24. `,
  25. )
  26. return { spec, marker }
  27. },
  28. })
  29. process.env.KIRINCODE_PLUGIN_META_FILE = path.join(tmp.path, "plugin-meta.json")
  30. const config = createTuiResolvedConfig({
  31. plugin: [],
  32. })
  33. const wait = spyOn(TuiConfig, "waitForDependencies").mockResolvedValue()
  34. const cwd = spyOn(process, "cwd").mockImplementation(() => tmp.path)
  35. try {
  36. await TuiPluginRuntime.init({
  37. api: createTuiPluginApi(),
  38. config,
  39. })
  40. await expect(TuiPluginRuntime.addPlugin(tmp.extra.spec)).resolves.toBe(true)
  41. await expect(fs.readFile(tmp.extra.marker, "utf8")).resolves.toBe("called")
  42. expect(TuiPluginRuntime.list().find((item) => item.id === "demo.add")).toEqual({
  43. id: "demo.add",
  44. source: "file",
  45. spec: tmp.extra.spec,
  46. target: tmp.extra.spec,
  47. enabled: true,
  48. active: true,
  49. })
  50. } finally {
  51. await TuiPluginRuntime.dispose()
  52. cwd.mockRestore()
  53. wait.mockRestore()
  54. delete process.env.KIRINCODE_PLUGIN_META_FILE
  55. }
  56. })
  57. test("retries runtime add for file plugins after dependency wait", async () => {
  58. await using tmp = await tmpdir({
  59. init: async (dir) => {
  60. const mod = path.join(dir, "retry-plugin")
  61. const spec = pathToFileURL(mod).href
  62. const marker = path.join(dir, "retry-add.txt")
  63. await fs.mkdir(mod, { recursive: true })
  64. return { mod, spec, marker }
  65. },
  66. })
  67. process.env.KIRINCODE_PLUGIN_META_FILE = path.join(tmp.path, "plugin-meta.json")
  68. const config = createTuiResolvedConfig({
  69. plugin: [],
  70. })
  71. const wait = spyOn(TuiConfig, "waitForDependencies").mockImplementation(async () => {
  72. await Bun.write(
  73. path.join(tmp.extra.mod, "index.ts"),
  74. `export default {
  75. id: "demo.add.retry",
  76. tui: async () => {
  77. await Bun.write(${JSON.stringify(tmp.extra.marker)}, "called")
  78. },
  79. }
  80. `,
  81. )
  82. })
  83. const cwd = spyOn(process, "cwd").mockImplementation(() => tmp.path)
  84. try {
  85. await TuiPluginRuntime.init({
  86. api: createTuiPluginApi(),
  87. config,
  88. })
  89. await expect(TuiPluginRuntime.addPlugin(tmp.extra.spec)).resolves.toBe(true)
  90. await expect(fs.readFile(tmp.extra.marker, "utf8")).resolves.toBe("called")
  91. expect(wait).toHaveBeenCalledTimes(1)
  92. expect(TuiPluginRuntime.list().find((item) => item.id === "demo.add.retry")?.active).toBe(true)
  93. } finally {
  94. await TuiPluginRuntime.dispose()
  95. cwd.mockRestore()
  96. wait.mockRestore()
  97. delete process.env.KIRINCODE_PLUGIN_META_FILE
  98. }
  99. })