jazz-tools 0.19.0 → 0.19.2
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/.turbo/turbo-build.log +53 -53
- package/CHANGELOG.md +21 -0
- package/dist/{chunk-P3YLNFN4.js → chunk-NCNM6UDZ.js} +61 -22
- package/dist/chunk-NCNM6UDZ.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/inspector/{custom-element-QESCMFY7.js → custom-element-ABVPHX53.js} +1118 -465
- package/dist/inspector/custom-element-ABVPHX53.js.map +1 -0
- package/dist/inspector/index.js +1090 -437
- package/dist/inspector/index.js.map +1 -1
- package/dist/inspector/register-custom-element.js +1 -1
- package/dist/inspector/tests/utils/history.test.d.ts +2 -0
- package/dist/inspector/tests/utils/history.test.d.ts.map +1 -0
- package/dist/inspector/tests/viewer/co-value-editor.test.d.ts +2 -0
- package/dist/inspector/tests/viewer/co-value-editor.test.d.ts.map +1 -0
- package/dist/inspector/tests/viewer/comap-view.test.d.ts +2 -0
- package/dist/inspector/tests/viewer/comap-view.test.d.ts.map +1 -0
- package/dist/inspector/ui/icon.d.ts +6 -0
- package/dist/inspector/ui/icon.d.ts.map +1 -1
- package/dist/inspector/ui/icons/add-icon.d.ts +2 -0
- package/dist/inspector/ui/icons/add-icon.d.ts.map +1 -0
- package/dist/inspector/ui/icons/edit-icon.d.ts +2 -0
- package/dist/inspector/ui/icons/edit-icon.d.ts.map +1 -0
- package/dist/inspector/ui/icons/history.d.ts +2 -0
- package/dist/inspector/ui/icons/history.d.ts.map +1 -0
- package/dist/inspector/utils/history.d.ts +3 -0
- package/dist/inspector/utils/history.d.ts.map +1 -0
- package/dist/inspector/utils/transactions-changes.d.ts +38 -0
- package/dist/inspector/utils/transactions-changes.d.ts.map +1 -0
- package/dist/inspector/viewer/co-map-view.d.ts +9 -0
- package/dist/inspector/viewer/co-map-view.d.ts.map +1 -0
- package/dist/inspector/viewer/co-value-editor.d.ts +10 -0
- package/dist/inspector/viewer/co-value-editor.d.ts.map +1 -0
- package/dist/inspector/viewer/grid-view.d.ts +3 -2
- package/dist/inspector/viewer/grid-view.d.ts.map +1 -1
- package/dist/inspector/viewer/history-view.d.ts.map +1 -1
- package/dist/inspector/viewer/page.d.ts.map +1 -1
- package/dist/testing.js +1 -1
- package/dist/tools/coValues/CoFieldInit.d.ts +2 -1
- package/dist/tools/coValues/CoFieldInit.d.ts.map +1 -1
- package/dist/tools/coValues/deepLoading.d.ts +8 -7
- package/dist/tools/coValues/deepLoading.d.ts.map +1 -1
- package/dist/tools/coValues/interfaces.d.ts +3 -3
- package/dist/tools/coValues/interfaces.d.ts.map +1 -1
- package/dist/tools/coValues/schemaUnion.d.ts +6 -9
- package/dist/tools/coValues/schemaUnion.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/CoDiscriminatedUnionSchema.d.ts +18 -7
- package/dist/tools/implementation/zodSchema/schemaTypes/CoDiscriminatedUnionSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/typeConverters/CoFieldSchemaInit.d.ts +3 -2
- package/dist/tools/implementation/zodSchema/typeConverters/CoFieldSchemaInit.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/unionUtils.d.ts.map +1 -1
- package/dist/tools/subscribe/SubscriptionScope.d.ts +1 -0
- package/dist/tools/subscribe/SubscriptionScope.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/inspector/tests/utils/history.test.ts +401 -0
- package/src/inspector/tests/viewer/co-value-editor.test.tsx +903 -0
- package/src/inspector/tests/viewer/comap-view.test.tsx +581 -0
- package/src/inspector/ui/icon.tsx +6 -0
- package/src/inspector/ui/icons/add-icon.tsx +21 -0
- package/src/inspector/ui/icons/edit-icon.tsx +17 -0
- package/src/inspector/ui/icons/history.tsx +28 -0
- package/src/inspector/ui/modal.tsx +3 -3
- package/src/inspector/utils/history.ts +49 -0
- package/src/inspector/utils/transactions-changes.ts +98 -0
- package/src/inspector/viewer/co-map-view.tsx +312 -0
- package/src/inspector/viewer/co-value-editor.tsx +164 -0
- package/src/inspector/viewer/grid-view.tsx +139 -10
- package/src/inspector/viewer/history-view.tsx +16 -118
- package/src/inspector/viewer/page.tsx +13 -0
- package/src/react-core/tests/usePassPhraseAuth.test.ts +1 -1
- package/src/tools/coValues/CoFieldInit.ts +6 -3
- package/src/tools/coValues/coList.ts +1 -1
- package/src/tools/coValues/deepLoading.ts +85 -71
- package/src/tools/coValues/interfaces.ts +3 -3
- package/src/tools/coValues/schemaUnion.ts +19 -14
- package/src/tools/implementation/zodSchema/schemaTypes/CoDiscriminatedUnionSchema.ts +69 -9
- package/src/tools/implementation/zodSchema/typeConverters/CoFieldSchemaInit.ts +12 -7
- package/src/tools/implementation/zodSchema/unionUtils.ts +35 -4
- package/src/tools/subscribe/SubscriptionScope.ts +3 -14
- package/src/tools/tests/coDiscriminatedUnion.test.ts +347 -5
- package/src/tools/tests/coVector.test.ts +43 -0
- package/src/tools/tests/deepLoading.test.ts +55 -59
- package/src/tools/tests/schema.resolved.test.ts +70 -1
- package/dist/chunk-P3YLNFN4.js.map +0 -1
- package/dist/inspector/custom-element-QESCMFY7.js.map +0 -1
|
@@ -0,0 +1,903 @@
|
|
|
1
|
+
// @vitest-environment happy-dom
|
|
2
|
+
import { afterEach, beforeAll, describe, expect, it, vi } from "vitest";
|
|
3
|
+
import { setActiveAccount, setupJazzTestSync } from "jazz-tools/testing";
|
|
4
|
+
import { co, z } from "jazz-tools";
|
|
5
|
+
import {
|
|
6
|
+
cleanup,
|
|
7
|
+
fireEvent,
|
|
8
|
+
render,
|
|
9
|
+
screen,
|
|
10
|
+
waitFor,
|
|
11
|
+
} from "@testing-library/react";
|
|
12
|
+
import { CoValueEditor } from "../../viewer/co-value-editor";
|
|
13
|
+
import { setup } from "goober";
|
|
14
|
+
import React from "react";
|
|
15
|
+
|
|
16
|
+
describe("CoValueEditor", async () => {
|
|
17
|
+
const account = await setupJazzTestSync();
|
|
18
|
+
setActiveAccount(account);
|
|
19
|
+
|
|
20
|
+
beforeAll(() => {
|
|
21
|
+
setup(React.createElement);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
afterEach(() => {
|
|
25
|
+
cleanup();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
describe("Initial Rendering", () => {
|
|
29
|
+
it("should render with number value", async () => {
|
|
30
|
+
const value = co
|
|
31
|
+
.map({
|
|
32
|
+
count: z.number(),
|
|
33
|
+
})
|
|
34
|
+
.create({ count: 42 });
|
|
35
|
+
|
|
36
|
+
const onCancel = vi.fn();
|
|
37
|
+
|
|
38
|
+
render(
|
|
39
|
+
<CoValueEditor
|
|
40
|
+
node={account.$jazz.localNode}
|
|
41
|
+
property="count"
|
|
42
|
+
value={42}
|
|
43
|
+
coValue={value.$jazz.raw}
|
|
44
|
+
onCancel={onCancel}
|
|
45
|
+
/>,
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
expect(screen.getByLabelText("Type")).toBeDefined();
|
|
49
|
+
expect(screen.getByDisplayValue("number")).toBeDefined();
|
|
50
|
+
expect(screen.getByDisplayValue("42")).toBeDefined();
|
|
51
|
+
expect(screen.getByText("Cancel")).toBeDefined();
|
|
52
|
+
expect(screen.getByText("Submit")).toBeDefined();
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it("should render with string value", async () => {
|
|
56
|
+
const value = co
|
|
57
|
+
.map({
|
|
58
|
+
name: z.string(),
|
|
59
|
+
})
|
|
60
|
+
.create({ name: "test" });
|
|
61
|
+
|
|
62
|
+
const onCancel = vi.fn();
|
|
63
|
+
|
|
64
|
+
render(
|
|
65
|
+
<CoValueEditor
|
|
66
|
+
node={account.$jazz.localNode}
|
|
67
|
+
property="name"
|
|
68
|
+
value="test"
|
|
69
|
+
coValue={value.$jazz.raw}
|
|
70
|
+
onCancel={onCancel}
|
|
71
|
+
/>,
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
expect(screen.getByDisplayValue("string")).toBeDefined();
|
|
75
|
+
expect(screen.getByDisplayValue("test")).toBeDefined();
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it("should render with boolean true value", async () => {
|
|
79
|
+
const value = co
|
|
80
|
+
.map({
|
|
81
|
+
active: z.boolean(),
|
|
82
|
+
})
|
|
83
|
+
.create({ active: true });
|
|
84
|
+
|
|
85
|
+
const onCancel = vi.fn();
|
|
86
|
+
|
|
87
|
+
render(
|
|
88
|
+
<CoValueEditor
|
|
89
|
+
node={account.$jazz.localNode}
|
|
90
|
+
property="active"
|
|
91
|
+
value={true}
|
|
92
|
+
coValue={value.$jazz.raw}
|
|
93
|
+
onCancel={onCancel}
|
|
94
|
+
/>,
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
expect(screen.getByDisplayValue("true")).toBeDefined();
|
|
98
|
+
expect(screen.queryByRole("textbox")).toBeNull();
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it("should render with boolean false value", async () => {
|
|
102
|
+
const value = co
|
|
103
|
+
.map({
|
|
104
|
+
active: z.boolean(),
|
|
105
|
+
})
|
|
106
|
+
.create({ active: false });
|
|
107
|
+
|
|
108
|
+
const onCancel = vi.fn();
|
|
109
|
+
|
|
110
|
+
render(
|
|
111
|
+
<CoValueEditor
|
|
112
|
+
node={account.$jazz.localNode}
|
|
113
|
+
property="active"
|
|
114
|
+
value={false}
|
|
115
|
+
coValue={value.$jazz.raw}
|
|
116
|
+
onCancel={onCancel}
|
|
117
|
+
/>,
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
expect(screen.getByDisplayValue("false")).toBeDefined();
|
|
121
|
+
expect(screen.queryByRole("textbox")).toBeNull();
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it("should render with null value", async () => {
|
|
125
|
+
const value = co
|
|
126
|
+
.map({
|
|
127
|
+
data: z.string().nullable(),
|
|
128
|
+
})
|
|
129
|
+
.create({ data: null });
|
|
130
|
+
|
|
131
|
+
const onCancel = vi.fn();
|
|
132
|
+
|
|
133
|
+
render(
|
|
134
|
+
<CoValueEditor
|
|
135
|
+
node={account.$jazz.localNode}
|
|
136
|
+
property="data"
|
|
137
|
+
value={null}
|
|
138
|
+
coValue={value.$jazz.raw}
|
|
139
|
+
onCancel={onCancel}
|
|
140
|
+
/>,
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
expect(screen.getByDisplayValue("null")).toBeDefined();
|
|
144
|
+
expect(screen.queryByRole("textbox")).toBeNull();
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it("should render with undefined value", async () => {
|
|
148
|
+
const value = co
|
|
149
|
+
.map({
|
|
150
|
+
optional: z.string().optional(),
|
|
151
|
+
})
|
|
152
|
+
.create({});
|
|
153
|
+
|
|
154
|
+
const onCancel = vi.fn();
|
|
155
|
+
|
|
156
|
+
render(
|
|
157
|
+
<CoValueEditor
|
|
158
|
+
node={account.$jazz.localNode}
|
|
159
|
+
property="optional"
|
|
160
|
+
value={undefined}
|
|
161
|
+
coValue={value.$jazz.raw}
|
|
162
|
+
onCancel={onCancel}
|
|
163
|
+
/>,
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
expect(screen.getByDisplayValue("undefined")).toBeDefined();
|
|
167
|
+
expect(screen.queryByRole("textbox")).toBeNull();
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
it("should render with object value", async () => {
|
|
171
|
+
const value = co
|
|
172
|
+
.map({
|
|
173
|
+
config: z.json(),
|
|
174
|
+
})
|
|
175
|
+
.create({ config: { foo: "bar", num: 123 } });
|
|
176
|
+
|
|
177
|
+
const onCancel = vi.fn();
|
|
178
|
+
|
|
179
|
+
render(
|
|
180
|
+
<CoValueEditor
|
|
181
|
+
node={account.$jazz.localNode}
|
|
182
|
+
property="config"
|
|
183
|
+
value={{ foo: "bar", num: 123 }}
|
|
184
|
+
coValue={value.$jazz.raw}
|
|
185
|
+
onCancel={onCancel}
|
|
186
|
+
/>,
|
|
187
|
+
);
|
|
188
|
+
|
|
189
|
+
expect(screen.getByDisplayValue("object")).toBeDefined();
|
|
190
|
+
const textarea = screen.getByRole("textbox") as HTMLTextAreaElement;
|
|
191
|
+
expect(textarea).toBeDefined();
|
|
192
|
+
expect(textarea.value).toBe(
|
|
193
|
+
JSON.stringify({ foo: "bar", num: 123 }, null, 2),
|
|
194
|
+
);
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
describe("Type Selection", () => {
|
|
199
|
+
it("should show textarea when number type is selected", async () => {
|
|
200
|
+
const value = co
|
|
201
|
+
.map({
|
|
202
|
+
count: z.number(),
|
|
203
|
+
})
|
|
204
|
+
.create({ count: 42 });
|
|
205
|
+
|
|
206
|
+
const onCancel = vi.fn();
|
|
207
|
+
|
|
208
|
+
render(
|
|
209
|
+
<CoValueEditor
|
|
210
|
+
node={account.$jazz.localNode}
|
|
211
|
+
property="count"
|
|
212
|
+
value={42}
|
|
213
|
+
coValue={value.$jazz.raw}
|
|
214
|
+
onCancel={onCancel}
|
|
215
|
+
/>,
|
|
216
|
+
);
|
|
217
|
+
|
|
218
|
+
const select = screen.getByLabelText("Type");
|
|
219
|
+
expect(screen.getByRole("textbox")).toBeDefined();
|
|
220
|
+
|
|
221
|
+
fireEvent.change(select, { target: { value: "number" } });
|
|
222
|
+
expect(screen.getByRole("textbox")).toBeDefined();
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
it("should show textarea when string type is selected", async () => {
|
|
226
|
+
const value = co
|
|
227
|
+
.map({
|
|
228
|
+
name: z.string(),
|
|
229
|
+
})
|
|
230
|
+
.create({ name: "test" });
|
|
231
|
+
|
|
232
|
+
const onCancel = vi.fn();
|
|
233
|
+
|
|
234
|
+
render(
|
|
235
|
+
<CoValueEditor
|
|
236
|
+
node={account.$jazz.localNode}
|
|
237
|
+
property="name"
|
|
238
|
+
value="test"
|
|
239
|
+
coValue={value.$jazz.raw}
|
|
240
|
+
onCancel={onCancel}
|
|
241
|
+
/>,
|
|
242
|
+
);
|
|
243
|
+
|
|
244
|
+
const select = screen.getByLabelText("Type");
|
|
245
|
+
expect(screen.getByRole("textbox")).toBeDefined();
|
|
246
|
+
|
|
247
|
+
fireEvent.change(select, { target: { value: "string" } });
|
|
248
|
+
expect(screen.getByRole("textbox")).toBeDefined();
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
it("should show textarea when object type is selected", async () => {
|
|
252
|
+
const value = co
|
|
253
|
+
.map({
|
|
254
|
+
data: z.json(),
|
|
255
|
+
})
|
|
256
|
+
.create({ data: {} });
|
|
257
|
+
|
|
258
|
+
const onCancel = vi.fn();
|
|
259
|
+
|
|
260
|
+
render(
|
|
261
|
+
<CoValueEditor
|
|
262
|
+
node={account.$jazz.localNode}
|
|
263
|
+
property="data"
|
|
264
|
+
value={{}}
|
|
265
|
+
coValue={value.$jazz.raw}
|
|
266
|
+
onCancel={onCancel}
|
|
267
|
+
/>,
|
|
268
|
+
);
|
|
269
|
+
|
|
270
|
+
const select = screen.getByLabelText("Type");
|
|
271
|
+
expect(screen.getByRole("textbox")).toBeDefined();
|
|
272
|
+
|
|
273
|
+
fireEvent.change(select, { target: { value: "object" } });
|
|
274
|
+
expect(screen.getByRole("textbox")).toBeDefined();
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
it("should hide textarea when boolean type is selected", async () => {
|
|
278
|
+
const value = co
|
|
279
|
+
.map({
|
|
280
|
+
count: z.number(),
|
|
281
|
+
})
|
|
282
|
+
.create({ count: 42 });
|
|
283
|
+
|
|
284
|
+
const onCancel = vi.fn();
|
|
285
|
+
|
|
286
|
+
render(
|
|
287
|
+
<CoValueEditor
|
|
288
|
+
node={account.$jazz.localNode}
|
|
289
|
+
property="count"
|
|
290
|
+
value={42}
|
|
291
|
+
coValue={value.$jazz.raw}
|
|
292
|
+
onCancel={onCancel}
|
|
293
|
+
/>,
|
|
294
|
+
);
|
|
295
|
+
|
|
296
|
+
const select = screen.getByLabelText("Type");
|
|
297
|
+
fireEvent.change(select, { target: { value: "true" } });
|
|
298
|
+
|
|
299
|
+
await waitFor(() => {
|
|
300
|
+
expect(screen.queryByRole("textbox")).toBeNull();
|
|
301
|
+
});
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
it("should hide textarea when null type is selected", async () => {
|
|
305
|
+
const value = co
|
|
306
|
+
.map({
|
|
307
|
+
count: z.number(),
|
|
308
|
+
})
|
|
309
|
+
.create({ count: 42 });
|
|
310
|
+
|
|
311
|
+
const onCancel = vi.fn();
|
|
312
|
+
|
|
313
|
+
render(
|
|
314
|
+
<CoValueEditor
|
|
315
|
+
node={account.$jazz.localNode}
|
|
316
|
+
property="count"
|
|
317
|
+
value={42}
|
|
318
|
+
coValue={value.$jazz.raw}
|
|
319
|
+
onCancel={onCancel}
|
|
320
|
+
/>,
|
|
321
|
+
);
|
|
322
|
+
|
|
323
|
+
const select = screen.getByLabelText("Type");
|
|
324
|
+
fireEvent.change(select, { target: { value: "null" } });
|
|
325
|
+
|
|
326
|
+
await waitFor(() => {
|
|
327
|
+
expect(screen.queryByRole("textbox")).toBeNull();
|
|
328
|
+
});
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
it("should hide textarea when undefined type is selected", async () => {
|
|
332
|
+
const value = co
|
|
333
|
+
.map({
|
|
334
|
+
count: z.number(),
|
|
335
|
+
})
|
|
336
|
+
.create({ count: 42 });
|
|
337
|
+
|
|
338
|
+
const onCancel = vi.fn();
|
|
339
|
+
|
|
340
|
+
render(
|
|
341
|
+
<CoValueEditor
|
|
342
|
+
node={account.$jazz.localNode}
|
|
343
|
+
property="count"
|
|
344
|
+
value={42}
|
|
345
|
+
coValue={value.$jazz.raw}
|
|
346
|
+
onCancel={onCancel}
|
|
347
|
+
/>,
|
|
348
|
+
);
|
|
349
|
+
|
|
350
|
+
const select = screen.getByLabelText("Type");
|
|
351
|
+
fireEvent.change(select, { target: { value: "undefined" } });
|
|
352
|
+
|
|
353
|
+
await waitFor(() => {
|
|
354
|
+
expect(screen.queryByRole("textbox")).toBeNull();
|
|
355
|
+
});
|
|
356
|
+
});
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
describe("Form Submission", () => {
|
|
360
|
+
it("should submit number value", async () => {
|
|
361
|
+
const value = co
|
|
362
|
+
.map({
|
|
363
|
+
count: z.number(),
|
|
364
|
+
})
|
|
365
|
+
.create({ count: 42 });
|
|
366
|
+
|
|
367
|
+
const onCancel = vi.fn();
|
|
368
|
+
const makeTransactionSpy = vi.spyOn(
|
|
369
|
+
value.$jazz.raw.core,
|
|
370
|
+
"makeTransaction",
|
|
371
|
+
);
|
|
372
|
+
|
|
373
|
+
render(
|
|
374
|
+
<CoValueEditor
|
|
375
|
+
node={account.$jazz.localNode}
|
|
376
|
+
property="count"
|
|
377
|
+
value={42}
|
|
378
|
+
coValue={value.$jazz.raw}
|
|
379
|
+
onCancel={onCancel}
|
|
380
|
+
/>,
|
|
381
|
+
);
|
|
382
|
+
|
|
383
|
+
const textarea = screen.getByRole("textbox");
|
|
384
|
+
fireEvent.change(textarea, { target: { value: "100" } });
|
|
385
|
+
|
|
386
|
+
const submitButton = screen.getByText("Submit");
|
|
387
|
+
fireEvent.click(submitButton);
|
|
388
|
+
|
|
389
|
+
await waitFor(() => {
|
|
390
|
+
expect(makeTransactionSpy).toHaveBeenCalledWith(
|
|
391
|
+
[{ op: "set", key: "count", value: 100 }],
|
|
392
|
+
"private",
|
|
393
|
+
);
|
|
394
|
+
expect(onCancel).toHaveBeenCalled();
|
|
395
|
+
});
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
it("should submit string value", async () => {
|
|
399
|
+
const value = co
|
|
400
|
+
.map({
|
|
401
|
+
name: z.string(),
|
|
402
|
+
})
|
|
403
|
+
.create({ name: "test" });
|
|
404
|
+
|
|
405
|
+
const onCancel = vi.fn();
|
|
406
|
+
const makeTransactionSpy = vi.spyOn(
|
|
407
|
+
value.$jazz.raw.core,
|
|
408
|
+
"makeTransaction",
|
|
409
|
+
);
|
|
410
|
+
|
|
411
|
+
render(
|
|
412
|
+
<CoValueEditor
|
|
413
|
+
node={account.$jazz.localNode}
|
|
414
|
+
property="name"
|
|
415
|
+
value="test"
|
|
416
|
+
coValue={value.$jazz.raw}
|
|
417
|
+
onCancel={onCancel}
|
|
418
|
+
/>,
|
|
419
|
+
);
|
|
420
|
+
|
|
421
|
+
const textarea = screen.getByRole("textbox");
|
|
422
|
+
fireEvent.change(textarea, { target: { value: "updated" } });
|
|
423
|
+
|
|
424
|
+
const submitButton = screen.getByText("Submit");
|
|
425
|
+
fireEvent.click(submitButton);
|
|
426
|
+
|
|
427
|
+
await waitFor(() => {
|
|
428
|
+
expect(makeTransactionSpy).toHaveBeenCalledWith(
|
|
429
|
+
[{ op: "set", key: "name", value: "updated" }],
|
|
430
|
+
"private",
|
|
431
|
+
);
|
|
432
|
+
expect(onCancel).toHaveBeenCalled();
|
|
433
|
+
});
|
|
434
|
+
});
|
|
435
|
+
|
|
436
|
+
it("should submit boolean true value", async () => {
|
|
437
|
+
const value = co
|
|
438
|
+
.map({
|
|
439
|
+
active: z.boolean(),
|
|
440
|
+
})
|
|
441
|
+
.create({ active: false });
|
|
442
|
+
|
|
443
|
+
const onCancel = vi.fn();
|
|
444
|
+
const makeTransactionSpy = vi.spyOn(
|
|
445
|
+
value.$jazz.raw.core,
|
|
446
|
+
"makeTransaction",
|
|
447
|
+
);
|
|
448
|
+
|
|
449
|
+
render(
|
|
450
|
+
<CoValueEditor
|
|
451
|
+
node={account.$jazz.localNode}
|
|
452
|
+
property="active"
|
|
453
|
+
value={false}
|
|
454
|
+
coValue={value.$jazz.raw}
|
|
455
|
+
onCancel={onCancel}
|
|
456
|
+
/>,
|
|
457
|
+
);
|
|
458
|
+
|
|
459
|
+
const select = screen.getByLabelText("Type");
|
|
460
|
+
fireEvent.change(select, { target: { value: "true" } });
|
|
461
|
+
|
|
462
|
+
const submitButton = screen.getByText("Submit");
|
|
463
|
+
fireEvent.click(submitButton);
|
|
464
|
+
|
|
465
|
+
await waitFor(() => {
|
|
466
|
+
expect(makeTransactionSpy).toHaveBeenCalledWith(
|
|
467
|
+
[{ op: "set", key: "active", value: true }],
|
|
468
|
+
"private",
|
|
469
|
+
);
|
|
470
|
+
expect(onCancel).toHaveBeenCalled();
|
|
471
|
+
});
|
|
472
|
+
});
|
|
473
|
+
|
|
474
|
+
it("should submit boolean false value", async () => {
|
|
475
|
+
const value = co
|
|
476
|
+
.map({
|
|
477
|
+
active: z.boolean(),
|
|
478
|
+
})
|
|
479
|
+
.create({ active: true });
|
|
480
|
+
|
|
481
|
+
const onCancel = vi.fn();
|
|
482
|
+
const makeTransactionSpy = vi.spyOn(
|
|
483
|
+
value.$jazz.raw.core,
|
|
484
|
+
"makeTransaction",
|
|
485
|
+
);
|
|
486
|
+
|
|
487
|
+
render(
|
|
488
|
+
<CoValueEditor
|
|
489
|
+
node={account.$jazz.localNode}
|
|
490
|
+
property="active"
|
|
491
|
+
value={true}
|
|
492
|
+
coValue={value.$jazz.raw}
|
|
493
|
+
onCancel={onCancel}
|
|
494
|
+
/>,
|
|
495
|
+
);
|
|
496
|
+
|
|
497
|
+
const select = screen.getByLabelText("Type");
|
|
498
|
+
fireEvent.change(select, { target: { value: "false" } });
|
|
499
|
+
|
|
500
|
+
const submitButton = screen.getByText("Submit");
|
|
501
|
+
fireEvent.click(submitButton);
|
|
502
|
+
|
|
503
|
+
await waitFor(() => {
|
|
504
|
+
expect(makeTransactionSpy).toHaveBeenCalledWith(
|
|
505
|
+
[{ op: "set", key: "active", value: false }],
|
|
506
|
+
"private",
|
|
507
|
+
);
|
|
508
|
+
expect(onCancel).toHaveBeenCalled();
|
|
509
|
+
});
|
|
510
|
+
});
|
|
511
|
+
|
|
512
|
+
it("should submit null value", async () => {
|
|
513
|
+
const value = co
|
|
514
|
+
.map({
|
|
515
|
+
data: z.string().nullable(),
|
|
516
|
+
})
|
|
517
|
+
.create({ data: "test" });
|
|
518
|
+
|
|
519
|
+
const onCancel = vi.fn();
|
|
520
|
+
const makeTransactionSpy = vi.spyOn(
|
|
521
|
+
value.$jazz.raw.core,
|
|
522
|
+
"makeTransaction",
|
|
523
|
+
);
|
|
524
|
+
|
|
525
|
+
render(
|
|
526
|
+
<CoValueEditor
|
|
527
|
+
node={account.$jazz.localNode}
|
|
528
|
+
property="data"
|
|
529
|
+
value="test"
|
|
530
|
+
coValue={value.$jazz.raw}
|
|
531
|
+
onCancel={onCancel}
|
|
532
|
+
/>,
|
|
533
|
+
);
|
|
534
|
+
|
|
535
|
+
const select = screen.getByLabelText("Type");
|
|
536
|
+
fireEvent.change(select, { target: { value: "null" } });
|
|
537
|
+
|
|
538
|
+
const submitButton = screen.getByText("Submit");
|
|
539
|
+
fireEvent.click(submitButton);
|
|
540
|
+
|
|
541
|
+
await waitFor(() => {
|
|
542
|
+
expect(makeTransactionSpy).toHaveBeenCalledWith(
|
|
543
|
+
[{ op: "set", key: "data", value: null }],
|
|
544
|
+
"private",
|
|
545
|
+
);
|
|
546
|
+
expect(onCancel).toHaveBeenCalled();
|
|
547
|
+
});
|
|
548
|
+
});
|
|
549
|
+
|
|
550
|
+
it("should submit undefined value", async () => {
|
|
551
|
+
const value = co
|
|
552
|
+
.map({
|
|
553
|
+
optional: z.string().optional(),
|
|
554
|
+
})
|
|
555
|
+
.create({ optional: "test" });
|
|
556
|
+
|
|
557
|
+
const onCancel = vi.fn();
|
|
558
|
+
const makeTransactionSpy = vi.spyOn(
|
|
559
|
+
value.$jazz.raw.core,
|
|
560
|
+
"makeTransaction",
|
|
561
|
+
);
|
|
562
|
+
|
|
563
|
+
render(
|
|
564
|
+
<CoValueEditor
|
|
565
|
+
node={account.$jazz.localNode}
|
|
566
|
+
property="optional"
|
|
567
|
+
value="test"
|
|
568
|
+
coValue={value.$jazz.raw}
|
|
569
|
+
onCancel={onCancel}
|
|
570
|
+
/>,
|
|
571
|
+
);
|
|
572
|
+
|
|
573
|
+
const select = screen.getByLabelText("Type");
|
|
574
|
+
fireEvent.change(select, { target: { value: "undefined" } });
|
|
575
|
+
|
|
576
|
+
const submitButton = screen.getByText("Submit");
|
|
577
|
+
fireEvent.click(submitButton);
|
|
578
|
+
|
|
579
|
+
await waitFor(() => {
|
|
580
|
+
expect(makeTransactionSpy).toHaveBeenCalledWith(
|
|
581
|
+
[{ op: "set", key: "optional", value: undefined }],
|
|
582
|
+
"private",
|
|
583
|
+
);
|
|
584
|
+
expect(onCancel).toHaveBeenCalled();
|
|
585
|
+
});
|
|
586
|
+
});
|
|
587
|
+
|
|
588
|
+
it("should submit object value", async () => {
|
|
589
|
+
const value = co
|
|
590
|
+
.map({
|
|
591
|
+
config: z.json(),
|
|
592
|
+
})
|
|
593
|
+
.create({ config: {} });
|
|
594
|
+
|
|
595
|
+
const onCancel = vi.fn();
|
|
596
|
+
const makeTransactionSpy = vi.spyOn(
|
|
597
|
+
value.$jazz.raw.core,
|
|
598
|
+
"makeTransaction",
|
|
599
|
+
);
|
|
600
|
+
|
|
601
|
+
render(
|
|
602
|
+
<CoValueEditor
|
|
603
|
+
node={account.$jazz.localNode}
|
|
604
|
+
property="config"
|
|
605
|
+
value={{}}
|
|
606
|
+
coValue={value.$jazz.raw}
|
|
607
|
+
onCancel={onCancel}
|
|
608
|
+
/>,
|
|
609
|
+
);
|
|
610
|
+
|
|
611
|
+
const textarea = screen.getByRole("textbox");
|
|
612
|
+
const newObject = { foo: "bar", nested: { value: 123 } };
|
|
613
|
+
fireEvent.change(textarea, {
|
|
614
|
+
target: { value: JSON.stringify(newObject, null, 2) },
|
|
615
|
+
});
|
|
616
|
+
|
|
617
|
+
const submitButton = screen.getByText("Submit");
|
|
618
|
+
fireEvent.click(submitButton);
|
|
619
|
+
|
|
620
|
+
await waitFor(() => {
|
|
621
|
+
expect(makeTransactionSpy).toHaveBeenCalledWith(
|
|
622
|
+
[{ op: "set", key: "config", value: newObject }],
|
|
623
|
+
"private",
|
|
624
|
+
);
|
|
625
|
+
expect(onCancel).toHaveBeenCalled();
|
|
626
|
+
});
|
|
627
|
+
});
|
|
628
|
+
|
|
629
|
+
it("should prevent default form submission", async () => {
|
|
630
|
+
const value = co
|
|
631
|
+
.map({
|
|
632
|
+
count: z.number(),
|
|
633
|
+
})
|
|
634
|
+
.create({ count: 42 });
|
|
635
|
+
|
|
636
|
+
const onCancel = vi.fn();
|
|
637
|
+
|
|
638
|
+
render(
|
|
639
|
+
<CoValueEditor
|
|
640
|
+
node={account.$jazz.localNode}
|
|
641
|
+
property="count"
|
|
642
|
+
value={42}
|
|
643
|
+
coValue={value.$jazz.raw}
|
|
644
|
+
onCancel={onCancel}
|
|
645
|
+
/>,
|
|
646
|
+
);
|
|
647
|
+
|
|
648
|
+
const form = screen.getByRole("textbox").closest("form");
|
|
649
|
+
expect(form).toBeDefined();
|
|
650
|
+
|
|
651
|
+
const submitEvent = new Event("submit", {
|
|
652
|
+
bubbles: true,
|
|
653
|
+
cancelable: true,
|
|
654
|
+
});
|
|
655
|
+
const preventDefaultSpy = vi.spyOn(submitEvent, "preventDefault");
|
|
656
|
+
const stopPropagationSpy = vi.spyOn(submitEvent, "stopPropagation");
|
|
657
|
+
|
|
658
|
+
if (form) {
|
|
659
|
+
fireEvent(form, submitEvent);
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
expect(preventDefaultSpy).toHaveBeenCalled();
|
|
663
|
+
expect(stopPropagationSpy).toHaveBeenCalled();
|
|
664
|
+
});
|
|
665
|
+
});
|
|
666
|
+
|
|
667
|
+
describe("Cancel Button", () => {
|
|
668
|
+
it("should call onCancel when cancel button is clicked", async () => {
|
|
669
|
+
const value = co
|
|
670
|
+
.map({
|
|
671
|
+
count: z.number(),
|
|
672
|
+
})
|
|
673
|
+
.create({ count: 42 });
|
|
674
|
+
|
|
675
|
+
const onCancel = vi.fn();
|
|
676
|
+
|
|
677
|
+
render(
|
|
678
|
+
<CoValueEditor
|
|
679
|
+
node={account.$jazz.localNode}
|
|
680
|
+
property="count"
|
|
681
|
+
value={42}
|
|
682
|
+
coValue={value.$jazz.raw}
|
|
683
|
+
onCancel={onCancel}
|
|
684
|
+
/>,
|
|
685
|
+
);
|
|
686
|
+
|
|
687
|
+
const cancelButton = screen.getByText("Cancel");
|
|
688
|
+
fireEvent.click(cancelButton);
|
|
689
|
+
|
|
690
|
+
expect(onCancel).toHaveBeenCalledTimes(1);
|
|
691
|
+
});
|
|
692
|
+
|
|
693
|
+
it("should not make transaction when cancel is clicked", async () => {
|
|
694
|
+
const value = co
|
|
695
|
+
.map({
|
|
696
|
+
count: z.number(),
|
|
697
|
+
})
|
|
698
|
+
.create({ count: 42 });
|
|
699
|
+
|
|
700
|
+
const onCancel = vi.fn();
|
|
701
|
+
const makeTransactionSpy = vi.spyOn(
|
|
702
|
+
value.$jazz.raw.core,
|
|
703
|
+
"makeTransaction",
|
|
704
|
+
);
|
|
705
|
+
|
|
706
|
+
render(
|
|
707
|
+
<CoValueEditor
|
|
708
|
+
node={account.$jazz.localNode}
|
|
709
|
+
property="count"
|
|
710
|
+
value={42}
|
|
711
|
+
coValue={value.$jazz.raw}
|
|
712
|
+
onCancel={onCancel}
|
|
713
|
+
/>,
|
|
714
|
+
);
|
|
715
|
+
|
|
716
|
+
const cancelButton = screen.getByText("Cancel");
|
|
717
|
+
fireEvent.click(cancelButton);
|
|
718
|
+
|
|
719
|
+
expect(makeTransactionSpy).not.toHaveBeenCalled();
|
|
720
|
+
});
|
|
721
|
+
});
|
|
722
|
+
|
|
723
|
+
describe("Event Propagation", () => {
|
|
724
|
+
it("should stop propagation on select click", async () => {
|
|
725
|
+
const value = co
|
|
726
|
+
.map({
|
|
727
|
+
count: z.number(),
|
|
728
|
+
})
|
|
729
|
+
.create({ count: 42 });
|
|
730
|
+
|
|
731
|
+
const onCancel = vi.fn();
|
|
732
|
+
|
|
733
|
+
render(
|
|
734
|
+
<CoValueEditor
|
|
735
|
+
node={account.$jazz.localNode}
|
|
736
|
+
property="count"
|
|
737
|
+
value={42}
|
|
738
|
+
coValue={value.$jazz.raw}
|
|
739
|
+
onCancel={onCancel}
|
|
740
|
+
/>,
|
|
741
|
+
);
|
|
742
|
+
|
|
743
|
+
const select = screen.getByLabelText("Type");
|
|
744
|
+
const clickEvent = new MouseEvent("click", { bubbles: true });
|
|
745
|
+
const stopPropagationSpy = vi.spyOn(clickEvent, "stopPropagation");
|
|
746
|
+
|
|
747
|
+
fireEvent(select, clickEvent);
|
|
748
|
+
|
|
749
|
+
expect(stopPropagationSpy).toHaveBeenCalled();
|
|
750
|
+
});
|
|
751
|
+
|
|
752
|
+
it("should stop propagation on textarea click", async () => {
|
|
753
|
+
const value = co
|
|
754
|
+
.map({
|
|
755
|
+
count: z.number(),
|
|
756
|
+
})
|
|
757
|
+
.create({ count: 42 });
|
|
758
|
+
|
|
759
|
+
const onCancel = vi.fn();
|
|
760
|
+
|
|
761
|
+
render(
|
|
762
|
+
<CoValueEditor
|
|
763
|
+
node={account.$jazz.localNode}
|
|
764
|
+
property="count"
|
|
765
|
+
value={42}
|
|
766
|
+
coValue={value.$jazz.raw}
|
|
767
|
+
onCancel={onCancel}
|
|
768
|
+
/>,
|
|
769
|
+
);
|
|
770
|
+
|
|
771
|
+
const textarea = screen.getByRole("textbox");
|
|
772
|
+
const clickEvent = new MouseEvent("click", { bubbles: true });
|
|
773
|
+
const stopPropagationSpy = vi.spyOn(clickEvent, "stopPropagation");
|
|
774
|
+
|
|
775
|
+
fireEvent(textarea, clickEvent);
|
|
776
|
+
|
|
777
|
+
expect(stopPropagationSpy).toHaveBeenCalled();
|
|
778
|
+
});
|
|
779
|
+
});
|
|
780
|
+
|
|
781
|
+
describe("Edge Cases", () => {
|
|
782
|
+
it("should handle decimal number input", async () => {
|
|
783
|
+
const value = co
|
|
784
|
+
.map({
|
|
785
|
+
count: z.number(),
|
|
786
|
+
})
|
|
787
|
+
.create({ count: 42 });
|
|
788
|
+
|
|
789
|
+
const onCancel = vi.fn();
|
|
790
|
+
const makeTransactionSpy = vi.spyOn(
|
|
791
|
+
value.$jazz.raw.core,
|
|
792
|
+
"makeTransaction",
|
|
793
|
+
);
|
|
794
|
+
|
|
795
|
+
render(
|
|
796
|
+
<CoValueEditor
|
|
797
|
+
node={account.$jazz.localNode}
|
|
798
|
+
property="count"
|
|
799
|
+
value={42}
|
|
800
|
+
coValue={value.$jazz.raw}
|
|
801
|
+
onCancel={onCancel}
|
|
802
|
+
/>,
|
|
803
|
+
);
|
|
804
|
+
|
|
805
|
+
const textarea = screen.getByRole("textbox");
|
|
806
|
+
fireEvent.change(textarea, { target: { value: "3.14" } });
|
|
807
|
+
|
|
808
|
+
const submitButton = screen.getByText("Submit");
|
|
809
|
+
fireEvent.click(submitButton);
|
|
810
|
+
|
|
811
|
+
await waitFor(() => {
|
|
812
|
+
expect(makeTransactionSpy).toHaveBeenCalledWith(
|
|
813
|
+
[{ op: "set", key: "count", value: 3.14 }],
|
|
814
|
+
"private",
|
|
815
|
+
);
|
|
816
|
+
});
|
|
817
|
+
});
|
|
818
|
+
|
|
819
|
+
it("should handle empty string input", async () => {
|
|
820
|
+
const value = co
|
|
821
|
+
.map({
|
|
822
|
+
name: z.string(),
|
|
823
|
+
})
|
|
824
|
+
.create({ name: "test" });
|
|
825
|
+
|
|
826
|
+
const onCancel = vi.fn();
|
|
827
|
+
const makeTransactionSpy = vi.spyOn(
|
|
828
|
+
value.$jazz.raw.core,
|
|
829
|
+
"makeTransaction",
|
|
830
|
+
);
|
|
831
|
+
|
|
832
|
+
render(
|
|
833
|
+
<CoValueEditor
|
|
834
|
+
node={account.$jazz.localNode}
|
|
835
|
+
property="name"
|
|
836
|
+
value="test"
|
|
837
|
+
coValue={value.$jazz.raw}
|
|
838
|
+
onCancel={onCancel}
|
|
839
|
+
/>,
|
|
840
|
+
);
|
|
841
|
+
|
|
842
|
+
const textarea = screen.getByRole("textbox");
|
|
843
|
+
fireEvent.change(textarea, { target: { value: "" } });
|
|
844
|
+
|
|
845
|
+
const submitButton = screen.getByText("Submit");
|
|
846
|
+
fireEvent.click(submitButton);
|
|
847
|
+
|
|
848
|
+
await waitFor(() => {
|
|
849
|
+
expect(makeTransactionSpy).toHaveBeenCalledWith(
|
|
850
|
+
[{ op: "set", key: "name", value: "" }],
|
|
851
|
+
"private",
|
|
852
|
+
);
|
|
853
|
+
});
|
|
854
|
+
});
|
|
855
|
+
|
|
856
|
+
it("should handle complex nested object", async () => {
|
|
857
|
+
const value = co
|
|
858
|
+
.map({
|
|
859
|
+
config: z.json(),
|
|
860
|
+
})
|
|
861
|
+
.create({ config: {} });
|
|
862
|
+
|
|
863
|
+
const onCancel = vi.fn();
|
|
864
|
+
const makeTransactionSpy = vi.spyOn(
|
|
865
|
+
value.$jazz.raw.core,
|
|
866
|
+
"makeTransaction",
|
|
867
|
+
);
|
|
868
|
+
|
|
869
|
+
render(
|
|
870
|
+
<CoValueEditor
|
|
871
|
+
node={account.$jazz.localNode}
|
|
872
|
+
property="config"
|
|
873
|
+
value={{}}
|
|
874
|
+
coValue={value.$jazz.raw}
|
|
875
|
+
onCancel={onCancel}
|
|
876
|
+
/>,
|
|
877
|
+
);
|
|
878
|
+
|
|
879
|
+
const textarea = screen.getByRole("textbox");
|
|
880
|
+
const complexObject = {
|
|
881
|
+
nested: {
|
|
882
|
+
deep: {
|
|
883
|
+
value: [1, 2, 3],
|
|
884
|
+
items: [{ id: 1 }, { id: 2 }],
|
|
885
|
+
},
|
|
886
|
+
},
|
|
887
|
+
};
|
|
888
|
+
fireEvent.change(textarea, {
|
|
889
|
+
target: { value: JSON.stringify(complexObject, null, 2) },
|
|
890
|
+
});
|
|
891
|
+
|
|
892
|
+
const submitButton = screen.getByText("Submit");
|
|
893
|
+
fireEvent.click(submitButton);
|
|
894
|
+
|
|
895
|
+
await waitFor(() => {
|
|
896
|
+
expect(makeTransactionSpy).toHaveBeenCalledWith(
|
|
897
|
+
[{ op: "set", key: "config", value: complexObject }],
|
|
898
|
+
"private",
|
|
899
|
+
);
|
|
900
|
+
});
|
|
901
|
+
});
|
|
902
|
+
});
|
|
903
|
+
});
|