@tui-sandbox/library 5.1.2 → 6.0.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": "5.1.2",
3
+ "version": "6.0.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "bin": {
@@ -8,8 +8,8 @@
8
8
  },
9
9
  "dependencies": {
10
10
  "@catppuccin/palette": "1.7.1",
11
- "@trpc/client": "11.0.0-rc.633",
12
- "@trpc/server": "11.0.0-rc.633",
11
+ "@trpc/client": "11.0.0-rc.638",
12
+ "@trpc/server": "11.0.0-rc.638",
13
13
  "@xterm/addon-attach": "0.11.0",
14
14
  "@xterm/addon-fit": "0.10.0",
15
15
  "@xterm/xterm": "5.5.0",
@@ -22,7 +22,7 @@
22
22
  "node-pty": "1.0.0",
23
23
  "prettier": "3.3.3",
24
24
  "tsx": "4.19.2",
25
- "type-fest": "4.26.1",
25
+ "type-fest": "4.27.0",
26
26
  "winston": "3.17.0",
27
27
  "zod": "3.23.8"
28
28
  },
@@ -36,6 +36,10 @@
36
36
  "vite": "5.4.11",
37
37
  "vitest": "2.1.5"
38
38
  },
39
+ "peerDependencies": {
40
+ "cypress": "^13",
41
+ "type-fest": "4.27.0"
42
+ },
39
43
  "scripts": {
40
44
  "build": "concurrently --names 'vite,tsc' 'vite build' 'tsc' --prefix-colors blue,green",
41
45
  "dev": "concurrently --names 'client,server' 'pnpm dev:client' 'pnpm dev:server' --prefix-colors blue,green",
@@ -1,6 +1,8 @@
1
1
  import { stat } from "node:fs/promises"
2
2
  import path from "node:path"
3
- import { startTestServer } from "../server/index.js"
3
+ import { createCypressSupportFile } from "../server/cypress-support/createCypressSupportFile.js"
4
+ import type { TestServerConfig } from "../server/index.js"
5
+ import { startTestServer, updateTestdirectorySchemaFile } from "../server/index.js"
4
6
 
5
7
  //
6
8
  // This is the main entrypoint to tui-sandbox
@@ -12,18 +14,25 @@ const args = process.argv.slice(2)
12
14
  if (args[0] !== "start") {
13
15
  throw new Error(`Usage: tui start`)
14
16
  }
17
+ const outputFileName = "MyTestDirectory.ts"
15
18
 
16
19
  /** The cwd in the user's directory when they are running this script. Not the
17
20
  * cwd of the script itself. */
18
21
  const cwd = process.cwd()
19
- console.log(`🚀 Starting test server in ${cwd}`)
20
- await stat(path.join(cwd, "MyTestDirectory.ts"))
22
+ console.log(`🚀 Starting test server in ${cwd} - this should be the root of your integration-tests directory 🤞🏻`)
23
+ await stat(path.join(cwd, outputFileName))
21
24
 
22
25
  try {
23
- await startTestServer({
26
+ const config = {
24
27
  testEnvironmentPath: path.join(cwd, "test-environment/"),
25
- outputFilePath: path.join(cwd, "MyTestDirectory.ts"),
28
+ outputFilePath: path.join(cwd, outputFileName),
29
+ } satisfies TestServerConfig
30
+ await createCypressSupportFile({
31
+ cypressSupportDirectoryPath: path.join(cwd, "cypress", "support"),
32
+ supportFileName: "tui-sandbox.ts",
26
33
  })
34
+ await updateTestdirectorySchemaFile(config)
35
+ await startTestServer(config)
27
36
  } catch (e) {
28
37
  console.error(e)
29
38
  }
@@ -6,8 +6,6 @@ import express from "express"
6
6
  import { accessSync } from "fs"
7
7
  import path from "path"
8
8
  import { fileURLToPath } from "url"
9
- import type { TestServerConfig } from "./updateTestdirectorySchemaFile.js"
10
- import { updateTestdirectorySchemaFile } from "./updateTestdirectorySchemaFile.js"
11
9
 
12
10
  export type TestServerSettings = {
13
11
  port: number
@@ -19,11 +17,9 @@ const __dirname = path.dirname(__filename)
19
17
  export class TestServer {
20
18
  public constructor(private readonly settings: TestServerSettings) {}
21
19
 
22
- public async startAndRun(appRouter: AnyTRPCRouter, config: TestServerConfig): Promise<void> {
20
+ public async startAndRun(appRouter: AnyTRPCRouter): Promise<void> {
23
21
  console.log("🚀 Server starting")
24
22
 
25
- await updateTestdirectorySchemaFile(config)
26
-
27
23
  const app = express()
28
24
  app.use(
29
25
  "/trpc",
@@ -0,0 +1,56 @@
1
+ import { createCypressSupportFileContents } from "./contents.js"
2
+
3
+ it("should return the expected contents", async () => {
4
+ // this test is to help track breaking changes with releases
5
+ expect(await createCypressSupportFileContents()).toMatchInlineSnapshot(`
6
+ "/// <reference types="cypress" />
7
+ //
8
+ // This file is autogenerated by tui-sandbox. Do not edit it directly.
9
+ //
10
+ import type { StartNeovimGenericArguments } from "@tui-sandbox/library/dist/src/server/types"
11
+ import type { OverrideProperties } from "type-fest"
12
+ import type { MyTestDirectory, MyTestDirectoryFile } from "../../MyTestDirectory"
13
+
14
+ export type NeovimContext = {
15
+ contents: MyTestDirectory
16
+ rootPathAbsolute: string
17
+ }
18
+
19
+ declare global {
20
+ interface Window {
21
+ startNeovim(startArguments?: MyStartNeovimServerArguments): Promise<NeovimContext>
22
+ }
23
+ }
24
+
25
+ type MyStartNeovimServerArguments = OverrideProperties<
26
+ StartNeovimGenericArguments,
27
+ {
28
+ filename?: MyTestDirectoryFile | { openInVerticalSplits: MyTestDirectoryFile[] }
29
+ // NOTE: right now you need to make sure the config-modifications directory exists in your test directory
30
+ startupScriptModifications?: Array<keyof MyTestDirectory["config-modifications"]["contents"]>
31
+ }
32
+ >
33
+
34
+ Cypress.Commands.add("startNeovim", (startArguments?: MyStartNeovimServerArguments) => {
35
+ cy.window().then(async win => {
36
+ return await win.startNeovim(startArguments)
37
+ })
38
+ })
39
+
40
+ Cypress.Commands.add("typeIntoTerminal", (text: string, options?: Partial<Cypress.TypeOptions>) => {
41
+ // the syntax for keys is described here:
42
+ // https://docs.cypress.io/api/commands/type
43
+ cy.get("textarea").focus().type(text, options)
44
+ })
45
+
46
+ declare global {
47
+ namespace Cypress {
48
+ interface Chainable {
49
+ startNeovim(args?: MyStartNeovimServerArguments): Chainable<NeovimContext>
50
+ typeIntoTerminal(text: string, options?: Partial<Cypress.TypeOptions>): Chainable<void>
51
+ }
52
+ }
53
+ }
54
+ "
55
+ `)
56
+ })
@@ -0,0 +1,64 @@
1
+ import { format, resolveConfig } from "prettier"
2
+ import { fileURLToPath } from "url"
3
+
4
+ const __filename = fileURLToPath(import.meta.url)
5
+
6
+ export async function createCypressSupportFileContents(): Promise<string> {
7
+ // this is the interface of tui-sandbox as far as cypress in the user's
8
+ // application is concerned
9
+ let text = `
10
+ /// <reference types="cypress" />
11
+ //
12
+ // This file is autogenerated by tui-sandbox. Do not edit it directly.
13
+ //
14
+ import type { OverrideProperties } from "type-fest"
15
+ import type { StartNeovimGenericArguments } from "@tui-sandbox/library/dist/src/server/types"
16
+ import type { MyTestDirectory, MyTestDirectoryFile } from "../../MyTestDirectory"
17
+
18
+ export type NeovimContext = {
19
+ contents: MyTestDirectory
20
+ rootPathAbsolute: string
21
+ }
22
+
23
+ declare global {
24
+ interface Window {
25
+ startNeovim(startArguments?: MyStartNeovimServerArguments): Promise<NeovimContext>
26
+ }
27
+ }
28
+
29
+ type MyStartNeovimServerArguments = OverrideProperties<
30
+ StartNeovimGenericArguments,
31
+ {
32
+ filename?: MyTestDirectoryFile | { openInVerticalSplits: MyTestDirectoryFile[] }
33
+ // NOTE: right now you need to make sure the config-modifications directory exists in your test directory
34
+ startupScriptModifications?: Array<keyof MyTestDirectory["config-modifications"]["contents"]>
35
+ }
36
+ >
37
+
38
+ Cypress.Commands.add("startNeovim", (startArguments?: MyStartNeovimServerArguments) => {
39
+ cy.window().then(async win => {
40
+ return await win.startNeovim(startArguments)
41
+ })
42
+ })
43
+
44
+ Cypress.Commands.add("typeIntoTerminal", (text: string, options?: Partial<Cypress.TypeOptions>) => {
45
+ // the syntax for keys is described here:
46
+ // https://docs.cypress.io/api/commands/type
47
+ cy.get("textarea").focus().type(text, options)
48
+ })
49
+
50
+ declare global {
51
+ namespace Cypress {
52
+ interface Chainable {
53
+ startNeovim(args?: MyStartNeovimServerArguments): Chainable<NeovimContext>
54
+ typeIntoTerminal(text: string, options?: Partial<Cypress.TypeOptions>): Chainable<void>
55
+ }
56
+ }
57
+ }
58
+ `
59
+
60
+ const options = await resolveConfig(__filename)
61
+ text = await format(text, { ...options, parser: "typescript" })
62
+
63
+ return text
64
+ }
@@ -0,0 +1,44 @@
1
+ import { readFileSync, writeFileSync } from "fs"
2
+ import { createCypressSupportFileContents } from "./contents.js"
3
+ import type { CreateCypressSupportFileResult } from "./createCypressSupportFile.js"
4
+ import { createCypressSupportFile } from "./createCypressSupportFile.js"
5
+
6
+ vi.mock("fs")
7
+ vi.mock("./contents.ts")
8
+
9
+ const mocked = {
10
+ readFileSync: vi.mocked(readFileSync),
11
+ writeFileSync: vi.mocked(writeFileSync),
12
+ createCypressSupportFileContents: vi.mocked(createCypressSupportFileContents),
13
+ }
14
+
15
+ describe("createCypressSupportFileContents", () => {
16
+ it("should update the file if the schema has changed", async () => {
17
+ mocked.readFileSync.mockImplementationOnce(() => "")
18
+ mocked.writeFileSync.mockImplementationOnce(() => {
19
+ //
20
+ })
21
+
22
+ const result = await createCypressSupportFile({
23
+ cypressSupportDirectoryPath: "cypress/support",
24
+ supportFileName: "tui-sandbox.ts",
25
+ })
26
+
27
+ expect(result).toBe("updated" satisfies CreateCypressSupportFileResult)
28
+ })
29
+
30
+ it("should not update the file if the schema has not changed", async () => {
31
+ mocked.readFileSync.mockImplementationOnce(() => "contents")
32
+ mocked.writeFileSync.mockImplementationOnce(() => {
33
+ //
34
+ })
35
+ mocked.createCypressSupportFileContents.mockImplementationOnce(async () => "contents")
36
+
37
+ const result = await createCypressSupportFile({
38
+ cypressSupportDirectoryPath: "cypress/support",
39
+ supportFileName: "tui-sandbox.ts",
40
+ })
41
+
42
+ expect(result).toBe("did-nothing" satisfies CreateCypressSupportFileResult)
43
+ })
44
+ })
@@ -0,0 +1,40 @@
1
+ import { readFileSync, writeFileSync } from "fs"
2
+ import path from "path"
3
+ import { createCypressSupportFileContents } from "./contents.js"
4
+
5
+ export type CreateCypressSupportFileArgs = {
6
+ cypressSupportDirectoryPath: string
7
+ supportFileName: string
8
+ }
9
+
10
+ export type CreateCypressSupportFileResult = "updated" | "did-nothing"
11
+
12
+ /**
13
+ * This is the interface of tui-sandbox as far as cypress in the user's
14
+ * application is concerned. It needs to be checked for changes once per
15
+ * tui-sandbox version.
16
+ */
17
+ export async function createCypressSupportFile({
18
+ cypressSupportDirectoryPath,
19
+ supportFileName,
20
+ }: CreateCypressSupportFileArgs): Promise<CreateCypressSupportFileResult> {
21
+ const text = await createCypressSupportFileContents()
22
+
23
+ let oldSchema = ""
24
+ const outputFilePath = path.join(cypressSupportDirectoryPath, supportFileName)
25
+ try {
26
+ oldSchema = readFileSync(outputFilePath, "utf-8")
27
+ } catch (error) {
28
+ console.log(`No existing cypress support file found at ${outputFilePath}, creating a new one`)
29
+ }
30
+
31
+ if (oldSchema !== text) {
32
+ // it's important to not write the file if the schema hasn't changed
33
+ // because file watchers will trigger on file changes and we don't want to
34
+ // trigger a build if the schema hasn't changed
35
+ writeFileSync(outputFilePath, text)
36
+ return "updated"
37
+ } else {
38
+ return "did-nothing"
39
+ }
40
+ }
@@ -73,7 +73,7 @@ export async function startTestServer(config: TestServerConfig): Promise<TestSer
73
73
  port: 3000,
74
74
  })
75
75
  const appRouter = await createAppRouter(config)
76
- await testServer.startAndRun(appRouter, config)
76
+ await testServer.startAndRun(appRouter)
77
77
 
78
78
  return testServer
79
79
  }