@tui-sandbox/library 7.5.6 → 7.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tui-sandbox/library",
3
- "version": "7.5.6",
3
+ "version": "7.7.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "bin": {
@@ -8,13 +8,13 @@
8
8
  },
9
9
  "dependencies": {
10
10
  "@catppuccin/palette": "1.7.1",
11
- "@trpc/client": "11.0.0-rc.682",
12
- "@trpc/server": "11.0.0-rc.682",
11
+ "@trpc/client": "11.0.0-rc.695",
12
+ "@trpc/server": "11.0.0-rc.695",
13
13
  "@xterm/addon-attach": "0.11.0",
14
14
  "@xterm/addon-fit": "0.10.0",
15
15
  "@xterm/xterm": "5.5.0",
16
16
  "command-exists": "1.2.9",
17
- "core-js": "3.39.0",
17
+ "core-js": "3.40.0",
18
18
  "cors": "2.8.5",
19
19
  "dree": "5.1.5",
20
20
  "express": "4.21.2",
@@ -22,7 +22,7 @@
22
22
  "node-pty": "1.0.0",
23
23
  "prettier": "3.4.2",
24
24
  "tsx": "4.19.2",
25
- "type-fest": "4.31.0",
25
+ "type-fest": "4.32.0",
26
26
  "winston": "3.17.0",
27
27
  "zod": "3.24.1"
28
28
  },
@@ -31,9 +31,9 @@
31
31
  "@types/command-exists": "1.2.3",
32
32
  "@types/cors": "2.8.17",
33
33
  "@types/express": "5.0.0",
34
- "@types/node": "22.10.2",
34
+ "@types/node": "22.10.5",
35
35
  "nodemon": "3.1.9",
36
- "vite": "6.0.6",
36
+ "vite": "6.0.7",
37
37
  "vitest": "2.1.8"
38
38
  },
39
39
  "peerDependencies": {
@@ -36,6 +36,8 @@ declare global {
36
36
  }
37
37
  }
38
38
 
39
+ /** Arguments for starting the neovim server. They are built based on your test
40
+ * environment in a type safe manner. */
39
41
  type MyStartNeovimServerArguments = OverrideProperties<
40
42
  StartNeovimGenericArguments,
41
43
  {
@@ -1,15 +1,19 @@
1
1
  import { readFileSync, writeFileSync } from "fs"
2
+ import { mkdir, stat } from "fs/promises"
2
3
  import { createCypressSupportFileContents } from "./contents.js"
3
4
  import type { CreateCypressSupportFileResult } from "./createCypressSupportFile.js"
4
5
  import { createCypressSupportFile } from "./createCypressSupportFile.js"
5
6
 
6
7
  vi.mock("fs")
8
+ vi.mock("fs/promises")
7
9
  vi.mock("./contents.ts")
8
10
 
9
11
  const mocked = {
10
12
  readFileSync: vi.mocked(readFileSync),
11
13
  writeFileSync: vi.mocked(writeFileSync),
12
14
  createCypressSupportFileContents: vi.mocked(createCypressSupportFileContents),
15
+ mkdir: vi.mocked(mkdir),
16
+ stat: vi.mocked(stat),
13
17
  }
14
18
 
15
19
  describe("createCypressSupportFileContents", () => {
@@ -41,4 +45,24 @@ describe("createCypressSupportFileContents", () => {
41
45
 
42
46
  expect(result).toBe("did-nothing" satisfies CreateCypressSupportFileResult)
43
47
  })
48
+
49
+ it("should create the config-modifications directory if it does not exist", async () => {
50
+ // This directory is required to exist so that a type safe schema of the
51
+ // neovimArguments can be built and used.
52
+ mocked.readFileSync.mockImplementationOnce(() => "")
53
+ mocked.writeFileSync.mockImplementationOnce(() => {
54
+ //
55
+ })
56
+ mocked.createCypressSupportFileContents.mockImplementationOnce(async () => "contents")
57
+ mocked.stat.mockRejectedValueOnce(new Error("ENOENT"))
58
+
59
+ const result = await createCypressSupportFile({
60
+ cypressSupportDirectoryPath: "cypress/support",
61
+ supportFileName: "tui-sandbox.ts",
62
+ })
63
+
64
+ expect(result).toBe("updated" satisfies CreateCypressSupportFileResult)
65
+ expect(mocked.mkdir).toHaveBeenCalledWith("cypress/support/config-modifications")
66
+ expect(mocked.mkdir).toHaveBeenCalledTimes(1)
67
+ })
44
68
  })
@@ -1,4 +1,5 @@
1
1
  import { readFileSync, writeFileSync } from "fs"
2
+ import { mkdir, stat } from "fs/promises"
2
3
  import path from "path"
3
4
  import { createCypressSupportFileContents } from "./contents.js"
4
5
 
@@ -18,6 +19,17 @@ export async function createCypressSupportFile({
18
19
  cypressSupportDirectoryPath,
19
20
  supportFileName,
20
21
  }: CreateCypressSupportFileArgs): Promise<CreateCypressSupportFileResult> {
22
+ // create config-modifications directory if it doesn't exist
23
+ const configModificationsDirectoryPath = path.join(cypressSupportDirectoryPath, "config-modifications")
24
+ try {
25
+ await stat(configModificationsDirectoryPath)
26
+ } catch (error) {
27
+ console.log(
28
+ `Creating config-modifications directory at ${configModificationsDirectoryPath}. You can put Neovim startup scripts into this directory, and load them when starting your Neovim test.`
29
+ )
30
+ await mkdir(configModificationsDirectoryPath)
31
+ }
32
+
21
33
  const text = await createCypressSupportFileContents()
22
34
 
23
35
  let oldSchema = ""
@@ -59,6 +59,12 @@ describe("dirtree", () => {
59
59
  extension: z.literal("lua"),
60
60
  stem: z.literal("init."),
61
61
  }),
62
+ "prepare.lua": z.object({
63
+ name: z.literal("prepare.lua"),
64
+ type: z.literal("file"),
65
+ extension: z.literal("lua"),
66
+ stem: z.literal("prepare."),
67
+ }),
62
68
  }),
