@peter.naydenov/cuts 1.4.5 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -18,20 +18,20 @@ function show ( dependencies, state ) {
18
18
  { shortcutMngr, askForPromise, log, findInstructions, setInstruction } = dependencies
19
19
  , showTask = askForPromise ()
20
20
  , unloadTask = askForPromise ()
21
- , { opened, scenes, sceneNames, currentPage } = state
21
+ , { opened, scenes, sceneNames, currentScene } = state
22
+ , hasBeforeHide = currentScene && (typeof scenes[currentScene].beforeHide === 'function')
22
23
  ;
23
24
 
24
- if ( currentPage ) { // Execute 'beforeUnload' function if exists
25
- const closingFn = scenes[currentPage].beforeHide;
26
- if ( typeof closingFn === 'function' ) {
27
- closingFn ({ done:unloadTask.done, dependencies: shortcutMngr.getDependencies() })
28
- }
29
- } // if currentPage
25
+ if ( hasBeforeHide ) { // Execute 'beforeUnload' function if exists
26
+ const closingFn = scenes[currentScene].beforeHide;
27
+ // TODO: If async elements in beforeUnload, we will
28
+ // need full unloadTask and function should return a promise
29
+ closingFn ({ done:unloadTask.done, dependencies: shortcutMngr.getDependencies() })
30
+ } // if currentScene
30
31
  else unloadTask.done ( true )
31
32
 
32
33
 
33
34
  unloadTask.onComplete ( continueLoading => {
34
-
35
35
  if ( !continueLoading ) {
36
36
  // if the 'beforeUnload' function returns false
37
37
  // Cancel loading the new scene
@@ -40,21 +40,19 @@ function show ( dependencies, state ) {
40
40
  }
41
41
 
42
42
  if ( !sceneNames.has ( requestedScene ) ) {
43
- if ( log ) {
44
- log ({
45
- message: `Scene ${requestedScene} is not available.`
46
- , level : 1
47
- , type : 'error'
48
- })
49
- showTask.done ()
50
- return showTask.promise
51
- }
43
+ log ({
44
+ message: `Scene "${requestedScene}" is not available.`
45
+ , level : 1
46
+ , type : 'error'
47
+ })
48
+ showTask.done ()
49
+ return showTask.promise
52
50
  }
53
51
 
54
52
  if ( !opened && options.ssr ) { // Check for Server side rendering on first scene load only
55
53
  // Executes only once when the scene manager is started
56
54
  state.opened = true
57
- state.currentPage = requestedScene
55
+ state.currentScene = requestedScene
58
56
  shortcutMngr.changeContext ( requestedScene )
59
57
  showTask.done ()
60
58
  return showTask.promise
@@ -62,33 +60,33 @@ function show ( dependencies, state ) {
62
60
 
63
61
  const { show, parents=[] } = scenes[requestedScene];
64
62
 
65
- if ( parents[0] === '*' ) {
66
- show ().then ( () => showTask.done () )
67
- state.currentParents.push ( state.currentPage )
68
- state.currentPage = requestedScene
69
- return showTask.promise
70
- }
63
+ if ( parents[0] === '*' ) {
64
+ const overlayTask = setInstruction(show, ...args)()
65
+ overlayTask.then ( () => showTask.done () )
66
+ state.currentParents.push ( state.currentScene )
67
+ state.currentScene = requestedScene
68
+ return showTask.promise
69
+ }
70
+
71
+ let checkParents = ( parents.length === 0 ) ? true : parents.every ( name => sceneNames.has ( name ) )
71
72
 
72
- let checkParents = parents.forEach ( name => sceneNames.has ( name ) ) || true ;
73
73
  if ( !checkParents ) {
74
- if ( log ) {
75
- log ({
76
- message: `Some of '${requestedScene}' parent scenes are not set.`
77
- , level : 1
78
- , type : 'error'
79
- })
80
- }
74
+ log ({
75
+ message: `Some of '${requestedScene}' parent scenes are not set.`
76
+ , level : 1
77
+ , type : 'error'
78
+ })
81
79
  showTask.done ()
82
80
  return showTask.promise
83
81
  }
84
82
 
85
- function getStep ([name, action]) { // Returns a scene function(hide or show) according to instructions
83
+ function getStep ([name, action]) { // Returns a scene function(hide or show) according to instructions
86
84
  if ( action === 'show' ) {
87
- if ( state.currentScene ) state.currentParents.push ( state.currentScene )
85
+ if ( state.currentScene ) state.currentParents = [...scenes[state.currentScene].parents]
88
86
  state.currentScene = name
89
87
  }
90
88
  else {
91
- let el = state.currentParents.pop ();
89
+ let el = scenes[name].parents.at ( -1 )
92
90
  state.currentScene = el
93
91
  }
94
92
  return scenes[name][action]
@@ -96,22 +94,22 @@ function show ( dependencies, state ) {
96
94
 
97
95
  if ( !state.currentParents ) state.currentParents = []
98
96
  const
99
- g = findInstructions ( state.currentScene, state.currentParents, requestedScene, parents )
97
+ g = findInstructions ( state.currentScene, state.currentParents, requestedScene, parents )
100
98
  , instructions = []
101
99
  ;
102
-
103
- for ( let inst of g ) {
104
- [inst]
105
- .map ( getStep )
106
- .map ( step => instructions.push ( setInstruction(step),...args ))
107
- // Note: Methods 'show' and 'hide' are async, but we need to provide them a data,
108
- // so we need to wrap them in a another function that returns a promise
109
- }
110
-
100
+
101
+ for ( let inst of g ) {
102
+ const step = getStep ( inst )
103
+ instructions.push ( setInstruction(step, ...args) )
104
+ // Note: Methods 'show' and 'hide' are async, but we need to provide them a data,
105
+ // so we need to wrap them in a another function that returns a promise
106
+ }
111
107
  const goingTask = askForPromise.sequence ( instructions ); // Execute open steps(show and hide) in sequence
112
108
 
113
109
  goingTask.onComplete ( () => {
114
110
  state.opened = true
111
+ state.currentScene = requestedScene
112
+ state.currentParents = scenes[requestedScene].parents || null
115
113
  shortcutMngr.changeContext ( requestedScene )
116
114
  if ( typeof scenes[requestedScene].afterShow === 'function' ) scenes[requestedScene].afterShow ({ dependencies: shortcutMngr.getDependencies(), done: () => {} })
117
115
  showTask.done ()
@@ -7,9 +7,9 @@ describe ( 'Find a Position', () => {
7
7
 
8
8
 
9
9
 
10
- it ( 'Switch top level pages', () => {
10
+ it ( 'Switch top level scenes', () => {
11
11
  let result = []
12
- let g = findInstructions ( 'old', undefined, 'new', undefined )
12
+ let g = findInstructions ( 'old', [], 'new', [] )
13
13
 
14
14
  for (const n of g) { result.push(n) }
15
15
 
@@ -19,13 +19,13 @@ describe ( 'Find a Position', () => {
19
19
 
20
20
  expect(result[1][0]).toBe ( 'new' )
21
21
  expect(result[1][1]).toBe ( 'show' )
22
- }) // it switch top level pages
22
+ }) // it switch top level scenes
23
23
 
24
24
 
25
25
 
26
- it ( 'Switch from child page to top level page', () => {
26
+ it ( 'Switch from child scene to top level scene', () => {
27
27
  let result = []
28
- let g = findInstructions ( 'old', ['one', 'two'], 'new', undefined )
28
+ let g = findInstructions ( 'old', ['one', 'two'], 'new', [] )
29
29
 
30
30
  for (const n of g) { result.push(n) }
31
31
 
@@ -33,11 +33,11 @@ describe ( 'Find a Position', () => {
33
33
  expect(result[1]).toEqual(['two', 'hide'])
34
34
  expect(result[2]).toEqual(['one', 'hide'])
35
35
  expect(result[3]).toEqual(['new', 'show'])
36
- }) // it switch from child page to top level page
36
+ }) // it switch from child scene to top level scene
37
37
 
38
38
 
39
39
 
40
- it ( 'Switch to child page', () => {
40
+ it ( 'Switch to child scene', () => {
41
41
  let result = []
42
42
  let g = findInstructions ( 'old', ['bla'], 'new', ['old', 'two', 'three'])
43
43
  for (const n of g) { result.push(n) }
@@ -46,23 +46,23 @@ describe ( 'Find a Position', () => {
46
46
  expect(result[0]).toEqual(['two', 'show'])
47
47
  expect(result[1]).toEqual(['three', 'show'])
48
48
  expect(result[2]).toEqual(['new', 'show'])
49
- }) // it switch to child page
49
+ }) // it switch to child scene
50
50
 
51
51
 
52
52
 
53
- it ( 'From child page to other siblings page', () => {
53
+ it ( 'From child scene to other siblings scene', () => {
54
54
  let result = []
55
55
  let g = findInstructions('old', ['two', 'three'], 'new', ['two', 'three'])
56
56
  for (const n of g) { result.push(n) }
57
57
 
58
58
  expect(result).toHaveLength ( 2 )
59
59
  expect(result[0]).toEqual(['old', 'hide'])
60
- expect(result[1]).toEqual(['new', 'show'])
61
- }) // it from top level page to not own child page
60
+ expect(result[1]).toEqual(['new', 'show'])
61
+ }) // it from top level scene to not own child scene
62
62
 
63
63
 
64
64
 
65
- it ( 'From top level page to not own child page', () => {
65
+ it ( 'From top level scene to not own child scene', () => {
66
66
  let result = []
67
67
  let g = findInstructions('old', undefined, 'new', ['two', 'three'])
68
68
  for (const n of g) { result.push(n) }
@@ -70,8 +70,8 @@ describe ( 'Find a Position', () => {
70
70
  expect(result).toHaveLength(3)
71
71
  expect(result[0]).toEqual(['old', 'hide'])
72
72
  expect(result[1]).toEqual(['two', 'show'])
73
- expect(result[2]).toEqual(['three', 'show'])
74
- }) // it from top level page to not own child page
73
+ expect(result[2]).toEqual(['three', 'show'])
74
+ }) // it from top level scene to not own child scene
75
75
 
76
76
 
77
77
 
@@ -105,4 +105,15 @@ describe ( 'Find a Position', () => {
105
105
  expect(result[6]).toEqual(['new', 'show'])
106
106
  }) // it long chain of parents
107
107
 
108
+
109
+
110
+ it ( 'Target scene is in the list of parents of the current scene', () => {
111
+ let result = []
112
+ let g = findInstructions ( 'token-get-role', ['tokens', 'token-pop'], 'tokens', [] )
113
+ for (const n of g) { result.push(n) }
114
+ expect ( result ).toHaveLength ( 2 )
115
+ expect ( result[0] ).toEqual ( [ 'token-get-role', 'hide' ])
116
+ expect ( result[1] ).toEqual ( [ 'token-pop', 'hide' ])
117
+ }) // it Target scene is in the list of parents of the current scene
118
+
108
119
  }) // describe
@@ -0,0 +1,412 @@
1
+ import { describe, it, expect } from 'vitest'
2
+ import cuts from "../src/main.js"
3
+
4
+
5
+
6
+ describe ( 'Cuts integration', () => {
7
+
8
+
9
+
10
+ it ( 'Open a scene, and 2 levels deep child', async () => {
11
+ const calls = [];
12
+
13
+ const scenes = [
14
+ { name: 'top', scene: { show: ({task}) => { calls.push('show top'); task.done() }, hide: ({task}) => { calls.push('hide top'); task.done() } } },
15
+ { name: 'mid', scene: { show: ({task}) => { calls.push('show mid'); task.done() }, hide: ({task}) => { calls.push('hide mid'); task.done() }, parents: ['top'] } },
16
+ { name: 'deep', scene: { show: ({task}) => { calls.push('show deep'); task.done() }, hide: ({task}) => { calls.push('hide deep'); task.done() }, parents: ['top', 'mid'] } }
17
+ ]
18
+
19
+ const script = cuts();
20
+ script.setScenes ( scenes )
21
+
22
+ await script.show ({ scene: 'top' })
23
+ expect ( calls ).toEqual ([ 'show top' ])
24
+
25
+ await script.show ({ scene: 'deep' })
26
+ expect ( calls ).toEqual ([
27
+ 'show top',
28
+ 'show mid',
29
+ 'show deep'
30
+ ])
31
+
32
+ await script.show ({ scene: 'top' })
33
+ expect ( calls ).toEqual ([
34
+ 'show top',
35
+ 'show mid',
36
+ 'show deep',
37
+ 'hide deep',
38
+ 'hide mid'
39
+ ])
40
+
41
+ await script.show ({ scene: 'deep' })
42
+ expect ( calls ).toEqual ([
43
+ 'show top',
44
+ 'show mid',
45
+ 'show deep',
46
+ 'hide deep',
47
+ 'hide mid',
48
+ 'show mid',
49
+ 'show deep'
50
+ ])
51
+ }) // it Open a scene, and 2 levels deep child
52
+
53
+
54
+
55
+ it ( 'Load plugins', async () => {
56
+ const script = cuts()
57
+ const plugins = await script.loadPlugins ( ['Key', 'Click'] )
58
+ expect ( plugins ).toHaveLength ( 2 )
59
+ }) // it Load plugins
60
+
61
+
62
+
63
+
64
+
65
+
66
+
67
+ it ( 'beforeHide', async () => {
68
+ const script = cuts ();
69
+ const calls = [];
70
+ const scenes = [
71
+ {
72
+ name: 'top'
73
+ , scene: {
74
+ show: ({task}) => { calls.push('show top'); task.done() },
75
+ hide: ({task}) => { calls.push('hide top'); task.done() } ,
76
+ // Prevent unload event:
77
+ 'beforeHide': ({ done }) => done ( false ) ,
78
+ 'click: left-1': () => calls.push('click left-1')
79
+ }
80
+ },
81
+ {
82
+ name: 'other'
83
+ , scene: {
84
+ show: ({task}) => { calls.push('show other'); task.done() },
85
+ hide: ({task}) => { calls.push('hide other'); task.done() }
86
+ }
87
+ }
88
+ ];
89
+
90
+ script.setScenes ( scenes )
91
+ await script.show ({ scene: 'top' })
92
+ expect ( calls ).toEqual (['show top'])
93
+
94
+ await script.show ({ scene: 'other' })
95
+ expect ( calls ).toEqual (['show top'])
96
+ expect ( script.getState().scene ).toEqual ( 'top' )
97
+ }) // it beforeHide
98
+
99
+
100
+
101
+ it ( 'Call no existing scene', async () => {
102
+ const script = cuts ({ logLevel : 1 });
103
+ const calls = [];
104
+ const scenes = [
105
+ {
106
+ name: 'top'
107
+ , scene: {
108
+ show: ({task}) => { calls.push('show top'); task.done() },
109
+ hide: ({task}) => { calls.push('hide top'); task.done() } ,
110
+ 'click: left-1': () => calls.push ( 'click left-1' ),
111
+ '@app-error': ( arg ) => {
112
+ calls.push ( 'app-error' )
113
+ expect ( arg.type ).toBe ( 'error' )
114
+ expect ( arg.message ).toBe ( 'Scene "any" is not available.' )
115
+ }
116
+ }
117
+ },
118
+ {
119
+ name: 'other'
120
+ , scene: {
121
+ show: ({task}) => { calls.push('show other'); task.done() },
122
+ hide: ({task}) => { calls.push('hide other'); task.done() }
123
+ }
124
+ }
125
+ ];
126
+
127
+ script.setScenes ( scenes )
128
+ await script.show ({ scene: 'top' })
129
+ expect ( calls ).toEqual (['show top'])
130
+
131
+ await script.show ({ scene: 'any' })
132
+ expect ( calls ).toEqual (['show top', 'app-error'])
133
+ expect ( script.getState().scene ).toEqual ( 'top' )
134
+ }) // it Call no existing scene
135
+
136
+
137
+
138
+ it ( 'Server side rendering (SSR)', async () => {
139
+ const script = cuts ();
140
+ const calls = [];
141
+ const scenes = [
142
+ {
143
+ name: 'home',
144
+ scene: {
145
+ show: ({task}) => { calls.push('show home'); task.done() },
146
+ hide: ({task}) => { calls.push('hide home'); task.done() }
147
+ }
148
+ }
149
+ ];
150
+
151
+ script.setScenes ( scenes )
152
+
153
+ // SSR mode: show without executing the scene's show function
154
+ await script.show({ scene: 'home', options: { ssr: true } })
155
+
156
+ expect(calls).toEqual([]); // show function should not be called
157
+ expect(script.getState().scene ).toBe ( 'home' )
158
+ expect(script.getState().opened ).toBe ( true )
159
+
160
+ // Subsequent show should execute normally
161
+ await script.show ({ scene: 'home' })
162
+ expect( calls ).toEqual(['hide home', 'show home'])
163
+ }) // it Server side rendering (SSR)
164
+
165
+
166
+
167
+ it ( 'Non existing parents error', async () => {
168
+ const script = cuts ();
169
+ const calls = [];
170
+ const scenes = [
171
+ {
172
+ name: 'child'
173
+ , scene: {
174
+ show: ({task}) => { calls.push('show child'); task.done() },
175
+ hide: ({task}) => { calls.push('hide child'); task.done() },
176
+ parents: [ 'nonexistent' ]
177
+ }
178
+ }
179
+ ];
180
+ script.setScenes ( scenes )
181
+ await script.show ({ scene: 'child' })
182
+ expect ( calls ).toEqual ([])
183
+ expect ( script.getState().scene ).toBe ( null )
184
+ }) // it Non existing parents error
185
+
186
+
187
+
188
+ it ( 'No name scene', async () => {
189
+ const script = cuts({ logLevel : 0 });
190
+ const scenes = [
191
+ {
192
+ scene: {
193
+ show: ({task}) => task.done(),
194
+ hide: ({task}) => task.done()
195
+ }
196
+ }
197
+ ];
198
+ script.setScenes ( scenes );
199
+ expect ( script.listScenes() ).toEqual ( [] );
200
+ }) // it No name scene
201
+
202
+
203
+
204
+ it ( 'No scene in definition', async () => {
205
+ const script = cuts({ logLevel : 0 });
206
+ const scenes = [ {name: 'top'} ];
207
+ script.setScenes ( scenes );
208
+ expect ( script.listScenes() ).toEqual ( [] );
209
+ }) // it No scene in definition
210
+
211
+
212
+
213
+ it ( 'List shortcuts', async () => {
214
+ const script = cuts ()
215
+ const calls = [];
216
+
217
+ const scenes = [
218
+ {
219
+ name: 'top'
220
+ , scene: {
221
+ show: ({task}) => { calls.push('show top'); task.done() },
222
+ hide: ({task}) => { calls.push('hide top'); task.done() } ,
223
+ 'click: left-1': () => calls.push('click left-1')
224
+ }
225
+ }
226
+ ];
227
+
228
+ script.setScenes ( scenes )
229
+ expect ( script.listShortcuts( 'top' ) ).toEqual ( ['click: left-1'] )
230
+ }) // it List shortcuts
231
+
232
+
233
+
234
+ it ( 'List shortcuts', async () => {
235
+ const script = cuts ()
236
+ const calls = [];
237
+
238
+ const scenes = [
239
+ {
240
+ name: 'top'
241
+ , scene: {
242
+ show: ({task}) => { calls.push('show top'); task.done() },
243
+ hide: ({task}) => { calls.push('hide top'); task.done() } ,
244
+ 'click: left-1': () => calls.push('click left-1')
245
+ }
246
+ }
247
+ ];
248
+
249
+ script.setScenes ( scenes )
250
+ expect ( script.listShortcuts( 'none' ) ).toEqual ( null )
251
+ }) // it List shortcuts
252
+
253
+
254
+
255
+ it ( 'Jump functionality', async () => {
256
+ const script = cuts({ logLevel : 0 });
257
+ const calls = [];
258
+ const scenes = [
259
+ {
260
+ name: 'home'
261
+ , scene: {
262
+ show: ({task}) => { calls.push('show home'); task.done() },
263
+ hide: ({task}) => { calls.push('hide home'); task.done() }
264
+ }
265
+ },
266
+ {
267
+ name: 'settings'
268
+ , scene: {
269
+ show: ({task}) => { calls.push('show settings'); task.done() },
270
+ hide: ({task}) => { calls.push('hide settings'); task.done() }
271
+ }
272
+ }
273
+ ];
274
+
275
+ script.setScenes ( scenes );
276
+
277
+ await script.show ({ scene: 'home' });
278
+ expect ( calls ).toEqual (['show home']);
279
+ expect ( script.getState().scene ).toEqual ( 'home' );
280
+
281
+ await script.jump ({ scene: 'settings' });
282
+ expect ( calls ).toEqual (['show home', 'hide home', 'show settings']);
283
+ expect ( script.getState().scene ).toEqual ( 'settings' );
284
+
285
+ await script.jumpBack ();
286
+ expect ( calls ).toEqual (['show home', 'hide home', 'show settings', 'hide settings', 'show home']);
287
+ expect ( script.getState().scene ).toEqual ( 'home' );
288
+ }) // it Jump functionality
289
+
290
+
291
+
292
+ it ( 'Jump with hops', async () => {
293
+ const script = cuts();
294
+ const calls = [];
295
+ const scenes = [
296
+ {
297
+ name: 'scene1'
298
+ , scene: {
299
+ show: ({task}) => { calls.push('show scene1'); task.done() },
300
+ hide: ({task}) => { calls.push('hide scene1'); task.done() }
301
+ }
302
+ },
303
+ {
304
+ name: 'scene2'
305
+ , scene: {
306
+ show: ({task}) => { calls.push('show scene2'); task.done() },
307
+ hide: ({task}) => { calls.push('hide scene2'); task.done() }
308
+ }
309
+ },
310
+ {
311
+ name: 'scene3'
312
+ , scene: {
313
+ show: ({task}) => { calls.push('show scene3'); task.done() },
314
+ hide: ({task}) => { calls.push('hide scene3'); task.done() }
315
+ }
316
+ }
317
+ ];
318
+
319
+ script.setScenes ( scenes );
320
+
321
+ await script.show ({ scene: 'scene1' });
322
+ expect ( script.getState().scene ).toEqual ( 'scene1' );
323
+
324
+ await script.jump ({ scene: 'scene2' });
325
+ expect ( script.getState().scene ).toEqual ( 'scene2' );
326
+
327
+ await script.jump ({ scene: 'scene3' });
328
+ expect ( script.getState().scene ).toEqual ( 'scene3' );
329
+
330
+ await script.jumpBack ({ hops: 2 });
331
+ expect ( script.getState().scene ).toEqual ( 'scene1' );
332
+ }) // it Jump with hops
333
+
334
+
335
+
336
+ it ( 'Jumps reset and jump back on empty stack', async () => {
337
+ const script = cuts();
338
+ const scenes = [
339
+ {
340
+ name: 'scene1'
341
+ , scene: {
342
+ show: ({task}) => task.done(),
343
+ hide: ({task}) => task.done()
344
+ }
345
+ },
346
+ {
347
+ name: 'scene2'
348
+ , scene: {
349
+ show: ({task}) => task.done(),
350
+ hide: ({task}) => task.done()
351
+ }
352
+ }
353
+ ];
354
+
355
+ script.setScenes ( scenes );
356
+
357
+ await script.show ({ scene: 'scene1' });
358
+ await script.jump ({ scene: 'scene2' });
359
+ expect ( script.getState().scene ).toEqual ( 'scene2' );
360
+
361
+ script.jumpsReset();
362
+
363
+ const result = await script.jumpBack();
364
+ expect ( result ).toBeUndefined();
365
+ expect ( script.getState().scene ).toEqual ( 'scene2' ); // scene should not change
366
+ }) // it Jumps reset and jump back on empty stack
367
+
368
+
369
+
370
+ it ( 'Show scene with wildcard parent', async () => {
371
+ // Test for scenes with parents: ['*']
372
+ // The '*' wildcard allows the scene to be shown as an overlay over any current scene
373
+ // without hiding the underlying scene. The previous scene is preserved in currentParents.
374
+ const script = cuts();
375
+ const calls = [];
376
+ const scenes = [
377
+ {
378
+ name: 'base'
379
+ , scene: {
380
+ show: ({task}) => { calls.push('show base'); task.done() },
381
+ hide: ({task}) => { calls.push('hide base'); task.done() }
382
+ }
383
+ },
384
+ {
385
+ name: 'overlay' // This scene uses '*' to indicate it can overlay any scene
386
+ , scene: {
387
+ show: ({task}) => {
388
+ calls.push ( 'show overlay' )
389
+ task.done ()
390
+ },
391
+ hide: ({task}) => { calls.push('hide overlay'); task.done() },
392
+ parents: ['*'] // '*' means this scene can be shown over any current scene
393
+ }
394
+ }
395
+ ];
396
+
397
+ script.setScenes ( scenes );
398
+
399
+ await script.show ({ scene: 'base' });
400
+ expect ( calls ).toEqual (['show base']);
401
+ expect ( script.getState().scene ).toEqual ( 'base' );
402
+ expect ( script.getState().parents ).toEqual ( [] );
403
+
404
+ await script.show ({ scene: 'overlay' });
405
+ expect ( calls ).toEqual (['show base', 'show overlay']); // Note: 'hide base' is not called
406
+ expect ( script.getState().scene ).toEqual ( 'overlay' );
407
+ expect ( script.getState().parents ).toEqual ( ['base'] ); // Previous scene is saved
408
+ }) // it Show scene with wildcard parent
409
+
410
+
411
+
412
+ }) // describe