@voltro/testing 0.85.0 → 0.87.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.
- package/CHANGELOG.md +5987 -0
- package/README.md +11 -0
- package/THIRD-PARTY-NOTICES.md +864 -253
- package/dist/client.d.ts +5 -0
- package/dist/client.js +85 -97
- package/dist/dialect.d.ts +20 -0
- package/dist/dialect.js +1051 -653
- package/dist/factory.js +65 -0
- package/dist/fieldKeys.js +73 -0
- package/dist/fieldKeysSql.js +14 -0
- package/dist/fixtureRow.js +30 -0
- package/dist/formBindingHarness.js +46 -0
- package/dist/hotStoreSqlParity.js +132 -0
- package/dist/hydrateFixtureRows.js +22 -0
- package/dist/index.d.ts +125 -7
- package/dist/index.js +22 -933
- package/dist/invoke.js +82 -0
- package/dist/mockClock.js +78 -0
- package/dist/mockLLM.js +19 -0
- package/dist/mockWebhooks.js +26 -0
- package/dist/platform.js +1 -5
- package/dist/reachable.js +27 -0
- package/dist/serviceApiMock.js +53 -0
- package/dist/subject.js +11 -0
- package/dist/subscribeContext.js +16 -0
- package/dist/system.d.ts +99 -0
- package/dist/system.js +94 -0
- package/dist/testApps.js +111 -0
- package/dist/testContext.js +269 -0
- package/dist/testEventBus.js +73 -0
- package/dist/testRequest.js +121 -0
- package/dist/withConnections.js +26 -0
- package/dist/workflowRunner.js +85 -0
- package/package.json +16 -9
package/dist/client.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { FormBinding } from '@voltro/client';
|
|
|
6
6
|
import { FormStateSnapshot } from '@voltro/client';
|
|
7
7
|
import { ReactElement } from 'react';
|
|
8
8
|
import { ReactNode } from 'react';
|
|
9
|
+
import { RecoveryOptions } from '@voltro/client';
|
|
9
10
|
import { UseFormBindingOptions } from '@voltro/client';
|
|
10
11
|
|
|
11
12
|
/** The snapshot shape `useConnectionStatus` subscribes to. */
|
|
@@ -177,6 +178,10 @@ export declare interface VoltroTestClientConfig {
|
|
|
177
178
|
readonly mutations?: Readonly<Record<string, Handler>>;
|
|
178
179
|
/** Action handlers per tag. */
|
|
179
180
|
readonly actions?: Readonly<Record<string, Handler>>;
|
|
181
|
+
/** The client's recovery options, as an app passes them — `replayWindowMs` is how
|
|
182
|
+
* long an action waits for a disconnected transport before it is refused
|
|
183
|
+
* (default 10 s, at least 250 ms). */
|
|
184
|
+
readonly recovery?: RecoveryOptions;
|
|
180
185
|
}
|
|
181
186
|
|
|
182
187
|
export { }
|
package/dist/client.js
CHANGED
|
@@ -1,85 +1,47 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}), l, u = () => (l = a(o, e, r.binding ?? {}), null), d = i(globalThis.document.createElement("div"));
|
|
15
|
-
return await t(async () => {
|
|
16
|
-
d.render(n(s.Provider, null, n(u)));
|
|
17
|
-
}), {
|
|
18
|
-
binding: () => l,
|
|
19
|
-
fill: (e, n) => {
|
|
20
|
-
t(() => {
|
|
21
|
-
l.field(e).setValue(n);
|
|
22
|
-
});
|
|
23
|
-
},
|
|
24
|
-
blur: (e) => {
|
|
25
|
-
t(() => {
|
|
26
|
-
l.field(e).onBlur();
|
|
27
|
-
});
|
|
28
|
-
},
|
|
29
|
-
submit: async () => {
|
|
30
|
-
let e;
|
|
31
|
-
return await t(async () => {
|
|
32
|
-
e = await l.submit();
|
|
33
|
-
}), e;
|
|
34
|
-
},
|
|
35
|
-
errors: () => l.errors,
|
|
36
|
-
state: () => l.state,
|
|
37
|
-
client: s,
|
|
38
|
-
unmount: () => {
|
|
39
|
-
t(() => {
|
|
40
|
-
d.unmount();
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
};
|
|
44
|
-
}, s = {
|
|
45
|
-
runPromise: e.runPromise,
|
|
46
|
-
runPromiseExit: e.runPromiseExit,
|
|
47
|
-
runFork: e.runFork,
|
|
48
|
-
dispose: () => e.void
|
|
49
|
-
}, c = (t = {}) => {
|
|
50
|
-
let a = t.apiName ?? "app", o = /* @__PURE__ */ new Map(), c = /* @__PURE__ */ new Map(), l = /* @__PURE__ */ new Map(), u = [];
|
|
51
|
-
for (let [e, n] of Object.entries(t.subscriptions ?? {})) o.set(e, {
|
|
1
|
+
import { renderFormBinding as e } from "./formBindingHarness.js";
|
|
2
|
+
import { Effect as t } from "effect";
|
|
3
|
+
import { createElement as n } from "react";
|
|
4
|
+
import { FrameworkRuntimesContext as r, INITIAL_RECOVERY_SNAPSHOT as i, RpcErrorBus as a, resolveRecoveryOptions as o } from "@voltro/client";
|
|
5
|
+
//#region src/client.tsx
|
|
6
|
+
var s = {
|
|
7
|
+
runPromise: t.runPromise,
|
|
8
|
+
runPromiseExit: t.runPromiseExit,
|
|
9
|
+
runFork: t.runFork,
|
|
10
|
+
dispose: () => t.void
|
|
11
|
+
}, c = (e = {}) => {
|
|
12
|
+
let c = e.apiName ?? "app", l = /* @__PURE__ */ new Map(), u = /* @__PURE__ */ new Map(), d = /* @__PURE__ */ new Map(), f = [];
|
|
13
|
+
for (let [t, n] of Object.entries(e.subscriptions ?? {})) l.set(t, {
|
|
52
14
|
data: n,
|
|
53
15
|
error: void 0,
|
|
54
16
|
revision: 0,
|
|
55
17
|
pendingPatches: 0,
|
|
56
18
|
emittedAt: void 0
|
|
57
19
|
});
|
|
58
|
-
let
|
|
20
|
+
let p = (e) => l.get(e) ?? {
|
|
59
21
|
data: void 0,
|
|
60
22
|
error: void 0,
|
|
61
23
|
revision: -1,
|
|
62
24
|
pendingPatches: 0,
|
|
63
25
|
emittedAt: void 0
|
|
64
|
-
},
|
|
65
|
-
|
|
66
|
-
for (let t of
|
|
67
|
-
},
|
|
26
|
+
}, m = (e) => {
|
|
27
|
+
d.delete(e);
|
|
28
|
+
for (let t of u.get(e) ?? []) t();
|
|
29
|
+
}, h = (e) => String(e[0] ?? ""), g = {
|
|
68
30
|
peek: (e) => {
|
|
69
|
-
let t =
|
|
31
|
+
let t = h(e), n = d.get(t);
|
|
70
32
|
if (n) return n;
|
|
71
|
-
let r =
|
|
33
|
+
let r = p(t), i = {
|
|
72
34
|
data: r.data,
|
|
73
35
|
revision: r.revision,
|
|
74
36
|
emittedAt: r.emittedAt,
|
|
75
37
|
error: r.error,
|
|
76
38
|
pendingPatches: r.pendingPatches
|
|
77
39
|
};
|
|
78
|
-
return
|
|
40
|
+
return d.set(t, i), i;
|
|
79
41
|
},
|
|
80
42
|
subscribe: (e, t, n, r) => {
|
|
81
|
-
let i =
|
|
82
|
-
return a.add(r),
|
|
43
|
+
let i = h(e), a = u.get(i) ?? /* @__PURE__ */ new Set();
|
|
44
|
+
return a.add(r), u.set(i, a), { unsubscribe: () => {
|
|
83
45
|
a.delete(r);
|
|
84
46
|
} };
|
|
85
47
|
},
|
|
@@ -92,9 +54,9 @@ var o = async (e, r = {}) => {
|
|
|
92
54
|
update: () => {},
|
|
93
55
|
forTag: () => ({ patchedCount: 0 }),
|
|
94
56
|
refreshAll: () => {
|
|
95
|
-
|
|
57
|
+
_ += 1;
|
|
96
58
|
}
|
|
97
|
-
},
|
|
59
|
+
}, _ = 0, v = {
|
|
98
60
|
rawTransport: "connected",
|
|
99
61
|
status: "connected",
|
|
100
62
|
failureCount: 0,
|
|
@@ -102,83 +64,109 @@ var o = async (e, r = {}) => {
|
|
|
102
64
|
failedSubscriptions: [],
|
|
103
65
|
pendingMutationReplays: 0,
|
|
104
66
|
mutationReplay: "unknown"
|
|
105
|
-
},
|
|
106
|
-
|
|
107
|
-
|
|
67
|
+
}, y = /* @__PURE__ */ new Set(), b = o(e.recovery), x = new a(), S = !0, C = {
|
|
68
|
+
options: b,
|
|
69
|
+
subscribe: (e) => (y.add(e), () => {
|
|
70
|
+
y.delete(e);
|
|
108
71
|
}),
|
|
109
|
-
getSnapshot: () =>
|
|
72
|
+
getSnapshot: () => v,
|
|
73
|
+
getServerSnapshot: () => i,
|
|
74
|
+
getPreloadSeedPermission: () => S,
|
|
75
|
+
invalidatePreloadSeeds: () => {
|
|
76
|
+
if (S) {
|
|
77
|
+
S = !1;
|
|
78
|
+
for (let e of y) e();
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
onVisibleError: (e) => x.on(e),
|
|
82
|
+
waitForProtocolReady: (e, t) => {
|
|
83
|
+
if (t?.aborted) return Promise.resolve(!1);
|
|
84
|
+
if (v.rawTransport === "connected") return Promise.resolve(!0);
|
|
85
|
+
let n = b.replayWindowMs - (Date.now() - e);
|
|
86
|
+
return n <= 0 ? Promise.resolve(!1) : new Promise((e) => {
|
|
87
|
+
let r = (n) => {
|
|
88
|
+
y.delete(i), clearTimeout(o), t?.removeEventListener("abort", a), e(n);
|
|
89
|
+
}, i = () => {
|
|
90
|
+
v.rawTransport === "connected" && r(!0);
|
|
91
|
+
}, a = () => r(!1), o = setTimeout(() => r(!1), n);
|
|
92
|
+
y.add(i), t?.addEventListener("abort", a, { once: !0 }), t?.aborted && a();
|
|
93
|
+
});
|
|
94
|
+
},
|
|
95
|
+
reserveMutationReplay: () => void 0,
|
|
96
|
+
waitForMutationReplaySupport: async () => !1,
|
|
97
|
+
replayWindowRemaining: () => 0,
|
|
110
98
|
reportExternalSuccess: () => {},
|
|
111
99
|
subjectSignal: new AbortController().signal
|
|
112
|
-
},
|
|
113
|
-
let i =
|
|
100
|
+
}, w = {}, T = (e, n, r) => {
|
|
101
|
+
let i = e.split("."), a = w;
|
|
114
102
|
for (let e of i.slice(0, -1)) a[e] = a[e] ?? {}, a = a[e];
|
|
115
|
-
a[i[i.length - 1]] = (i) =>
|
|
116
|
-
try: async () => (
|
|
103
|
+
a[i[i.length - 1]] = (i) => t.tryPromise({
|
|
104
|
+
try: async () => (f.push({
|
|
117
105
|
kind: n,
|
|
118
|
-
tag:
|
|
106
|
+
tag: e,
|
|
119
107
|
input: i
|
|
120
108
|
}), await r(i)),
|
|
121
109
|
catch: (e) => e
|
|
122
110
|
});
|
|
123
111
|
};
|
|
124
|
-
for (let [
|
|
125
|
-
for (let [
|
|
126
|
-
let
|
|
112
|
+
for (let [t, n] of Object.entries(e.mutations ?? {})) T(t, "mutation", n);
|
|
113
|
+
for (let [t, n] of Object.entries(e.actions ?? {})) T(t, "action", n);
|
|
114
|
+
let E = {
|
|
127
115
|
runtime: s,
|
|
128
|
-
cache:
|
|
129
|
-
recovery:
|
|
130
|
-
client:
|
|
116
|
+
cache: g,
|
|
117
|
+
recovery: C,
|
|
118
|
+
client: w,
|
|
131
119
|
descriptors: {},
|
|
132
120
|
inspectBaseUrl: "http://test.local",
|
|
133
|
-
errorBus:
|
|
134
|
-
},
|
|
121
|
+
errorBus: x
|
|
122
|
+
}, D = {
|
|
135
123
|
get: (e) => {
|
|
136
|
-
if (e !==
|
|
137
|
-
return
|
|
124
|
+
if (e !== c) throw Error(`makeVoltroTestClient: component asked for api '${e}' but the harness was built for '${c}'. Pass { apiName: '${e}' }.`);
|
|
125
|
+
return E;
|
|
138
126
|
},
|
|
139
|
-
names: [
|
|
127
|
+
names: [c]
|
|
140
128
|
};
|
|
141
129
|
return {
|
|
142
|
-
Provider: ({ children: e }) => n(r.Provider, { value:
|
|
130
|
+
Provider: ({ children: e }) => n(r.Provider, { value: D }, e),
|
|
143
131
|
setSubscription: (e, t, n) => {
|
|
144
|
-
let r =
|
|
145
|
-
|
|
132
|
+
let r = p(e);
|
|
133
|
+
l.set(e, {
|
|
146
134
|
data: t,
|
|
147
135
|
error: void 0,
|
|
148
136
|
revision: r.revision + 1,
|
|
149
137
|
pendingPatches: n?.pendingPatches ?? 0,
|
|
150
138
|
emittedAt: n?.emittedAt
|
|
151
|
-
}),
|
|
139
|
+
}), m(e);
|
|
152
140
|
},
|
|
153
141
|
failSubscription: (e, t) => {
|
|
154
|
-
|
|
142
|
+
l.set(e, {
|
|
155
143
|
data: void 0,
|
|
156
144
|
error: t,
|
|
157
145
|
revision: -1,
|
|
158
146
|
pendingPatches: 0,
|
|
159
147
|
emittedAt: void 0
|
|
160
|
-
}),
|
|
148
|
+
}), m(e);
|
|
161
149
|
},
|
|
162
150
|
resetSubscription: (e) => {
|
|
163
|
-
|
|
151
|
+
l.delete(e), m(e);
|
|
164
152
|
},
|
|
165
|
-
calls:
|
|
153
|
+
calls: f,
|
|
166
154
|
setConnectionStatus: (e, t) => {
|
|
167
|
-
|
|
168
|
-
...
|
|
155
|
+
v = {
|
|
156
|
+
...v,
|
|
169
157
|
...t,
|
|
170
158
|
status: e,
|
|
171
159
|
rawTransport: t?.rawTransport ?? (e === "connected" ? "connected" : "disconnected")
|
|
172
160
|
};
|
|
173
|
-
for (let e of
|
|
161
|
+
for (let e of y) e();
|
|
174
162
|
},
|
|
175
163
|
get refreshes() {
|
|
176
|
-
return
|
|
164
|
+
return _;
|
|
177
165
|
},
|
|
178
166
|
emitRpcError: (e) => {
|
|
179
|
-
|
|
167
|
+
E.errorBus.emit(e);
|
|
180
168
|
}
|
|
181
169
|
};
|
|
182
170
|
};
|
|
183
171
|
//#endregion
|
|
184
|
-
export { s as FAKE_RUNTIME, c as makeVoltroTestClient,
|
|
172
|
+
export { s as FAKE_RUNTIME, c as makeVoltroTestClient, e as renderFormBinding };
|
package/dist/dialect.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { applySchema } from '@voltro/database/sql';
|
|
2
2
|
import { DataStore } from '@voltro/database';
|
|
3
|
+
import { DialectId } from '@voltro/database';
|
|
3
4
|
import { Effect } from 'effect';
|
|
4
5
|
import { SqlClient } from 'effect/sql';
|
|
5
6
|
import { SqlDialect } from '@voltro/database';
|
|
@@ -48,6 +49,22 @@ export declare interface DialectFixtureSession {
|
|
|
48
49
|
readonly dispose: () => Promise<void>;
|
|
49
50
|
}
|
|
50
51
|
|
|
52
|
+
export declare interface HotSqlFixture {
|
|
53
|
+
readonly dialect: DialectId;
|
|
54
|
+
readonly name: string;
|
|
55
|
+
readonly make: () => Promise<HotSqlFixtureSession>;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** A real SQL fixture owns a fresh physical namespace and every connection it opens. */
|
|
59
|
+
export declare interface HotSqlFixtureSession {
|
|
60
|
+
readonly store: DataStore;
|
|
61
|
+
/** Open another independent SQL connection/pool to the same owned tables. */
|
|
62
|
+
readonly connect: () => Promise<DataStore>;
|
|
63
|
+
/** Re-apply the declared tables; SQL fixtures must keep DDL idempotent. */
|
|
64
|
+
readonly migrate: () => Promise<void>;
|
|
65
|
+
readonly dispose: () => Promise<void>;
|
|
66
|
+
}
|
|
67
|
+
|
|
51
68
|
/**
|
|
52
69
|
* Register the dialect's parity suite with vitest. Calls
|
|
53
70
|
* `describe(...)` so the dialect's name appears in test output.
|
|
@@ -64,4 +81,7 @@ export declare interface DialectFixtureSession {
|
|
|
64
81
|
*/
|
|
65
82
|
export declare const runDialectParity: (fixture: DialectFixture) => void;
|
|
66
83
|
|
|
84
|
+
/** Identical HotStore assertions for every live SQL dialect; no fixture opt-outs. */
|
|
85
|
+
export declare const runHotStoreSqlParity: (fixture: HotSqlFixture) => void;
|
|
86
|
+
|
|
67
87
|
export { }
|