@gradio/client 2.0.4 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/dist/browser.js +569 -541
- package/dist/client.d.ts +1 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/helpers/api_info.d.ts.map +1 -1
- package/dist/helpers/zerogpu.d.ts +3 -0
- package/dist/helpers/zerogpu.d.ts.map +1 -0
- package/dist/index.js +45 -9
- package/dist/types.d.ts +3 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/submit.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/client.ts +8 -4
- package/src/helpers/api_info.ts +4 -1
- package/src/helpers/zerogpu.ts +40 -0
- package/src/test/api_info.test.ts +12 -5
- package/src/test/apply_diff.test.ts +1 -0
- package/src/test/data.test.ts +194 -118
- package/src/test/handlers.ts +0 -6
- package/src/test/init.test.ts +6 -3
- package/src/test/init_helpers.test.ts +7 -4
- package/src/test/mock_eventsource.ts +1 -1
- package/src/test/post_data.test.ts +7 -3
- package/src/test/server.ts +28 -3
- package/src/test/spaces.test.ts +6 -3
- package/src/test/stream.test.ts +17 -11
- package/src/test/upload_files.test.ts +7 -4
- package/src/test/view_api.test.ts +6 -3
- package/src/types.ts +3 -0
- package/src/utils/submit.ts +12 -6
- package/vite.config.ts +104 -0
- package/vite.config.js +0 -52
package/src/test/data.test.ts
CHANGED
|
@@ -11,11 +11,64 @@ import { config_response, endpoint_info } from "./test_data";
|
|
|
11
11
|
import { BlobRef, Command } from "../types";
|
|
12
12
|
import { FileData } from "../upload";
|
|
13
13
|
|
|
14
|
-
const IS_NODE =
|
|
14
|
+
const IS_NODE =
|
|
15
|
+
typeof process !== "undefined" && process.env.TEST_MODE === "node";
|
|
16
|
+
|
|
17
|
+
class FakeBuffer {
|
|
18
|
+
static from(data: string) {
|
|
19
|
+
return new Blob([data]);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
static isBuffer() {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
static isEncoding() {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
static byteLength() {
|
|
31
|
+
return 0;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
static concat() {
|
|
35
|
+
return new Blob([]);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
static compare() {
|
|
39
|
+
return 0;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
static alloc() {
|
|
43
|
+
return new Blob([]);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
static allocUnsafe() {
|
|
47
|
+
return new Blob([]);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
static allocUnsafeSlow() {
|
|
51
|
+
return new Blob([]);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
static poolSize = 0;
|
|
55
|
+
|
|
56
|
+
static of() {
|
|
57
|
+
return new Blob([]);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
equals(other: Blob) {
|
|
61
|
+
return this.toString() === other.toString();
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (!IS_NODE) {
|
|
66
|
+
globalThis.Buffer = FakeBuffer as unknown as BufferConstructor;
|
|
67
|
+
}
|
|
15
68
|
|
|
16
69
|
describe("walk_and_store_blobs", () => {
|
|
17
|
-
it("should convert a Buffer to a Blob", async () => {
|
|
18
|
-
const buffer = Buffer.from("test data");
|
|
70
|
+
it.skipIf(!IS_NODE)("should convert a Buffer to a Blob", async () => {
|
|
71
|
+
const buffer = globalThis.Buffer.from("test data");
|
|
19
72
|
const parts = await walk_and_store_blobs(buffer, "text");
|
|
20
73
|
|
|
21
74
|
expect(parts).toHaveLength(1);
|
|
@@ -74,75 +127,87 @@ describe("walk_and_store_blobs", () => {
|
|
|
74
127
|
expect(parts[0].blob).toBeInstanceOf(Blob);
|
|
75
128
|
});
|
|
76
129
|
|
|
77
|
-
it(
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
130
|
+
it.skipIf(!IS_NODE)(
|
|
131
|
+
"should handle deep structures with arrays (with equality check)",
|
|
132
|
+
async () => {
|
|
133
|
+
const image = new Blob([]);
|
|
134
|
+
|
|
135
|
+
const obj = {
|
|
136
|
+
a: [
|
|
137
|
+
{
|
|
138
|
+
b: [
|
|
139
|
+
{
|
|
140
|
+
data: [[image], image, [image, [image]]]
|
|
141
|
+
}
|
|
142
|
+
]
|
|
143
|
+
}
|
|
144
|
+
]
|
|
145
|
+
};
|
|
146
|
+
const parts = await walk_and_store_blobs(obj);
|
|
147
|
+
|
|
148
|
+
async function map_path(obj: Record<string, any>, parts: BlobRef[]) {
|
|
149
|
+
const { path, blob } = parts[parts.length - 1];
|
|
150
|
+
let ref = obj;
|
|
151
|
+
path.forEach((p) => (ref = ref[p]));
|
|
152
|
+
|
|
153
|
+
// since ref is a Blob and blob is a Blob, we deep equal check the two buffers instead
|
|
154
|
+
if (ref instanceof Blob && blob instanceof Blob) {
|
|
155
|
+
const refBuffer = Buffer.from(await ref.arrayBuffer());
|
|
156
|
+
const blobBuffer = Buffer.from(await blob.arrayBuffer());
|
|
157
|
+
return refBuffer.equals(blobBuffer);
|
|
88
158
|
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
const parts = await walk_and_store_blobs(obj);
|
|
92
|
-
|
|
93
|
-
async function map_path(obj: Record<string, any>, parts: BlobRef[]) {
|
|
94
|
-
const { path, blob } = parts[parts.length - 1];
|
|
95
|
-
let ref = obj;
|
|
96
|
-
path.forEach((p) => (ref = ref[p]));
|
|
97
|
-
|
|
98
|
-
// since ref is a Blob and blob is a Blob, we deep equal check the two buffers instead
|
|
99
|
-
if (ref instanceof Blob && blob instanceof Blob) {
|
|
100
|
-
const refBuffer = Buffer.from(await ref.arrayBuffer());
|
|
101
|
-
const blobBuffer = Buffer.from(await blob.arrayBuffer());
|
|
102
|
-
return refBuffer.equals(blobBuffer);
|
|
159
|
+
|
|
160
|
+
return ref === blob;
|
|
103
161
|
}
|
|
104
162
|
|
|
105
|
-
|
|
163
|
+
expect(parts[0].blob).toBeInstanceOf(Blob);
|
|
164
|
+
expect(map_path(obj, parts)).toBeTruthy();
|
|
106
165
|
}
|
|
166
|
+
);
|
|
107
167
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
const buffer = Buffer.from("test");
|
|
114
|
-
const parts = await walk_and_store_blobs(buffer, undefined, ["blob"]);
|
|
115
|
-
|
|
116
|
-
expect(parts).toHaveLength(1);
|
|
117
|
-
expect(parts[0].blob).toBeInstanceOf(Blob);
|
|
118
|
-
expect(parts[0].path).toEqual(["blob"]);
|
|
119
|
-
});
|
|
168
|
+
it.skipIf(!IS_NODE)(
|
|
169
|
+
"should handle buffer instances and return a BlobRef",
|
|
170
|
+
async () => {
|
|
171
|
+
const buffer = Buffer.from("test");
|
|
172
|
+
const parts = await walk_and_store_blobs(buffer, undefined, ["blob"]);
|
|
120
173
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
174
|
+
expect(parts).toHaveLength(1);
|
|
175
|
+
expect(parts[0].blob).toBeInstanceOf(Blob);
|
|
176
|
+
expect(parts[0].path).toEqual(["blob"]);
|
|
177
|
+
}
|
|
178
|
+
);
|
|
124
179
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
180
|
+
it.skipIf(!IS_NODE)(
|
|
181
|
+
"should handle buffer instances with a path and return a BlobRef with the path",
|
|
182
|
+
async () => {
|
|
183
|
+
const buffer = Buffer.from("test data");
|
|
184
|
+
const parts = await walk_and_store_blobs(buffer);
|
|
129
185
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
186
|
+
expect(parts).toHaveLength(1);
|
|
187
|
+
expect(parts[0].path).toEqual([]);
|
|
188
|
+
expect(parts[0].blob).toBeInstanceOf(Blob);
|
|
189
|
+
}
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
it.skipIf(!IS_NODE)(
|
|
193
|
+
"should convert an object with deep structures to BlobRefs",
|
|
194
|
+
async () => {
|
|
195
|
+
const param = {
|
|
196
|
+
a: {
|
|
197
|
+
b: {
|
|
198
|
+
data: {
|
|
199
|
+
image: Buffer.from("test image")
|
|
200
|
+
}
|
|
136
201
|
}
|
|
137
202
|
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
const parts = await walk_and_store_blobs(param);
|
|
203
|
+
};
|
|
204
|
+
const parts = await walk_and_store_blobs(param);
|
|
141
205
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
206
|
+
expect(parts).toHaveLength(1);
|
|
207
|
+
expect(parts[0].path).toEqual(["a", "b", "data", "image"]);
|
|
208
|
+
expect(parts[0].blob).toBeInstanceOf(Blob);
|
|
209
|
+
}
|
|
210
|
+
);
|
|
146
211
|
});
|
|
147
212
|
describe("update_object", () => {
|
|
148
213
|
it("should update the value of a nested property", () => {
|
|
@@ -227,46 +292,50 @@ describe("post_message", () => {
|
|
|
227
292
|
vi.restoreAllMocks();
|
|
228
293
|
});
|
|
229
294
|
|
|
230
|
-
it(
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
295
|
+
it.skipIf(IS_NODE)(
|
|
296
|
+
"should send a message to the parent window and resolve with received data",
|
|
297
|
+
async () => {
|
|
298
|
+
const test_data = { key: "value" };
|
|
299
|
+
const test_origin = "https://huggingface.co";
|
|
300
|
+
|
|
301
|
+
// Create a mock for window.parent.postMessage that we'll spy on
|
|
302
|
+
const post_message_spy = vi
|
|
303
|
+
.spyOn(window.parent, "postMessage")
|
|
304
|
+
.mockImplementation(() => {});
|
|
305
|
+
|
|
306
|
+
// Mock MessageChannel
|
|
307
|
+
const original_message_channel = globalThis.MessageChannel;
|
|
308
|
+
const mock_port1 = {
|
|
309
|
+
onmessage: null as unknown as (event: { data: any }) => void,
|
|
310
|
+
close: vi.fn()
|
|
311
|
+
};
|
|
312
|
+
const mock_port2 = {};
|
|
235
313
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
postMessage: post_message_mock
|
|
314
|
+
class MockMessageChannel {
|
|
315
|
+
port1 = mock_port1;
|
|
316
|
+
port2 = mock_port2;
|
|
240
317
|
}
|
|
241
|
-
};
|
|
242
318
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
onmessage: (handler) => {
|
|
246
|
-
onmessage = handler;
|
|
247
|
-
},
|
|
248
|
-
close: vi.fn()
|
|
249
|
-
},
|
|
250
|
-
port2: {}
|
|
251
|
-
};
|
|
319
|
+
// Replace MessageChannel with our mock version
|
|
320
|
+
globalThis.MessageChannel = MockMessageChannel as any;
|
|
252
321
|
|
|
253
|
-
|
|
254
|
-
this.port1 = message_channel_mock.port1;
|
|
255
|
-
this.port2 = message_channel_mock.port2;
|
|
256
|
-
return this;
|
|
257
|
-
});
|
|
322
|
+
const promise = post_message(test_data, test_origin);
|
|
258
323
|
|
|
259
|
-
|
|
324
|
+
// Simulate receiving a message back
|
|
325
|
+
if (mock_port1.onmessage) {
|
|
326
|
+
mock_port1.onmessage({ data: test_data } as any);
|
|
327
|
+
}
|
|
260
328
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
329
|
+
await expect(promise).resolves.toEqual(test_data);
|
|
330
|
+
expect(post_message_spy).toHaveBeenCalledWith(test_data, test_origin, [
|
|
331
|
+
mock_port2
|
|
332
|
+
]);
|
|
264
333
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
334
|
+
// Restore original MessageChannel
|
|
335
|
+
globalThis.MessageChannel = original_message_channel;
|
|
336
|
+
post_message_spy.mockRestore();
|
|
337
|
+
}
|
|
338
|
+
);
|
|
270
339
|
});
|
|
271
340
|
|
|
272
341
|
describe("handle_file", () => {
|
|
@@ -277,31 +346,38 @@ describe("handle_file", () => {
|
|
|
277
346
|
expect(result).toBe(blob);
|
|
278
347
|
});
|
|
279
348
|
|
|
280
|
-
it(
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
const file_path = "./owl.png";
|
|
287
|
-
const result = handle_file(file_path) as Command;
|
|
288
|
-
expect(result).toBeInstanceOf(Command);
|
|
289
|
-
expect(result).toEqual({
|
|
290
|
-
type: "command",
|
|
291
|
-
command: "upload_file",
|
|
292
|
-
meta: { path: "./owl.png", name: "./owl.png", orig_path: "./owl.png" },
|
|
293
|
-
fileData: undefined
|
|
294
|
-
});
|
|
295
|
-
});
|
|
296
|
-
|
|
297
|
-
it("should handle a File object and return it as FileData", () => {
|
|
298
|
-
if (IS_NODE) {
|
|
299
|
-
return;
|
|
349
|
+
it.skipIf(!IS_NODE)(
|
|
350
|
+
"should handle a Buffer object and return it as a blob",
|
|
351
|
+
() => {
|
|
352
|
+
const buffer = Buffer.from("test data");
|
|
353
|
+
const result = handle_file(buffer) as FileData;
|
|
354
|
+
expect(result).toBeInstanceOf(Blob);
|
|
300
355
|
}
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
356
|
+
);
|
|
357
|
+
|
|
358
|
+
it.skipIf(!IS_NODE)(
|
|
359
|
+
"should handle a local file path and return a Command object",
|
|
360
|
+
() => {
|
|
361
|
+
const file_path = "./owl.png";
|
|
362
|
+
const result = handle_file(file_path) as Command;
|
|
363
|
+
expect(result).toBeInstanceOf(Command);
|
|
364
|
+
expect(result).toEqual({
|
|
365
|
+
type: "command",
|
|
366
|
+
command: "upload_file",
|
|
367
|
+
meta: { path: "./owl.png", name: "./owl.png", orig_path: "./owl.png" },
|
|
368
|
+
fileData: undefined
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
);
|
|
372
|
+
|
|
373
|
+
it.skipIf(IS_NODE)(
|
|
374
|
+
"should handle a File object and return it as FileData",
|
|
375
|
+
() => {
|
|
376
|
+
const file = new File(["test image"], "test.png", { type: "image/png" });
|
|
377
|
+
const result = handle_file(file) as FileData;
|
|
378
|
+
expect(result).toBeInstanceOf(Blob);
|
|
379
|
+
}
|
|
380
|
+
);
|
|
305
381
|
|
|
306
382
|
it("should throw an error for invalid input", () => {
|
|
307
383
|
const invalid_input = 123;
|
package/src/test/handlers.ts
CHANGED
|
@@ -630,9 +630,6 @@ export const handlers: RequestHandler[] = [
|
|
|
630
630
|
status: 200,
|
|
631
631
|
headers: {
|
|
632
632
|
"Content-Type": "application/json",
|
|
633
|
-
"Set-Cookie":
|
|
634
|
-
"access-token-123=abc; HttpOnly; Path=/; SameSite=none; Secure",
|
|
635
|
-
// @ts-ignore - multiple Set-Cookie headers are returned
|
|
636
633
|
"Set-Cookie":
|
|
637
634
|
"access-token-unsecure-123=abc; HttpOnly; Path=/; SameSite=none; Secure"
|
|
638
635
|
}
|
|
@@ -673,9 +670,6 @@ export const handlers: RequestHandler[] = [
|
|
|
673
670
|
status: 200,
|
|
674
671
|
headers: {
|
|
675
672
|
"Content-Type": "application/json",
|
|
676
|
-
"Set-Cookie":
|
|
677
|
-
"access-token-123=abc; HttpOnly; Path=/; SameSite=none; Secure",
|
|
678
|
-
// @ts-ignore - multiple Set-Cookie headers are returned
|
|
679
673
|
"Set-Cookie":
|
|
680
674
|
"access-token-unsecure-123=abc; HttpOnly; Path=/; SameSite=none; Secure"
|
|
681
675
|
}
|
package/src/test/init.test.ts
CHANGED
|
@@ -22,11 +22,14 @@ const broken_app_reference = "hmb/bye_world";
|
|
|
22
22
|
const direct_app_reference = "https://hmb-hello-world.hf.space";
|
|
23
23
|
const secret_direct_app_reference = "https://hmb-secret-world.hf.space";
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
let server: Awaited<ReturnType<typeof initialise_server>>;
|
|
26
26
|
|
|
27
|
-
beforeAll(() =>
|
|
27
|
+
beforeAll(async () => {
|
|
28
|
+
server = await initialise_server();
|
|
29
|
+
await server.start({ quiet: true });
|
|
30
|
+
});
|
|
28
31
|
afterEach(() => server.resetHandlers());
|
|
29
|
-
afterAll(() => server.
|
|
32
|
+
afterAll(() => server.stop());
|
|
30
33
|
|
|
31
34
|
describe("Client class", () => {
|
|
32
35
|
describe("initialisation", () => {
|
|
@@ -9,11 +9,14 @@ import { beforeAll, afterEach, afterAll, it, expect, describe } from "vitest";
|
|
|
9
9
|
import { Client } from "../client";
|
|
10
10
|
import { INVALID_CREDENTIALS_MSG, MISSING_CREDENTIALS_MSG } from "../constants";
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
let server: Awaited<ReturnType<typeof initialise_server>>;
|
|
13
13
|
|
|
14
|
-
beforeAll(() =>
|
|
14
|
+
beforeAll(async () => {
|
|
15
|
+
server = await initialise_server();
|
|
16
|
+
await server.start({ quiet: true });
|
|
17
|
+
});
|
|
15
18
|
afterEach(() => server.resetHandlers());
|
|
16
|
-
afterAll(() => server.
|
|
19
|
+
afterAll(() => server.stop());
|
|
17
20
|
|
|
18
21
|
describe("resolve_root", () => {
|
|
19
22
|
it('should return the base URL if the root path starts with "http://"', () => {
|
|
@@ -102,7 +105,7 @@ describe("resolve_cookies", () => {
|
|
|
102
105
|
|
|
103
106
|
it("should connect to a private and authenticated space", async () => {
|
|
104
107
|
const client = await Client.connect("hmb/private_auth_space", {
|
|
105
|
-
|
|
108
|
+
token: "hf_123",
|
|
106
109
|
auth: ["admin", "pass1234"]
|
|
107
110
|
});
|
|
108
111
|
|
|
@@ -2,12 +2,16 @@ import { Client } from "../client";
|
|
|
2
2
|
|
|
3
3
|
import { initialise_server } from "./server";
|
|
4
4
|
import { BROKEN_CONNECTION_MSG } from "../constants";
|
|
5
|
-
const server = initialise_server();
|
|
6
5
|
import { beforeAll, afterEach, afterAll, it, expect, describe } from "vitest";
|
|
7
6
|
|
|
8
|
-
|
|
7
|
+
let server: Awaited<ReturnType<typeof initialise_server>>;
|
|
8
|
+
|
|
9
|
+
beforeAll(async () => {
|
|
10
|
+
server = await initialise_server();
|
|
11
|
+
await server.start({ quiet: true });
|
|
12
|
+
});
|
|
9
13
|
afterEach(() => server.resetHandlers());
|
|
10
|
-
afterAll(() => server.
|
|
14
|
+
afterAll(() => server.stop());
|
|
11
15
|
|
|
12
16
|
describe("post_data", () => {
|
|
13
17
|
it("should send a POST request with the correct headers and body", async () => {
|
package/src/test/server.ts
CHANGED
|
@@ -1,6 +1,31 @@
|
|
|
1
|
-
import { setupServer } from "msw/node";
|
|
2
1
|
import { handlers } from "./handlers";
|
|
2
|
+
// import type { StartOptions } from 'msw';
|
|
3
|
+
import type { SetupWorker, StartOptions } from "msw/browser";
|
|
3
4
|
|
|
4
|
-
|
|
5
|
-
|
|
5
|
+
const IS_NODE =
|
|
6
|
+
typeof process !== "undefined" && process.env.TEST_MODE === "node";
|
|
7
|
+
|
|
8
|
+
interface MockServer {
|
|
9
|
+
start: (opts: StartOptions) => void | ReturnType<SetupWorker["start"]>;
|
|
10
|
+
stop: () => void | Promise<void>;
|
|
11
|
+
resetHandlers: (...handlers: any[]) => void;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export async function initialise_server(): Promise<MockServer> {
|
|
15
|
+
if (IS_NODE) {
|
|
16
|
+
const { setupServer } = await import("msw/node");
|
|
17
|
+
const server = setupServer(...handlers);
|
|
18
|
+
return {
|
|
19
|
+
start: (opts: StartOptions) => server.listen(opts),
|
|
20
|
+
stop: () => server.close(),
|
|
21
|
+
resetHandlers: (...h) => server.resetHandlers(...h)
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
const { setupWorker } = await import("msw/browser");
|
|
25
|
+
const worker = setupWorker(...handlers);
|
|
26
|
+
return {
|
|
27
|
+
start: (opts: StartOptions) => worker.start(opts),
|
|
28
|
+
stop: () => worker.stop(),
|
|
29
|
+
resetHandlers: (...h) => worker.resetHandlers(...h)
|
|
30
|
+
};
|
|
6
31
|
}
|
package/src/test/spaces.test.ts
CHANGED
|
@@ -11,11 +11,14 @@ import { initialise_server } from "./server";
|
|
|
11
11
|
import { hardware_sleeptime_response } from "./test_data";
|
|
12
12
|
import { vi } from "vitest";
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
let server: Awaited<ReturnType<typeof initialise_server>>;
|
|
15
15
|
|
|
16
|
-
beforeAll(() =>
|
|
16
|
+
beforeAll(async () => {
|
|
17
|
+
server = await initialise_server();
|
|
18
|
+
await server.start({ quiet: true });
|
|
19
|
+
});
|
|
17
20
|
afterEach(() => server.resetHandlers());
|
|
18
|
-
afterAll(() => server.
|
|
21
|
+
afterAll(() => server.stop());
|
|
19
22
|
|
|
20
23
|
describe("set_space_timeout", () => {
|
|
21
24
|
it("should set the sleep timeout for a space", async () => {
|
package/src/test/stream.test.ts
CHANGED
|
@@ -14,11 +14,14 @@ import {
|
|
|
14
14
|
beforeEach
|
|
15
15
|
} from "vitest";
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
let server: Awaited<ReturnType<typeof initialise_server>>;
|
|
18
18
|
|
|
19
|
-
beforeAll(() =>
|
|
19
|
+
beforeAll(async () => {
|
|
20
|
+
server = await initialise_server();
|
|
21
|
+
await server.start({ quiet: true });
|
|
22
|
+
});
|
|
20
23
|
afterEach(() => server.resetHandlers());
|
|
21
|
-
afterAll(() => server.
|
|
24
|
+
afterAll(() => server.stop());
|
|
22
25
|
|
|
23
26
|
describe("open_stream", () => {
|
|
24
27
|
let app: Client;
|
|
@@ -37,10 +40,10 @@ describe("open_stream", () => {
|
|
|
37
40
|
vi.clearAllMocks();
|
|
38
41
|
});
|
|
39
42
|
|
|
40
|
-
it("should throw an error if config is not defined", () => {
|
|
43
|
+
it("should throw an error if config is not defined", async () => {
|
|
41
44
|
app.config = undefined;
|
|
42
45
|
|
|
43
|
-
expect(async () => {
|
|
46
|
+
await expect(async () => {
|
|
44
47
|
await app.open_stream();
|
|
45
48
|
}).rejects.toThrow("Could not resolve app config");
|
|
46
49
|
});
|
|
@@ -60,22 +63,25 @@ describe("open_stream", () => {
|
|
|
60
63
|
throw new Error("stream instance is not defined");
|
|
61
64
|
}
|
|
62
65
|
|
|
63
|
-
const onMessageCallback = app.stream_instance.onmessage.bind(app);
|
|
64
|
-
const onErrorCallback = app.stream_instance.onerror.bind(app);
|
|
65
|
-
|
|
66
66
|
const message = { msg: "hello jerry" };
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
app.stream_instance.onmessage({
|
|
69
|
+
data: JSON.stringify(message)
|
|
70
|
+
} as MessageEvent);
|
|
69
71
|
expect(app.stream_status.open).toBe(true);
|
|
70
72
|
|
|
71
73
|
expect(app.event_callbacks).toEqual({});
|
|
72
74
|
expect(app.pending_stream_messages).toEqual({});
|
|
73
75
|
|
|
74
76
|
const close_stream_message = { msg: "close_stream" };
|
|
75
|
-
|
|
77
|
+
app.stream_instance.onmessage({
|
|
78
|
+
data: JSON.stringify(close_stream_message)
|
|
79
|
+
} as MessageEvent);
|
|
76
80
|
expect(app.stream_status.open).toBe(false);
|
|
77
81
|
|
|
78
|
-
|
|
82
|
+
app.stream_instance.onerror({
|
|
83
|
+
data: JSON.stringify("404")
|
|
84
|
+
} as MessageEvent);
|
|
79
85
|
expect(app.stream_status.open).toBe(false);
|
|
80
86
|
});
|
|
81
87
|
});
|
|
@@ -3,18 +3,21 @@ import { describe, it, expect, afterEach, beforeAll, afterAll } from "vitest";
|
|
|
3
3
|
import { Client } from "..";
|
|
4
4
|
import { initialise_server } from "./server";
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
let server: Awaited<ReturnType<typeof initialise_server>>;
|
|
7
7
|
|
|
8
|
-
beforeAll(() =>
|
|
8
|
+
beforeAll(async () => {
|
|
9
|
+
server = await initialise_server();
|
|
10
|
+
await server.start({ quiet: true });
|
|
11
|
+
});
|
|
9
12
|
afterEach(() => server.resetHandlers());
|
|
10
|
-
afterAll(() => server.
|
|
13
|
+
afterAll(() => server.stop());
|
|
11
14
|
|
|
12
15
|
describe("upload_files", () => {
|
|
13
16
|
it("should upload files successfully", async () => {
|
|
14
17
|
const root_url = "https://hmb-hello-world.hf.space";
|
|
15
18
|
|
|
16
19
|
const client = await Client.connect("hmb/hello_world", {
|
|
17
|
-
|
|
20
|
+
token: "hf_token"
|
|
18
21
|
});
|
|
19
22
|
|
|
20
23
|
const files = [new Blob([], { type: "image/jpeg" })];
|
|
@@ -8,11 +8,14 @@ const app_reference = "hmb/hello_world";
|
|
|
8
8
|
const secret_app_reference = "hmb/secret_world";
|
|
9
9
|
const secret_direct_app_reference = "https://hmb-secret-world.hf.space";
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
let server: Awaited<ReturnType<typeof initialise_server>>;
|
|
12
12
|
|
|
13
|
-
beforeAll(() =>
|
|
13
|
+
beforeAll(async () => {
|
|
14
|
+
server = await initialise_server();
|
|
15
|
+
await server.start({ quiet: true });
|
|
16
|
+
});
|
|
14
17
|
afterEach(() => server.resetHandlers());
|
|
15
|
-
afterAll(() => server.
|
|
18
|
+
afterAll(() => server.stop());
|
|
16
19
|
|
|
17
20
|
describe("view_api", () => {
|
|
18
21
|
test("viewing the api of a running, public app", async () => {
|
package/src/types.ts
CHANGED
|
@@ -402,6 +402,9 @@ export interface Status {
|
|
|
402
402
|
changed_state_ids?: number[];
|
|
403
403
|
time_limit?: number;
|
|
404
404
|
session_not_found?: boolean;
|
|
405
|
+
used_cache?: "full" | "partial" | null;
|
|
406
|
+
cache_duration?: number;
|
|
407
|
+
avg_time?: number;
|
|
405
408
|
}
|
|
406
409
|
|
|
407
410
|
export interface StatusMessage extends Status {
|