fix(shadcn): flaky create-project tests (#7590)

* fix(shadcn): flaky create-project tests

* fix

* fix
This commit is contained in:
shadcn
2025-06-11 13:50:35 +04:00
committed by GitHub
parent c5d90c718a
commit 92cfb9a30e
2 changed files with 90 additions and 4 deletions

View File

@@ -0,0 +1,5 @@
---
"shadcn": patch
---
fix flacky tests

View File

@@ -1,8 +1,17 @@
import { fetchRegistry } from "@/src/registry/api"
import { spinner } from "@/src/utils/spinner"
import { execa } from "execa"
import fs from "fs-extra"
import prompts from "prompts"
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"
import {
afterEach,
beforeEach,
describe,
expect,
it,
vi,
type MockInstance,
} from "vitest"
import { TEMPLATES, createProject } from "./create-project"
@@ -14,16 +23,85 @@ vi.mock("@/src/registry/api")
vi.mock("@/src/utils/get-package-manager", () => ({
getPackageManager: vi.fn().mockResolvedValue("npm"),
}))
vi.mock("@/src/utils/spinner")
vi.mock("@/src/utils/logger", () => ({
logger: {
break: vi.fn(),
error: vi.fn(),
info: vi.fn(),
},
}))
describe("createProject", () => {
let mockExit: MockInstance
beforeEach(() => {
vi.clearAllMocks()
// Reset all fs mocks
vi.mocked(fs.access).mockResolvedValue(undefined)
vi.mocked(fs.existsSync).mockReturnValue(false)
vi.mocked(fs.ensureDir).mockResolvedValue(undefined)
vi.mocked(fs.writeFile).mockResolvedValue(undefined)
vi.mocked(fs.move).mockResolvedValue(undefined)
vi.mocked(fs.remove).mockResolvedValue(undefined)
// Mock execa to resolve immediately without actual execution
vi.mocked(execa).mockResolvedValue({
stdout: "",
stderr: "",
exitCode: 0,
signal: undefined,
signalDescription: undefined,
command: "",
escapedCommand: "",
failed: false,
timedOut: false,
isCanceled: false,
killed: false,
} as any)
// Mock fetch for monorepo template
global.fetch = vi.fn().mockResolvedValue({
ok: true,
arrayBuffer: () => Promise.resolve(new ArrayBuffer(0)),
} as any)
// Reset prompts mock
vi.mocked(prompts).mockResolvedValue({ type: "next", name: "my-app" })
// Reset registry mock
vi.mocked(fetchRegistry).mockResolvedValue([])
// Mock spinner function
const mockSpinner = {
start: vi.fn().mockReturnThis(),
succeed: vi.fn().mockReturnThis(),
fail: vi.fn().mockReturnThis(),
stop: vi.fn().mockReturnThis(),
text: "",
prefixText: "",
suffixText: "",
color: "cyan" as const,
indent: 0,
spinner: "dots" as const,
isSpinning: false,
interval: 100,
stream: process.stderr,
clear: vi.fn(),
render: vi.fn(),
frame: vi.fn(),
stopAndPersist: vi.fn(),
warn: vi.fn(),
info: vi.fn(),
}
vi.mocked(spinner).mockReturnValue(mockSpinner as any)
})
afterEach(() => {
vi.resetAllMocks()
mockExit?.mockRestore()
delete (global as any).fetch
})
it("should create a Next.js project with default options", async () => {
@@ -84,10 +162,13 @@ describe("createProject", () => {
})
it("should throw error if project path already exists", async () => {
vi.mocked(fs.existsSync).mockReturnValue(true)
// Mock fs.existsSync to return true only for the specific package.json path
vi.mocked(fs.existsSync).mockImplementation((path: any) => {
return path.toString().includes("existing-app/package.json")
})
vi.mocked(prompts).mockResolvedValue({ type: "next", name: "existing-app" })
const mockExit = vi
mockExit = vi
.spyOn(process, "exit")
.mockImplementation(() => undefined as never)
@@ -103,7 +184,7 @@ describe("createProject", () => {
vi.mocked(fs.access).mockRejectedValue(new Error("Permission denied"))
vi.mocked(prompts).mockResolvedValue({ type: "next", name: "my-app" })
const mockExit = vi
mockExit = vi
.spyOn(process, "exit")
.mockImplementation(() => undefined as never)