1+ import { mount , ReactWrapper } from 'enzyme' ;
2+ import { extendJest , Cmd , Sub , Task , Program , ProgramProps } from "react-tea-cup" ;
3+ import React , { ReactNode } from 'react' ;
4+ import { Dispatcher } from 'tea-cup-core' ;
5+ // import 'jest-enzyme';
6+
7+ extendJest ( expect ) ;
8+
9+ const init1 : ( ) => [ number , Cmd < string > ] = ( ) => {
10+ return [ 0 , toCmd ( 'go' ) ] ;
11+ }
12+
13+ const view1 : ( dispatch : Dispatcher < string > , model : number ) => React . ReactNode = ( dispatch : Dispatcher < string > , model : number ) => {
14+ return ( < div className = { 'count' } > { model } </ div > ) ;
15+ }
16+
17+ const update1 : ( msg : string , model : number ) => [ number , Cmd < string > ] = ( msg : string , model : number ) => {
18+ return [ model + 1 , model < 5 ? toCmd ( 'go' ) : Cmd . none ( ) ] ;
19+ }
20+
21+ // const toCmd = (msg: string) => Task.perform(Time.in(0), () => msg);
22+ const toCmd = ( msg : string ) => Task . perform ( Task . succeed ( 0 ) , ( ) => msg ) ;
23+
24+ describe ( 'Test Program' , ( ) => {
25+
26+ it ( 'first' , ( ) => {
27+ const props : ProgramProps < number , string > = {
28+ init : init1 ,
29+ view : view1 ,
30+ update : update1 ,
31+ subscriptions : ( ) => Sub . none < string > ( )
32+ }
33+ return mountWhenIdle ( props ) . then ( ( [ model , wrapper ] ) => {
34+ expect ( model ) . toEqual ( 6 )
35+ // expect(wrapper).toHaveHTML('')
36+ expect ( wrapper . find ( '.count' ) ) . toHaveText ( '6' )
37+ } )
38+ } )
39+ } )
40+
41+ function mountWhenIdle < Model , Msg > ( props : ProgramProps < Model , Msg > ) {
42+ const testable = new Testable ( props ) ;
43+ // return Promise.resolve(mount(<Program {...testable.programProps} />));
44+ return testable . mountWhenIdle ( )
45+ }
46+
47+ class Testable < Model , Msg > {
48+ private resolve ?: ( idle : [ Model , ReactWrapper < Program < Model , Msg > , ProgramProps < Model , Msg > , never > ] ) => void ;
49+ private cmds : Cmd < Msg > [ ] = [ ] ;
50+ private dispatch ?: Dispatcher < Msg > ;
51+ private model ?: Model ;
52+ private viewed ?: ReactNode ;
53+
54+ constructor ( private readonly props : ProgramProps < Model , Msg > ) {
55+ }
56+
57+ get programProps ( ) {
58+ const props : ProgramProps < Model , Msg > = {
59+ init : this . props . init ,
60+ view : ( dispatch : Dispatcher < Msg > , model : Model ) => this . view ( dispatch , model ) ,
61+ update : ( msg : Msg , model : Model ) => this . update ( msg , model ) ,
62+ subscriptions : this . props . subscriptions
63+ }
64+ return props
65+ }
66+
67+ private view ( dispatch : Dispatcher < Msg > , model : Model ) {
68+ this . dispatch = dispatch ;
69+ this . viewed = this . props . view ( dispatch , model ) ;
70+ return this . viewed ;
71+ }
72+
73+ private update ( msg : Msg , model : Model ) : [ Model , Cmd < Msg > ] {
74+ const [ model1 , cmd1 ] = this . props . update ( msg , model ) ;
75+ this . model = model1 ;
76+ this . cmds . push ( cmd1 ) ;
77+ setTimeout ( ( ) => {
78+ this . process ( ) ;
79+ } , 0 ) ;
80+ return [ model1 , Cmd . none ( ) ] ;
81+ }
82+
83+ private process ( ) {
84+ this . cmds = this . cmds . filter ( cmd => cmd . constructor . name !== 'CmdNone' )
85+ if ( this . cmds . length === 0 ) {
86+ this . resolve ?.( [ this . model ! , mount ( < > { this . viewed } </ > ) ] ) ;
87+ return ;
88+ }
89+ const first = this . cmds [ 0 ]
90+ this . cmds = this . cmds . slice ( 1 )
91+ first . execute ( this . dispatch ! )
92+ }
93+
94+ mountWhenIdle ( ) : Promise < [ Model , ReactWrapper < Program < Model , Msg > , ProgramProps < Model , Msg > , never > ] > {
95+ mount ( < Program { ...this . programProps } /> )
96+ return new Promise ( resolve => {
97+ this . resolve = resolve ;
98+ } ) ;
99+ }
100+ }
0 commit comments