community-jazz-vue 0.15.4
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 +21 -0
- package/CHANGELOG.md +2201 -0
- package/LICENSE.txt +19 -0
- package/README.md +26 -0
- package/dist/Image.vue.d.ts +26 -0
- package/dist/auth/JazzVueProviderWithClerk.d.ts +83 -0
- package/dist/auth/PasskeyAuthBasicUI.vue.d.ts +21 -0
- package/dist/auth/useClerkAuth.d.ts +2 -0
- package/dist/auth/useIsAuthenticated.d.ts +1 -0
- package/dist/auth/usePasskeyAuth.d.ts +18 -0
- package/dist/auth/usePassphraseAuth.d.ts +20 -0
- package/dist/composables.d.ts +22 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +667 -0
- package/dist/index.js.map +1 -0
- package/dist/provider-CCZVJj45.js +143 -0
- package/dist/provider-CCZVJj45.js.map +1 -0
- package/dist/provider.d.ts +172 -0
- package/dist/testing.d.ts +30 -0
- package/dist/testing.js +41 -0
- package/dist/testing.js.map +1 -0
- package/dist/tests/fixtures.d.ts +1 -0
- package/dist/tests/proxyBehavior.test.d.ts +1 -0
- package/dist/tests/testUtils.d.ts +9 -0
- package/dist/tests/useAcceptInvite.test.d.ts +1 -0
- package/dist/tests/useAccount.test.d.ts +1 -0
- package/dist/tests/useCoState.test.d.ts +1 -0
- package/dist/tests/useInboxSender.test.d.ts +1 -0
- package/dist/tests/useIsAuthenticated.test.d.ts +1 -0
- package/dist/tests/usePassphraseAuth.test.d.ts +1 -0
- package/dist/utils/contextManager.d.ts +3 -0
- package/package.json +53 -0
- package/src/Image.vue +151 -0
- package/src/auth/JazzVueProviderWithClerk.ts +123 -0
- package/src/auth/PasskeyAuthBasicUI.vue +153 -0
- package/src/auth/useClerkAuth.ts +35 -0
- package/src/auth/useIsAuthenticated.ts +21 -0
- package/src/auth/usePasskeyAuth.ts +48 -0
- package/src/auth/usePassphraseAuth.ts +57 -0
- package/src/composables.ts +323 -0
- package/src/index.ts +14 -0
- package/src/provider.ts +192 -0
- package/src/testing.ts +45 -0
- package/src/tests/fixtures.ts +2050 -0
- package/src/tests/proxyBehavior.test.ts +267 -0
- package/src/tests/testUtils.ts +75 -0
- package/src/tests/useAcceptInvite.test.ts +55 -0
- package/src/tests/useAccount.test.ts +59 -0
- package/src/tests/useCoState.test.ts +175 -0
- package/src/tests/useInboxSender.test.ts +58 -0
- package/src/tests/useIsAuthenticated.test.ts +35 -0
- package/src/tests/usePassphraseAuth.test.ts +95 -0
- package/src/utils/contextManager.ts +31 -0
- package/src/vite-env.d.ts +7 -0
- package/tsconfig.json +20 -0
- package/vite.config.ts +31 -0
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
// @vitest-environment happy-dom
|
|
2
|
+
|
|
3
|
+
import { Group, co, z } from "jazz-tools";
|
|
4
|
+
import { beforeAll, describe, expect, it } from "vitest";
|
|
5
|
+
import { isProxy, nextTick, toRaw } from "vue";
|
|
6
|
+
import { useAccount, useCoState } from "../composables.js";
|
|
7
|
+
import { createJazzTestAccount } from "../testing.js";
|
|
8
|
+
import { withJazzTestSetup } from "./testUtils.js";
|
|
9
|
+
|
|
10
|
+
const TestMap = co.map({
|
|
11
|
+
content: z.string(),
|
|
12
|
+
get nested() {
|
|
13
|
+
return co.optional(TestMap);
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
const AccountRoot = co.map({
|
|
18
|
+
value: z.string(),
|
|
19
|
+
testMap: co.optional(TestMap),
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
const AccountProfile = co.map({
|
|
23
|
+
name: z.string(),
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
const AccountSchema = co
|
|
27
|
+
.account({
|
|
28
|
+
root: AccountRoot,
|
|
29
|
+
profile: AccountProfile,
|
|
30
|
+
})
|
|
31
|
+
.withMigration((account) => {
|
|
32
|
+
if (!account.root) {
|
|
33
|
+
account.root = AccountRoot.create({ value: "test" }, { owner: account });
|
|
34
|
+
}
|
|
35
|
+
if (!account.profile) {
|
|
36
|
+
// Profile must be owned by a Group, not the account itself
|
|
37
|
+
const group = Group.create();
|
|
38
|
+
account.profile = AccountProfile.create(
|
|
39
|
+
{ name: "Test User" },
|
|
40
|
+
{ owner: group },
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
describe("Proxy Behavior Verification", () => {
|
|
46
|
+
// Create a single account for all tests to avoid parallel account creation
|
|
47
|
+
let sharedAccount: any;
|
|
48
|
+
let sharedAccountWithSchema: any;
|
|
49
|
+
|
|
50
|
+
beforeAll(async () => {
|
|
51
|
+
try {
|
|
52
|
+
sharedAccount = await createJazzTestAccount();
|
|
53
|
+
sharedAccountWithSchema = await createJazzTestAccount({ AccountSchema });
|
|
54
|
+
} catch (error) {
|
|
55
|
+
console.warn("Failed to create test account:", error);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("should not expose Vue proxies to Jazz objects in useCoState", async () => {
|
|
60
|
+
const testMap = TestMap.create(
|
|
61
|
+
{
|
|
62
|
+
content: "test content",
|
|
63
|
+
},
|
|
64
|
+
{ owner: sharedAccount },
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
const [result] = withJazzTestSetup(() => useCoState(TestMap, testMap.id), {
|
|
68
|
+
account: sharedAccount,
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// The returned value should not be a Vue proxy
|
|
72
|
+
expect(isProxy(result.value)).toBe(false);
|
|
73
|
+
|
|
74
|
+
// Properties should also not be proxies
|
|
75
|
+
if (result.value) {
|
|
76
|
+
expect(isProxy(result.value.content)).toBe(false);
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it("should handle nested object access without proxy issues", async () => {
|
|
81
|
+
const nestedMap = TestMap.create(
|
|
82
|
+
{
|
|
83
|
+
content: "nested content",
|
|
84
|
+
},
|
|
85
|
+
{ owner: sharedAccountWithSchema },
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
const rootMap = AccountRoot.create(
|
|
89
|
+
{
|
|
90
|
+
value: "root value",
|
|
91
|
+
testMap: nestedMap,
|
|
92
|
+
},
|
|
93
|
+
{ owner: sharedAccountWithSchema },
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
// Update account root
|
|
97
|
+
sharedAccountWithSchema.root = rootMap;
|
|
98
|
+
|
|
99
|
+
const [accountResult] = withJazzTestSetup(
|
|
100
|
+
() => useAccount(AccountSchema, { resolve: { root: { testMap: true } } }),
|
|
101
|
+
{ account: sharedAccountWithSchema },
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
await nextTick();
|
|
105
|
+
|
|
106
|
+
// Should be able to access deeply nested properties without proxy issues
|
|
107
|
+
const me = accountResult.me.value;
|
|
108
|
+
expect(me).toBeDefined();
|
|
109
|
+
expect(me?.root).toBeDefined();
|
|
110
|
+
expect(me?.root?.testMap).toBeDefined();
|
|
111
|
+
expect(me?.root?.testMap?.content).toBe("nested content");
|
|
112
|
+
|
|
113
|
+
// None of these should be Vue proxies
|
|
114
|
+
expect(isProxy(me)).toBe(false);
|
|
115
|
+
expect(isProxy(me?.root)).toBe(false);
|
|
116
|
+
expect(isProxy(me?.root?.testMap)).toBe(false);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it("should handle reactivity updates without breaking Jazz object integrity", async () => {
|
|
120
|
+
const account = await createJazzTestAccount();
|
|
121
|
+
|
|
122
|
+
const testMap = TestMap.create(
|
|
123
|
+
{
|
|
124
|
+
content: "initial content",
|
|
125
|
+
},
|
|
126
|
+
{ owner: account },
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
const [result] = withJazzTestSetup(() => useCoState(TestMap, testMap.id), {
|
|
130
|
+
account,
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
// Initial state
|
|
134
|
+
expect(result.value?.content).toBe("initial content");
|
|
135
|
+
expect(isProxy(result.value)).toBe(false);
|
|
136
|
+
|
|
137
|
+
// Update the Jazz object
|
|
138
|
+
testMap.content = "updated content";
|
|
139
|
+
await nextTick();
|
|
140
|
+
|
|
141
|
+
// Should reactively update
|
|
142
|
+
expect(result.value?.content).toBe("updated content");
|
|
143
|
+
|
|
144
|
+
// Should still not be a proxy after update
|
|
145
|
+
expect(isProxy(result.value)).toBe(false);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it("should not require toRaw() calls in user code", async () => {
|
|
149
|
+
const account = await createJazzTestAccount();
|
|
150
|
+
|
|
151
|
+
const testMap = TestMap.create(
|
|
152
|
+
{
|
|
153
|
+
content: "test content",
|
|
154
|
+
},
|
|
155
|
+
{ owner: account },
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
const [result] = withJazzTestSetup(() => useCoState(TestMap, testMap.id), {
|
|
159
|
+
account,
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
// User should be able to use the object directly without toRaw()
|
|
163
|
+
const jazzObject = result.value;
|
|
164
|
+
expect(jazzObject).toBeDefined();
|
|
165
|
+
|
|
166
|
+
// Should be able to call Jazz methods directly
|
|
167
|
+
expect(() => {
|
|
168
|
+
jazzObject?.content; // Access property
|
|
169
|
+
// In a real scenario, user might call other Jazz methods here
|
|
170
|
+
}).not.toThrow();
|
|
171
|
+
|
|
172
|
+
// Should not need toRaw() to access properties
|
|
173
|
+
expect(jazzObject?.content).toBe("test content");
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
it("should handle context manager objects without proxy issues", async () => {
|
|
177
|
+
const account = await createJazzTestAccount();
|
|
178
|
+
|
|
179
|
+
const [result] = withJazzTestSetup(() => useAccount(), {
|
|
180
|
+
account,
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
// The account object should not be a proxy
|
|
184
|
+
expect(isProxy(result.me.value)).toBe(false);
|
|
185
|
+
|
|
186
|
+
// The agent should be accessible and usable without toRaw() calls
|
|
187
|
+
expect(result.agent).toBeDefined();
|
|
188
|
+
expect(typeof result.agent).toBe("object");
|
|
189
|
+
|
|
190
|
+
// Should be able to access agent properties without proxy issues
|
|
191
|
+
expect(() => {
|
|
192
|
+
const agentType = result.agent._type; // Access agent property
|
|
193
|
+
expect(agentType).toBeDefined();
|
|
194
|
+
}).not.toThrow();
|
|
195
|
+
|
|
196
|
+
// LogOut function should work without proxy issues
|
|
197
|
+
expect(typeof result.logOut).toBe("function");
|
|
198
|
+
expect(() => {
|
|
199
|
+
// Should be able to call without toRaw()
|
|
200
|
+
result.logOut.toString(); // Safe way to test function access
|
|
201
|
+
}).not.toThrow();
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
it("should maintain object identity across reactive updates", async () => {
|
|
205
|
+
const account = await createJazzTestAccount();
|
|
206
|
+
|
|
207
|
+
const testMap = TestMap.create(
|
|
208
|
+
{
|
|
209
|
+
content: "initial",
|
|
210
|
+
},
|
|
211
|
+
{ owner: account },
|
|
212
|
+
);
|
|
213
|
+
|
|
214
|
+
const [result] = withJazzTestSetup(() => useCoState(TestMap, testMap.id), {
|
|
215
|
+
account,
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
const initialObject = result.value;
|
|
219
|
+
const initialId = initialObject?.id;
|
|
220
|
+
|
|
221
|
+
// Update content
|
|
222
|
+
testMap.content = "updated";
|
|
223
|
+
await nextTick();
|
|
224
|
+
|
|
225
|
+
const updatedObject = result.value;
|
|
226
|
+
|
|
227
|
+
// Object identity should be maintained (same Jazz object)
|
|
228
|
+
expect(updatedObject?.id).toBe(initialId);
|
|
229
|
+
expect(isProxy(updatedObject)).toBe(false);
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
it("should handle sign-up and project creation scenarios without refresh", async () => {
|
|
233
|
+
// This test simulates the scenario mentioned in memories where proxy issues
|
|
234
|
+
// recur after sign-up and project creation without refresh
|
|
235
|
+
|
|
236
|
+
const account = await createJazzTestAccount({ AccountSchema });
|
|
237
|
+
|
|
238
|
+
const [accountResult] = withJazzTestSetup(() => useAccount(AccountSchema), {
|
|
239
|
+
account,
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
// Simulate project creation
|
|
243
|
+
const newProject = TestMap.create(
|
|
244
|
+
{
|
|
245
|
+
content: "new project",
|
|
246
|
+
},
|
|
247
|
+
{ owner: account },
|
|
248
|
+
);
|
|
249
|
+
|
|
250
|
+
const [projectResult] = withJazzTestSetup(
|
|
251
|
+
() => useCoState(TestMap, newProject.id),
|
|
252
|
+
{
|
|
253
|
+
account,
|
|
254
|
+
},
|
|
255
|
+
);
|
|
256
|
+
|
|
257
|
+
await nextTick();
|
|
258
|
+
|
|
259
|
+
// Both account and project should work without proxy issues
|
|
260
|
+
expect(isProxy(accountResult.me.value)).toBe(false);
|
|
261
|
+
expect(isProxy(projectResult.value)).toBe(false);
|
|
262
|
+
|
|
263
|
+
// Should be able to access properties without toRaw()
|
|
264
|
+
expect(accountResult.me.value?.id).toBeDefined();
|
|
265
|
+
expect(projectResult.value?.content).toBe("new project");
|
|
266
|
+
});
|
|
267
|
+
});
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { Account, AnonymousJazzAgent } from "jazz-tools";
|
|
2
|
+
import { createApp, defineComponent, h } from "vue";
|
|
3
|
+
import { JazzTestProvider } from "../testing";
|
|
4
|
+
|
|
5
|
+
// biome-ignore lint/suspicious/noExplicitAny: Complex generic typing with Jazz framework internals
|
|
6
|
+
export const withJazzTestSetup = <C extends (...args: any[]) => any>(
|
|
7
|
+
composable: C,
|
|
8
|
+
{
|
|
9
|
+
account,
|
|
10
|
+
isAuthenticated,
|
|
11
|
+
}: {
|
|
12
|
+
account?: Account | { guest: AnonymousJazzAgent };
|
|
13
|
+
isAuthenticated?: boolean;
|
|
14
|
+
} = {},
|
|
15
|
+
) => {
|
|
16
|
+
// biome-ignore lint/suspicious/noImplicitAnyLet: Not sure what the type is
|
|
17
|
+
let result;
|
|
18
|
+
|
|
19
|
+
const wrapper = defineComponent({
|
|
20
|
+
setup() {
|
|
21
|
+
result = composable();
|
|
22
|
+
// suppress missing template warning
|
|
23
|
+
return () => {};
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
const app = createApp({
|
|
28
|
+
setup() {
|
|
29
|
+
return () =>
|
|
30
|
+
h(
|
|
31
|
+
JazzTestProvider,
|
|
32
|
+
{
|
|
33
|
+
account,
|
|
34
|
+
isAuthenticated,
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
default: () => h(wrapper),
|
|
38
|
+
},
|
|
39
|
+
);
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
app.mount(document.createElement("div"));
|
|
44
|
+
// return the result and the app instance
|
|
45
|
+
// for testing provide/unmount
|
|
46
|
+
return [result, app] as [ReturnType<C>, ReturnType<typeof createApp>];
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export function waitFor(callback: () => void) {
|
|
50
|
+
return new Promise<void>((resolve, reject) => {
|
|
51
|
+
const checkPassed = () => {
|
|
52
|
+
try {
|
|
53
|
+
return { ok: callback(), error: null };
|
|
54
|
+
} catch (error) {
|
|
55
|
+
return { ok: false, error };
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
let retries = 0;
|
|
60
|
+
|
|
61
|
+
const interval = setInterval(() => {
|
|
62
|
+
const { ok, error } = checkPassed();
|
|
63
|
+
|
|
64
|
+
if (ok !== false) {
|
|
65
|
+
clearInterval(interval);
|
|
66
|
+
resolve();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (++retries > 10) {
|
|
70
|
+
clearInterval(interval);
|
|
71
|
+
reject(error);
|
|
72
|
+
}
|
|
73
|
+
}, 100);
|
|
74
|
+
});
|
|
75
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// @vitest-environment happy-dom
|
|
2
|
+
|
|
3
|
+
import { Group, type ID, co, z } from "jazz-tools";
|
|
4
|
+
import { describe, expect, it } from "vitest";
|
|
5
|
+
import { createInviteLink, useAcceptInvite } from "../index.js";
|
|
6
|
+
import { createJazzTestAccount, linkAccounts } from "../testing.js";
|
|
7
|
+
import { waitFor, withJazzTestSetup } from "./testUtils.js";
|
|
8
|
+
|
|
9
|
+
describe("useAcceptInvite", () => {
|
|
10
|
+
it("should accept the invite", async () => {
|
|
11
|
+
const TestMap = co.map({
|
|
12
|
+
value: z.string(),
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
const account = await createJazzTestAccount();
|
|
16
|
+
const inviteSender = await createJazzTestAccount();
|
|
17
|
+
|
|
18
|
+
await linkAccounts(account, inviteSender);
|
|
19
|
+
|
|
20
|
+
let acceptedId: ID<co.loaded<typeof TestMap>> | undefined;
|
|
21
|
+
|
|
22
|
+
const invitelink = createInviteLink(
|
|
23
|
+
TestMap.create(
|
|
24
|
+
{ value: "hello" },
|
|
25
|
+
{ owner: Group.create({ owner: inviteSender }) },
|
|
26
|
+
),
|
|
27
|
+
"reader",
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
location.href = invitelink;
|
|
31
|
+
|
|
32
|
+
withJazzTestSetup(
|
|
33
|
+
() =>
|
|
34
|
+
useAcceptInvite({
|
|
35
|
+
invitedObjectSchema: TestMap,
|
|
36
|
+
onAccept: (id) => {
|
|
37
|
+
acceptedId = id;
|
|
38
|
+
},
|
|
39
|
+
}),
|
|
40
|
+
{
|
|
41
|
+
account,
|
|
42
|
+
},
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
await waitFor(() => {
|
|
46
|
+
expect(acceptedId).toBeDefined();
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const accepted = await TestMap.load(acceptedId!, {
|
|
50
|
+
loadAs: account,
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
expect(accepted?.value).toEqual("hello");
|
|
54
|
+
});
|
|
55
|
+
});
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// @vitest-environment happy-dom
|
|
2
|
+
|
|
3
|
+
import { Group, co, z } from "jazz-tools";
|
|
4
|
+
import { describe, expect, it } from "vitest";
|
|
5
|
+
import { useAccount } from "../composables.js";
|
|
6
|
+
import { createJazzTestAccount, createJazzTestGuest } from "../testing.js";
|
|
7
|
+
import { withJazzTestSetup } from "./testUtils.js";
|
|
8
|
+
|
|
9
|
+
const AccountRoot = co.map({
|
|
10
|
+
value: z.string(),
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
const AccountProfile = co.map({
|
|
14
|
+
name: z.string(),
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
const AccountSchema = co
|
|
18
|
+
.account({
|
|
19
|
+
root: AccountRoot,
|
|
20
|
+
profile: AccountProfile,
|
|
21
|
+
})
|
|
22
|
+
.withMigration((account) => {
|
|
23
|
+
if (!account.root) {
|
|
24
|
+
account.root = AccountRoot.create({ value: "123" }, { owner: account });
|
|
25
|
+
}
|
|
26
|
+
if (!account.profile) {
|
|
27
|
+
// Profile must be owned by a Group, not the account itself
|
|
28
|
+
const group = Group.create();
|
|
29
|
+
account.profile = AccountProfile.create(
|
|
30
|
+
{ name: "Test User" },
|
|
31
|
+
{ owner: group },
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
describe("useAccount", () => {
|
|
37
|
+
it("should return the correct value", async () => {
|
|
38
|
+
const account = await createJazzTestAccount();
|
|
39
|
+
|
|
40
|
+
const [result] = withJazzTestSetup(() => useAccount(), {
|
|
41
|
+
account,
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
expect(result.me.value).toEqual(account);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("should handle guest mode correctly", async () => {
|
|
48
|
+
const guestAccount = await createJazzTestGuest();
|
|
49
|
+
|
|
50
|
+
const [result] = withJazzTestSetup(() => useAccount(), {
|
|
51
|
+
account: guestAccount,
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// In guest mode, me should be null and agent should be the guest
|
|
55
|
+
expect(result.me.value).toBe(null);
|
|
56
|
+
expect(result.agent._type).toBe("Anonymous");
|
|
57
|
+
expect(typeof result.logOut).toBe("function");
|
|
58
|
+
});
|
|
59
|
+
});
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
// @vitest-environment happy-dom
|
|
2
|
+
|
|
3
|
+
import { type CoValue, type ID, co, cojsonInternals, z } from "jazz-tools";
|
|
4
|
+
import { createJazzTestAccount, setupJazzTestSync } from "jazz-tools/testing";
|
|
5
|
+
import { beforeEach, describe, expect, expectTypeOf, it } from "vitest";
|
|
6
|
+
import type { ComputedRef, Ref, ShallowRef } from "vue";
|
|
7
|
+
import { useCoState } from "../index.js";
|
|
8
|
+
import { waitFor, withJazzTestSetup } from "./testUtils.js";
|
|
9
|
+
|
|
10
|
+
beforeEach(async () => {
|
|
11
|
+
await setupJazzTestSync();
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
cojsonInternals.setCoValueLoadingRetryDelay(300);
|
|
15
|
+
|
|
16
|
+
describe("useCoState", () => {
|
|
17
|
+
it("should return the correct value", async () => {
|
|
18
|
+
const TestMap = co.map({
|
|
19
|
+
content: z.string(),
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
const account = await createJazzTestAccount();
|
|
23
|
+
|
|
24
|
+
const map = TestMap.create(
|
|
25
|
+
{
|
|
26
|
+
content: "123",
|
|
27
|
+
},
|
|
28
|
+
{ owner: account },
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
const [result] = withJazzTestSetup(() => useCoState(TestMap, map.id, {}), {
|
|
32
|
+
account,
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
expect(result.value?.content).toBe("123");
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("should update the value when the coValue changes", async () => {
|
|
39
|
+
const TestMap = co.map({
|
|
40
|
+
content: z.string(),
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
const account = await createJazzTestAccount();
|
|
44
|
+
|
|
45
|
+
const map = TestMap.create(
|
|
46
|
+
{
|
|
47
|
+
content: "123",
|
|
48
|
+
},
|
|
49
|
+
{ owner: account },
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
const [result] = withJazzTestSetup(() => useCoState(TestMap, map.id, {}), {
|
|
53
|
+
account,
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
expect(result.value?.content).toBe("123");
|
|
57
|
+
|
|
58
|
+
map.content = "456";
|
|
59
|
+
|
|
60
|
+
expect(result.value?.content).toBe("456");
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it("should load nested values if requested", async () => {
|
|
64
|
+
const TestNestedMap = co.map({
|
|
65
|
+
content: z.string(),
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
const TestMap = co.map({
|
|
69
|
+
content: z.string(),
|
|
70
|
+
nested: TestNestedMap,
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
const account = await createJazzTestAccount();
|
|
74
|
+
|
|
75
|
+
const map = TestMap.create(
|
|
76
|
+
{
|
|
77
|
+
content: "123",
|
|
78
|
+
nested: TestNestedMap.create(
|
|
79
|
+
{
|
|
80
|
+
content: "456",
|
|
81
|
+
},
|
|
82
|
+
{ owner: account },
|
|
83
|
+
),
|
|
84
|
+
},
|
|
85
|
+
{ owner: account },
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
const [result] = withJazzTestSetup(
|
|
89
|
+
() =>
|
|
90
|
+
useCoState(TestMap, map.id, {
|
|
91
|
+
resolve: {
|
|
92
|
+
nested: true,
|
|
93
|
+
},
|
|
94
|
+
}),
|
|
95
|
+
{
|
|
96
|
+
account,
|
|
97
|
+
},
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
expect(result.value?.content).toBe("123");
|
|
101
|
+
expect(result.value?.nested?.content).toBe("456");
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it("should load nested values on access even if not requested", async () => {
|
|
105
|
+
const TestNestedMap = co.map({
|
|
106
|
+
content: z.string(),
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
const TestMap = co.map({
|
|
110
|
+
content: z.string(),
|
|
111
|
+
nested: TestNestedMap,
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
const account = await createJazzTestAccount();
|
|
115
|
+
|
|
116
|
+
const map = TestMap.create(
|
|
117
|
+
{
|
|
118
|
+
content: "123",
|
|
119
|
+
nested: TestNestedMap.create(
|
|
120
|
+
{
|
|
121
|
+
content: "456",
|
|
122
|
+
},
|
|
123
|
+
{ owner: account },
|
|
124
|
+
),
|
|
125
|
+
},
|
|
126
|
+
{ owner: account },
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
const [result] = withJazzTestSetup(() => useCoState(TestMap, map.id, {}), {
|
|
130
|
+
account,
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
expect(result.value?.content).toBe("123");
|
|
134
|
+
expect(result.value?.nested?.content).toBe("456");
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it("should return null if the coValue is not found", async () => {
|
|
138
|
+
const TestMap = co.map({
|
|
139
|
+
content: z.string(),
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
await createJazzTestAccount({
|
|
143
|
+
isCurrentActiveAccount: true,
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
const [result] = withJazzTestSetup(() =>
|
|
147
|
+
useCoState(TestMap, "co_z123" as ID<co.loaded<typeof TestMap>>, {}),
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
expect(result.value).toBeUndefined();
|
|
151
|
+
|
|
152
|
+
await waitFor(() => {
|
|
153
|
+
expect(result.value).toBeNull();
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it("should return the same type as Schema", () => {
|
|
158
|
+
const TestMap = co.map({
|
|
159
|
+
value: z.string(),
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
const map = TestMap.create({
|
|
163
|
+
value: "123",
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
const [result] = withJazzTestSetup(() =>
|
|
167
|
+
useCoState(TestMap, map.id as ID<CoValue>, {
|
|
168
|
+
resolve: true,
|
|
169
|
+
}),
|
|
170
|
+
);
|
|
171
|
+
expectTypeOf(result).toEqualTypeOf<
|
|
172
|
+
Ref<co.loaded<typeof TestMap> | null | undefined>
|
|
173
|
+
>();
|
|
174
|
+
});
|
|
175
|
+
});
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// @vitest-environment happy-dom
|
|
2
|
+
|
|
3
|
+
import { CoMap, Group, Inbox, type Loaded, co, z } from "jazz-tools";
|
|
4
|
+
import { describe, expect, it } from "vitest";
|
|
5
|
+
import { experimental_useInboxSender } from "../composables.js";
|
|
6
|
+
import { createJazzTestAccount, linkAccounts } from "../testing.js";
|
|
7
|
+
import { withJazzTestSetup } from "./testUtils.js";
|
|
8
|
+
|
|
9
|
+
describe("useInboxSender", () => {
|
|
10
|
+
it("should send the message to the inbox", async () => {
|
|
11
|
+
const TestMap = co.map({
|
|
12
|
+
value: z.string(),
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
const account = await createJazzTestAccount();
|
|
16
|
+
const inboxReceiver = await createJazzTestAccount();
|
|
17
|
+
|
|
18
|
+
await linkAccounts(account, inboxReceiver);
|
|
19
|
+
|
|
20
|
+
const [result] = withJazzTestSetup(
|
|
21
|
+
() =>
|
|
22
|
+
experimental_useInboxSender<
|
|
23
|
+
Loaded<typeof TestMap>,
|
|
24
|
+
Loaded<typeof TestMap>
|
|
25
|
+
>(inboxReceiver.id),
|
|
26
|
+
{
|
|
27
|
+
account,
|
|
28
|
+
},
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
const sendMessage = result;
|
|
32
|
+
|
|
33
|
+
const promise = sendMessage(
|
|
34
|
+
TestMap.create(
|
|
35
|
+
{ value: "hello" },
|
|
36
|
+
{ owner: Group.create({ owner: account }) },
|
|
37
|
+
),
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
const inbox = await Inbox.load(inboxReceiver);
|
|
41
|
+
|
|
42
|
+
const incoming = await new Promise<Loaded<typeof TestMap>>((resolve) => {
|
|
43
|
+
inbox.subscribe(TestMap, async (message) => {
|
|
44
|
+
resolve(message);
|
|
45
|
+
|
|
46
|
+
return TestMap.create({ value: "got it" }, { owner: message._owner });
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
expect(incoming.value).toEqual("hello");
|
|
51
|
+
const response = await promise;
|
|
52
|
+
const responseMap = await TestMap.load(response, {
|
|
53
|
+
loadAs: account,
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
expect(responseMap!.value).toEqual("got it");
|
|
57
|
+
});
|
|
58
|
+
});
|