66 */
77import childProcess from 'child_process'
88import stripFinalNewline from 'strip-final-newline'
9- import stripAnsi from 'strip-ansi'
109import { RenderOptions , TestInstance } from '../types/pure'
1110import { _runObservers } from './mutation-observer'
1211import { getQueriesForElement } from './get-queries-for-instance'
1312
14- class NotBoundToInstanceError extends Error {
15- constructor ( prop : string ) {
16- super ( `
17- You've attempted to read '${ prop } ' from a destructured value.
18- Please do not destructure \`${ prop } \` from \`render\`, instead do something like this:
19-
20- const client = render( /* ... */ );
21- expect(client.${ prop } ).toBe(["Hi"]);
22-
23- Because ${ prop } relies on mutation to function, you'll be left with stale data if this is not done
24- ` )
25- }
26- }
27-
2813async function render (
2914 command : string ,
3015 args : string [ ] = [ ] ,
@@ -40,6 +25,8 @@ async function render(
4025 let _readyPromiseInternals : null | { resolve : Function ; reject : Function } =
4126 null
4227
28+ let _isReadyResolved = false ;
29+
4330 const execOutputAPI = {
4431 _isOutputAPI : true ,
4532 _isReady : new Promise (
@@ -51,42 +38,35 @@ async function render(
5138 } ,
5239 // An array of strings gathered from stdout when unable to do
5340 // `await stdout` because of inquirer interactive prompts
54- _stdoutArr : [ ] as string [ ] ,
55- get stdoutArr ( ) : string [ ] {
56- // TODO: This error throwing doesn't _actually_ work, because
57- // when the value is initially destructured, `this`, _is_ defined
58- // and later, when the user goes to run `console.log(stdoutArr`), it's no
59- // longer referencing this getter - instead it's a new variable that's assigned
60- // a non-getter string
61- if ( ! ( this as unknown ) || ! this . _isOutputAPI ) {
62- throw new NotBoundToInstanceError ( 'stdoutArr' )
63- }
64- return this . _stdoutArr
65- } ,
66- set stdoutArr ( val : string [ ] ) { } ,
41+ stdoutArr : [ ] as Array < string | Buffer > ,
6742 get stdoutStr ( ) : string {
68- if ( ! ( this as unknown ) || ! this . _isOutputAPI ) {
69- throw new NotBoundToInstanceError ( 'stdoutStr' )
70- }
7143 return this . stdoutArr . join ( '\n' )
7244 } ,
7345 set stdoutStr ( val : string ) { } ,
7446 }
7547
7648 exec . stdout . on ( 'data' , ( result : string | Buffer ) => {
77- // TODO: Move `strip-ansi` to `normalizer` within `queries-text` instead
78- const resStr = stripAnsi ( stripFinalNewline ( result as string ) . toString ( ) )
49+ const resStr = stripFinalNewline ( result as string ) ;
7950 execOutputAPI . stdoutArr . push ( resStr )
8051 _runObservers ( )
81- if ( _readyPromiseInternals ) _readyPromiseInternals . resolve ( )
52+ if ( _readyPromiseInternals && ! _isReadyResolved ) {
53+ _readyPromiseInternals . resolve ( )
54+ _isReadyResolved = true ;
55+ }
8256 } )
8357
8458 exec . stdout . on ( 'error' , result => {
85- if ( _readyPromiseInternals ) _readyPromiseInternals . reject ( result )
59+ if ( _readyPromiseInternals && ! _isReadyResolved ) {
60+ _readyPromiseInternals . reject ( result )
61+ _isReadyResolved = true ;
62+ }
8663 } )
8764
8865 exec . stderr . on ( 'data' , ( result : string ) => {
89- if ( _readyPromiseInternals ) _readyPromiseInternals . reject ( new Error ( result ) )
66+ if ( _readyPromiseInternals && ! _isReadyResolved ) {
67+ _readyPromiseInternals . reject ( new Error ( result ) )
68+ _isReadyResolved = true ;
69+ }
9070 } )
9171
9272 await execOutputAPI . _isReady
0 commit comments