66 */
77
88import { BasicTransitionStrategy } from './basic_strategy' ;
9+ import type { AlertEpisodeStatus , AlertEventStatus } from '../../../resources/alert_events' ;
910import { alertEpisodeStatus , alertEventStatus } from '../../../resources/alert_events' ;
1011import { createRuleResponse } from '../../test_utils' ;
1112import { buildLatestAlertEvent , buildStrategyStateTransitionContext } from '../test_utils' ;
@@ -17,6 +18,33 @@ describe('BasicTransitionStrategy', () => {
1718 strategy = new BasicTransitionStrategy ( ) ;
1819 } ) ;
1920
21+ const getNextState = ( ...args : Parameters < typeof buildStrategyStateTransitionContext > ) =>
22+ strategy . getNextState ( buildStrategyStateTransitionContext ( ...args ) ) ;
23+
24+ const expectTransition = ( {
25+ from,
26+ on,
27+ to,
28+ } : {
29+ from ?: AlertEpisodeStatus | null ;
30+ on : AlertEventStatus ;
31+ to : AlertEpisodeStatus ;
32+ } ) => {
33+ const result = getNextState ( {
34+ eventStatus : on ,
35+ ...( from !== undefined
36+ ? {
37+ previousEpisode : buildLatestAlertEvent ( {
38+ episodeStatus : from ,
39+ eventStatus : on ,
40+ } ) ,
41+ }
42+ : { } ) ,
43+ } ) ;
44+
45+ expect ( result ) . toEqual ( { status : to } ) ;
46+ } ;
47+
2048 it ( 'has name "basic"' , ( ) => {
2149 expect ( strategy . name ) . toBe ( 'basic' ) ;
2250 } ) ;
@@ -32,246 +60,101 @@ describe('BasicTransitionStrategy', () => {
3260
3361 describe ( 'no previous episode' , ( ) => {
3462 it ( 'returns pending when there is no previous episode' , ( ) => {
35- const result = strategy . getNextState (
36- buildStrategyStateTransitionContext ( {
37- eventStatus : alertEventStatus . breached ,
38- } )
39- ) ;
40- expect ( result ) . toEqual ( { status : alertEpisodeStatus . pending } ) ;
63+ expectTransition ( {
64+ on : alertEventStatus . breached ,
65+ to : alertEpisodeStatus . pending ,
66+ } ) ;
4167 } ) ;
4268
4369 it ( 'returns pending when previous episode status is null' , ( ) => {
44- const result = strategy . getNextState (
45- buildStrategyStateTransitionContext ( {
46- eventStatus : alertEventStatus . breached ,
47- previousEpisode : buildLatestAlertEvent ( {
48- episodeStatus : null ,
49- eventStatus : alertEventStatus . breached ,
50- } ) ,
51- } )
52- ) ;
53- expect ( result ) . toEqual ( { status : alertEpisodeStatus . pending } ) ;
70+ expectTransition ( {
71+ from : null ,
72+ on : alertEventStatus . breached ,
73+ to : alertEpisodeStatus . pending ,
74+ } ) ;
5475 } ) ;
5576
5677 it ( 'returns pending when the current state is unknown' , ( ) => {
57- const result = strategy . getNextState (
58- buildStrategyStateTransitionContext ( {
59- eventStatus : alertEventStatus . breached ,
60- previousEpisode : {
61- ...buildLatestAlertEvent ( {
62- episodeStatus : alertEpisodeStatus . pending ,
63- eventStatus : alertEventStatus . breached ,
64- } ) ,
65- // @ts -expect-error - unknown state testing
66- last_episode_status : 'unknown_state' ,
67- } ,
68- } )
69- ) ;
70- expect ( result ) . toEqual ( { status : alertEpisodeStatus . pending } ) ;
71- } ) ;
72- } ) ;
73-
74- describe ( 'state transitions from inactive' , ( ) => {
75- const currentState = alertEpisodeStatus . inactive ;
76-
77- it ( 'transitions to pending on breached event' , ( ) => {
78- const result = strategy . getNextState (
79- buildStrategyStateTransitionContext ( {
80- eventStatus : alertEventStatus . breached ,
81- previousEpisode : buildLatestAlertEvent ( {
82- episodeStatus : currentState ,
78+ const result = getNextState ( {
79+ eventStatus : alertEventStatus . breached ,
80+ previousEpisode : {
81+ ...buildLatestAlertEvent ( {
82+ episodeStatus : alertEpisodeStatus . pending ,
8383 eventStatus : alertEventStatus . breached ,
8484 } ) ,
85- } )
86- ) ;
85+ // @ts -expect-error - unknown state testing
86+ last_episode_status : 'unknown_state' ,
87+ } ,
88+ } ) ;
8789 expect ( result ) . toEqual ( { status : alertEpisodeStatus . pending } ) ;
8890 } ) ;
91+ } ) ;
8992
90- it ( 'stays inactive on recovered event' , ( ) => {
91- const result = strategy . getNextState (
92- buildStrategyStateTransitionContext ( {
93- eventStatus : alertEventStatus . recovered ,
94- previousEpisode : buildLatestAlertEvent ( {
95- episodeStatus : currentState ,
96- eventStatus : alertEventStatus . recovered ,
97- } ) ,
98- } )
99- ) ;
100- expect ( result ) . toEqual ( { status : alertEpisodeStatus . inactive } ) ;
101- } ) ;
102-
103- it ( 'stays inactive on no_data event' , ( ) => {
104- const result = strategy . getNextState (
105- buildStrategyStateTransitionContext ( {
106- eventStatus : alertEventStatus . no_data ,
107- previousEpisode : buildLatestAlertEvent ( {
108- episodeStatus : currentState ,
109- eventStatus : alertEventStatus . no_data ,
110- } ) ,
111- } )
112- ) ;
113- expect ( result ) . toEqual ( { status : alertEpisodeStatus . inactive } ) ;
93+ describe ( 'state transitions from inactive' , ( ) => {
94+ it . each < [ string , AlertEventStatus , AlertEpisodeStatus ] > ( [
95+ [ 'pending' , alertEventStatus . breached , alertEpisodeStatus . pending ] ,
96+ [ 'inactive' , alertEventStatus . recovered , alertEpisodeStatus . inactive ] ,
97+ [ 'inactive' , alertEventStatus . no_data , alertEpisodeStatus . inactive ] ,
98+ ] ) ( 'transitions to %s on %s event' , ( _label , on , to ) => {
99+ expectTransition ( { from : alertEpisodeStatus . inactive , on, to } ) ;
114100 } ) ;
115101 } ) ;
116102
117103 describe ( 'state transitions from pending' , ( ) => {
118- const currentState = alertEpisodeStatus . pending ;
119-
120- it ( 'transitions to active on breached event' , ( ) => {
121- const result = strategy . getNextState (
122- buildStrategyStateTransitionContext ( {
123- eventStatus : alertEventStatus . breached ,
124- previousEpisode : buildLatestAlertEvent ( {
125- episodeStatus : currentState ,
126- eventStatus : alertEventStatus . breached ,
127- } ) ,
128- } )
129- ) ;
130- expect ( result ) . toEqual ( { status : alertEpisodeStatus . active } ) ;
131- } ) ;
132-
133- it ( 'transitions to inactive on recovered event' , ( ) => {
134- const result = strategy . getNextState (
135- buildStrategyStateTransitionContext ( {
136- eventStatus : alertEventStatus . recovered ,
137- previousEpisode : buildLatestAlertEvent ( {
138- episodeStatus : currentState ,
139- eventStatus : alertEventStatus . recovered ,
140- } ) ,
141- } )
142- ) ;
143- expect ( result ) . toEqual ( { status : alertEpisodeStatus . inactive } ) ;
144- } ) ;
145-
146- it ( 'stays pending on no_data event' , ( ) => {
147- const result = strategy . getNextState (
148- buildStrategyStateTransitionContext ( {
149- eventStatus : alertEventStatus . no_data ,
150- previousEpisode : buildLatestAlertEvent ( {
151- episodeStatus : currentState ,
152- eventStatus : alertEventStatus . no_data ,
153- } ) ,
154- } )
155- ) ;
156- expect ( result ) . toEqual ( { status : alertEpisodeStatus . pending } ) ;
104+ it . each < [ string , AlertEventStatus , AlertEpisodeStatus ] > ( [
105+ [ 'active' , alertEventStatus . breached , alertEpisodeStatus . active ] ,
106+ [ 'inactive' , alertEventStatus . recovered , alertEpisodeStatus . inactive ] ,
107+ [ 'pending' , alertEventStatus . no_data , alertEpisodeStatus . pending ] ,
108+ ] ) ( 'transitions to %s on %s event' , ( _label , on , to ) => {
109+ expectTransition ( { from : alertEpisodeStatus . pending , on, to } ) ;
157110 } ) ;
158111 } ) ;
159112
160113 describe ( 'state transitions from active' , ( ) => {
161- const currentState = alertEpisodeStatus . active ;
162-
163- it ( 'stays active on breached event' , ( ) => {
164- const result = strategy . getNextState (
165- buildStrategyStateTransitionContext ( {
166- eventStatus : alertEventStatus . breached ,
167- previousEpisode : buildLatestAlertEvent ( {
168- episodeStatus : currentState ,
169- eventStatus : alertEventStatus . breached ,
170- } ) ,
171- } )
172- ) ;
173- expect ( result ) . toEqual ( { status : alertEpisodeStatus . active } ) ;
174- } ) ;
175-
176- it ( 'transitions to recovering on recovered event' , ( ) => {
177- const result = strategy . getNextState (
178- buildStrategyStateTransitionContext ( {
179- eventStatus : alertEventStatus . recovered ,
180- previousEpisode : buildLatestAlertEvent ( {
181- episodeStatus : currentState ,
182- eventStatus : alertEventStatus . recovered ,
183- } ) ,
184- } )
185- ) ;
186- expect ( result ) . toEqual ( { status : alertEpisodeStatus . recovering } ) ;
187- } ) ;
188-
189- it ( 'stays active on no_data event' , ( ) => {
190- const result = strategy . getNextState (
191- buildStrategyStateTransitionContext ( {
192- eventStatus : alertEventStatus . no_data ,
193- previousEpisode : buildLatestAlertEvent ( {
194- episodeStatus : currentState ,
195- eventStatus : alertEventStatus . no_data ,
196- } ) ,
197- } )
198- ) ;
199- expect ( result ) . toEqual ( { status : alertEpisodeStatus . active } ) ;
114+ it . each < [ string , AlertEventStatus , AlertEpisodeStatus ] > ( [
115+ [ 'active' , alertEventStatus . breached , alertEpisodeStatus . active ] ,
116+ [ 'recovering' , alertEventStatus . recovered , alertEpisodeStatus . recovering ] ,
117+ [ 'active' , alertEventStatus . no_data , alertEpisodeStatus . active ] ,
118+ ] ) ( 'transitions to %s on %s event' , ( _label , on , to ) => {
119+ expectTransition ( { from : alertEpisodeStatus . active , on, to } ) ;
200120 } ) ;
201121 } ) ;
202122
203123 describe ( 'state transitions from recovering' , ( ) => {
204- const currentState = alertEpisodeStatus . recovering ;
205-
206- it ( 'transitions to active on breached event' , ( ) => {
207- const result = strategy . getNextState (
208- buildStrategyStateTransitionContext ( {
209- eventStatus : alertEventStatus . breached ,
210- previousEpisode : buildLatestAlertEvent ( {
211- episodeStatus : currentState ,
212- eventStatus : alertEventStatus . breached ,
213- } ) ,
214- } )
215- ) ;
216- expect ( result ) . toEqual ( { status : alertEpisodeStatus . active } ) ;
217- } ) ;
218-
219- it ( 'transitions to inactive on recovered event' , ( ) => {
220- const result = strategy . getNextState (
221- buildStrategyStateTransitionContext ( {
222- eventStatus : alertEventStatus . recovered ,
223- previousEpisode : buildLatestAlertEvent ( {
224- episodeStatus : currentState ,
225- eventStatus : alertEventStatus . recovered ,
226- } ) ,
227- } )
228- ) ;
229- expect ( result ) . toEqual ( { status : alertEpisodeStatus . inactive } ) ;
230- } ) ;
231-
232- it ( 'stays recovering on no_data event' , ( ) => {
233- const result = strategy . getNextState (
234- buildStrategyStateTransitionContext ( {
235- eventStatus : alertEventStatus . no_data ,
236- previousEpisode : buildLatestAlertEvent ( {
237- episodeStatus : currentState ,
238- eventStatus : alertEventStatus . no_data ,
239- } ) ,
240- } )
241- ) ;
242- expect ( result ) . toEqual ( { status : alertEpisodeStatus . recovering } ) ;
124+ it . each < [ string , AlertEventStatus , AlertEpisodeStatus ] > ( [
125+ [ 'active' , alertEventStatus . breached , alertEpisodeStatus . active ] ,
126+ [ 'inactive' , alertEventStatus . recovered , alertEpisodeStatus . inactive ] ,
127+ [ 'recovering' , alertEventStatus . no_data , alertEpisodeStatus . recovering ] ,
128+ ] ) ( 'transitions to %s on %s event' , ( _label , on , to ) => {
129+ expectTransition ( { from : alertEpisodeStatus . recovering , on, to } ) ;
243130 } ) ;
244131 } ) ;
245132
246133 describe ( 'defensive fallbacks' , ( ) => {
247134 it ( 'returns pending for unknown current state' , ( ) => {
248- const result = strategy . getNextState (
249- buildStrategyStateTransitionContext ( {
250- eventStatus : alertEventStatus . breached ,
251- previousEpisode : {
252- ...buildLatestAlertEvent ( {
253- episodeStatus : alertEpisodeStatus . pending ,
254- eventStatus : alertEventStatus . breached ,
255- } ) ,
256- // @ts -expect-error - unknown state testing
257- last_episode_status : 'unknown_state' ,
258- } ,
259- } )
260- ) ;
135+ const result = getNextState ( {
136+ eventStatus : alertEventStatus . breached ,
137+ previousEpisode : {
138+ ...buildLatestAlertEvent ( {
139+ episodeStatus : alertEpisodeStatus . pending ,
140+ eventStatus : alertEventStatus . breached ,
141+ } ) ,
142+ // @ts -expect-error - unknown state testing
143+ last_episode_status : 'unknown_state' ,
144+ } ,
145+ } ) ;
261146 expect ( result ) . toEqual ( { status : alertEpisodeStatus . pending } ) ;
262147 } ) ;
263148
264149 it ( 'returns current state for unknown event status' , ( ) => {
265- const result = strategy . getNextState (
266- buildStrategyStateTransitionContext ( {
267- // @ts -expect-error - unknown event status testing
268- eventStatus : 'unknown_event' ,
269- previousEpisode : buildLatestAlertEvent ( {
270- episodeStatus : alertEpisodeStatus . active ,
271- eventStatus : alertEventStatus . breached ,
272- } ) ,
273- } )
274- ) ;
150+ const result = getNextState ( {
151+ // @ts -expect-error - unknown event status testing
152+ eventStatus : 'unknown_event' ,
153+ previousEpisode : buildLatestAlertEvent ( {
154+ episodeStatus : alertEpisodeStatus . active ,
155+ eventStatus : alertEventStatus . breached ,
156+ } ) ,
157+ } ) ;
275158 expect ( result ) . toEqual ( { status : alertEpisodeStatus . active } ) ;
276159 } ) ;
277160 } ) ;
0 commit comments