11import { fetchRegistry } from "@/src/registry/api"
2+ import { spinner } from "@/src/utils/spinner"
23import { execa } from "execa"
34import fs from "fs-extra"
45import prompts from "prompts"
5- import { afterEach , beforeEach , describe , expect , it , vi } from "vitest"
6+ import {
7+ afterEach ,
8+ beforeEach ,
9+ describe ,
10+ expect ,
11+ it ,
12+ vi ,
13+ type MockInstance ,
14+ } from "vitest"
615
716import { TEMPLATES , createProject } from "./create-project"
817
@@ -14,16 +23,85 @@ vi.mock("@/src/registry/api")
1423vi . mock ( "@/src/utils/get-package-manager" , ( ) => ( {
1524 getPackageManager : vi . fn ( ) . mockResolvedValue ( "npm" ) ,
1625} ) )
26+ vi . mock ( "@/src/utils/spinner" )
27+ vi . mock ( "@/src/utils/logger" , ( ) => ( {
28+ logger : {
29+ break : vi . fn ( ) ,
30+ error : vi . fn ( ) ,
31+ info : vi . fn ( ) ,
32+ } ,
33+ } ) )
1734
1835describe ( "createProject" , ( ) => {
36+ let mockExit : MockInstance
37+
1938 beforeEach ( ( ) => {
2039 vi . clearAllMocks ( )
40+
41+ // Reset all fs mocks
2142 vi . mocked ( fs . access ) . mockResolvedValue ( undefined )
2243 vi . mocked ( fs . existsSync ) . mockReturnValue ( false )
44+ vi . mocked ( fs . ensureDir ) . mockResolvedValue ( undefined )
45+ vi . mocked ( fs . writeFile ) . mockResolvedValue ( undefined )
46+ vi . mocked ( fs . move ) . mockResolvedValue ( undefined )
47+ vi . mocked ( fs . remove ) . mockResolvedValue ( undefined )
48+
49+ // Mock execa to resolve immediately without actual execution
50+ vi . mocked ( execa ) . mockResolvedValue ( {
51+ stdout : "" ,
52+ stderr : "" ,
53+ exitCode : 0 ,
54+ signal : undefined ,
55+ signalDescription : undefined ,
56+ command : "" ,
57+ escapedCommand : "" ,
58+ failed : false ,
59+ timedOut : false ,
60+ isCanceled : false ,
61+ killed : false ,
62+ } as any )
63+
64+ // Mock fetch for monorepo template
65+ global . fetch = vi . fn ( ) . mockResolvedValue ( {
66+ ok : true ,
67+ arrayBuffer : ( ) => Promise . resolve ( new ArrayBuffer ( 0 ) ) ,
68+ } as any )
69+
70+ // Reset prompts mock
71+ vi . mocked ( prompts ) . mockResolvedValue ( { type : "next" , name : "my-app" } )
72+
73+ // Reset registry mock
74+ vi . mocked ( fetchRegistry ) . mockResolvedValue ( [ ] )
75+
76+ // Mock spinner function
77+ const mockSpinner = {
78+ start : vi . fn ( ) . mockReturnThis ( ) ,
79+ succeed : vi . fn ( ) . mockReturnThis ( ) ,
80+ fail : vi . fn ( ) . mockReturnThis ( ) ,
81+ stop : vi . fn ( ) . mockReturnThis ( ) ,
82+ text : "" ,
83+ prefixText : "" ,
84+ suffixText : "" ,
85+ color : "cyan" as const ,
86+ indent : 0 ,
87+ spinner : "dots" as const ,
88+ isSpinning : false ,
89+ interval : 100 ,
90+ stream : process . stderr ,
91+ clear : vi . fn ( ) ,
92+ render : vi . fn ( ) ,
93+ frame : vi . fn ( ) ,
94+ stopAndPersist : vi . fn ( ) ,
95+ warn : vi . fn ( ) ,
96+ info : vi . fn ( ) ,
97+ }
98+ vi . mocked ( spinner ) . mockReturnValue ( mockSpinner as any )
2399 } )
24100
25101 afterEach ( ( ) => {
26102 vi . resetAllMocks ( )
103+ mockExit ?. mockRestore ( )
104+ delete ( global as any ) . fetch
27105 } )
28106
29107 it ( "should create a Next.js project with default options" , async ( ) => {
@@ -84,10 +162,13 @@ describe("createProject", () => {
84162 } )
85163
86164 it ( "should throw error if project path already exists" , async ( ) => {
87- vi . mocked ( fs . existsSync ) . mockReturnValue ( true )
165+ // Mock fs.existsSync to return true only for the specific package.json path
166+ vi . mocked ( fs . existsSync ) . mockImplementation ( ( path : any ) => {
167+ return path . toString ( ) . includes ( "existing-app/package.json" )
168+ } )
88169 vi . mocked ( prompts ) . mockResolvedValue ( { type : "next" , name : "existing-app" } )
89170
90- const mockExit = vi
171+ mockExit = vi
91172 . spyOn ( process , "exit" )
92173 . mockImplementation ( ( ) => undefined as never )
93174
@@ -103,7 +184,7 @@ describe("createProject", () => {
103184 vi . mocked ( fs . access ) . mockRejectedValue ( new Error ( "Permission denied" ) )
104185 vi . mocked ( prompts ) . mockResolvedValue ( { type : "next" , name : "my-app" } )
105186
106- const mockExit = vi
187+ mockExit = vi
107188 . spyOn ( process , "exit" )
108189 . mockImplementation ( ( ) => undefined as never )
109190
0 commit comments