@player-ui/async-node-plugin 0.8.0-next.4 → 0.8.0-next.5
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.
- package/dist/AsyncNodePlugin.native.js +249 -262
- package/dist/AsyncNodePlugin.native.js.map +1 -1
- package/dist/cjs/index.cjs +23 -16
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/index.legacy-esm.js +23 -16
- package/dist/index.mjs +23 -16
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/src/index.test.ts +421 -401
- package/src/index.ts +31 -17
- package/types/index.d.ts +1 -0
package/src/index.test.ts
CHANGED
|
@@ -1,549 +1,569 @@
|
|
|
1
|
-
import { expect, test,
|
|
1
|
+
import { expect, test, describe } from "vitest";
|
|
2
2
|
import { Node, InProgressState, ViewInstance } from "@player-ui/player";
|
|
3
|
-
import { Player } from "@player-ui/player";
|
|
3
|
+
import { Player, Parser } from "@player-ui/player";
|
|
4
4
|
import { waitFor } from "@testing-library/react";
|
|
5
5
|
import { AsyncNodePlugin, AsyncNodePluginPlugin } from "./index";
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
7
|
+
describe("view", () => {
|
|
8
|
+
const basicFRFWithActions = {
|
|
9
|
+
id: "test-flow",
|
|
10
|
+
views: [
|
|
11
|
+
{
|
|
12
|
+
id: "my-view",
|
|
13
|
+
actions: [
|
|
14
|
+
{
|
|
15
|
+
asset: {
|
|
16
|
+
id: "action-0",
|
|
17
|
+
type: "action",
|
|
18
|
+
value: "{{foo.bar}}",
|
|
19
|
+
},
|
|
18
20
|
},
|
|
21
|
+
{
|
|
22
|
+
id: "nodeId",
|
|
23
|
+
async: "true",
|
|
24
|
+
},
|
|
25
|
+
],
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
navigation: {
|
|
29
|
+
BEGIN: "FLOW_1",
|
|
30
|
+
FLOW_1: {
|
|
31
|
+
startState: "VIEW_1",
|
|
32
|
+
VIEW_1: {
|
|
33
|
+
state_type: "VIEW",
|
|
34
|
+
ref: "my-view",
|
|
35
|
+
transitions: {},
|
|
19
36
|
},
|
|
20
|
-
{
|
|
21
|
-
id: "nodeId",
|
|
22
|
-
async: "true",
|
|
23
|
-
},
|
|
24
|
-
],
|
|
25
|
-
},
|
|
26
|
-
],
|
|
27
|
-
navigation: {
|
|
28
|
-
BEGIN: "FLOW_1",
|
|
29
|
-
FLOW_1: {
|
|
30
|
-
startState: "VIEW_1",
|
|
31
|
-
VIEW_1: {
|
|
32
|
-
state_type: "VIEW",
|
|
33
|
-
ref: "my-view",
|
|
34
|
-
transitions: {},
|
|
35
37
|
},
|
|
36
38
|
},
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
|
+
};
|
|
39
40
|
|
|
40
|
-
const asyncNodeTest = async (resolvedValue: any) => {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
const asyncNodeTest = async (resolvedValue: any) => {
|
|
42
|
+
const plugin = new AsyncNodePlugin({
|
|
43
|
+
plugins: [new AsyncNodePluginPlugin()],
|
|
44
|
+
});
|
|
44
45
|
|
|
45
|
-
|
|
46
|
+
let deferredResolve: ((value: any) => void) | undefined;
|
|
46
47
|
|
|
47
|
-
|
|
48
|
+
let updateContent: any;
|
|
48
49
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
50
|
+
plugin.hooks.onAsyncNode.tap(
|
|
51
|
+
"test",
|
|
52
|
+
async (node: Node.Async, update: (content: any) => void) => {
|
|
53
|
+
const result = new Promise((resolve) => {
|
|
54
|
+
deferredResolve = resolve; // Promise would be resolved only once
|
|
55
|
+
});
|
|
55
56
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
57
|
+
updateContent = update;
|
|
58
|
+
// Return the result to follow the same mechanism as before
|
|
59
|
+
return result;
|
|
60
|
+
},
|
|
61
|
+
);
|
|
61
62
|
|
|
62
|
-
|
|
63
|
+
let updateNumber = 0;
|
|
63
64
|
|
|
64
|
-
|
|
65
|
+
const player = new Player({ plugins: [plugin] });
|
|
65
66
|
|
|
66
|
-
|
|
67
|
+
let viewInstance: ViewInstance | undefined;
|
|
67
68
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
69
|
+
player.hooks.viewController.tap("async-node-test", (vc) => {
|
|
70
|
+
vc.hooks.view.tap("async-node-test", (view) => {
|
|
71
|
+
viewInstance = view;
|
|
72
|
+
view.hooks.onUpdate.tap("async-node-test", () => {
|
|
73
|
+
updateNumber++;
|
|
74
|
+
});
|
|
73
75
|
});
|
|
74
76
|
});
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
player.start(basicFRFWithActions as any);
|
|
78
77
|
|
|
79
|
-
|
|
80
|
-
?.lastUpdate;
|
|
78
|
+
player.start(basicFRFWithActions as any);
|
|
81
79
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
expect(view?.actions[1]).toBeUndefined();
|
|
80
|
+
let view = (player.getState() as InProgressState).controllers.view
|
|
81
|
+
.currentView?.lastUpdate;
|
|
85
82
|
|
|
86
|
-
|
|
87
|
-
expect(
|
|
88
|
-
|
|
83
|
+
expect(view).toBeDefined();
|
|
84
|
+
expect(view?.actions[0].asset.type).toBe("action");
|
|
85
|
+
expect(view?.actions[1]).toBeUndefined();
|
|
89
86
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
87
|
+
await waitFor(() => {
|
|
88
|
+
expect(deferredResolve).toBeDefined();
|
|
89
|
+
});
|
|
94
90
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
91
|
+
// Consumer responds with null/undefined
|
|
92
|
+
if (deferredResolve) {
|
|
93
|
+
deferredResolve(resolvedValue);
|
|
94
|
+
}
|
|
98
95
|
|
|
99
|
-
|
|
100
|
-
|
|
96
|
+
await waitFor(() => {
|
|
97
|
+
expect(updateNumber).toBe(1);
|
|
98
|
+
});
|
|
101
99
|
|
|
102
|
-
|
|
103
|
-
|
|
100
|
+
view = (player.getState() as InProgressState).controllers.view.currentView
|
|
101
|
+
?.lastUpdate;
|
|
104
102
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
updateContent(resolvedValue);
|
|
108
|
-
}
|
|
103
|
+
expect(view?.actions[0].asset.type).toBe("action");
|
|
104
|
+
expect(view?.actions.length).toBe(1);
|
|
109
105
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
106
|
+
// Consumer responds with null/undefined
|
|
107
|
+
if (deferredResolve) {
|
|
108
|
+
updateContent(resolvedValue);
|
|
109
|
+
}
|
|
114
110
|
|
|
115
|
-
|
|
116
|
-
|
|
111
|
+
//Even after an update, the view should not change as we are deleting the resolved node if there is no view update
|
|
112
|
+
await waitFor(() => {
|
|
113
|
+
expect(updateNumber).toBe(1);
|
|
114
|
+
});
|
|
117
115
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
};
|
|
116
|
+
view = (player.getState() as InProgressState).controllers.view.currentView
|
|
117
|
+
?.lastUpdate;
|
|
121
118
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
}
|
|
119
|
+
expect(view?.actions[0].asset.type).toBe("action");
|
|
120
|
+
expect(view?.actions.length).toBe(1);
|
|
121
|
+
};
|
|
125
122
|
|
|
126
|
-
test("should return current node view when the resolved node is
|
|
127
|
-
|
|
128
|
-
});
|
|
123
|
+
test("should return current node view when the resolved node is null", async () => {
|
|
124
|
+
await asyncNodeTest(null);
|
|
125
|
+
});
|
|
129
126
|
|
|
130
|
-
test("
|
|
131
|
-
|
|
132
|
-
plugins: [new AsyncNodePluginPlugin()],
|
|
127
|
+
test("should return current node view when the resolved node is undefined", async () => {
|
|
128
|
+
await asyncNodeTest(undefined);
|
|
133
129
|
});
|
|
134
130
|
|
|
135
|
-
|
|
131
|
+
test("can handle multiple updates through callback mechanism", async () => {
|
|
132
|
+
const plugin = new AsyncNodePlugin({
|
|
133
|
+
plugins: [new AsyncNodePluginPlugin()],
|
|
134
|
+
});
|
|
136
135
|
|
|
137
|
-
|
|
136
|
+
let deferredResolve: ((value: any) => void) | undefined;
|
|
138
137
|
|
|
139
|
-
|
|
140
|
-
"test",
|
|
141
|
-
async (node: Node.Async, update: (content: any) => void) => {
|
|
142
|
-
const result = new Promise((resolve) => {
|
|
143
|
-
deferredResolve = resolve; // Promise would be resolved only once
|
|
144
|
-
});
|
|
138
|
+
let updateContent: any;
|
|
145
139
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
140
|
+
plugin.hooks.onAsyncNode.tap(
|
|
141
|
+
"test",
|
|
142
|
+
async (node: Node.Async, update: (content: any) => void) => {
|
|
143
|
+
const result = new Promise((resolve) => {
|
|
144
|
+
deferredResolve = resolve; // Promise would be resolved only once
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
updateContent = update;
|
|
148
|
+
// Return the result to follow the same mechanism as before
|
|
149
|
+
return result;
|
|
150
|
+
},
|
|
151
|
+
);
|
|
151
152
|
|
|
152
|
-
|
|
153
|
+
let updateNumber = 0;
|
|
153
154
|
|
|
154
|
-
|
|
155
|
+
const player = new Player({ plugins: [plugin] });
|
|
155
156
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
157
|
+
player.hooks.viewController.tap("async-node-test", (vc) => {
|
|
158
|
+
vc.hooks.view.tap("async-node-test", (view) => {
|
|
159
|
+
view.hooks.onUpdate.tap("async-node-test", (update) => {
|
|
160
|
+
updateNumber++;
|
|
161
|
+
});
|
|
160
162
|
});
|
|
161
163
|
});
|
|
162
|
-
});
|
|
163
164
|
|
|
164
|
-
|
|
165
|
+
player.start(basicFRFWithActions as any);
|
|
165
166
|
|
|
166
|
-
|
|
167
|
-
|
|
167
|
+
let view = (player.getState() as InProgressState).controllers.view
|
|
168
|
+
.currentView?.lastUpdate;
|
|
168
169
|
|
|
169
|
-
|
|
170
|
-
|
|
170
|
+
expect(view).toBeDefined();
|
|
171
|
+
expect(view?.actions[1]).toBeUndefined();
|
|
171
172
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
if (deferredResolve) {
|
|
178
|
-
deferredResolve({
|
|
179
|
-
asset: {
|
|
180
|
-
id: "next-label-action",
|
|
181
|
-
type: "action",
|
|
182
|
-
value: "dummy value",
|
|
183
|
-
},
|
|
173
|
+
await waitFor(() => {
|
|
174
|
+
expect(updateNumber).toBe(1);
|
|
175
|
+
expect(deferredResolve).toBeDefined();
|
|
184
176
|
});
|
|
185
|
-
}
|
|
186
177
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
178
|
+
if (deferredResolve) {
|
|
179
|
+
deferredResolve({
|
|
180
|
+
asset: {
|
|
181
|
+
id: "next-label-action",
|
|
182
|
+
type: "action",
|
|
183
|
+
value: "dummy value",
|
|
184
|
+
},
|
|
185
|
+
});
|
|
186
|
+
}
|
|
190
187
|
|
|
191
|
-
|
|
192
|
-
|
|
188
|
+
await waitFor(() => {
|
|
189
|
+
expect(updateNumber).toBe(2);
|
|
190
|
+
});
|
|
193
191
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
expect(updateNumber).toBe(2);
|
|
192
|
+
view = (player.getState() as InProgressState).controllers.view.currentView
|
|
193
|
+
?.lastUpdate;
|
|
197
194
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
195
|
+
expect(view?.actions[0].asset.type).toBe("action");
|
|
196
|
+
expect(view?.actions[1].asset.type).toBe("action");
|
|
197
|
+
expect(updateNumber).toBe(2);
|
|
201
198
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
199
|
+
if (deferredResolve) {
|
|
200
|
+
updateContent(null);
|
|
201
|
+
}
|
|
205
202
|
|
|
206
|
-
|
|
207
|
-
|
|
203
|
+
await waitFor(() => {
|
|
204
|
+
expect(updateNumber).toBe(3);
|
|
205
|
+
});
|
|
208
206
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
});
|
|
207
|
+
view = (player.getState() as InProgressState).controllers.view.currentView
|
|
208
|
+
?.lastUpdate;
|
|
212
209
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
plugins: [new AsyncNodePluginPlugin()],
|
|
210
|
+
expect(view?.actions[0].asset.type).toBe("action");
|
|
211
|
+
expect(view?.actions[1]).toBeUndefined();
|
|
216
212
|
});
|
|
217
213
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
return new Promise((resolve) => {
|
|
222
|
-
deferredResolve = resolve;
|
|
214
|
+
test("replaces async nodes with provided node", async () => {
|
|
215
|
+
const plugin = new AsyncNodePlugin({
|
|
216
|
+
plugins: [new AsyncNodePluginPlugin()],
|
|
223
217
|
});
|
|
224
|
-
});
|
|
225
|
-
let updateNumber = 0;
|
|
226
218
|
|
|
227
|
-
|
|
219
|
+
let deferredResolve: ((value: any) => void) | undefined;
|
|
228
220
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
updateNumber++;
|
|
221
|
+
plugin.hooks.onAsyncNode.tap("test", async (node: Node.Async) => {
|
|
222
|
+
return new Promise((resolve) => {
|
|
223
|
+
deferredResolve = resolve;
|
|
233
224
|
});
|
|
234
225
|
});
|
|
235
|
-
|
|
226
|
+
let updateNumber = 0;
|
|
236
227
|
|
|
237
|
-
|
|
228
|
+
const player = new Player({ plugins: [plugin] });
|
|
238
229
|
|
|
239
|
-
|
|
240
|
-
|
|
230
|
+
player.hooks.viewController.tap("async-node-test", (vc) => {
|
|
231
|
+
vc.hooks.view.tap("async-node-test", (view) => {
|
|
232
|
+
view.hooks.onUpdate.tap("async-node-test", (update) => {
|
|
233
|
+
updateNumber++;
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
});
|
|
241
237
|
|
|
242
|
-
|
|
243
|
-
expect(view?.actions[0].asset.type).toBe("action");
|
|
244
|
-
expect(view?.actions[1]).toBeUndefined();
|
|
245
|
-
expect(updateNumber).toBe(1);
|
|
238
|
+
player.start(basicFRFWithActions as any);
|
|
246
239
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
});
|
|
240
|
+
let view = (player.getState() as InProgressState).controllers.view
|
|
241
|
+
.currentView?.lastUpdate;
|
|
250
242
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
243
|
+
expect(view).toBeDefined();
|
|
244
|
+
expect(view?.actions[0].asset.type).toBe("action");
|
|
245
|
+
expect(view?.actions[1]).toBeUndefined();
|
|
246
|
+
expect(updateNumber).toBe(1);
|
|
247
|
+
|
|
248
|
+
await waitFor(() => {
|
|
249
|
+
expect(deferredResolve).toBeDefined();
|
|
258
250
|
});
|
|
259
|
-
}
|
|
260
251
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
252
|
+
if (deferredResolve) {
|
|
253
|
+
deferredResolve({
|
|
254
|
+
asset: {
|
|
255
|
+
id: "next-label-action",
|
|
256
|
+
type: "action",
|
|
257
|
+
value: "dummy value",
|
|
258
|
+
},
|
|
259
|
+
});
|
|
260
|
+
}
|
|
264
261
|
|
|
265
|
-
|
|
266
|
-
|
|
262
|
+
await waitFor(() => {
|
|
263
|
+
expect(updateNumber).toBe(2);
|
|
264
|
+
});
|
|
267
265
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
});
|
|
266
|
+
view = (player.getState() as InProgressState).controllers.view.currentView
|
|
267
|
+
?.lastUpdate;
|
|
271
268
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
plugins: [new AsyncNodePluginPlugin()],
|
|
269
|
+
expect(view?.actions[0].asset.type).toBe("action");
|
|
270
|
+
expect(view?.actions[1].asset.type).toBe("action");
|
|
275
271
|
});
|
|
276
272
|
|
|
277
|
-
|
|
273
|
+
test("replaces async nodes with multi node", async () => {
|
|
274
|
+
const plugin = new AsyncNodePlugin({
|
|
275
|
+
plugins: [new AsyncNodePluginPlugin()],
|
|
276
|
+
});
|
|
278
277
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
278
|
+
let deferredResolve: ((value: any) => void) | undefined;
|
|
279
|
+
|
|
280
|
+
plugin.hooks.onAsyncNode.tap("test", async (node) => {
|
|
281
|
+
return new Promise((resolve) => {
|
|
282
|
+
deferredResolve = resolve;
|
|
283
|
+
});
|
|
282
284
|
});
|
|
283
|
-
});
|
|
284
285
|
|
|
285
|
-
|
|
286
|
+
let updateNumber = 0;
|
|
286
287
|
|
|
287
|
-
|
|
288
|
+
const player = new Player({ plugins: [plugin] });
|
|
288
289
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
290
|
+
player.hooks.viewController.tap("async-node-test", (vc) => {
|
|
291
|
+
vc.hooks.view.tap("async-node-test", (view) => {
|
|
292
|
+
view.hooks.onUpdate.tap("async-node-test", (update) => {
|
|
293
|
+
updateNumber++;
|
|
294
|
+
});
|
|
293
295
|
});
|
|
294
296
|
});
|
|
295
|
-
});
|
|
296
297
|
|
|
297
|
-
|
|
298
|
+
player.start(basicFRFWithActions as any);
|
|
298
299
|
|
|
299
|
-
|
|
300
|
-
|
|
300
|
+
let view = (player.getState() as InProgressState).controllers.view
|
|
301
|
+
.currentView?.lastUpdate;
|
|
301
302
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
303
|
+
expect(view).toBeDefined();
|
|
304
|
+
expect(view?.actions[1]).toBeUndefined();
|
|
305
|
+
expect(updateNumber).toBe(1);
|
|
305
306
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
307
|
+
await waitFor(() => {
|
|
308
|
+
expect(deferredResolve).toBeDefined();
|
|
309
|
+
});
|
|
309
310
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
311
|
+
if (deferredResolve) {
|
|
312
|
+
deferredResolve([
|
|
313
|
+
{
|
|
314
|
+
asset: {
|
|
315
|
+
id: "value-1",
|
|
316
|
+
type: "text",
|
|
317
|
+
value: "1st value in the multinode",
|
|
318
|
+
},
|
|
317
319
|
},
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
320
|
+
{
|
|
321
|
+
asset: {
|
|
322
|
+
id: "value-2",
|
|
323
|
+
type: "text",
|
|
324
|
+
value: "2nd value in the multinode",
|
|
325
|
+
},
|
|
324
326
|
},
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
await waitFor(() => {
|
|
330
|
-
expect(updateNumber).toBe(2);
|
|
331
|
-
});
|
|
327
|
+
]);
|
|
328
|
+
}
|
|
332
329
|
|
|
333
|
-
|
|
334
|
-
|
|
330
|
+
await waitFor(() => {
|
|
331
|
+
expect(updateNumber).toBe(2);
|
|
332
|
+
});
|
|
335
333
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
expect(view?.actions[2].asset.type).toBe("text");
|
|
339
|
-
});
|
|
334
|
+
view = (player.getState() as InProgressState).controllers.view.currentView
|
|
335
|
+
?.lastUpdate;
|
|
340
336
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
337
|
+
expect(view?.actions[0].asset.type).toBe("action");
|
|
338
|
+
expect(view?.actions[1].asset.type).toBe("text");
|
|
339
|
+
expect(view?.actions[2].asset.type).toBe("text");
|
|
344
340
|
});
|
|
345
341
|
|
|
346
|
-
|
|
342
|
+
test("replaces async nodes with chained multiNodes", async () => {
|
|
343
|
+
const plugin = new AsyncNodePlugin({
|
|
344
|
+
plugins: [new AsyncNodePluginPlugin()],
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
let deferredResolve: ((value: any) => void) | undefined;
|
|
347
348
|
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
349
|
+
plugin.hooks.onAsyncNode.tap("test", async (node: Node.Async) => {
|
|
350
|
+
return new Promise((resolve) => {
|
|
351
|
+
deferredResolve = resolve;
|
|
352
|
+
});
|
|
351
353
|
});
|
|
352
|
-
|
|
353
|
-
let updateNumber = 0;
|
|
354
|
+
let updateNumber = 0;
|
|
354
355
|
|
|
355
|
-
|
|
356
|
+
const player = new Player({ plugins: [plugin] });
|
|
356
357
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
358
|
+
player.hooks.viewController.tap("async-node-test", (vc) => {
|
|
359
|
+
vc.hooks.view.tap("async-node-test", (view) => {
|
|
360
|
+
view.hooks.onUpdate.tap("async-node-test", (update) => {
|
|
361
|
+
updateNumber++;
|
|
362
|
+
});
|
|
361
363
|
});
|
|
362
364
|
});
|
|
363
|
-
});
|
|
364
365
|
|
|
365
|
-
|
|
366
|
+
player.start(basicFRFWithActions as any);
|
|
366
367
|
|
|
367
|
-
|
|
368
|
-
|
|
368
|
+
let view = (player.getState() as InProgressState).controllers.view
|
|
369
|
+
.currentView?.lastUpdate;
|
|
369
370
|
|
|
370
|
-
|
|
371
|
-
|
|
371
|
+
expect(view).toBeDefined();
|
|
372
|
+
expect(view?.actions[1]).toBeUndefined();
|
|
372
373
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
374
|
+
await waitFor(() => {
|
|
375
|
+
expect(updateNumber).toBe(1);
|
|
376
|
+
expect(deferredResolve).toBeDefined();
|
|
377
|
+
});
|
|
377
378
|
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
379
|
+
if (deferredResolve) {
|
|
380
|
+
deferredResolve([
|
|
381
|
+
{
|
|
382
|
+
asset: {
|
|
383
|
+
id: "value-1",
|
|
384
|
+
type: "text",
|
|
385
|
+
value: "1st value in the multinode",
|
|
386
|
+
},
|
|
385
387
|
},
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
}
|
|
388
|
+
{
|
|
389
|
+
id: "another-async",
|
|
390
|
+
async: true,
|
|
391
|
+
},
|
|
392
|
+
]);
|
|
393
|
+
}
|
|
393
394
|
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
395
|
+
await waitFor(() => {
|
|
396
|
+
expect(updateNumber).toBe(2);
|
|
397
|
+
});
|
|
397
398
|
|
|
398
|
-
|
|
399
|
-
|
|
399
|
+
view = (player.getState() as InProgressState).controllers.view.currentView
|
|
400
|
+
?.lastUpdate;
|
|
400
401
|
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
402
|
+
expect(view?.actions[0].asset.type).toBe("action");
|
|
403
|
+
expect(view?.actions[1].asset.type).toBe("text");
|
|
404
|
+
expect(view?.actions[2]).toBeUndefined();
|
|
405
|
+
expect(updateNumber).toBe(2);
|
|
405
406
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
407
|
+
if (deferredResolve) {
|
|
408
|
+
deferredResolve([
|
|
409
|
+
{
|
|
410
|
+
asset: {
|
|
411
|
+
id: "value-2",
|
|
412
|
+
type: "text",
|
|
413
|
+
value: "2nd value in the multinode",
|
|
414
|
+
},
|
|
413
415
|
},
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
416
|
+
{
|
|
417
|
+
asset: {
|
|
418
|
+
id: "value-3",
|
|
419
|
+
type: "text",
|
|
420
|
+
value: "3rd value in the multinode",
|
|
421
|
+
},
|
|
420
422
|
},
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
await waitFor(() => {
|
|
426
|
-
expect(updateNumber).toBe(3);
|
|
427
|
-
});
|
|
423
|
+
]);
|
|
424
|
+
}
|
|
428
425
|
|
|
429
|
-
|
|
430
|
-
|
|
426
|
+
await waitFor(() => {
|
|
427
|
+
expect(updateNumber).toBe(3);
|
|
428
|
+
});
|
|
431
429
|
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
expect(view?.actions[2].asset.type).toBe("text");
|
|
435
|
-
expect(view?.actions[3].asset.type).toBe("text");
|
|
436
|
-
});
|
|
430
|
+
view = (player.getState() as InProgressState).controllers.view.currentView
|
|
431
|
+
?.lastUpdate;
|
|
437
432
|
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
433
|
+
expect(view?.actions[0].asset.type).toBe("action");
|
|
434
|
+
expect(view?.actions[1].asset.type).toBe("text");
|
|
435
|
+
expect(view?.actions[2].asset.type).toBe("text");
|
|
436
|
+
expect(view?.actions[3].asset.type).toBe("text");
|
|
441
437
|
});
|
|
442
438
|
|
|
443
|
-
|
|
439
|
+
test("replaces async nodes with chained multiNodes singular", async () => {
|
|
440
|
+
const plugin = new AsyncNodePlugin({
|
|
441
|
+
plugins: [new AsyncNodePluginPlugin()],
|
|
442
|
+
});
|
|
443
|
+
|
|
444
|
+
let deferredResolve: ((value: any) => void) | undefined;
|
|
444
445
|
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
446
|
+
plugin.hooks.onAsyncNode.tap("test", async (node: Node.Async) => {
|
|
447
|
+
return new Promise((resolve) => {
|
|
448
|
+
deferredResolve = resolve;
|
|
449
|
+
});
|
|
448
450
|
});
|
|
449
|
-
|
|
450
|
-
let updateNumber = 0;
|
|
451
|
+
let updateNumber = 0;
|
|
451
452
|
|
|
452
|
-
|
|
453
|
+
const player = new Player({ plugins: [plugin] });
|
|
453
454
|
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
455
|
+
player.hooks.viewController.tap("async-node-test", (vc) => {
|
|
456
|
+
vc.hooks.view.tap("async-node-test", (view) => {
|
|
457
|
+
view.hooks.onUpdate.tap("async-node-test", (update) => {
|
|
458
|
+
updateNumber++;
|
|
459
|
+
});
|
|
458
460
|
});
|
|
459
461
|
});
|
|
460
|
-
});
|
|
461
462
|
|
|
462
|
-
|
|
463
|
+
player.start(basicFRFWithActions as any);
|
|
463
464
|
|
|
464
|
-
|
|
465
|
-
|
|
465
|
+
let view = (player.getState() as InProgressState).controllers.view
|
|
466
|
+
.currentView?.lastUpdate;
|
|
466
467
|
|
|
467
|
-
|
|
468
|
-
|
|
468
|
+
expect(view).toBeDefined();
|
|
469
|
+
expect(view?.actions[1]).toBeUndefined();
|
|
469
470
|
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
471
|
+
await waitFor(() => {
|
|
472
|
+
expect(updateNumber).toBe(1);
|
|
473
|
+
expect(deferredResolve).toBeDefined();
|
|
474
|
+
});
|
|
474
475
|
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
476
|
+
if (deferredResolve) {
|
|
477
|
+
deferredResolve([
|
|
478
|
+
{
|
|
479
|
+
asset: {
|
|
480
|
+
id: "value-1",
|
|
481
|
+
type: "text",
|
|
482
|
+
value: "1st value in the multinode",
|
|
483
|
+
},
|
|
482
484
|
},
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
}
|
|
485
|
+
{
|
|
486
|
+
id: "another-async",
|
|
487
|
+
async: true,
|
|
488
|
+
},
|
|
489
|
+
]);
|
|
490
|
+
}
|
|
490
491
|
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
492
|
+
await waitFor(() => {
|
|
493
|
+
expect(updateNumber).toBe(2);
|
|
494
|
+
});
|
|
494
495
|
|
|
495
|
-
|
|
496
|
-
|
|
496
|
+
view = (player.getState() as InProgressState).controllers.view.currentView
|
|
497
|
+
?.lastUpdate;
|
|
497
498
|
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
499
|
+
expect(view?.actions[0].asset.type).toBe("action");
|
|
500
|
+
expect(view?.actions[1].asset.type).toBe("text");
|
|
501
|
+
expect(view?.actions[2]).toBeUndefined();
|
|
501
502
|
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
503
|
+
if (deferredResolve) {
|
|
504
|
+
deferredResolve({
|
|
505
|
+
asset: {
|
|
506
|
+
id: "value-2",
|
|
507
|
+
type: "text",
|
|
508
|
+
value: "2nd value in the multinode",
|
|
509
|
+
},
|
|
510
|
+
});
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
await waitFor(() => {
|
|
514
|
+
expect(updateNumber).toBe(3);
|
|
509
515
|
});
|
|
510
|
-
}
|
|
511
516
|
|
|
512
|
-
|
|
513
|
-
|
|
517
|
+
view = (player.getState() as InProgressState).controllers.view.currentView
|
|
518
|
+
?.lastUpdate;
|
|
519
|
+
|
|
520
|
+
expect(view?.actions[0].asset.type).toBe("action");
|
|
521
|
+
expect(view?.actions[1].asset.type).toBe("text");
|
|
522
|
+
expect(view?.actions[2].asset.type).toBe("text");
|
|
514
523
|
});
|
|
515
524
|
|
|
516
|
-
|
|
517
|
-
|
|
525
|
+
test("should call onAsyncNode hook when async node is encountered", async () => {
|
|
526
|
+
const plugin = new AsyncNodePlugin({
|
|
527
|
+
plugins: [new AsyncNodePluginPlugin()],
|
|
528
|
+
});
|
|
518
529
|
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
530
|
+
let localNode: Node.Async;
|
|
531
|
+
plugin.hooks.onAsyncNode.tap("test", async (node: Node.Async) => {
|
|
532
|
+
if (node !== null) {
|
|
533
|
+
// assigns node value to a local variable
|
|
534
|
+
localNode = node;
|
|
535
|
+
}
|
|
523
536
|
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
537
|
+
return new Promise((resolve) => {
|
|
538
|
+
resolve("Promise resolved");
|
|
539
|
+
});
|
|
540
|
+
});
|
|
528
541
|
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
// assigns node value to a local variable
|
|
533
|
-
localNode = node;
|
|
534
|
-
}
|
|
542
|
+
const player = new Player({ plugins: [plugin] });
|
|
543
|
+
|
|
544
|
+
player.start(basicFRFWithActions as any);
|
|
535
545
|
|
|
536
|
-
|
|
537
|
-
|
|
546
|
+
await waitFor(() => {
|
|
547
|
+
expect(localNode.id).toStrictEqual("nodeId");
|
|
548
|
+
expect(localNode.type).toStrictEqual("async");
|
|
538
549
|
});
|
|
539
550
|
});
|
|
551
|
+
});
|
|
540
552
|
|
|
541
|
-
|
|
553
|
+
describe("parser", () => {
|
|
554
|
+
test("missing node-id parent async node", async () => {
|
|
555
|
+
const parser = new Parser();
|
|
556
|
+
new AsyncNodePluginPlugin().applyParser(parser);
|
|
557
|
+
const parsedAST = parser.parseObject({ async: "true" });
|
|
558
|
+
|
|
559
|
+
expect(parsedAST).toStrictEqual(null);
|
|
560
|
+
});
|
|
542
561
|
|
|
543
|
-
|
|
562
|
+
test("missing node-id child async node", async () => {
|
|
563
|
+
const parser = new Parser();
|
|
564
|
+
new AsyncNodePluginPlugin().applyParser(parser);
|
|
565
|
+
const parsedAST = parser.parseObject({ fields: { async: "true" } });
|
|
544
566
|
|
|
545
|
-
|
|
546
|
-
expect(localNode.id).toStrictEqual("nodeId");
|
|
547
|
-
expect(localNode.type).toStrictEqual("async");
|
|
567
|
+
expect(parsedAST).toStrictEqual(null);
|
|
548
568
|
});
|
|
549
569
|
});
|