1- import { always , call , cond , entry , exit , on , start } from "./index" ;
1+ import { always , compound , cond , entry , exit , on , start } from "./index" ;
22
33const fetch = jest . fn ( ) ;
44beforeEach ( fetch . mockClear ) ;
55
66const finishedLoading = jest . fn ( ) ;
77beforeEach ( finishedLoading . mockClear ) ;
88
9+ const succeeded = jest . fn ( ) ;
10+ beforeEach ( succeeded . mockClear ) ;
11+
912describe ( "Machine with entry and exit actions" , ( ) => {
1013 const someURL = new URL ( "https://example.org/" ) ;
1114 function fetchData ( ) {
@@ -22,7 +25,9 @@ describe("Machine with entry and exit actions", () => {
2225 yield on ( "SUCCESS" , success ) ;
2326 yield on ( "FAILURE" , failure ) ;
2427 }
25- function * success ( ) { }
28+ function * success ( ) {
29+ yield entry ( succeeded ) ;
30+ }
2631 function * failure ( ) {
2732 yield on ( "RETRY" , loading ) ;
2833 }
@@ -63,11 +68,13 @@ describe("Machine with entry and exit actions", () => {
6368 expect ( finishedLoading ) . toHaveBeenCalledTimes ( 1 ) ;
6469 expect ( loader . changeCount ) . toEqual ( 2 ) ;
6570 expect ( loader . value ) . toEqual ( "success" ) ;
71+ expect ( succeeded ) . toHaveBeenCalledTimes ( 1 ) ;
6672
6773 const transitionResult2 = loader . next ( "FETCH" ) ;
68- expect ( transitionResult2 . actions ) . toEqual ( [ ] ) ;
74+ // expect(transitionResult2.actions).toEqual([]);
6975 expect ( loader . changeCount ) . toEqual ( 2 ) ;
7076 expect ( loader . value ) . toEqual ( "success" ) ;
77+ expect ( succeeded ) . toHaveBeenCalledTimes ( 1 ) ;
7178
7279 await loader . resolved ;
7380 } ) ;
@@ -79,7 +86,7 @@ describe("Machine with entry and exit actions", () => {
7986 } ) ;
8087
8188 test ( "sending events" , async ( ) => {
82- const loader = start ( Loader , [ { url : someURL } ] ) ;
89+ const loader = start ( Loader ) ;
8390 expect ( loader . value ) . toEqual ( "idle" ) ;
8491
8592 const transitionResult = loader . next ( "FETCH" ) ;
@@ -116,9 +123,7 @@ describe("Machine with entry and exit actions", () => {
116123 } ) ;
117124} ) ;
118125
119- describe ( "Form Field Machine with entry and exit actions" , ( ) => {
120- // const validate = jest.fn();
121- // beforeEach(validate.mockClear);
126+ describe ( "Form Field Machine with always()" , ( ) => {
122127 const isValid = jest . fn ( ) ;
123128 beforeEach ( isValid . mockClear ) ;
124129
@@ -127,20 +132,12 @@ describe("Form Field Machine with entry and exit actions", () => {
127132 yield on ( "CHANGE" , editing ) ;
128133 }
129134 function * editing ( ) {
130- // yield exit(validate);
131135 yield on ( "CHANGE" , editing ) ;
132136 yield on ( "BLUR" , validating ) ;
133137 }
134138 function * validating ( ) {
135139 yield always ( cond ( isValid , valid ) ) ;
136140 yield always ( invalid ) ;
137-
138- // yield on(null, cond(isValid, valid));
139- // yield on(null, invalid);
140-
141- // yield always([cond(isValid, valid), invalid]);
142- // return [cond(isValid, valid), invalid];
143- // return conds([[isValid, valid], [true, invalid]]);
144141 }
145142 function * invalid ( ) {
146143 yield on ( "CHANGE" , editing ) ;
@@ -152,11 +149,6 @@ describe("Form Field Machine with entry and exit actions", () => {
152149 return initial ;
153150 }
154151
155- test ( "creating" , ( ) => {
156- const formField = start ( FormField ) ;
157- expect ( formField ) . toBeDefined ( ) ;
158- } ) ;
159-
160152 describe ( "when is valid" , ( ) => {
161153 beforeEach ( ( ) => {
162154 isValid . mockReturnValue ( true ) ;
@@ -173,11 +165,11 @@ describe("Form Field Machine with entry and exit actions", () => {
173165
174166 formField . next ( "CHANGE" ) ;
175167 expect ( formField . value ) . toEqual ( "editing" ) ;
176- expect ( formField . changeCount ) . toEqual ( 2 ) ;
168+ expect ( formField . changeCount ) . toEqual ( 1 ) ;
177169
178170 formField . next ( "BLUR" ) ;
179171 expect ( formField . value ) . toEqual ( "valid" ) ;
180- expect ( formField . changeCount ) . toEqual ( 4 ) ;
172+ expect ( formField . changeCount ) . toEqual ( 3 ) ;
181173 } ) ;
182174 } ) ;
183175
@@ -197,106 +189,79 @@ describe("Form Field Machine with entry and exit actions", () => {
197189
198190 formField . next ( "CHANGE" ) ;
199191 expect ( formField . value ) . toEqual ( "editing" ) ;
200- expect ( formField . changeCount ) . toEqual ( 2 ) ;
192+ expect ( formField . changeCount ) . toEqual ( 1 ) ;
201193
202194 formField . next ( "BLUR" ) ;
203195 expect ( formField . value ) . toEqual ( "invalid" ) ;
204- expect ( formField . changeCount ) . toEqual ( 4 ) ;
196+ expect ( formField . changeCount ) . toEqual ( 3 ) ;
205197 } ) ;
206198 } ) ;
207199} ) ;
208200
209- describe ( "Machine with call " , ( ) => {
210- function Loader ( { url } : { url : URL } ) {
211- function * idle ( ) {
212- yield on ( "FETCH" , loading ) ;
213- }
214- function * loading ( ) {
215- yield call ( fetch , [ url . toString ( ) ] ) ;
216- yield on ( "SUCCESS" , success ) ;
217- yield on ( "FAILURE " , failure ) ;
201+ describe ( "Hierarchical Traffic Lights Machine " , ( ) => {
202+ // const validate = jest.fn();
203+ // beforeEach(validate.mockClear);
204+ const isValid = jest . fn ( ) ;
205+ beforeEach ( isValid . mockClear ) ;
206+
207+ function PedestrianFactory ( ) {
208+ function * walk ( ) {
209+ yield on ( "PED_COUNTDOWN " , wait ) ;
218210 }
219- function * success ( ) { }
220- function * failure ( ) {
221- yield on ( "RETRY" , loading ) ;
211+ function * wait ( ) {
212+ yield on ( "PED_COUNTDOWN" , stop ) ;
222213 }
214+ function * stop ( ) { }
215+ function * blinking ( ) { }
223216
224- return idle ;
217+ return { walk , blinking } ;
225218 }
219+ function * TrafficLights ( ) {
220+ const { walk, blinking } = PedestrianFactory ( ) ;
226221
227- const someURL = new URL ( "https://example.org/" ) ;
228-
229- test ( "creating" , ( ) => {
230- const loader = start ( Loader , [ { url : someURL } ] ) ;
231- expect ( loader ) . toBeDefined ( ) ;
232- } ) ;
233-
234- describe ( "when fetch succeeds" , ( ) => {
235- beforeEach ( ( ) => {
236- fetch . mockResolvedValue ( 42 ) ;
237- } ) ;
238-
239- test ( "sending events" , async ( ) => {
240- const loader = start ( Loader , [ { url : someURL } ] ) ;
241- expect ( loader . value ) . toEqual ( "idle" ) ;
242- await expect ( loader . resolved ) . resolves . toEqual ( [ ] ) ;
243-
244- loader . next ( "NOOP" ) ;
245- expect ( loader . value ) . toEqual ( "idle" ) ;
246- expect ( loader . changeCount ) . toEqual ( 0 ) ;
247- await expect ( loader . resolved ) . resolves . toEqual ( [ ] ) ;
248-
249- loader . next ( "FETCH" ) ;
250- expect ( loader . value ) . toEqual ( "loading" ) ;
251- expect ( loader . changeCount ) . toEqual ( 1 ) ;
252-
253- expect ( fetch ) . toHaveBeenCalledWith ( "https://example.org/" ) ;
254-
255- await expect ( loader . resolved ) . resolves . toEqual ( [ 42 ] ) ;
256- expect ( loader . changeCount ) . toEqual ( 2 ) ;
257- expect ( loader . value ) . toEqual ( "success" ) ;
258-
259- loader . next ( "FETCH" ) ;
260- expect ( loader . changeCount ) . toEqual ( 2 ) ;
261-
262- await loader . resolved ;
263- } ) ;
264- } ) ;
265-
266- describe ( "when fetch fails" , ( ) => {
267- beforeEach ( ( ) => {
268- fetch . mockRejectedValueOnce ( new Error ( "Failed!" ) ) . mockResolvedValue ( 42 ) ;
269- } ) ;
270-
271- test ( "sending events" , async ( ) => {
272- const loader = start ( Loader , [ { url : someURL } ] ) ;
273- expect ( loader . value ) . toEqual ( "idle" ) ;
274-
275- loader . next ( "FETCH" ) ;
276- expect ( loader . value ) . toEqual ( "loading" ) ;
277- expect ( loader . changeCount ) . toEqual ( 1 ) ;
278-
279- expect ( fetch ) . toHaveBeenCalledTimes ( 1 ) ;
280- expect ( fetch ) . toHaveBeenLastCalledWith ( "https://example.org/" ) ;
281-
282- await expect ( loader . resolved ) . rejects . toEqual ( new Error ( "Failed!" ) ) ;
283- expect ( loader . changeCount ) . toEqual ( 2 ) ;
284- expect ( loader . value ) . toEqual ( "failure" ) ;
222+ function * green ( ) {
223+ yield on ( "TIMER" , yellow ) ;
224+ }
225+ function * yellow ( ) {
226+ yield on ( "TIMER" , red ) ;
227+ }
228+ function * red ( ) {
229+ yield on ( "TIMER" , green ) ;
285230
286- loader . next ( "FETCH" ) ;
287- expect ( fetch ) . toHaveBeenCalledTimes ( 1 ) ;
288- expect ( loader . changeCount ) . toEqual ( 2 ) ;
231+ return walk ;
232+ }
289233
290- loader . next ( "RETRY" ) ;
291- expect ( loader . value ) . toEqual ( "loading" ) ;
292- expect ( loader . changeCount ) . toEqual ( 3 ) ;
234+ yield on ( "POWER_OUTAGE" , compound ( red , blinking ) ) ;
235+ yield on ( "POWER_RESTORED" , compound ( red ) ) ;
293236
294- expect ( fetch ) . toHaveBeenCalledTimes ( 2 ) ;
295- expect ( fetch ) . toHaveBeenLastCalledWith ( "https://example.org/" ) ;
237+ return green ;
238+ }
296239
297- await expect ( loader . resolved ) . resolves . toEqual ( [ 42 ] ) ;
298- expect ( loader . changeCount ) . toEqual ( 4 ) ;
299- expect ( loader . value ) . toEqual ( "success" ) ;
300- } ) ;
240+ test ( "sending events" , ( ) => {
241+ const machine = start ( TrafficLights ) ;
242+ expect ( machine ) . toBeDefined ( ) ;
243+ expect ( machine . value ) . toEqual ( "green" ) ;
244+
245+ machine . next ( "TIMER" ) ;
246+ expect ( machine . value ) . toEqual ( "yellow" ) ;
247+ expect ( machine . changeCount ) . toEqual ( 1 ) ;
248+
249+ machine . next ( "TIMER" ) ;
250+ // expect(machine.value).toEqual("red");
251+ // expect(machine.value).toEqual(["red", "walk"]);
252+ expect ( machine . value ) . toEqual ( { "red" : "walk" } ) ;
253+ expect ( machine . changeCount ) . toEqual ( 3 ) ;
254+
255+ machine . next ( "TIMER" ) ;
256+ expect ( machine . value ) . toEqual ( "green" ) ;
257+ expect ( machine . changeCount ) . toEqual ( 4 ) ;
258+
259+ machine . next ( "POWER_RESTORED" ) ;
260+ expect ( machine . value ) . toEqual ( { "red" : "walk" } ) ;
261+ expect ( machine . changeCount ) . toEqual ( 6 ) ;
262+
263+ machine . next ( "POWER_OUTAGE" ) ;
264+ expect ( machine . value ) . toEqual ( { "red" : "blinking" } ) ;
265+ expect ( machine . changeCount ) . toEqual ( 7 ) ;
301266 } ) ;
302267} ) ;
0 commit comments