jazz-tools 0.11.5 → 0.11.7
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 +5 -5
- package/CHANGELOG.md +18 -0
- package/dist/{chunk-IOK4K3XC.js → chunk-HH3Z4JSB.js} +65 -43
- package/dist/chunk-HH3Z4JSB.js.map +1 -0
- package/dist/coValues/extensions/imageDef.d.ts +1 -0
- package/dist/coValues/extensions/imageDef.d.ts.map +1 -1
- package/dist/coValues/interfaces.d.ts.map +1 -1
- package/dist/exports.d.ts +1 -1
- package/dist/exports.d.ts.map +1 -1
- package/dist/implementation/subscriptionScope.d.ts +2 -1
- package/dist/implementation/subscriptionScope.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/testing.js +1 -1
- package/dist/tests/imageDef.test.d.ts +2 -0
- package/dist/tests/imageDef.test.d.ts.map +1 -0
- package/package.json +2 -2
- package/src/coValues/extensions/imageDef.ts +22 -15
- package/src/coValues/group.ts +1 -1
- package/src/coValues/interfaces.ts +12 -1
- package/src/exports.ts +1 -0
- package/src/implementation/subscriptionScope.ts +59 -32
- package/src/tests/coFeed.test.ts +32 -0
- package/src/tests/imageDef.test.ts +269 -0
- package/src/tests/subscribe.test.ts +52 -2
- package/dist/chunk-IOK4K3XC.js.map +0 -1
@@ -0,0 +1,269 @@
|
|
1
|
+
import { WasmCrypto } from "cojson/crypto/WasmCrypto";
|
2
|
+
import { describe, expect, test } from "vitest";
|
3
|
+
import { Account, FileStream, ImageDefinition, co } from "../exports.js";
|
4
|
+
|
5
|
+
const Crypto = await WasmCrypto.create();
|
6
|
+
|
7
|
+
describe("ImageDefinition", async () => {
|
8
|
+
const me = await Account.create({
|
9
|
+
creationProps: { name: "Test User" },
|
10
|
+
crypto: Crypto,
|
11
|
+
});
|
12
|
+
|
13
|
+
test("Construction with basic properties", () => {
|
14
|
+
const imageDef = ImageDefinition.create(
|
15
|
+
{
|
16
|
+
originalSize: [1920, 1080],
|
17
|
+
placeholderDataURL: "data:image/jpeg;base64,...",
|
18
|
+
},
|
19
|
+
{ owner: me },
|
20
|
+
);
|
21
|
+
|
22
|
+
expect(imageDef.originalSize).toEqual([1920, 1080]);
|
23
|
+
expect(imageDef.placeholderDataURL).toBe("data:image/jpeg;base64,...");
|
24
|
+
});
|
25
|
+
|
26
|
+
test("highestResAvailable with no resolutions", () => {
|
27
|
+
const imageDef = ImageDefinition.create(
|
28
|
+
{
|
29
|
+
originalSize: [1920, 1080],
|
30
|
+
},
|
31
|
+
{ owner: me },
|
32
|
+
);
|
33
|
+
|
34
|
+
const result = imageDef.highestResAvailable();
|
35
|
+
expect(result).toBeUndefined();
|
36
|
+
});
|
37
|
+
|
38
|
+
test("highestResAvailable with single resolution", () => {
|
39
|
+
const imageDef = ImageDefinition.create(
|
40
|
+
{
|
41
|
+
originalSize: [1920, 1080],
|
42
|
+
},
|
43
|
+
{ owner: me },
|
44
|
+
);
|
45
|
+
|
46
|
+
const stream = FileStream.create({ owner: me });
|
47
|
+
stream.start({ mimeType: "image/jpeg" });
|
48
|
+
stream.push(new Uint8Array([1, 2, 3]));
|
49
|
+
stream.end();
|
50
|
+
|
51
|
+
imageDef["1920x1080"] = stream;
|
52
|
+
|
53
|
+
const result = imageDef.highestResAvailable();
|
54
|
+
expect(result).toBeDefined();
|
55
|
+
expect(result?.res).toBe("1920x1080");
|
56
|
+
expect(result?.stream).toStrictEqual(stream);
|
57
|
+
});
|
58
|
+
|
59
|
+
test("highestResAvailable with multiple resolutions", () => {
|
60
|
+
const imageDef = ImageDefinition.create(
|
61
|
+
{
|
62
|
+
originalSize: [1920, 1080],
|
63
|
+
},
|
64
|
+
{ owner: me },
|
65
|
+
);
|
66
|
+
|
67
|
+
const stream1 = FileStream.create({ owner: me });
|
68
|
+
stream1.start({ mimeType: "image/jpeg" });
|
69
|
+
stream1.push(new Uint8Array([1, 2, 3]));
|
70
|
+
stream1.end();
|
71
|
+
|
72
|
+
const stream2 = FileStream.create({ owner: me });
|
73
|
+
stream2.start({ mimeType: "image/jpeg" });
|
74
|
+
stream2.push(new Uint8Array([4, 5, 6]));
|
75
|
+
stream2.end();
|
76
|
+
|
77
|
+
imageDef["1920x1080"] = stream1;
|
78
|
+
imageDef["1280x720"] = stream2;
|
79
|
+
|
80
|
+
const result = imageDef.highestResAvailable();
|
81
|
+
expect(result).toBeDefined();
|
82
|
+
expect(result?.res).toBe("1920x1080");
|
83
|
+
expect(result?.stream).toStrictEqual(stream1);
|
84
|
+
});
|
85
|
+
|
86
|
+
test("highestResAvailable with maxWidth option", () => {
|
87
|
+
const imageDef = ImageDefinition.create(
|
88
|
+
{
|
89
|
+
originalSize: [1920, 1080],
|
90
|
+
},
|
91
|
+
{ owner: me },
|
92
|
+
);
|
93
|
+
|
94
|
+
const stream1 = FileStream.create({ owner: me });
|
95
|
+
stream1.start({ mimeType: "image/jpeg" });
|
96
|
+
stream1.push(new Uint8Array([1, 2, 3]));
|
97
|
+
stream1.end();
|
98
|
+
|
99
|
+
const stream2 = FileStream.create({ owner: me });
|
100
|
+
stream2.start({ mimeType: "image/jpeg" });
|
101
|
+
stream2.push(new Uint8Array([4, 5, 6]));
|
102
|
+
stream2.end();
|
103
|
+
|
104
|
+
imageDef["1920x1080"] = stream1;
|
105
|
+
imageDef["1280x720"] = stream2;
|
106
|
+
|
107
|
+
const result = imageDef.highestResAvailable({ maxWidth: 1500 });
|
108
|
+
expect(result).toBeDefined();
|
109
|
+
expect(result?.res).toBe("1280x720");
|
110
|
+
expect(result?.stream).toStrictEqual(stream2);
|
111
|
+
});
|
112
|
+
|
113
|
+
test("highestResAvailable with missing chunks", () => {
|
114
|
+
const imageDef = ImageDefinition.create(
|
115
|
+
{
|
116
|
+
originalSize: [1920, 1080],
|
117
|
+
},
|
118
|
+
{ owner: me },
|
119
|
+
);
|
120
|
+
|
121
|
+
const stream1 = FileStream.create({ owner: me });
|
122
|
+
stream1.start({ mimeType: "image/jpeg" });
|
123
|
+
stream1.push(new Uint8Array([1, 2, 3]));
|
124
|
+
stream1.end();
|
125
|
+
|
126
|
+
const stream2 = FileStream.create({ owner: me });
|
127
|
+
stream2.start({ mimeType: "image/jpeg" });
|
128
|
+
// Don't end stream2, so it has no chunks
|
129
|
+
|
130
|
+
imageDef["1920x1080"] = stream1;
|
131
|
+
imageDef["1280x720"] = stream2;
|
132
|
+
|
133
|
+
const result = imageDef.highestResAvailable();
|
134
|
+
expect(result).toBeDefined();
|
135
|
+
expect(result?.res).toBe("1920x1080");
|
136
|
+
expect(result?.stream).toStrictEqual(stream1);
|
137
|
+
});
|
138
|
+
|
139
|
+
test("highestResAvailable with missing chunks in middle stream", () => {
|
140
|
+
const imageDef = ImageDefinition.create(
|
141
|
+
{
|
142
|
+
originalSize: [1920, 1080],
|
143
|
+
},
|
144
|
+
{ owner: me },
|
145
|
+
);
|
146
|
+
|
147
|
+
const stream1 = FileStream.create({ owner: me });
|
148
|
+
stream1.start({ mimeType: "image/jpeg" });
|
149
|
+
stream1.push(new Uint8Array([1, 2, 3]));
|
150
|
+
stream1.end();
|
151
|
+
|
152
|
+
const stream2 = FileStream.create({ owner: me });
|
153
|
+
stream2.start({ mimeType: "image/jpeg" });
|
154
|
+
// Don't end stream2, so it has no chunks
|
155
|
+
|
156
|
+
const stream3 = FileStream.create({ owner: me });
|
157
|
+
stream3.start({ mimeType: "image/jpeg" });
|
158
|
+
stream3.push(new Uint8Array([7, 8, 9]));
|
159
|
+
stream3.end();
|
160
|
+
|
161
|
+
imageDef["1920x1080"] = stream1;
|
162
|
+
imageDef["1280x720"] = stream2;
|
163
|
+
imageDef["1024x576"] = stream3;
|
164
|
+
|
165
|
+
const result = imageDef.highestResAvailable();
|
166
|
+
expect(result).toBeDefined();
|
167
|
+
expect(result?.res).toBe("1920x1080");
|
168
|
+
expect(result?.stream).toStrictEqual(stream1);
|
169
|
+
});
|
170
|
+
|
171
|
+
test("highestResAvailable with non-resolution keys", () => {
|
172
|
+
const imageDef = ImageDefinition.create(
|
173
|
+
{
|
174
|
+
originalSize: [1920, 1080],
|
175
|
+
},
|
176
|
+
{ owner: me },
|
177
|
+
);
|
178
|
+
|
179
|
+
const stream = FileStream.create({ owner: me });
|
180
|
+
stream.start({ mimeType: "image/jpeg" });
|
181
|
+
stream.push(new Uint8Array([1, 2, 3]));
|
182
|
+
stream.end();
|
183
|
+
|
184
|
+
// @ts-expect-error - Testing invalid key
|
185
|
+
imageDef["invalid-key"] = stream;
|
186
|
+
|
187
|
+
const result = imageDef.highestResAvailable();
|
188
|
+
expect(result).toBeUndefined();
|
189
|
+
});
|
190
|
+
|
191
|
+
test("highestResAvailable with targetWidth option", () => {
|
192
|
+
const imageDef = ImageDefinition.create(
|
193
|
+
{
|
194
|
+
originalSize: [1920, 1080],
|
195
|
+
},
|
196
|
+
{ owner: me },
|
197
|
+
);
|
198
|
+
|
199
|
+
const stream1 = FileStream.create({ owner: me });
|
200
|
+
stream1.start({ mimeType: "image/jpeg" });
|
201
|
+
stream1.push(new Uint8Array([1, 2, 3]));
|
202
|
+
stream1.end();
|
203
|
+
|
204
|
+
const stream2 = FileStream.create({ owner: me });
|
205
|
+
stream2.start({ mimeType: "image/jpeg" });
|
206
|
+
stream2.push(new Uint8Array([4, 5, 6]));
|
207
|
+
stream2.end();
|
208
|
+
|
209
|
+
const stream3 = FileStream.create({ owner: me });
|
210
|
+
stream3.start({ mimeType: "image/jpeg" });
|
211
|
+
stream3.push(new Uint8Array([7, 8, 9]));
|
212
|
+
stream3.end();
|
213
|
+
|
214
|
+
imageDef["1920x1080"] = stream1;
|
215
|
+
imageDef["1280x720"] = stream2;
|
216
|
+
imageDef["800x450"] = stream3;
|
217
|
+
|
218
|
+
// Should return 1280x720 as it's the smallest resolution >= 1000px
|
219
|
+
const result1 = imageDef.highestResAvailable({ targetWidth: 1000 });
|
220
|
+
expect(result1).toBeDefined();
|
221
|
+
expect(result1?.res).toBe("1280x720");
|
222
|
+
expect(result1?.stream).toStrictEqual(stream2);
|
223
|
+
|
224
|
+
// Should return 800x450 as it's the smallest resolution >= 700px
|
225
|
+
const result2 = imageDef.highestResAvailable({ targetWidth: 700 });
|
226
|
+
expect(result2).toBeDefined();
|
227
|
+
expect(result2?.res).toBe("800x450");
|
228
|
+
expect(result2?.stream).toStrictEqual(stream3);
|
229
|
+
|
230
|
+
// Should return 1920x1080 as it's the smallest resolution >= 1500px
|
231
|
+
const result3 = imageDef.highestResAvailable({ targetWidth: 1500 });
|
232
|
+
expect(result3).toBeDefined();
|
233
|
+
expect(result3?.res).toBe("1920x1080");
|
234
|
+
expect(result3?.stream).toStrictEqual(stream1);
|
235
|
+
});
|
236
|
+
|
237
|
+
test("highestResAvailable with targetWidth and incomplete streams", () => {
|
238
|
+
const imageDef = ImageDefinition.create(
|
239
|
+
{
|
240
|
+
originalSize: [1920, 1080],
|
241
|
+
},
|
242
|
+
{ owner: me },
|
243
|
+
);
|
244
|
+
|
245
|
+
const stream1 = FileStream.create({ owner: me });
|
246
|
+
stream1.start({ mimeType: "image/jpeg" });
|
247
|
+
stream1.push(new Uint8Array([1, 2, 3]));
|
248
|
+
stream1.end();
|
249
|
+
|
250
|
+
const stream2 = FileStream.create({ owner: me });
|
251
|
+
stream2.start({ mimeType: "image/jpeg" });
|
252
|
+
// Don't end stream2, so it has no chunks
|
253
|
+
|
254
|
+
const stream3 = FileStream.create({ owner: me });
|
255
|
+
stream3.start({ mimeType: "image/jpeg" });
|
256
|
+
stream3.push(new Uint8Array([7, 8, 9]));
|
257
|
+
stream3.end();
|
258
|
+
|
259
|
+
imageDef["1920x1080"] = stream1;
|
260
|
+
imageDef["1280x720"] = stream2;
|
261
|
+
imageDef["800x450"] = stream3;
|
262
|
+
|
263
|
+
// Should skip 1280x720 as it's incomplete and return 1920x1080
|
264
|
+
const result = imageDef.highestResAvailable({ targetWidth: 1000 });
|
265
|
+
expect(result).toBeDefined();
|
266
|
+
expect(result?.res).toBe("800x450");
|
267
|
+
expect(result?.stream).toStrictEqual(stream1);
|
268
|
+
});
|
269
|
+
});
|
@@ -1,4 +1,12 @@
|
|
1
|
-
import {
|
1
|
+
import {
|
2
|
+
assert,
|
3
|
+
beforeEach,
|
4
|
+
describe,
|
5
|
+
expect,
|
6
|
+
it,
|
7
|
+
onTestFinished,
|
8
|
+
vi,
|
9
|
+
} from "vitest";
|
2
10
|
import {
|
3
11
|
Account,
|
4
12
|
CoFeed,
|
@@ -15,7 +23,7 @@ import {
|
|
15
23
|
createCoValueObservable,
|
16
24
|
subscribeToCoValue,
|
17
25
|
} from "../internal.js";
|
18
|
-
import { setupJazzTestSync } from "../testing.js";
|
26
|
+
import { createJazzTestAccount, setupJazzTestSync } from "../testing.js";
|
19
27
|
import { setupAccount, waitFor } from "./utils.js";
|
20
28
|
|
21
29
|
class ChatRoom extends CoMap {
|
@@ -352,6 +360,48 @@ describe("subscribeToCoValue", () => {
|
|
352
360
|
expect(lastValue.messages[0]).toBe(initialValue.messages[0]);
|
353
361
|
expect(lastValue.messages[1]).toBe(initialValue.messages[1]);
|
354
362
|
});
|
363
|
+
|
364
|
+
it("should emit only once when loading a list of values", async () => {
|
365
|
+
class TestMap extends CoMap {
|
366
|
+
value = co.string;
|
367
|
+
}
|
368
|
+
|
369
|
+
class TestList extends CoList.Of(co.ref(TestMap)) {}
|
370
|
+
|
371
|
+
const account = await createJazzTestAccount({
|
372
|
+
isCurrentActiveAccount: true,
|
373
|
+
});
|
374
|
+
|
375
|
+
const list = TestList.create([
|
376
|
+
TestMap.create({ value: "1" }),
|
377
|
+
TestMap.create({ value: "2" }),
|
378
|
+
TestMap.create({ value: "3" }),
|
379
|
+
TestMap.create({ value: "4" }),
|
380
|
+
TestMap.create({ value: "5" }),
|
381
|
+
]);
|
382
|
+
|
383
|
+
const updateFn = vi.fn();
|
384
|
+
|
385
|
+
const unsubscribe = subscribeToCoValue(
|
386
|
+
TestList,
|
387
|
+
list.id,
|
388
|
+
account,
|
389
|
+
[{}],
|
390
|
+
(value) => {
|
391
|
+
updateFn(value);
|
392
|
+
},
|
393
|
+
);
|
394
|
+
|
395
|
+
onTestFinished(unsubscribe);
|
396
|
+
|
397
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
398
|
+
|
399
|
+
assert(list);
|
400
|
+
|
401
|
+
expect(list[0]?.value).toBe("1");
|
402
|
+
|
403
|
+
expect(updateFn).toHaveBeenCalledTimes(1);
|
404
|
+
});
|
355
405
|
});
|
356
406
|
|
357
407
|
describe("createCoValueObservable", () => {
|