11import type { ChildProcessWithoutNullStreams } from "node:child_process" ;
22import { execFileSync , spawn } from "node:child_process" ;
3+ import { EventEmitter } from "node:events" ;
34import {
45 existsSync ,
56 mkdirSync ,
@@ -13,23 +14,25 @@ import { createRequire } from "node:module";
1314import { tmpdir } from "node:os" ;
1415import path from "node:path" ;
1516import { fileURLToPath , pathToFileURL } from "node:url" ;
17+ import { stripVTControlCharacters as stripAnsi } from "node:util" ;
1618import semver from "semver" ;
17- import stripAnsi from "strip-ansi" ;
1819
1920import { jestTimeout } from "./setupAfterEnv" ;
2021import { server } from "./msw" ;
2122
2223const __filename = fileURLToPath ( import . meta. url ) ;
2324const __dirname = path . dirname ( __filename ) ;
2425const nodeRequire = createRequire ( import . meta. url ) ;
25- const execaModuleId = nodeRequire . resolve ( "execa" ) ;
26- const mockedExeca = jest . fn ( ) ;
26+ const actualChildProcess = nodeRequire (
27+ "node:child_process" ,
28+ ) as typeof import ( "node:child_process" ) ;
29+ const mockedSpawn = jest . fn ( actualChildProcess . spawn ) ;
2730const REPO_ROOT = path . resolve ( __dirname , "../../.." ) ;
2831const BUILT_CLI = path . resolve ( __dirname , "../dist/cli.js" ) ;
2932
30- ( jest as any ) . unstable_mockModule ( execaModuleId , ( ) => ( {
31- default : mockedExeca ,
32- execa : mockedExeca ,
33+ ( jest as any ) . unstable_mockModule ( "node:child_process" , ( ) => ( {
34+ ... actualChildProcess ,
35+ spawn : mockedSpawn ,
3336} ) ) ;
3437
3538let createReactRouter : typeof import ( "../index" ) . createReactRouter ;
@@ -67,6 +70,7 @@ describe("create-react-router CLI", () => {
6770
6871 beforeEach ( ( ) => {
6972 jest . clearAllMocks ( ) ;
73+ mockedSpawn . mockImplementation ( actualChildProcess . spawn ) ;
7074 } ) ;
7175
7276 afterEach ( async ( ) => {
@@ -76,6 +80,14 @@ describe("create-react-router CLI", () => {
7680 tempDirs = new Set < string > ( ) ;
7781 } ) ;
7882
83+ function mockSpawnSuccess ( ) {
84+ mockedSpawn . mockImplementation ( ( ) => {
85+ let child = new EventEmitter ( ) ;
86+ process . nextTick ( ( ) => child . emit ( "exit" , 0 , null ) ) ;
87+ return child as ReturnType < typeof spawn > ;
88+ } ) ;
89+ }
90+
7991 function getProjectDir ( name : string ) {
8092 let tmpDir = path . join ( TEMP_DIR , name ) ;
8193 tempDirs . add ( tmpDir ) ;
@@ -580,8 +592,7 @@ describe("create-react-router CLI", () => {
580592
581593 let projectDir = getProjectDir ( "npm-install-default" ) ;
582594
583- let execa = mockedExeca ;
584- execa . mockImplementation ( async ( ) => { } ) ;
595+ mockSpawnSuccess ( ) ;
585596
586597 // Suppress terminal output
587598 let stdoutMock = jest
@@ -599,7 +610,7 @@ describe("create-react-router CLI", () => {
599610
600611 stdoutMock . mockReset ( ) ;
601612
602- expect ( execa ) . toHaveBeenCalledWith (
613+ expect ( mockedSpawn ) . toHaveBeenCalledWith (
603614 "npm" ,
604615 expect . arrayContaining ( [ "install" ] ) ,
605616 expect . anything ( ) ,
@@ -615,8 +626,7 @@ describe("create-react-router CLI", () => {
615626
616627 let projectDir = getProjectDir ( "npm-install-on-unknown-package-manager" ) ;
617628
618- let execa = mockedExeca ;
619- execa . mockImplementation ( async ( ) => { } ) ;
629+ mockSpawnSuccess ( ) ;
620630
621631 // Suppress terminal output
622632 let stdoutMock = jest
@@ -634,7 +644,7 @@ describe("create-react-router CLI", () => {
634644
635645 stdoutMock . mockReset ( ) ;
636646
637- expect ( execa ) . toHaveBeenCalledWith (
647+ expect ( mockedSpawn ) . toHaveBeenCalledWith (
638648 "npm" ,
639649 expect . arrayContaining ( [ "install" ] ) ,
640650 expect . anything ( ) ,
@@ -650,8 +660,7 @@ describe("create-react-router CLI", () => {
650660
651661 let projectDir = getProjectDir ( "npm-install-from-user-agent" ) ;
652662
653- let execa = mockedExeca ;
654- execa . mockImplementation ( async ( ) => { } ) ;
663+ mockSpawnSuccess ( ) ;
655664
656665 // Suppress terminal output
657666 let stdoutMock = jest
@@ -669,7 +678,7 @@ describe("create-react-router CLI", () => {
669678
670679 stdoutMock . mockReset ( ) ;
671680
672- expect ( execa ) . toHaveBeenCalledWith (
681+ expect ( mockedSpawn ) . toHaveBeenCalledWith (
673682 "npm" ,
674683 expect . arrayContaining ( [ "install" ] ) ,
675684 expect . anything ( ) ,
@@ -684,8 +693,7 @@ describe("create-react-router CLI", () => {
684693
685694 let projectDir = getProjectDir ( "yarn-create-from-user-agent" ) ;
686695
687- let execa = mockedExeca ;
688- execa . mockImplementation ( async ( ) => { } ) ;
696+ mockSpawnSuccess ( ) ;
689697
690698 // Suppress terminal output
691699 let stdoutMock = jest
@@ -703,7 +711,7 @@ describe("create-react-router CLI", () => {
703711
704712 stdoutMock . mockReset ( ) ;
705713
706- expect ( execa ) . toHaveBeenCalledWith (
714+ expect ( mockedSpawn ) . toHaveBeenCalledWith (
707715 "yarn" ,
708716 expect . arrayContaining ( [ "install" ] ) ,
709717 expect . anything ( ) ,
@@ -718,8 +726,7 @@ describe("create-react-router CLI", () => {
718726
719727 let projectDir = getProjectDir ( "pnpm-create-from-user-agent" ) ;
720728
721- let execa = mockedExeca ;
722- execa . mockImplementation ( async ( ) => { } ) ;
729+ mockSpawnSuccess ( ) ;
723730
724731 // Suppress terminal output
725732 let stdoutMock = jest
@@ -737,7 +744,7 @@ describe("create-react-router CLI", () => {
737744
738745 stdoutMock . mockReset ( ) ;
739746
740- expect ( execa ) . toHaveBeenCalledWith (
747+ expect ( mockedSpawn ) . toHaveBeenCalledWith (
741748 "pnpm" ,
742749 expect . arrayContaining ( [ "install" ] ) ,
743750 expect . anything ( ) ,
@@ -752,8 +759,7 @@ describe("create-react-router CLI", () => {
752759
753760 let projectDir = getProjectDir ( "bun-create-from-user-agent" ) ;
754761
755- let execa = mockedExeca ;
756- execa . mockImplementation ( async ( ) => { } ) ;
762+ mockSpawnSuccess ( ) ;
757763
758764 // Suppress terminal output
759765 let stdoutMock = jest
@@ -771,7 +777,7 @@ describe("create-react-router CLI", () => {
771777
772778 stdoutMock . mockReset ( ) ;
773779
774- expect ( execa ) . toHaveBeenCalledWith (
780+ expect ( mockedSpawn ) . toHaveBeenCalledWith (
775781 "bun" ,
776782 expect . arrayContaining ( [ "install" ] ) ,
777783 expect . anything ( ) ,
@@ -786,8 +792,7 @@ describe("create-react-router CLI", () => {
786792
787793 let projectDir = getProjectDir ( "deno-create-from-user-agent" ) ;
788794
789- let execa = mockedExeca ;
790- execa . mockImplementation ( async ( ) => { } ) ;
795+ mockSpawnSuccess ( ) ;
791796
792797 // Suppress terminal output
793798 let stdoutMock = jest
@@ -805,7 +810,7 @@ describe("create-react-router CLI", () => {
805810
806811 stdoutMock . mockReset ( ) ;
807812
808- expect ( execa ) . toHaveBeenCalledWith (
813+ expect ( mockedSpawn ) . toHaveBeenCalledWith (
809814 "deno" ,
810815 expect . arrayContaining ( [ "install" ] ) ,
811816 expect . anything ( ) ,
@@ -820,8 +825,7 @@ describe("create-react-router CLI", () => {
820825
821826 let projectDir = getProjectDir ( "pnpm-create-override" ) ;
822827
823- let execa = mockedExeca ;
824- execa . mockImplementation ( async ( ) => { } ) ;
828+ mockSpawnSuccess ( ) ;
825829
826830 // Suppress terminal output
827831 let stdoutMock = jest
@@ -841,7 +845,7 @@ describe("create-react-router CLI", () => {
841845
842846 stdoutMock . mockReset ( ) ;
843847
844- expect ( execa ) . toHaveBeenCalledWith (
848+ expect ( mockedSpawn ) . toHaveBeenCalledWith (
845849 "pnpm" ,
846850 expect . arrayContaining ( [ "install" ] ) ,
847851 expect . anything ( ) ,
0 commit comments