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.
Files changed (56) hide show
  1. package/.turbo/turbo-build.log +21 -0
  2. package/CHANGELOG.md +2201 -0
  3. package/LICENSE.txt +19 -0
  4. package/README.md +26 -0
  5. package/dist/Image.vue.d.ts +26 -0
  6. package/dist/auth/JazzVueProviderWithClerk.d.ts +83 -0
  7. package/dist/auth/PasskeyAuthBasicUI.vue.d.ts +21 -0
  8. package/dist/auth/useClerkAuth.d.ts +2 -0
  9. package/dist/auth/useIsAuthenticated.d.ts +1 -0
  10. package/dist/auth/usePasskeyAuth.d.ts +18 -0
  11. package/dist/auth/usePassphraseAuth.d.ts +20 -0
  12. package/dist/composables.d.ts +22 -0
  13. package/dist/index.d.ts +11 -0
  14. package/dist/index.js +667 -0
  15. package/dist/index.js.map +1 -0
  16. package/dist/provider-CCZVJj45.js +143 -0
  17. package/dist/provider-CCZVJj45.js.map +1 -0
  18. package/dist/provider.d.ts +172 -0
  19. package/dist/testing.d.ts +30 -0
  20. package/dist/testing.js +41 -0
  21. package/dist/testing.js.map +1 -0
  22. package/dist/tests/fixtures.d.ts +1 -0
  23. package/dist/tests/proxyBehavior.test.d.ts +1 -0
  24. package/dist/tests/testUtils.d.ts +9 -0
  25. package/dist/tests/useAcceptInvite.test.d.ts +1 -0
  26. package/dist/tests/useAccount.test.d.ts +1 -0
  27. package/dist/tests/useCoState.test.d.ts +1 -0
  28. package/dist/tests/useInboxSender.test.d.ts +1 -0
  29. package/dist/tests/useIsAuthenticated.test.d.ts +1 -0
  30. package/dist/tests/usePassphraseAuth.test.d.ts +1 -0
  31. package/dist/utils/contextManager.d.ts +3 -0
  32. package/package.json +53 -0
  33. package/src/Image.vue +151 -0
  34. package/src/auth/JazzVueProviderWithClerk.ts +123 -0
  35. package/src/auth/PasskeyAuthBasicUI.vue +153 -0
  36. package/src/auth/useClerkAuth.ts +35 -0
  37. package/src/auth/useIsAuthenticated.ts +21 -0
  38. package/src/auth/usePasskeyAuth.ts +48 -0
  39. package/src/auth/usePassphraseAuth.ts +57 -0
  40. package/src/composables.ts +323 -0
  41. package/src/index.ts +14 -0
  42. package/src/provider.ts +192 -0
  43. package/src/testing.ts +45 -0
  44. package/src/tests/fixtures.ts +2050 -0
  45. package/src/tests/proxyBehavior.test.ts +267 -0
  46. package/src/tests/testUtils.ts +75 -0
  47. package/src/tests/useAcceptInvite.test.ts +55 -0
  48. package/src/tests/useAccount.test.ts +59 -0
  49. package/src/tests/useCoState.test.ts +175 -0
  50. package/src/tests/useInboxSender.test.ts +58 -0
  51. package/src/tests/useIsAuthenticated.test.ts +35 -0
  52. package/src/tests/usePassphraseAuth.test.ts +95 -0
  53. package/src/utils/contextManager.ts +31 -0
  54. package/src/vite-env.d.ts +7 -0
  55. package/tsconfig.json +20 -0
  56. 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
+ });