|
| 1 | +import { runCommand } from "citty"; |
| 2 | +import { afterEach, beforeEach, expect, it, vi } from "vitest"; |
| 3 | +import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs"; |
| 4 | +import { tmpdir } from "node:os"; |
| 5 | +import { join } from "node:path"; |
| 6 | +import { addDevDependency } from "../src/utils/dev-deps"; |
| 7 | +import { START_DEVTOOLS_PACKAGE, START_DEVTOOLS_VERSION } from "../src/utils/constants"; |
| 8 | + |
| 9 | +const { confirm, createSolidV2 } = vi.hoisted(() => ({ |
| 10 | + confirm: vi.fn(), |
| 11 | + createSolidV2: vi.fn(), |
| 12 | +})); |
| 13 | + |
| 14 | +vi.mock("@clack/prompts", async (importOriginal) => ({ |
| 15 | + ...(await importOriginal<typeof import("@clack/prompts")>()), |
| 16 | + confirm, |
| 17 | +})); |
| 18 | + |
| 19 | +vi.mock("../src/create-solid-v2", async (importOriginal) => ({ |
| 20 | + ...(await importOriginal<typeof import("../src/create-solid-v2")>()), |
| 21 | + createSolidV2, |
| 22 | +})); |
| 23 | + |
| 24 | +import { createSolid } from "../src"; |
| 25 | + |
| 26 | +const TEMPLATE_PKG = { |
| 27 | + name: "example-basic", |
| 28 | + devDependencies: { "typescript": "^5.9.2", "vite": "^8.1.5" }, |
| 29 | + dependencies: { "solid-js": "^2.0.0-rc.0" }, |
| 30 | +}; |
| 31 | + |
| 32 | +let projectDir: string; |
| 33 | +beforeEach(() => { |
| 34 | + // Unroutable address: fetchTemplatesManifest fails fast and falls back to the |
| 35 | + // baked-in template lists, same trick used in manifest.test.ts / cli.test.ts. |
| 36 | + process.env.SOLID_CLI_TEMPLATES_MANIFEST_URL = "http://127.0.0.1:1/templates.json"; |
| 37 | + projectDir = join(mkdtempSync(join(tmpdir(), "solid-cli-devtools-")), "app"); |
| 38 | + // Stand in for the template download: just materialize a package.json |
| 39 | + createSolidV2.mockImplementation(async ({ destination }: { destination: string }) => { |
| 40 | + mkdirSync(destination, { recursive: true }); |
| 41 | + writeFileSync(join(destination, "package.json"), JSON.stringify(TEMPLATE_PKG, null, 2) + "\n"); |
| 42 | + }); |
| 43 | +}); |
| 44 | +afterEach(() => { |
| 45 | + delete process.env.SOLID_CLI_TEMPLATES_MANIFEST_URL; |
| 46 | + rmSync(join(projectDir, ".."), { recursive: true, force: true }); |
| 47 | + vi.clearAllMocks(); |
| 48 | +}); |
| 49 | + |
| 50 | +const readPkg = () => JSON.parse(readFileSync(join(projectDir, "package.json")).toString()); |
| 51 | + |
| 52 | +it("prompts for start-devtools on Solid 2.0 projects and adds it on yes", async () => { |
| 53 | + confirm.mockResolvedValueOnce(true); |
| 54 | + |
| 55 | + // --ssr answers the SSR toggle up front, so the only confirm left is devtools |
| 56 | + await runCommand(createSolid("test"), { rawArgs: [projectDir, "basic", "--solid", "--ts", "--ssr"] }); |
| 57 | + |
| 58 | + expect(confirm).toHaveBeenCalledTimes(1); |
| 59 | + expect(confirm.mock.calls[0][0].message).toContain(START_DEVTOOLS_PACKAGE); |
| 60 | + expect(readPkg().devDependencies[START_DEVTOOLS_PACKAGE]).toBe(START_DEVTOOLS_VERSION); |
| 61 | +}); |
| 62 | + |
| 63 | +it("leaves the project untouched when the devtools prompt is declined", async () => { |
| 64 | + confirm.mockResolvedValueOnce(false); |
| 65 | + |
| 66 | + await runCommand(createSolid("test"), { rawArgs: [projectDir, "basic", "--solid", "--ts", "--ssr"] }); |
| 67 | + |
| 68 | + expect(readPkg().devDependencies[START_DEVTOOLS_PACKAGE]).toBeUndefined(); |
| 69 | +}); |
| 70 | + |
| 71 | +it("skips the prompt when --devtools is passed", async () => { |
| 72 | + await runCommand(createSolid("test"), { rawArgs: [projectDir, "basic", "--solid", "--ts", "--ssr", "--devtools"] }); |
| 73 | + |
| 74 | + expect(confirm).not.toHaveBeenCalled(); |
| 75 | + expect(readPkg().devDependencies[START_DEVTOOLS_PACKAGE]).toBe(START_DEVTOOLS_VERSION); |
| 76 | +}); |
| 77 | + |
| 78 | +it("keeps devDependencies alphabetized and preserves the template's formatting", async () => { |
| 79 | + mkdirSync(projectDir, { recursive: true }); |
| 80 | + writeFileSync(join(projectDir, "package.json"), JSON.stringify(TEMPLATE_PKG, null, 2) + "\n"); |
| 81 | + |
| 82 | + await addDevDependency(projectDir, START_DEVTOOLS_PACKAGE, START_DEVTOOLS_VERSION); |
| 83 | + |
| 84 | + const raw = readFileSync(join(projectDir, "package.json")).toString(); |
| 85 | + expect(raw.endsWith("\n")).toBe(true); |
| 86 | + expect(raw).toContain(' "devDependencies"'); |
| 87 | + expect(Object.keys(readPkg().devDependencies)).toEqual([START_DEVTOOLS_PACKAGE, "typescript", "vite"]); |
| 88 | +}); |
0 commit comments