1- import { beforeEach , describe , expect , it , Mock , vi } from 'vitest ' ;
1+ import { ChildProcess } from 'node:child_process ' ;
22
3+ import { afterEach , describe , expect , it , Mock , vi } from 'vitest' ;
4+
5+ import { SpawnCommand } from '../command' ;
36import { createMockInstance } from '../fixtures/create-mock-instance' ;
47import { createFakeProcess , FakeCommand } from '../fixtures/fake-command' ;
58import { Logger } from '../logger' ;
6- import { getSpawnOpts } from '../spawn' ;
9+ import * as spawn from '../spawn' ;
710import { Teardown } from './teardown' ;
811
9- let spawn : Mock ;
10- let logger : Logger ;
12+ const spySpawn = vi
13+ . spyOn ( spawn , 'spawn' )
14+ . mockImplementation ( ( ) => createFakeProcess ( 1 ) as ChildProcess ) as Mock ;
15+ const logger = createMockInstance ( Logger ) ;
1116const commands = [ new FakeCommand ( ) ] ;
1217const teardown = 'cowsay bye' ;
1318
14- beforeEach ( ( ) => {
15- logger = createMockInstance ( Logger ) ;
16- spawn = vi . fn ( ( ) => createFakeProcess ( 1 ) ) ;
19+ afterEach ( ( ) => {
20+ vi . clearAllMocks ( ) ;
1721} ) ;
1822
19- const create = ( teardown : string [ ] ) =>
23+ const create = ( teardown : string [ ] , spawn ?: SpawnCommand ) =>
2024 new Teardown ( {
2125 spawn,
2226 logger,
@@ -31,61 +35,94 @@ it('returns commands unchanged', () => {
3135describe ( 'onFinish callback' , ( ) => {
3236 it ( 'does not spawn nothing if there are no teardown commands' , ( ) => {
3337 create ( [ ] ) . handle ( commands ) . onFinish ( ) ;
34- expect ( spawn ) . not . toHaveBeenCalled ( ) ;
38+ expect ( spySpawn ) . not . toHaveBeenCalled ( ) ;
3539 } ) ;
3640
3741 it ( 'runs teardown command' , ( ) => {
3842 create ( [ teardown ] ) . handle ( commands ) . onFinish ( ) ;
39- expect ( spawn ) . toHaveBeenCalledWith ( teardown , getSpawnOpts ( { stdio : 'raw' } ) ) ;
43+ expect ( spySpawn ) . toHaveBeenCalledWith ( teardown , spawn . getSpawnOpts ( { stdio : 'raw' } ) ) ;
44+ } ) ;
45+
46+ it ( 'runs teardown command with custom spawn function' , ( ) => {
47+ const customSpawn = vi . fn ( ( ) => createFakeProcess ( 1 ) ) ;
48+ create ( [ teardown ] , customSpawn ) . handle ( commands ) . onFinish ( ) ;
49+ expect ( customSpawn ) . toHaveBeenCalledWith ( teardown , spawn . getSpawnOpts ( { stdio : 'raw' } ) ) ;
4050 } ) ;
4151
4252 it ( 'waits for teardown command to close' , async ( ) => {
4353 const child = createFakeProcess ( 1 ) ;
44- spawn . mockReturnValue ( child ) ;
54+ spySpawn . mockReturnValue ( child ) ;
4555
4656 const result = create ( [ teardown ] ) . handle ( commands ) . onFinish ( ) ;
4757 child . emit ( 'close' , 1 , null ) ;
4858 await expect ( result ) . resolves . toBeUndefined ( ) ;
4959 } ) ;
5060
51- it ( 'rejects if teardown command errors' , async ( ) => {
61+ it ( 'rejects if teardown command errors (string)' , async ( ) => {
62+ const child = createFakeProcess ( 1 ) ;
63+ spySpawn . mockReturnValue ( child ) ;
64+
65+ const result = create ( [ teardown ] ) . handle ( commands ) . onFinish ( ) ;
66+ const error = 'fail' ;
67+ child . emit ( 'error' , error ) ;
68+ await expect ( result ) . rejects . toBeUndefined ( ) ;
69+ expect ( logger . logGlobalEvent ) . toHaveBeenLastCalledWith ( 'fail' ) ;
70+ } ) ;
71+
72+ it ( 'rejects if teardown command errors (error)' , async ( ) => {
73+ const child = createFakeProcess ( 1 ) ;
74+ spySpawn . mockReturnValue ( child ) ;
75+
76+ const result = create ( [ teardown ] ) . handle ( commands ) . onFinish ( ) ;
77+ const error = new Error ( 'fail' ) ;
78+ child . emit ( 'error' , error ) ;
79+ await expect ( result ) . rejects . toBeUndefined ( ) ;
80+ expect ( logger . logGlobalEvent ) . toHaveBeenLastCalledWith (
81+ expect . stringMatching ( / E r r o r : f a i l / ) ,
82+ ) ;
83+ } ) ;
84+
85+ it ( 'rejects if teardown command errors (error, no stack)' , async ( ) => {
5286 const child = createFakeProcess ( 1 ) ;
53- spawn . mockReturnValue ( child ) ;
87+ spySpawn . mockReturnValue ( child ) ;
5488
5589 const result = create ( [ teardown ] ) . handle ( commands ) . onFinish ( ) ;
56- child . emit ( 'error' , 'fail' ) ;
90+ const error = new Error ( 'fail' ) ;
91+ delete error . stack ;
92+ child . emit ( 'error' , error ) ;
5793 await expect ( result ) . rejects . toBeUndefined ( ) ;
94+ expect ( logger . logGlobalEvent ) . toHaveBeenLastCalledWith ( 'Error: fail' ) ;
5895 } ) ;
5996
6097 it ( 'runs multiple teardown commands in sequence' , async ( ) => {
6198 const child1 = createFakeProcess ( 1 ) ;
6299 const child2 = createFakeProcess ( 2 ) ;
63- spawn . mockReturnValueOnce ( child1 ) . mockReturnValueOnce ( child2 ) ;
100+ spySpawn . mockReturnValueOnce ( child1 ) . mockReturnValueOnce ( child2 ) ;
64101
65102 const result = create ( [ 'foo' , 'bar' ] ) . handle ( commands ) . onFinish ( ) ;
66103
67- expect ( spawn ) . toHaveBeenCalledTimes ( 1 ) ;
68- expect ( spawn ) . toHaveBeenLastCalledWith ( 'foo' , getSpawnOpts ( { stdio : 'raw' } ) ) ;
104+ expect ( spySpawn ) . toHaveBeenCalledTimes ( 1 ) ;
105+ expect ( spySpawn ) . toHaveBeenLastCalledWith ( 'foo' , spawn . getSpawnOpts ( { stdio : 'raw' } ) ) ;
69106
70107 child1 . emit ( 'close' , 1 , null ) ;
71108 await new Promise ( ( resolve ) => setTimeout ( resolve ) ) ;
72109
73- expect ( spawn ) . toHaveBeenCalledTimes ( 2 ) ;
74- expect ( spawn ) . toHaveBeenLastCalledWith ( 'bar' , getSpawnOpts ( { stdio : 'raw' } ) ) ;
110+ expect ( spySpawn ) . toHaveBeenCalledTimes ( 2 ) ;
111+ expect ( spySpawn ) . toHaveBeenLastCalledWith ( 'bar' , spawn . getSpawnOpts ( { stdio : 'raw' } ) ) ;
75112
76113 child2 . emit ( 'close' , 0 , null ) ;
77114 await expect ( result ) . resolves . toBeUndefined ( ) ;
78115 } ) ;
79116
80117 it ( 'stops running teardown commands on SIGINT' , async ( ) => {
81118 const child = createFakeProcess ( 1 ) ;
82- spawn . mockReturnValue ( child ) ;
119+ spySpawn . mockReturnValue ( child ) ;
83120
84121 const result = create ( [ 'foo' , 'bar' ] ) . handle ( commands ) . onFinish ( ) ;
85122 child . emit ( 'close' , null , 'SIGINT' ) ;
86123 await result ;
87124
88- expect ( spawn ) . toHaveBeenCalledTimes ( 1 ) ;
89- expect ( spawn ) . toHaveBeenLastCalledWith ( 'foo' , expect . anything ( ) ) ;
125+ expect ( spySpawn ) . toHaveBeenCalledTimes ( 1 ) ;
126+ expect ( spySpawn ) . toHaveBeenLastCalledWith ( 'foo' , expect . anything ( ) ) ;
90127 } ) ;
91128} ) ;
0 commit comments