@reventlessdev/reventless-local 3.0.0-alpha.142 → 3.0.0-alpha.144
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/CHANGELOG.md +22 -0
- package/package.json +9 -9
- package/src/Platform.res +252 -110
- package/src/Platform.res.mjs +522 -166
- package/src/adapter/Api/LocalGraphQL_SubscriptionResolvers.res +3 -3
- package/src/components/Aggregate_Builder.res +1 -0
- package/src/components/Aggregate_Builder.res.mjs +5 -0
- package/tests/PluginEventDecodeTest.res +47 -0
- package/tests/PluginEventDecodeTest.res.mjs +33 -0
- package/tests/adapter/GraphQLSubscriptionBridgeTest.res +6 -7
- package/tests/adapter/GraphQLSubscriptionBridgeTest.res.mjs +2 -3
- package/tests/plugin/ApiFragmentRegistry_GWT.res +103 -0
- package/tests/plugin/ApiFragmentRegistry_GWT.res.mjs +196 -0
- package/tests/plugin/ApiFragments_GWT.res +103 -0
- package/tests/plugin/ApiFragments_GWT.res.mjs +170 -0
- package/tests/plugin/PluginBehavior_GWT.res +2 -18
- package/tests/plugin/PluginBehavior_GWT.res.mjs +0 -37
- package/tests/plugin/Plugin_Fixtures.res +0 -7
- package/tests/plugin/Plugin_Fixtures.res.mjs +0 -21
- package/tests/plugin/PluginsProjection_GWT.res +0 -12
- package/tests/plugin/PluginsProjection_GWT.res.mjs +0 -19
- package/tests/plugin/UiFragmentRegistry_GWT.res +53 -0
- package/tests/plugin/UiFragmentRegistry_GWT.res.mjs +92 -0
- package/tests/plugin/UiFragments_GWT.res +55 -0
- package/tests/plugin/UiFragments_GWT.res.mjs +84 -0
- package/tests/plugin/UIFragmentRegistryProjection_GWT.res +0 -72
- package/tests/plugin/UIFragmentRegistryProjection_GWT.res.mjs +0 -117
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as ApiFragments$ReventlessCore from "@reventlessdev/reventless-core/src/admin/ApiFragmentRegistry/StateViewSlice/ApiFragments.res.mjs";
|
|
4
|
+
import * as Projection_GWT$ReventlessGwt from "@reventlessdev/reventless-gwt/src/Projection_GWT.res.mjs";
|
|
5
|
+
import * as ApiFragments_Projection$ReventlessCore from "@reventlessdev/reventless-core/src/admin/ApiFragmentRegistry/StateViewSlice/ApiFragments_Projection.res.mjs";
|
|
6
|
+
|
|
7
|
+
let Test = Projection_GWT$ReventlessGwt.Make({
|
|
8
|
+
name: ApiFragments$ReventlessCore.name,
|
|
9
|
+
stateSchema: ApiFragments$ReventlessCore.stateSchema,
|
|
10
|
+
consumedEventSchema: ApiFragments$ReventlessCore.consumedEventSchema,
|
|
11
|
+
subIdConfig: undefined
|
|
12
|
+
})({
|
|
13
|
+
project: ApiFragments_Projection$ReventlessCore.project
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
let fragment1 = {
|
|
17
|
+
encoded: `{"types":["type Catalog_Product { id: ID! }"],"mutations":[],"queries":[],"subscriptions":[],"subscriptionSources":[]}`,
|
|
18
|
+
protocol: "graphql"
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
let fragment2 = {
|
|
22
|
+
encoded: `{"types":["type Catalog_Product { id: ID!\\n name: String! }"],"mutations":[],"queries":[],"subscriptions":[],"subscriptionSources":[]}`,
|
|
23
|
+
protocol: "graphql"
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
let registeredState = {
|
|
27
|
+
pluginId: "p1",
|
|
28
|
+
encoded: `{"types":["type Catalog_Product { id: ID! }"],"mutations":[],"queries":[],"subscriptions":[],"subscriptionSources":[]}`,
|
|
29
|
+
protocol: "graphql",
|
|
30
|
+
apiTarget: "Domain",
|
|
31
|
+
registeredAt: "t0",
|
|
32
|
+
updatedAt: "t0",
|
|
33
|
+
pushStatus: "pending",
|
|
34
|
+
pushMessage: "",
|
|
35
|
+
pushedAt: ""
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
Test.describe("ApiFragments StateViewSlice projection", () => {
|
|
39
|
+
Test.test("ApiFragmentRegistered creates the row pending (registeredAt = updatedAt = event time)", undefined, () => Test.thenStateWithId(Test.whenEvent(Test.givenEvents([]), {
|
|
40
|
+
TAG: "ApiFragmentRegistered",
|
|
41
|
+
pluginId: "p1",
|
|
42
|
+
fragment: fragment1,
|
|
43
|
+
apiTarget: "Domain",
|
|
44
|
+
at: "t0"
|
|
45
|
+
}), "p1", registeredState));
|
|
46
|
+
Test.test("ApiFragmentPushRecorded(ok) marks the row ok with the push time", undefined, () => Test.thenStateWithId(Test.whenEvent(Test.givenEvents([{
|
|
47
|
+
TAG: "ApiFragmentRegistered",
|
|
48
|
+
pluginId: "p1",
|
|
49
|
+
fragment: fragment1,
|
|
50
|
+
apiTarget: "Domain",
|
|
51
|
+
at: "t0"
|
|
52
|
+
}]), {
|
|
53
|
+
TAG: "ApiFragmentPushRecorded",
|
|
54
|
+
pluginId: "p1",
|
|
55
|
+
ok: true,
|
|
56
|
+
message: "",
|
|
57
|
+
at: "t1"
|
|
58
|
+
}), "p1", {
|
|
59
|
+
pluginId: "p1",
|
|
60
|
+
encoded: `{"types":["type Catalog_Product { id: ID! }"],"mutations":[],"queries":[],"subscriptions":[],"subscriptionSources":[]}`,
|
|
61
|
+
protocol: "graphql",
|
|
62
|
+
apiTarget: "Domain",
|
|
63
|
+
registeredAt: "t0",
|
|
64
|
+
updatedAt: "t0",
|
|
65
|
+
pushStatus: "ok",
|
|
66
|
+
pushMessage: "",
|
|
67
|
+
pushedAt: "t1"
|
|
68
|
+
}));
|
|
69
|
+
Test.test("ApiFragmentPushRecorded(error) carries the message", undefined, () => Test.thenStateWithId(Test.whenEvent(Test.givenEvents([{
|
|
70
|
+
TAG: "ApiFragmentRegistered",
|
|
71
|
+
pluginId: "p1",
|
|
72
|
+
fragment: fragment1,
|
|
73
|
+
apiTarget: "Domain",
|
|
74
|
+
at: "t0"
|
|
75
|
+
}]), {
|
|
76
|
+
TAG: "ApiFragmentPushRecorded",
|
|
77
|
+
pluginId: "p1",
|
|
78
|
+
ok: false,
|
|
79
|
+
message: "stitch failed",
|
|
80
|
+
at: "t1"
|
|
81
|
+
}), "p1", {
|
|
82
|
+
pluginId: "p1",
|
|
83
|
+
encoded: `{"types":["type Catalog_Product { id: ID! }"],"mutations":[],"queries":[],"subscriptions":[],"subscriptionSources":[]}`,
|
|
84
|
+
protocol: "graphql",
|
|
85
|
+
apiTarget: "Domain",
|
|
86
|
+
registeredAt: "t0",
|
|
87
|
+
updatedAt: "t0",
|
|
88
|
+
pushStatus: "error",
|
|
89
|
+
pushMessage: "stitch failed",
|
|
90
|
+
pushedAt: "t1"
|
|
91
|
+
}));
|
|
92
|
+
Test.test("ApiFragmentUpdated replaces the fragment and resets the row to pending", undefined, () => Test.thenStateWithId(Test.whenEvent(Test.givenEvents([
|
|
93
|
+
{
|
|
94
|
+
TAG: "ApiFragmentRegistered",
|
|
95
|
+
pluginId: "p1",
|
|
96
|
+
fragment: fragment1,
|
|
97
|
+
apiTarget: "Domain",
|
|
98
|
+
at: "t0"
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
TAG: "ApiFragmentPushRecorded",
|
|
102
|
+
pluginId: "p1",
|
|
103
|
+
ok: true,
|
|
104
|
+
message: "",
|
|
105
|
+
at: "t1"
|
|
106
|
+
}
|
|
107
|
+
]), {
|
|
108
|
+
TAG: "ApiFragmentUpdated",
|
|
109
|
+
pluginId: "p1",
|
|
110
|
+
previousFragment: fragment1,
|
|
111
|
+
newFragment: fragment2,
|
|
112
|
+
apiTarget: "Domain",
|
|
113
|
+
at: "t2"
|
|
114
|
+
}), "p1", {
|
|
115
|
+
pluginId: "p1",
|
|
116
|
+
encoded: `{"types":["type Catalog_Product { id: ID!\\n name: String! }"],"mutations":[],"queries":[],"subscriptions":[],"subscriptionSources":[]}`,
|
|
117
|
+
protocol: "graphql",
|
|
118
|
+
apiTarget: "Domain",
|
|
119
|
+
registeredAt: "t0",
|
|
120
|
+
updatedAt: "t2",
|
|
121
|
+
pushStatus: "pending",
|
|
122
|
+
pushMessage: "",
|
|
123
|
+
pushedAt: "t1"
|
|
124
|
+
}));
|
|
125
|
+
Test.test("ApiFragmentUpdated carrying a new target moves the row to that API", undefined, () => Test.thenStateWithId(Test.whenEvent(Test.givenEvents([{
|
|
126
|
+
TAG: "ApiFragmentRegistered",
|
|
127
|
+
pluginId: "p1",
|
|
128
|
+
fragment: fragment1,
|
|
129
|
+
apiTarget: "Domain",
|
|
130
|
+
at: "t0"
|
|
131
|
+
}]), {
|
|
132
|
+
TAG: "ApiFragmentUpdated",
|
|
133
|
+
pluginId: "p1",
|
|
134
|
+
previousFragment: fragment1,
|
|
135
|
+
newFragment: fragment1,
|
|
136
|
+
apiTarget: "Platform",
|
|
137
|
+
at: "t1"
|
|
138
|
+
}), "p1", {
|
|
139
|
+
pluginId: "p1",
|
|
140
|
+
encoded: `{"types":["type Catalog_Product { id: ID! }"],"mutations":[],"queries":[],"subscriptions":[],"subscriptionSources":[]}`,
|
|
141
|
+
protocol: "graphql",
|
|
142
|
+
apiTarget: "Platform",
|
|
143
|
+
registeredAt: "t0",
|
|
144
|
+
updatedAt: "t1",
|
|
145
|
+
pushStatus: "pending",
|
|
146
|
+
pushMessage: "",
|
|
147
|
+
pushedAt: ""
|
|
148
|
+
}));
|
|
149
|
+
Test.test("ApiFragmentDeregistered removes the row", undefined, () => Test.thenNoState(Test.whenEvent(Test.givenEvents([{
|
|
150
|
+
TAG: "ApiFragmentRegistered",
|
|
151
|
+
pluginId: "p1",
|
|
152
|
+
fragment: fragment1,
|
|
153
|
+
apiTarget: "Domain",
|
|
154
|
+
at: "t0"
|
|
155
|
+
}]), {
|
|
156
|
+
TAG: "ApiFragmentDeregistered",
|
|
157
|
+
pluginId: "p1"
|
|
158
|
+
})));
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
let P;
|
|
162
|
+
|
|
163
|
+
export {
|
|
164
|
+
P,
|
|
165
|
+
Test,
|
|
166
|
+
fragment1,
|
|
167
|
+
fragment2,
|
|
168
|
+
registeredState,
|
|
169
|
+
}
|
|
170
|
+
/* Test Not a pure module */
|
|
@@ -160,22 +160,6 @@ describe("PluginBehavior:", () => {
|
|
|
160
160
|
->thenEvents([IncompatiblePluginDetected(pluginDefinition)])
|
|
161
161
|
)
|
|
162
162
|
|
|
163
|
-
//
|
|
164
|
-
|
|
165
|
-
givenEvents([VersionDetected("1")])
|
|
166
|
-
->whenCmd(Connect(pluginDefinitionWithUI))
|
|
167
|
-
->thenEvents([
|
|
168
|
-
VersionConnected(pluginDefinitionWithUI),
|
|
169
|
-
UIFragmentRegistered({pluginId: pluginDefinitionWithUI.id, manifest: uiManifest}),
|
|
170
|
-
])
|
|
171
|
-
)
|
|
172
|
-
|
|
173
|
-
test("Disconnect with UI fragments emits UIFragmentDeregistered", () =>
|
|
174
|
-
givenEvents([VersionConnected(pluginDefinitionWithUI)])
|
|
175
|
-
->whenCmd(Disconnect("1"))
|
|
176
|
-
->thenEvents([
|
|
177
|
-
VersionDisconnected(pluginDefinitionWithUI),
|
|
178
|
-
UIFragmentDeregistered({pluginId: pluginDefinitionWithUI.id}),
|
|
179
|
-
])
|
|
180
|
-
)
|
|
163
|
+
// UI-fragment registration no longer rides the Plugin aggregate — the
|
|
164
|
+
// UiFragmentRegistry StateChangeSlice owns it (see UiFragmentRegistry_GWT).
|
|
181
165
|
})
|
|
@@ -292,43 +292,6 @@ PluginTest.describe("PluginBehavior:", () => {
|
|
|
292
292
|
TAG: "IncompatiblePluginDetected",
|
|
293
293
|
_0: Plugin_Fixtures$ReventlessLocal.pluginDefinition
|
|
294
294
|
}]));
|
|
295
|
-
PluginTest.test("Connect with UI fragments emits UIFragmentRegistered", () => PluginTest.thenEvents(PluginTest.whenCmd(PluginTest.givenEvents([{
|
|
296
|
-
TAG: "VersionDetected",
|
|
297
|
-
_0: "1"
|
|
298
|
-
}]), {
|
|
299
|
-
TAG: "Connect",
|
|
300
|
-
_0: Plugin_Fixtures$ReventlessLocal.pluginDefinitionWithUI
|
|
301
|
-
}), [
|
|
302
|
-
{
|
|
303
|
-
TAG: "VersionConnected",
|
|
304
|
-
_0: Plugin_Fixtures$ReventlessLocal.pluginDefinitionWithUI
|
|
305
|
-
},
|
|
306
|
-
{
|
|
307
|
-
TAG: "UIFragmentRegistered",
|
|
308
|
-
_0: {
|
|
309
|
-
pluginId: Plugin_Fixtures$ReventlessLocal.pluginDefinitionWithUI.id,
|
|
310
|
-
manifest: Plugin_Fixtures$ReventlessLocal.uiManifest
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
]));
|
|
314
|
-
PluginTest.test("Disconnect with UI fragments emits UIFragmentDeregistered", () => PluginTest.thenEvents(PluginTest.whenCmd(PluginTest.givenEvents([{
|
|
315
|
-
TAG: "VersionConnected",
|
|
316
|
-
_0: Plugin_Fixtures$ReventlessLocal.pluginDefinitionWithUI
|
|
317
|
-
}]), {
|
|
318
|
-
TAG: "Disconnect",
|
|
319
|
-
_0: "1"
|
|
320
|
-
}), [
|
|
321
|
-
{
|
|
322
|
-
TAG: "VersionDisconnected",
|
|
323
|
-
_0: Plugin_Fixtures$ReventlessLocal.pluginDefinitionWithUI
|
|
324
|
-
},
|
|
325
|
-
{
|
|
326
|
-
TAG: "UIFragmentDeregistered",
|
|
327
|
-
_0: {
|
|
328
|
-
pluginId: Plugin_Fixtures$ReventlessLocal.pluginDefinitionWithUI.id
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
]));
|
|
332
295
|
});
|
|
333
296
|
|
|
334
297
|
export {
|
|
@@ -12,7 +12,6 @@ let pluginDefinition: Reventless.Plugin.pluginDefinition = {
|
|
|
12
12
|
extensionProtocols: [],
|
|
13
13
|
apiSchemaFragment: None,
|
|
14
14
|
apiTarget: None,
|
|
15
|
-
uiFragments: None,
|
|
16
15
|
structure: None,
|
|
17
16
|
dcbEventLog: None,
|
|
18
17
|
kind: Domain,
|
|
@@ -40,11 +39,6 @@ let uiManifest: Reventless.Plugin.uiFragmentManifest = {
|
|
|
40
39
|
pages: [],
|
|
41
40
|
}
|
|
42
41
|
|
|
43
|
-
let pluginDefinitionWithUI = {
|
|
44
|
-
...pluginDefinition,
|
|
45
|
-
uiFragments: Some(uiManifest),
|
|
46
|
-
}
|
|
47
|
-
|
|
48
42
|
let extensionPointNames2 = ["Test.Test"]
|
|
49
43
|
let pluginDefinition2 = {
|
|
50
44
|
Reventless.Plugin.id: "name2@1",
|
|
@@ -60,7 +54,6 @@ let pluginDefinition2 = {
|
|
|
60
54
|
extensionProtocols: [],
|
|
61
55
|
apiSchemaFragment: None,
|
|
62
56
|
apiTarget: None,
|
|
63
|
-
uiFragments: None,
|
|
64
57
|
structure: None,
|
|
65
58
|
dcbEventLog: None,
|
|
66
59
|
kind: Domain,
|
|
@@ -17,7 +17,6 @@ let pluginDefinition = {
|
|
|
17
17
|
extensionProtocols: [],
|
|
18
18
|
apiSchemaFragment: undefined,
|
|
19
19
|
apiTarget: undefined,
|
|
20
|
-
uiFragments: undefined,
|
|
21
20
|
structure: undefined,
|
|
22
21
|
dcbEventLog: undefined,
|
|
23
22
|
kind: "Domain"
|
|
@@ -33,7 +32,6 @@ let pluginDefinitionV2 = {
|
|
|
33
32
|
extensionProtocols: pluginDefinition.extensionProtocols,
|
|
34
33
|
apiSchemaFragment: pluginDefinition.apiSchemaFragment,
|
|
35
34
|
apiTarget: pluginDefinition.apiTarget,
|
|
36
|
-
uiFragments: pluginDefinition.uiFragments,
|
|
37
35
|
structure: pluginDefinition.structure,
|
|
38
36
|
dcbEventLog: pluginDefinition.dcbEventLog,
|
|
39
37
|
kind: pluginDefinition.kind
|
|
@@ -49,7 +47,6 @@ let pluginDefinitionInfra = {
|
|
|
49
47
|
extensionProtocols: pluginDefinition.extensionProtocols,
|
|
50
48
|
apiSchemaFragment: pluginDefinition.apiSchemaFragment,
|
|
51
49
|
apiTarget: pluginDefinition.apiTarget,
|
|
52
|
-
uiFragments: pluginDefinition.uiFragments,
|
|
53
50
|
structure: pluginDefinition.structure,
|
|
54
51
|
dcbEventLog: pluginDefinition.dcbEventLog,
|
|
55
52
|
kind: "PlatformInfrastructure"
|
|
@@ -71,22 +68,6 @@ let uiManifest = {
|
|
|
71
68
|
pages: uiManifest_pages
|
|
72
69
|
};
|
|
73
70
|
|
|
74
|
-
let pluginDefinitionWithUI = {
|
|
75
|
-
id: pluginDefinition.id,
|
|
76
|
-
name: pluginDefinition.name,
|
|
77
|
-
version: pluginDefinition.version,
|
|
78
|
-
extensionPoints: pluginDefinition.extensionPoints,
|
|
79
|
-
extensions: pluginDefinition.extensions,
|
|
80
|
-
eventCollector: pluginDefinition.eventCollector,
|
|
81
|
-
extensionProtocols: pluginDefinition.extensionProtocols,
|
|
82
|
-
apiSchemaFragment: pluginDefinition.apiSchemaFragment,
|
|
83
|
-
apiTarget: pluginDefinition.apiTarget,
|
|
84
|
-
uiFragments: uiManifest,
|
|
85
|
-
structure: pluginDefinition.structure,
|
|
86
|
-
dcbEventLog: pluginDefinition.dcbEventLog,
|
|
87
|
-
kind: pluginDefinition.kind
|
|
88
|
-
};
|
|
89
|
-
|
|
90
71
|
let extensionPointNames2 = ["Test.Test"];
|
|
91
72
|
|
|
92
73
|
let pluginDefinition2 = {
|
|
@@ -103,7 +84,6 @@ let pluginDefinition2 = {
|
|
|
103
84
|
extensionProtocols: [],
|
|
104
85
|
apiSchemaFragment: undefined,
|
|
105
86
|
apiTarget: undefined,
|
|
106
|
-
uiFragments: undefined,
|
|
107
87
|
structure: undefined,
|
|
108
88
|
dcbEventLog: undefined,
|
|
109
89
|
kind: "Domain"
|
|
@@ -119,7 +99,6 @@ export {
|
|
|
119
99
|
display,
|
|
120
100
|
state,
|
|
121
101
|
uiManifest,
|
|
122
|
-
pluginDefinitionWithUI,
|
|
123
102
|
extensionPointNames2,
|
|
124
103
|
pluginDefinition2,
|
|
125
104
|
}
|
|
@@ -86,18 +86,6 @@ describe("PluginsProjection:", () => {
|
|
|
86
86
|
->thenState(display(pluginDefinition, Retired, []))
|
|
87
87
|
)
|
|
88
88
|
|
|
89
|
-
test("UIFragmentRegistered is ignored by the current view", () =>
|
|
90
|
-
givenEvents([VersionConnected(pluginDefinition)])
|
|
91
|
-
->whenEvent(UIFragmentRegistered({pluginId: pluginDefinition.id, manifest: uiManifest}))
|
|
92
|
-
->thenState(state)
|
|
93
|
-
)
|
|
94
|
-
|
|
95
|
-
test("UIFragmentDeregistered is ignored by the current view", () =>
|
|
96
|
-
givenEvents([VersionConnected(pluginDefinition)])
|
|
97
|
-
->whenEvent(UIFragmentDeregistered({pluginId: pluginDefinition.id}))
|
|
98
|
-
->thenState(state)
|
|
99
|
-
)
|
|
100
|
-
|
|
101
89
|
test("IncompatiblePluginDetected leaves a connected row unchanged", () =>
|
|
102
90
|
givenEvents([VersionConnected(pluginDefinition)])
|
|
103
91
|
->whenEvent(IncompatiblePluginDetected(pluginDefinition))
|
|
@@ -92,25 +92,6 @@ PluginsProjectionTest.describe("PluginsProjection:", () => {
|
|
|
92
92
|
TAG: "VersionRetired",
|
|
93
93
|
_0: Plugin_Fixtures$ReventlessLocal.pluginDefinition
|
|
94
94
|
}), Plugin_Fixtures$ReventlessLocal.display(Plugin_Fixtures$ReventlessLocal.pluginDefinition, "Retired", [])));
|
|
95
|
-
PluginsProjectionTest.test("UIFragmentRegistered is ignored by the current view", undefined, () => PluginsProjectionTest.thenState(PluginsProjectionTest.whenEvent(PluginsProjectionTest.givenEvents([{
|
|
96
|
-
TAG: "VersionConnected",
|
|
97
|
-
_0: Plugin_Fixtures$ReventlessLocal.pluginDefinition
|
|
98
|
-
}]), {
|
|
99
|
-
TAG: "UIFragmentRegistered",
|
|
100
|
-
_0: {
|
|
101
|
-
pluginId: Plugin_Fixtures$ReventlessLocal.pluginDefinition.id,
|
|
102
|
-
manifest: Plugin_Fixtures$ReventlessLocal.uiManifest
|
|
103
|
-
}
|
|
104
|
-
}), Plugin_Fixtures$ReventlessLocal.state));
|
|
105
|
-
PluginsProjectionTest.test("UIFragmentDeregistered is ignored by the current view", undefined, () => PluginsProjectionTest.thenState(PluginsProjectionTest.whenEvent(PluginsProjectionTest.givenEvents([{
|
|
106
|
-
TAG: "VersionConnected",
|
|
107
|
-
_0: Plugin_Fixtures$ReventlessLocal.pluginDefinition
|
|
108
|
-
}]), {
|
|
109
|
-
TAG: "UIFragmentDeregistered",
|
|
110
|
-
_0: {
|
|
111
|
-
pluginId: Plugin_Fixtures$ReventlessLocal.pluginDefinition.id
|
|
112
|
-
}
|
|
113
|
-
}), Plugin_Fixtures$ReventlessLocal.state));
|
|
114
95
|
PluginsProjectionTest.test("IncompatiblePluginDetected leaves a connected row unchanged", undefined, () => PluginsProjectionTest.thenState(PluginsProjectionTest.whenEvent(PluginsProjectionTest.givenEvents([{
|
|
115
96
|
TAG: "VersionConnected",
|
|
116
97
|
_0: Plugin_Fixtures$ReventlessLocal.pluginDefinition
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// StateChangeSlice GWT for the UiFragmentRegistry write side (the platform UI-fragment
|
|
2
|
+
// registry extracted off the Plugin aggregate — event-sourced-fragment-registries plan).
|
|
3
|
+
open ReventlessCore
|
|
4
|
+
open Plugin_Fixtures
|
|
5
|
+
|
|
6
|
+
module Test = ReventlessGwt.Behavior_GWT.Make(UiFragmentRegistry, UiFragmentRegistry_Behavior)
|
|
7
|
+
open Test
|
|
8
|
+
open UiFragmentRegistry
|
|
9
|
+
|
|
10
|
+
let manifest2: Reventless.Plugin.uiFragmentManifest = {
|
|
11
|
+
remoteEntryUrl: "https://cdn.example.com/plugin@2.0/remoteEntry.js",
|
|
12
|
+
panels: [],
|
|
13
|
+
pages: [],
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
describe("UiFragmentRegistry StateChangeSlice", () => {
|
|
17
|
+
test("register on empty state emits UiFragmentRegistered", () =>
|
|
18
|
+
givenEvents([])
|
|
19
|
+
->whenCmd(RegisterUiFragment({pluginId: "p1", manifest: uiManifest, at: "t0"}))
|
|
20
|
+
->thenEvent(UiFragmentRegistered({pluginId: "p1", manifest: uiManifest, at: "t0"}))
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
test("re-registering an identical manifest is idempotent (no event)", () =>
|
|
24
|
+
givenEvents([UiFragmentRegistered({pluginId: "p1", manifest: uiManifest, at: "t0"})])
|
|
25
|
+
->whenCmd(RegisterUiFragment({pluginId: "p1", manifest: uiManifest, at: "t1"}))
|
|
26
|
+
->thenNoEvent
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
test("registering a changed manifest emits UiFragmentUpdated", () =>
|
|
30
|
+
givenEvents([UiFragmentRegistered({pluginId: "p1", manifest: uiManifest, at: "t0"})])
|
|
31
|
+
->whenCmd(RegisterUiFragment({pluginId: "p1", manifest: manifest2, at: "t1"}))
|
|
32
|
+
->thenEvent(
|
|
33
|
+
UiFragmentUpdated({
|
|
34
|
+
pluginId: "p1",
|
|
35
|
+
previousManifest: uiManifest,
|
|
36
|
+
newManifest: manifest2,
|
|
37
|
+
at: "t1",
|
|
38
|
+
}),
|
|
39
|
+
)
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
test("deregister emits UiFragmentDeregistered", () =>
|
|
43
|
+
givenEvents([UiFragmentRegistered({pluginId: "p1", manifest: uiManifest, at: "t0"})])
|
|
44
|
+
->whenCmd(DeregisterUiFragment({pluginId: "p1"}))
|
|
45
|
+
->thenEvent(UiFragmentDeregistered({pluginId: "p1"}))
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
test("deregistering an absent fragment is idempotent (no event)", () =>
|
|
49
|
+
givenEvents([])
|
|
50
|
+
->whenCmd(DeregisterUiFragment({pluginId: "p1"}))
|
|
51
|
+
->thenNoEvent
|
|
52
|
+
)
|
|
53
|
+
})
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Behavior_GWT$ReventlessGwt from "@reventlessdev/reventless-gwt/src/Behavior_GWT.res.mjs";
|
|
4
|
+
import * as Plugin_Fixtures$ReventlessLocal from "./Plugin_Fixtures.res.mjs";
|
|
5
|
+
import * as UiFragmentRegistry$ReventlessCore from "@reventlessdev/reventless-core/src/admin/UiFragmentRegistry/StateChangeSlice/UiFragmentRegistry.res.mjs";
|
|
6
|
+
import * as UiFragmentRegistry_Behavior$ReventlessCore from "@reventlessdev/reventless-core/src/admin/UiFragmentRegistry/StateChangeSlice/UiFragmentRegistry_Behavior.res.mjs";
|
|
7
|
+
|
|
8
|
+
let Test = Behavior_GWT$ReventlessGwt.Make({
|
|
9
|
+
name: UiFragmentRegistry$ReventlessCore.name,
|
|
10
|
+
consumedEventSchema: UiFragmentRegistry$ReventlessCore.consumedEventSchema,
|
|
11
|
+
commandSchema: UiFragmentRegistry$ReventlessCore.commandSchema,
|
|
12
|
+
errorSchema: UiFragmentRegistry$ReventlessCore.errorSchema,
|
|
13
|
+
eventSchema: UiFragmentRegistry$ReventlessCore.eventSchema
|
|
14
|
+
})({
|
|
15
|
+
initialState: undefined,
|
|
16
|
+
evolve: UiFragmentRegistry_Behavior$ReventlessCore.evolve,
|
|
17
|
+
decide: UiFragmentRegistry_Behavior$ReventlessCore.decide
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
let manifest2_panels = [];
|
|
21
|
+
|
|
22
|
+
let manifest2_pages = [];
|
|
23
|
+
|
|
24
|
+
let manifest2 = {
|
|
25
|
+
remoteEntryUrl: "https://cdn.example.com/plugin@2.0/remoteEntry.js",
|
|
26
|
+
panels: manifest2_panels,
|
|
27
|
+
pages: manifest2_pages
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
Test.describe("UiFragmentRegistry StateChangeSlice", () => {
|
|
31
|
+
Test.test("register on empty state emits UiFragmentRegistered", () => Test.thenEvent(Test.whenCmd(Test.givenEvents([]), {
|
|
32
|
+
TAG: "RegisterUiFragment",
|
|
33
|
+
pluginId: "p1",
|
|
34
|
+
manifest: Plugin_Fixtures$ReventlessLocal.uiManifest,
|
|
35
|
+
at: "t0"
|
|
36
|
+
}), {
|
|
37
|
+
TAG: "UiFragmentRegistered",
|
|
38
|
+
pluginId: "p1",
|
|
39
|
+
manifest: Plugin_Fixtures$ReventlessLocal.uiManifest,
|
|
40
|
+
at: "t0"
|
|
41
|
+
}));
|
|
42
|
+
Test.test("re-registering an identical manifest is idempotent (no event)", () => Test.thenNoEvent(Test.whenCmd(Test.givenEvents([{
|
|
43
|
+
TAG: "UiFragmentRegistered",
|
|
44
|
+
pluginId: "p1",
|
|
45
|
+
manifest: Plugin_Fixtures$ReventlessLocal.uiManifest,
|
|
46
|
+
at: "t0"
|
|
47
|
+
}]), {
|
|
48
|
+
TAG: "RegisterUiFragment",
|
|
49
|
+
pluginId: "p1",
|
|
50
|
+
manifest: Plugin_Fixtures$ReventlessLocal.uiManifest,
|
|
51
|
+
at: "t1"
|
|
52
|
+
})));
|
|
53
|
+
Test.test("registering a changed manifest emits UiFragmentUpdated", () => Test.thenEvent(Test.whenCmd(Test.givenEvents([{
|
|
54
|
+
TAG: "UiFragmentRegistered",
|
|
55
|
+
pluginId: "p1",
|
|
56
|
+
manifest: Plugin_Fixtures$ReventlessLocal.uiManifest,
|
|
57
|
+
at: "t0"
|
|
58
|
+
}]), {
|
|
59
|
+
TAG: "RegisterUiFragment",
|
|
60
|
+
pluginId: "p1",
|
|
61
|
+
manifest: manifest2,
|
|
62
|
+
at: "t1"
|
|
63
|
+
}), {
|
|
64
|
+
TAG: "UiFragmentUpdated",
|
|
65
|
+
pluginId: "p1",
|
|
66
|
+
previousManifest: Plugin_Fixtures$ReventlessLocal.uiManifest,
|
|
67
|
+
newManifest: manifest2,
|
|
68
|
+
at: "t1"
|
|
69
|
+
}));
|
|
70
|
+
Test.test("deregister emits UiFragmentDeregistered", () => Test.thenEvent(Test.whenCmd(Test.givenEvents([{
|
|
71
|
+
TAG: "UiFragmentRegistered",
|
|
72
|
+
pluginId: "p1",
|
|
73
|
+
manifest: Plugin_Fixtures$ReventlessLocal.uiManifest,
|
|
74
|
+
at: "t0"
|
|
75
|
+
}]), {
|
|
76
|
+
TAG: "DeregisterUiFragment",
|
|
77
|
+
pluginId: "p1"
|
|
78
|
+
}), {
|
|
79
|
+
TAG: "UiFragmentDeregistered",
|
|
80
|
+
pluginId: "p1"
|
|
81
|
+
}));
|
|
82
|
+
Test.test("deregistering an absent fragment is idempotent (no event)", () => Test.thenNoEvent(Test.whenCmd(Test.givenEvents([]), {
|
|
83
|
+
TAG: "DeregisterUiFragment",
|
|
84
|
+
pluginId: "p1"
|
|
85
|
+
})));
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
export {
|
|
89
|
+
Test,
|
|
90
|
+
manifest2,
|
|
91
|
+
}
|
|
92
|
+
/* Test Not a pure module */
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// StateViewSlice projection GWT for the UiFragments read side (replaces the old
|
|
2
|
+
// UIFragmentRegistryProjection over Plugin-aggregate events). Projects the UiFragmentRegistry
|
|
3
|
+
// slice's events into the manifest-per-plugin row that backs the Platform_UIFragments query.
|
|
4
|
+
open ReventlessCore
|
|
5
|
+
open Plugin_Fixtures
|
|
6
|
+
|
|
7
|
+
module Test = ReventlessGwt.Projection_GWT.Make(UiFragments, UiFragments_Projection)
|
|
8
|
+
open Test
|
|
9
|
+
open UiFragments
|
|
10
|
+
|
|
11
|
+
let manifest2: Reventless.Plugin.uiFragmentManifest = {
|
|
12
|
+
remoteEntryUrl: "https://cdn.example.com/plugin@2.0/remoteEntry.js",
|
|
13
|
+
panels: [],
|
|
14
|
+
pages: [],
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
let registeredState: UiFragments.state = {
|
|
18
|
+
pluginId: "p1",
|
|
19
|
+
remoteEntryUrl: uiManifest.remoteEntryUrl,
|
|
20
|
+
panels: uiManifest.panels,
|
|
21
|
+
pages: uiManifest.pages,
|
|
22
|
+
registeredAt: "t0",
|
|
23
|
+
updatedAt: "t0",
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
describe("UiFragments StateViewSlice projection", () => {
|
|
27
|
+
test("UiFragmentRegistered creates the row (registeredAt = updatedAt = event time)", () =>
|
|
28
|
+
givenEvents([])
|
|
29
|
+
->whenEvent(UiFragmentRegistered({pluginId: "p1", manifest: uiManifest, at: "t0"}))
|
|
30
|
+
->thenStateWithId("p1", registeredState)
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
test("UiFragmentUpdated updates manifest fields + updatedAt, keeps registeredAt", () =>
|
|
34
|
+
givenEvents([UiFragmentRegistered({pluginId: "p1", manifest: uiManifest, at: "t0"})])
|
|
35
|
+
->whenEvent(
|
|
36
|
+
UiFragmentUpdated({pluginId: "p1", previousManifest: uiManifest, newManifest: manifest2, at: "t1"}),
|
|
37
|
+
)
|
|
38
|
+
->thenStateWithId(
|
|
39
|
+
"p1",
|
|
40
|
+
{
|
|
41
|
+
...registeredState,
|
|
42
|
+
remoteEntryUrl: manifest2.remoteEntryUrl,
|
|
43
|
+
panels: manifest2.panels,
|
|
44
|
+
pages: manifest2.pages,
|
|
45
|
+
updatedAt: "t1",
|
|
46
|
+
},
|
|
47
|
+
)
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
test("UiFragmentDeregistered removes the row", () =>
|
|
51
|
+
givenEvents([UiFragmentRegistered({pluginId: "p1", manifest: uiManifest, at: "t0"})])
|
|
52
|
+
->whenEvent(UiFragmentDeregistered({pluginId: "p1"}))
|
|
53
|
+
->thenNoState
|
|
54
|
+
)
|
|
55
|
+
})
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as UiFragments$ReventlessCore from "@reventlessdev/reventless-core/src/admin/UiFragmentRegistry/StateViewSlice/UiFragments.res.mjs";
|
|
4
|
+
import * as Projection_GWT$ReventlessGwt from "@reventlessdev/reventless-gwt/src/Projection_GWT.res.mjs";
|
|
5
|
+
import * as Plugin_Fixtures$ReventlessLocal from "./Plugin_Fixtures.res.mjs";
|
|
6
|
+
import * as UiFragments_Projection$ReventlessCore from "@reventlessdev/reventless-core/src/admin/UiFragmentRegistry/StateViewSlice/UiFragments_Projection.res.mjs";
|
|
7
|
+
|
|
8
|
+
let Test = Projection_GWT$ReventlessGwt.Make({
|
|
9
|
+
name: UiFragments$ReventlessCore.name,
|
|
10
|
+
stateSchema: UiFragments$ReventlessCore.stateSchema,
|
|
11
|
+
consumedEventSchema: UiFragments$ReventlessCore.consumedEventSchema,
|
|
12
|
+
subIdConfig: undefined
|
|
13
|
+
})({
|
|
14
|
+
project: UiFragments_Projection$ReventlessCore.project
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
let manifest2_panels = [];
|
|
18
|
+
|
|
19
|
+
let manifest2_pages = [];
|
|
20
|
+
|
|
21
|
+
let manifest2 = {
|
|
22
|
+
remoteEntryUrl: "https://cdn.example.com/plugin@2.0/remoteEntry.js",
|
|
23
|
+
panels: manifest2_panels,
|
|
24
|
+
pages: manifest2_pages
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
let registeredState_remoteEntryUrl = Plugin_Fixtures$ReventlessLocal.uiManifest.remoteEntryUrl;
|
|
28
|
+
|
|
29
|
+
let registeredState_panels = Plugin_Fixtures$ReventlessLocal.uiManifest.panels;
|
|
30
|
+
|
|
31
|
+
let registeredState_pages = Plugin_Fixtures$ReventlessLocal.uiManifest.pages;
|
|
32
|
+
|
|
33
|
+
let registeredState = {
|
|
34
|
+
pluginId: "p1",
|
|
35
|
+
remoteEntryUrl: registeredState_remoteEntryUrl,
|
|
36
|
+
panels: registeredState_panels,
|
|
37
|
+
pages: registeredState_pages,
|
|
38
|
+
registeredAt: "t0",
|
|
39
|
+
updatedAt: "t0"
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
Test.describe("UiFragments StateViewSlice projection", () => {
|
|
43
|
+
Test.test("UiFragmentRegistered creates the row (registeredAt = updatedAt = event time)", undefined, () => Test.thenStateWithId(Test.whenEvent(Test.givenEvents([]), {
|
|
44
|
+
TAG: "UiFragmentRegistered",
|
|
45
|
+
pluginId: "p1",
|
|
46
|
+
manifest: Plugin_Fixtures$ReventlessLocal.uiManifest,
|
|
47
|
+
at: "t0"
|
|
48
|
+
}), "p1", registeredState));
|
|
49
|
+
Test.test("UiFragmentUpdated updates manifest fields + updatedAt, keeps registeredAt", undefined, () => Test.thenStateWithId(Test.whenEvent(Test.givenEvents([{
|
|
50
|
+
TAG: "UiFragmentRegistered",
|
|
51
|
+
pluginId: "p1",
|
|
52
|
+
manifest: Plugin_Fixtures$ReventlessLocal.uiManifest,
|
|
53
|
+
at: "t0"
|
|
54
|
+
}]), {
|
|
55
|
+
TAG: "UiFragmentUpdated",
|
|
56
|
+
pluginId: "p1",
|
|
57
|
+
previousManifest: Plugin_Fixtures$ReventlessLocal.uiManifest,
|
|
58
|
+
newManifest: manifest2,
|
|
59
|
+
at: "t1"
|
|
60
|
+
}), "p1", {
|
|
61
|
+
pluginId: "p1",
|
|
62
|
+
remoteEntryUrl: "https://cdn.example.com/plugin@2.0/remoteEntry.js",
|
|
63
|
+
panels: manifest2_panels,
|
|
64
|
+
pages: manifest2_pages,
|
|
65
|
+
registeredAt: "t0",
|
|
66
|
+
updatedAt: "t1"
|
|
67
|
+
}));
|
|
68
|
+
Test.test("UiFragmentDeregistered removes the row", undefined, () => Test.thenNoState(Test.whenEvent(Test.givenEvents([{
|
|
69
|
+
TAG: "UiFragmentRegistered",
|
|
70
|
+
pluginId: "p1",
|
|
71
|
+
manifest: Plugin_Fixtures$ReventlessLocal.uiManifest,
|
|
72
|
+
at: "t0"
|
|
73
|
+
}]), {
|
|
74
|
+
TAG: "UiFragmentDeregistered",
|
|
75
|
+
pluginId: "p1"
|
|
76
|
+
})));
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
export {
|
|
80
|
+
Test,
|
|
81
|
+
manifest2,
|
|
82
|
+
registeredState,
|
|
83
|
+
}
|
|
84
|
+
/* Test Not a pure module */
|