63
69
  }),
64
70
  }),
@@ -111,6 +117,24 @@ describe("dirtree", () => {
111
117
  extension: z.literal("txt"),
112
118
  stem: z.literal("initial-file."),
113
119
  }),
120
+ "lua-project": z.object({
121
+ name: z.literal("lua-project/"),
122
+ type: z.literal("directory"),
123
+ contents: z.object({
124
+ "config.lua": z.object({
125
+ name: z.literal("config.lua"),
126
+ type: z.literal("file"),
127
+ extension: z.literal("lua"),
128
+ stem: z.literal("config."),
129
+ }),
130
+ "init.lua": z.object({
131
+ name: z.literal("init.lua"),
132
+ type: z.literal("file"),
133
+ extension: z.literal("lua"),
134
+ stem: z.literal("init."),
135
+ }),
136
+ }),
137
+ }),
114
138
  "other-subdirectory": z.object({
115
139
  name: z.literal("other-subdirectory/"),
116
140
  type: z.literal("directory"),
@@ -176,6 +200,7 @@ describe("dirtree", () => {
176
200
  export const testDirectoryFiles = z.enum([
177
201
  ".config/.gitkeep",
178
202
  ".config/nvim/init.lua",
203
+ ".config/nvim/prepare.lua",
179
204
  ".config/nvim",
180
205
  ".config",
181
206
  "config-modifications/add_command_to_count_open_buffers.lua",
@@ -186,6 +211,9 @@ describe("dirtree", () => {
186
211
  "dir with spaces",
187
212
  "file.txt",
188
213
  "initial-file.txt",
214
+ "lua-project/config.lua",
215
+ "lua-project/init.lua",
216
+ "lua-project",
189
217
  "other-subdirectory/other-sub-file.txt",
190
218
  "other-subdirectory",
191
219
  "routes/posts.$postId/adjacent-file.txt",
@@ -1,6 +1,8 @@
1
1
  import assert from "assert"
2
2
  import { exec } from "child_process"
3
3
  import "core-js/proposals/async-explicit-resource-management.js"
4
+ import { access } from "fs/promises"
5
+ import path from "path"
4
6
  import util from "util"
5
7
  import type { BlockingCommandInput, ExCommandInput, LuaCodeInput } from "../server.js"
6
8
  import type {
@@ -15,14 +17,40 @@ import { convertEventEmitterToAsyncGenerator } from "../utilities/generator.js"
15
17
  import { Lazy } from "../utilities/Lazy.js"
16
18
  import type { TabId } from "../utilities/tabId.js"
17
19
  import { createTempDir, removeTestDirectories } from "./environment/createTempDir.js"
18
- import type { TerminalDimensions } from "./NeovimApplication.js"
20
+ import type { StdoutOrStderrMessage, TerminalDimensions } from "./NeovimApplication.js"
19
21
  import { NeovimApplication } from "./NeovimApplication.js"
20
22
 
21
23
  const neovims = new Map<TabId["tabId"], NeovimApplication>()
22
- export const resources: Lazy<AsyncDisposableStack> = new Lazy(() => {
24
+ const resources: Lazy<AsyncDisposableStack> = new Lazy(() => {
23
25
  return new AsyncDisposableStack()
24
26
  })
25
27
 
28
+ export async function installDependencies(testEnvironmentPath: string, config: DirectoriesConfig): Promise<void> {
29
+ await using app = new NeovimApplication(testEnvironmentPath)
30
+ const testDirectory = await prepareNewTestDirectory(config)
31
+ const prepareFilePath = path.join(testDirectory.rootPathAbsolute, ".config", "nvim", "prepare.lua")
32
+ try {
33
+ await access(prepareFilePath)
34
+ } catch (e) {
35
+ console.log(
36
+ `Neovim prepareFilePath does not exist: ${prepareFilePath}. If you want to run a prepare script before starting the tests, create it.`
37
+ )
38
+ return
39
+ }
40
+
41
+ console.log(`🚀 Running Neovim prepareFilePath ${prepareFilePath}...`)
42
+
43
+ app.events.on("stdout" satisfies StdoutOrStderrMessage, data => {
44
+ console.log(` neovim output: ${data}`)
45
+ })
46
+ await app.startNextAndKillCurrent(
47
+ testDirectory,
48
+ { filename: "empty.txt", headlessCmd: `lua dofile("${prepareFilePath}")` },
49
+ { cols: 80, rows: 24 }
50
+ )
51
+ await app.application.untilExit()
52
+ }
53
+
26
54
  export async function initializeStdout(
27
55
  options: { client: TabId },
28
56
  signal: AbortSignal | undefined,
@@ -106,7 +106,12 @@ export async function startTestServer(config: TestServerConfig): Promise<TestSer
106
106
  port: config.port,
107
107
  })
108
108
  const appRouter = await createAppRouter(config.directories)
109
- await testServer.startAndRun(appRouter)
109
+
110
+ await Promise.all([
111
+ // NOTE right now Neovim is always initialized
112
+ neovim.installDependencies(config.directories.testEnvironmentPath, config.directories),
113
+ testServer.startAndRun(appRouter),
114
+ ])
110
115
 
111
116
  return testServer
112
117
  }
@@ -0,0 +1,3 @@
1
+ export function timeout(ms: number): Promise<unknown> {
2
+ return new Promise((_, reject) => setTimeout(reject, ms))
3
+ }