@player-ui/asset-transform-plugin 0.7.4-next.4 → 0.7.5--canary.434.14868
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/cjs/index.cjs +137 -0
- package/dist/cjs/index.cjs.map +1 -0
- package/dist/{index.esm.js → index.legacy-esm.js} +31 -38
- package/dist/index.mjs +109 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +21 -58
- package/src/__tests__/index.test.ts +359 -0
- package/src/__tests__/propertiesToSkip.test.ts +445 -0
- package/src/__tests__/utils.test.ts +170 -0
- package/src/index.ts +9 -9
- package/src/propertiesToSkip.ts +3 -3
- package/src/utils.ts +2 -2
- package/types/index.d.ts +18 -0
- package/types/propertiesToSkip.d.ts +8 -0
- package/types/utils.d.ts +15 -0
- package/dist/index.cjs.js +0 -123
- package/dist/index.d.ts +0 -39
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
import { test, expect, vitest } from "vitest";
|
|
2
|
+
import type { InProgressState, TransformRegistry } from "@player-ui/player";
|
|
3
|
+
import { waitFor } from "@testing-library/react";
|
|
4
|
+
import { Player } from "@player-ui/player";
|
|
5
|
+
import type { Flow } from "@player-ui/types";
|
|
6
|
+
import { Registry } from "@player-ui/partial-match-registry";
|
|
7
|
+
import {
|
|
8
|
+
AssetTransformPlugin,
|
|
9
|
+
compose,
|
|
10
|
+
composeBefore,
|
|
11
|
+
propertiesToSkipTransform,
|
|
12
|
+
} from "..";
|
|
13
|
+
|
|
14
|
+
const basicContentWithActions: Flow<any> = {
|
|
15
|
+
id: "test-flow",
|
|
16
|
+
views: [
|
|
17
|
+
{
|
|
18
|
+
id: "my-view",
|
|
19
|
+
actions: [
|
|
20
|
+
{
|
|
21
|
+
asset: {
|
|
22
|
+
id: "next-label-action",
|
|
23
|
+
type: "action",
|
|
24
|
+
value: "{{foo.bar}}",
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
navigation: {
|
|
31
|
+
BEGIN: "FLOW_1",
|
|
32
|
+
FLOW_1: {
|
|
33
|
+
startState: "VIEW_1",
|
|
34
|
+
VIEW_1: {
|
|
35
|
+
state_type: "VIEW",
|
|
36
|
+
ref: "my-view",
|
|
37
|
+
transitions: {},
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const basicFRFWithActionsAndExpressions = (asset = "action"): Flow<any> => ({
|
|
44
|
+
id: "test-flow",
|
|
45
|
+
views: [
|
|
46
|
+
{
|
|
47
|
+
id: "my-view",
|
|
48
|
+
actions: [
|
|
49
|
+
{
|
|
50
|
+
asset: {
|
|
51
|
+
id: "next-label-action",
|
|
52
|
+
type: asset,
|
|
53
|
+
value: "{{foo.bar}}",
|
|
54
|
+
example: ['{{foo.bar}} = "test"'],
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
],
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
data: {
|
|
61
|
+
foo: {
|
|
62
|
+
bar: "1",
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
navigation: {
|
|
66
|
+
BEGIN: "FLOW_1",
|
|
67
|
+
FLOW_1: {
|
|
68
|
+
startState: "VIEW_1",
|
|
69
|
+
VIEW_1: {
|
|
70
|
+
state_type: "VIEW",
|
|
71
|
+
ref: "my-view",
|
|
72
|
+
transitions: {},
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
const otherAction: Flow<any> = {
|
|
79
|
+
...basicContentWithActions,
|
|
80
|
+
views: [
|
|
81
|
+
{
|
|
82
|
+
id: "my-view",
|
|
83
|
+
actions: [
|
|
84
|
+
{
|
|
85
|
+
asset: {
|
|
86
|
+
id: "next-label-action",
|
|
87
|
+
type: "stateful-action",
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
],
|
|
91
|
+
},
|
|
92
|
+
],
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const choice: Flow<any> = {
|
|
96
|
+
id: "some view",
|
|
97
|
+
views: [
|
|
98
|
+
{
|
|
99
|
+
id: "my-view",
|
|
100
|
+
actions: [
|
|
101
|
+
{
|
|
102
|
+
asset: {
|
|
103
|
+
id: "choice",
|
|
104
|
+
type: "choice",
|
|
105
|
+
value: "some value",
|
|
106
|
+
choiceDetail: {
|
|
107
|
+
asset: {
|
|
108
|
+
id: "choiceDetail",
|
|
109
|
+
type: "choiceItem",
|
|
110
|
+
value: "choice detail",
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
],
|
|
116
|
+
},
|
|
117
|
+
],
|
|
118
|
+
navigation: {
|
|
119
|
+
BEGIN: "FLOW_1",
|
|
120
|
+
FLOW_1: {
|
|
121
|
+
startState: "VIEW_1",
|
|
122
|
+
VIEW_1: {
|
|
123
|
+
state_type: "VIEW",
|
|
124
|
+
ref: "my-view",
|
|
125
|
+
transitions: {},
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
const registry: TransformRegistry = new Registry();
|
|
132
|
+
registry.set({ type: "action" }, (asset, options) => {
|
|
133
|
+
return {
|
|
134
|
+
...asset,
|
|
135
|
+
run: () => {
|
|
136
|
+
options.data.model.set([["foo.bar", "it worked!"]]);
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
});
|
|
140
|
+
registry.set(
|
|
141
|
+
{ type: "action-2" },
|
|
142
|
+
compose(
|
|
143
|
+
(asset, options) => {
|
|
144
|
+
return {
|
|
145
|
+
...asset,
|
|
146
|
+
run: () => {
|
|
147
|
+
options.data.model.set([["foo.bar", "it worked!"]]);
|
|
148
|
+
},
|
|
149
|
+
};
|
|
150
|
+
},
|
|
151
|
+
composeBefore(propertiesToSkipTransform(["example"])),
|
|
152
|
+
),
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
registry.set({ type: "stateful-action" }, (asset, options, store) => {
|
|
156
|
+
const [count, setCount] = store.useLocalState(1);
|
|
157
|
+
const [label] = store.useLocalState("some text");
|
|
158
|
+
|
|
159
|
+
return {
|
|
160
|
+
...asset,
|
|
161
|
+
count,
|
|
162
|
+
label,
|
|
163
|
+
increment() {
|
|
164
|
+
setCount(Math.min(count + 1, 2));
|
|
165
|
+
},
|
|
166
|
+
};
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
registry.set(
|
|
170
|
+
{ type: "choice" },
|
|
171
|
+
{
|
|
172
|
+
beforeResolve: (asset, options, store) => {
|
|
173
|
+
store.useSharedState("shared")("choice before resolve");
|
|
174
|
+
store.useLocalState(5);
|
|
175
|
+
|
|
176
|
+
return {
|
|
177
|
+
...asset,
|
|
178
|
+
children: [],
|
|
179
|
+
};
|
|
180
|
+
},
|
|
181
|
+
resolve: (asset, options, store) => {
|
|
182
|
+
const [count, setCount] = store.useLocalState(2);
|
|
183
|
+
const [label, setLabel] = store.useSharedState("shared")("newValue");
|
|
184
|
+
|
|
185
|
+
return {
|
|
186
|
+
...asset,
|
|
187
|
+
count,
|
|
188
|
+
label,
|
|
189
|
+
after: () => {
|
|
190
|
+
setCount(count + 1);
|
|
191
|
+
setLabel("i can reset this");
|
|
192
|
+
},
|
|
193
|
+
};
|
|
194
|
+
},
|
|
195
|
+
},
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
test("transforms matching assets", () => {
|
|
199
|
+
const player = new Player({ plugins: [new AssetTransformPlugin(registry)] });
|
|
200
|
+
player.start(basicContentWithActions);
|
|
201
|
+
|
|
202
|
+
// Should now add a run function
|
|
203
|
+
const view = (player.getState() as InProgressState).controllers.view
|
|
204
|
+
.currentView?.lastUpdate;
|
|
205
|
+
expect(typeof view?.actions[0].asset.run).toBe("function");
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
test("transforms matching assets and does not skip string resolution", () => {
|
|
209
|
+
const player = new Player({ plugins: [new AssetTransformPlugin(registry)] });
|
|
210
|
+
player.start(basicFRFWithActionsAndExpressions());
|
|
211
|
+
|
|
212
|
+
// Should now add a run function
|
|
213
|
+
const view = (player.getState() as InProgressState).controllers.view
|
|
214
|
+
.currentView?.lastUpdate;
|
|
215
|
+
|
|
216
|
+
expect(typeof view?.actions[0].asset.run).toBe("function");
|
|
217
|
+
expect(view?.actions[0].asset.example).toStrictEqual(['1 = "test"']);
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
test("transforms matching assets and skips string resolution", () => {
|
|
221
|
+
const player = new Player({ plugins: [new AssetTransformPlugin(registry)] });
|
|
222
|
+
player.start(basicFRFWithActionsAndExpressions("action-2"));
|
|
223
|
+
|
|
224
|
+
// Should now add a run function
|
|
225
|
+
const view = (player.getState() as InProgressState).controllers.view
|
|
226
|
+
.currentView?.lastUpdate;
|
|
227
|
+
|
|
228
|
+
expect(typeof view?.actions[0].asset.run).toBe("function");
|
|
229
|
+
expect(view?.actions[0].asset.example).toStrictEqual([
|
|
230
|
+
'{{foo.bar}} = "test"',
|
|
231
|
+
]);
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
test("uses shorthand version", () => {
|
|
235
|
+
const player = new Player({
|
|
236
|
+
plugins: [
|
|
237
|
+
new AssetTransformPlugin([
|
|
238
|
+
[
|
|
239
|
+
{ type: "action" },
|
|
240
|
+
(asset, options) => {
|
|
241
|
+
return {
|
|
242
|
+
...asset,
|
|
243
|
+
run: () => {
|
|
244
|
+
options.data.model.set([["foo.bar", "it worked!"]]);
|
|
245
|
+
},
|
|
246
|
+
};
|
|
247
|
+
},
|
|
248
|
+
],
|
|
249
|
+
]),
|
|
250
|
+
],
|
|
251
|
+
});
|
|
252
|
+
player.start(basicContentWithActions);
|
|
253
|
+
|
|
254
|
+
// Should now add a run function
|
|
255
|
+
const view = (player.getState() as InProgressState).controllers.view
|
|
256
|
+
.currentView?.lastUpdate;
|
|
257
|
+
expect(typeof view?.actions[0].asset.run).toBe("function");
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
test("transforms matching assets with all transform types", () => {
|
|
261
|
+
const player = new Player({ plugins: [new AssetTransformPlugin(registry)] });
|
|
262
|
+
player.start(choice);
|
|
263
|
+
|
|
264
|
+
// Should now add a run function
|
|
265
|
+
const view = (player.getState() as InProgressState).controllers.view
|
|
266
|
+
.currentView?.lastUpdate;
|
|
267
|
+
|
|
268
|
+
expect(typeof view?.actions[0].asset.choiceDetail).toBe("undefined");
|
|
269
|
+
expect(typeof view?.actions[0].asset.after).toBe("function");
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
test("keeps same transform when data stays the same", async () => {
|
|
273
|
+
const player = new Player({ plugins: [new AssetTransformPlugin(registry)] });
|
|
274
|
+
player.start(basicContentWithActions);
|
|
275
|
+
|
|
276
|
+
// Should now add a run function
|
|
277
|
+
const initialView = (player.getState() as InProgressState).controllers.view
|
|
278
|
+
.currentView?.lastUpdate;
|
|
279
|
+
|
|
280
|
+
expect(initialView?.actions[0].asset.value).toBe(undefined);
|
|
281
|
+
initialView?.actions[0].asset.run();
|
|
282
|
+
|
|
283
|
+
let updatedView = (player.getState() as InProgressState).controllers.view
|
|
284
|
+
.currentView?.lastUpdate;
|
|
285
|
+
await waitFor(() => {
|
|
286
|
+
updatedView = (player.getState() as InProgressState).controllers.view
|
|
287
|
+
.currentView?.lastUpdate;
|
|
288
|
+
expect(updatedView?.actions[0].asset.value).toBe("it worked!");
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
expect(updatedView?.actions[0].asset.value).toBe("it worked!");
|
|
292
|
+
|
|
293
|
+
updatedView?.actions[0].asset.run();
|
|
294
|
+
const nonUpdatedView = (player.getState() as InProgressState).controllers.view
|
|
295
|
+
.currentView?.lastUpdate;
|
|
296
|
+
expect(nonUpdatedView).toBe(updatedView);
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
test("updates when the transform store updates", () => {
|
|
300
|
+
const player = new Player({ plugins: [new AssetTransformPlugin(registry)] });
|
|
301
|
+
player.start(otherAction);
|
|
302
|
+
|
|
303
|
+
// Should now have the count and an increment function
|
|
304
|
+
const initialView = (player.getState() as InProgressState).controllers.view
|
|
305
|
+
.currentView?.lastUpdate;
|
|
306
|
+
expect(initialView?.actions[0].asset.count).toBe(1);
|
|
307
|
+
|
|
308
|
+
expect(initialView?.actions[0].asset.label).toBe("some text");
|
|
309
|
+
|
|
310
|
+
initialView?.actions[0].asset.increment();
|
|
311
|
+
|
|
312
|
+
const updatedView = (player.getState() as InProgressState).controllers.view
|
|
313
|
+
.currentView?.lastUpdate;
|
|
314
|
+
expect(updatedView?.actions[0].asset.count).toBe(2);
|
|
315
|
+
updatedView?.actions[0].asset.increment();
|
|
316
|
+
|
|
317
|
+
const nonUpdatedView = (player.getState() as InProgressState).controllers.view
|
|
318
|
+
.currentView?.lastUpdate;
|
|
319
|
+
expect(nonUpdatedView).toBe(updatedView);
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
test("uses the same store", () => {
|
|
323
|
+
const player = new Player({ plugins: [new AssetTransformPlugin(registry)] });
|
|
324
|
+
player.start(choice);
|
|
325
|
+
|
|
326
|
+
// Should now have the count and an increment function
|
|
327
|
+
const initialView = (player.getState() as InProgressState).controllers.view
|
|
328
|
+
.currentView?.lastUpdate;
|
|
329
|
+
expect(initialView?.actions[0].asset.count).toBe(2);
|
|
330
|
+
expect(initialView?.actions[0].asset.label).toBe("choice before resolve");
|
|
331
|
+
initialView?.actions[0].asset.after();
|
|
332
|
+
|
|
333
|
+
const updatedView = (player.getState() as InProgressState).controllers.view
|
|
334
|
+
.currentView?.lastUpdate;
|
|
335
|
+
expect(updatedView?.actions[0].asset.count).toBe(3);
|
|
336
|
+
expect(updatedView?.actions[0].asset.label).toBe("i can reset this");
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
test("merges registries", () => {
|
|
340
|
+
const actionFn1 = vitest.fn();
|
|
341
|
+
const actionFn2 = vitest.fn();
|
|
342
|
+
|
|
343
|
+
const player = new Player({
|
|
344
|
+
plugins: [
|
|
345
|
+
new AssetTransformPlugin([[{ type: "action" }, actionFn1]]),
|
|
346
|
+
new AssetTransformPlugin([[{ type: "action" }, actionFn2]]),
|
|
347
|
+
],
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
player.start(basicContentWithActions);
|
|
351
|
+
const { transformRegistry } = (player.getState() as InProgressState)
|
|
352
|
+
.controllers.view;
|
|
353
|
+
|
|
354
|
+
const transform = transformRegistry.get({ type: "action" });
|
|
355
|
+
transform?.resolve?.({}, {} as any, {} as any);
|
|
356
|
+
|
|
357
|
+
expect(actionFn1).not.toHaveBeenCalled();
|
|
358
|
+
expect(actionFn2).toHaveBeenCalled();
|
|
359
|
+
});
|