1
1
import { CaminoCommonContext , Etape } from './machine-common'
2
2
import { Actor , EventObject , createActor } from 'xstate'
3
- import { CaminoMachine , getNextEvents } from './machine-helper'
3
+ import { CaminoMachine } from './machine-helper'
4
4
import { expect } from 'vitest'
5
5
import { CaminoDate , dateAddDays , toCaminoDate } from 'camino-common/src/date'
6
6
import { EtapeTypeEtapeStatutValidPair } from 'camino-common/src/static/etapesTypesEtapesStatuts'
7
- import { isNotNullNorUndefined } from 'camino-common/src/typescript-tools'
7
+ import { isNotNullNorUndefined , onlyUnique } from 'camino-common/src/typescript-tools'
8
+ import { DemarchesStatuts } from 'camino-common/src/static/demarchesStatuts'
8
9
interface CustomMatchers < R = unknown > {
9
10
canOnlyTransitionTo < T extends EventObject , C extends CaminoCommonContext > ( context : { machine : CaminoMachine < C , T > ; date : CaminoDate } , _events : T [ 'type' ] [ ] ) : R
10
11
}
@@ -19,21 +20,18 @@ declare global {
19
20
interface InverseAsymmetricMatchers extends CustomMatchers { }
20
21
}
21
22
}
23
+
22
24
expect . extend ( {
23
25
canOnlyTransitionTo < T extends EventObject , C extends CaminoCommonContext > (
24
26
service : Actor < CaminoMachine < C , T > [ 'machine' ] > ,
25
27
{ machine, date } : { machine : CaminoMachine < C , T > ; date : CaminoDate } ,
26
28
events : T [ 'type' ] [ ]
27
29
) {
28
30
events = events . toSorted ( )
29
- const passEvents : ( typeof events ) [ number ] [ ] = getNextEvents ( service . getSnapshot ( ) )
30
- . filter ( ( event : string ) => machine . isEvent ( event ) )
31
- . filter ( ( event : ( typeof events ) [ number ] ) => {
32
- const events = machine . toPotentialCaminoXStateEvent ( event , date )
33
-
34
- return events . some ( event => service . getSnapshot ( ) . can ( event ) && service . getSnapshot ( ) . status !== 'done' )
35
- } )
36
- . toSorted ( )
31
+ const passEvents = machine
32
+ . possibleNextEvents ( service . getSnapshot ( ) , date )
33
+ . map ( ( { type } ) => type )
34
+ . filter ( onlyUnique )
37
35
38
36
if ( passEvents . length !== events . length || passEvents . some ( ( entry , index ) => entry !== events [ index ] ) ) {
39
37
return {
@@ -62,14 +60,10 @@ export const interpretMachine = <T extends EventObject, C extends CaminoCommonCo
62
60
throw new Error (
63
61
`Error: cannot execute step: '${ JSON . stringify ( etapeAFaire ) } ' after '${ JSON . stringify (
64
62
etapes . slice ( 0 , i ) . map ( etape => etape . etapeTypeId + '_' + etape . etapeStatutId )
65
- ) } '. The event ${ JSON . stringify ( event ) } should be one of '${ getNextEvents ( service . getSnapshot ( ) )
66
- . filter ( event => machine . isEvent ( event ) )
67
- . filter ( ( event : EventObject [ 'type' ] ) => {
68
- const events = machine . toPotentialCaminoXStateEvent ( event , etapeAFaire . date )
69
-
70
- return events . some ( event => service . getSnapshot ( ) . can ( event ) && service . getSnapshot ( ) . status !== 'done' )
71
- } )
72
- . toSorted ( ) } '`
63
+ ) } '. The event ${ JSON . stringify ( event ) } should be one of '${ machine
64
+ . possibleNextEvents ( service . getSnapshot ( ) , etapeAFaire . date )
65
+ . map ( ( { type } ) => type )
66
+ . filter ( onlyUnique ) } '`
73
67
)
74
68
}
75
69
service . send ( event )
@@ -78,11 +72,55 @@ export const interpretMachine = <T extends EventObject, C extends CaminoCommonCo
78
72
return service
79
73
}
80
74
75
+ export const getEventsTree = < T extends EventObject , C extends CaminoCommonContext > (
76
+ machine : CaminoMachine < C , T > ,
77
+ initDate : `${number } -${number } -${number } `,
78
+ etapes : readonly ( EtapeTypeEtapeStatutValidPair & Omit < Etape , 'date' | 'etapeTypeId' | 'etapeStatutId' | 'titreTypeId' | 'demarcheTypeId' > & { addDays ?: number } ) [ ]
79
+ ) : string [ ] => {
80
+ const { service, dateFin } = setDateAndOrderAndInterpretMachine ( machine , initDate , [ ] )
81
+ const passEvents : T [ 'type' ] [ ] = machine
82
+ . possibleNextEvents ( service . getSnapshot ( ) , dateFin )
83
+ . map ( ( { type } ) => type )
84
+ . filter ( onlyUnique )
85
+
86
+ const steps = [
87
+ {
88
+ type : 'RIEN' ,
89
+ visibilite : service . getSnapshot ( ) . context . visibilite ,
90
+ demarcheStatut : DemarchesStatuts [ service . getSnapshot ( ) . context . demarcheStatut ] . nom ,
91
+ events : passEvents ,
92
+ } ,
93
+ ...etapes . map ( ( _etape , index ) => {
94
+ const etapesToLaunch = etapes . slice ( 0 , index + 1 )
95
+ const { service, dateFin, etapes : etapesWithDates } = setDateAndOrderAndInterpretMachine ( machine , initDate , etapesToLaunch )
96
+
97
+ const passEvents : T [ 'type' ] [ ] = machine
98
+ . possibleNextEvents ( service . getSnapshot ( ) , dateFin )
99
+ . map ( ( { type } ) => type )
100
+ . filter ( onlyUnique )
101
+ const event = machine . eventFrom ( etapesWithDates [ etapesWithDates . length - 1 ] )
102
+
103
+ return {
104
+ type : event . type ,
105
+ visibilite : service . getSnapshot ( ) . context . visibilite ,
106
+ demarcheStatut : DemarchesStatuts [ service . getSnapshot ( ) . context . demarcheStatut ] . nom ,
107
+ events : passEvents ,
108
+ }
109
+ } ) ,
110
+ ]
111
+
112
+ const maxPadType = Math . max ( ...steps . map ( ( { type } ) => type . length ) )
113
+
114
+ return steps . map ( step => {
115
+ return `${ step . type . padEnd ( maxPadType , ' ' ) } (${ step . visibilite . padEnd ( 14 , ' ' ) } , ${ step . demarcheStatut . padEnd ( 23 , ' ' ) } ) -> [${ step . events . join ( ',' ) } ]`
116
+ } )
117
+ }
118
+
81
119
export const setDateAndOrderAndInterpretMachine = < T extends EventObject , C extends CaminoCommonContext > (
82
120
machine : CaminoMachine < C , T > ,
83
121
initDate : `${number } -${number } -${number } `,
84
122
etapes : readonly ( EtapeTypeEtapeStatutValidPair & Omit < Etape , 'date' | 'etapeTypeId' | 'etapeStatutId' | 'titreTypeId' | 'demarcheTypeId' > & { addDays ?: number } ) [ ]
85
- ) : { service : Actor < ( typeof machine ) [ 'machine' ] > ; dateFin : CaminoDate ; etapes : Etape [ ] } => {
123
+ ) : { service : Actor < ( typeof machine ) [ 'machine' ] > ; dateFin : CaminoDate ; etapes : Etape [ ] ; machine : CaminoMachine < C , T > } => {
86
124
const firstDate = toCaminoDate ( initDate )
87
125
let index = 0
88
126
const fullEtapes = etapes . map ( etape => {
@@ -96,7 +134,7 @@ export const setDateAndOrderAndInterpretMachine = <T extends EventObject, C exte
96
134
} )
97
135
const service = orderAndInterpretMachine ( machine , fullEtapes )
98
136
99
- return { service, dateFin : dateAddDays ( firstDate , etapes . length ) , etapes : fullEtapes }
137
+ return { service, dateFin : dateAddDays ( firstDate , etapes . length ) , etapes : fullEtapes , machine }
100
138
}
101
139
export const orderAndInterpretMachine = < T extends EventObject , C extends CaminoCommonContext > (
102
140
machine : CaminoMachine < C , T > ,
0 commit comments