@@ -2,6 +2,7 @@ import { mount, ReactWrapper } from 'enzyme';
22import { extendJest , Cmd , Sub , Task , Program , ProgramProps } from "react-tea-cup" ;
33import React , { ReactNode } from 'react' ;
44import { Dispatcher } from 'tea-cup-core' ;
5+ import { view } from './Counter' ;
56// import 'jest-enzyme';
67
78extendJest ( expect ) ;
@@ -36,6 +37,20 @@ describe('Test Program', () => {
3637 expect ( wrapper . find ( '.count' ) ) . toHaveText ( '6' )
3738 } )
3839 } )
40+
41+ it ( 'alternative' , ( ) => {
42+ const props : ProgramProps < number , string > = {
43+ init : init1 ,
44+ view : view1 ,
45+ update : update1 ,
46+ subscriptions : ( ) => Sub . none < string > ( )
47+ }
48+ return updateUntilIdle ( props ) . then ( ( [ model , wrapper ] ) => {
49+ expect ( model ) . toEqual ( 6 )
50+ // expect(wrapper).toHaveHTML('')
51+ expect ( wrapper . find ( '.count' ) ) . toHaveText ( '6' )
52+ } )
53+ } )
3954} )
4055
4156function mountWhenIdle < Model , Msg > ( props : ProgramProps < Model , Msg > ) {
@@ -44,6 +59,88 @@ function mountWhenIdle<Model, Msg>(props: ProgramProps<Model, Msg>) {
4459 return testable . mountWhenIdle ( )
4560}
4661
62+ type WrapperType < Model , Msg > = ReactWrapper < Program < Model , Msg > , ProgramProps < Model , Msg > , never >
63+ type ResolveType < Model , Msg > = ( idle : [ Model , WrapperType < Model , Msg > ] ) => void ;
64+
65+ function updateUntilIdle < Model , Msg > ( props : ProgramProps < Model , Msg > ) : Promise < [ Model , WrapperType < Model , Msg > ] > {
66+ return new Promise ( resolve => {
67+ mount ( < Program { ...testableProps ( resolve , props ) } /> )
68+ } )
69+ }
70+
71+ function testableProps < Model , Msg > ( resolve : ResolveType < Model , Msg > , props : ProgramProps < Model , Msg > ) {
72+ const props2 : ProgramProps < TestableModel < Model , Msg > , Msg > = {
73+ init : initTestable ( resolve , props . init ) ,
74+ view : viewTestable ( props . view ) ,
75+ update : updateTestable ( ( props . update ) ) ,
76+ subscriptions : suscriptionsTestable ( props )
77+ }
78+ return props2
79+ }
80+
81+ type TestableModel < Model , Msg > = {
82+ readonly resolve : ResolveType < Model , Msg > ;
83+ readonly cmds : Cmd < Msg > [ ] ;
84+ readonly model : Model ;
85+ }
86+
87+ function initTestable < Model , Msg > ( resolve : ResolveType < Model , Msg > , init : ProgramProps < Model , Msg > [ 'init' ] ) : ProgramProps < TestableModel < Model , Msg > , Msg > [ 'init' ] {
88+ const mac = init ( ) ;
89+ return ( ) => [ {
90+ resolve,
91+ cmds : [ mac [ 1 ] ] ,
92+ model : mac [ 0 ]
93+ } , Cmd . none ( ) ] ;
94+ }
95+
96+ function viewTestable < Model , Msg > ( view : ProgramProps < Model , Msg > [ 'view' ] ) : ProgramProps < TestableModel < Model , Msg > , Msg > [ 'view' ] {
97+ return ( dispatch : Dispatcher < Msg > , model : TestableModel < Model , Msg > ) => view ( dispatch , model . model ) ;
98+ }
99+
100+ function updateTestable < Model , Msg > ( update : ProgramProps < Model , Msg > [ 'update' ] ) : ProgramProps < TestableModel < Model , Msg > , Msg > [ 'update' ] {
101+ return ( msg : Msg , model : TestableModel < Model , Msg > ) => {
102+ const [ model1 , cmd1 ] = update ( msg , model . model ) ;
103+ const cmds = [ cmd1 ] . filter ( cmd => cmd . constructor . name !== 'CmdNone' )
104+ return [ {
105+ ...model ,
106+ cmds,
107+ model : model1 ,
108+ } , Cmd . none ( ) ] ;
109+ }
110+ }
111+
112+ function suscriptionsTestable < Model , Msg > ( props : ProgramProps < Model , Msg > ) : ProgramProps < TestableModel < Model , Msg > , Msg > [ 'subscriptions' ] {
113+ return ( model : TestableModel < Model , Msg > ) => {
114+ const subs = props . subscriptions ( model . model ) ;
115+ if ( model . cmds . length === 0 ) {
116+ const wrapper : WrapperType < Model , Msg > = mount ( < Program
117+ init = { ( ) => [ model . model , Cmd . none ( ) ] }
118+ update = { ( msg , model ) => [ model , Cmd . none ( ) ] }
119+ view = { ( d , m ) => props . view ( d , m ) }
120+ subscriptions = { ( d ) => Sub . none ( ) }
121+ /> )
122+ model . resolve ( [ model . model , wrapper ] ) ;
123+ return subs ;
124+ }
125+ return Sub . batch ( [ new TestableSub ( model . cmds ) , subs ] ) ;
126+ }
127+ }
128+
129+ class TestableSub < Msg > extends Sub < Msg > {
130+ constructor ( private readonly cmds : readonly Cmd < Msg > [ ] ) {
131+ super ( ) ;
132+ }
133+
134+ protected onInit ( ) : void {
135+ setTimeout ( ( ) => {
136+ if ( this . dispatcher !== undefined ) {
137+ const d = this . dispatcher . bind ( this ) ;
138+ this . cmds . map ( cmd => cmd . execute ( d ) ) ;
139+ }
140+ } , 0 )
141+ }
142+ }
143+
47144class Testable < Model , Msg > {
48145 private resolve ?: ( idle : [ Model , ReactWrapper < Program < Model , Msg > , ProgramProps < Model , Msg > , never > ] ) => void ;
49146 private cmds : Cmd < Msg > [ ] = [ ] ;
0 commit comments