@editframe/api 0.8.0-beta.5 → 0.8.0-beta.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.
Files changed (47) hide show
  1. package/dist/CHUNK_SIZE_BYTES.d.ts +1 -0
  2. package/dist/CHUNK_SIZE_BYTES.js +7 -0
  3. package/dist/client.d.ts +0 -2
  4. package/dist/client.js +2 -14
  5. package/dist/client.test.d.ts +1 -0
  6. package/dist/readableFromBuffers.d.ts +2 -0
  7. package/dist/resources/caption-file.d.ts +22 -3
  8. package/dist/resources/caption-file.js +28 -26
  9. package/dist/resources/caption-file.test.d.ts +1 -0
  10. package/dist/resources/image-file.d.ts +5 -3
  11. package/dist/resources/image-file.js +23 -27
  12. package/dist/resources/image-file.test.d.ts +1 -0
  13. package/dist/resources/isobmff-file.d.ts +2 -3
  14. package/dist/resources/isobmff-file.js +17 -23
  15. package/dist/resources/isobmff-file.test.d.ts +1 -0
  16. package/dist/resources/isobmff-track.d.ts +27 -28
  17. package/dist/resources/isobmff-track.js +18 -31
  18. package/dist/resources/isobmff-track.test.d.ts +1 -0
  19. package/dist/resources/renders.d.ts +4 -5
  20. package/dist/resources/renders.js +17 -21
  21. package/dist/resources/renders.test.d.ts +1 -0
  22. package/dist/resources/unprocessed-file.d.ts +14 -12
  23. package/dist/resources/unprocessed-file.js +36 -45
  24. package/dist/resources/unprocessed-file.test.d.ts +1 -0
  25. package/dist/resources/url-token.d.ts +0 -1
  26. package/dist/resources/url-token.test.d.ts +1 -0
  27. package/dist/streamChunker.d.ts +2 -0
  28. package/dist/streamChunker.js +17 -0
  29. package/dist/streamChunker.test.d.ts +1 -0
  30. package/dist/uploadChunks.d.ts +10 -0
  31. package/dist/uploadChunks.js +65 -0
  32. package/dist/uploadChunks.test.d.ts +1 -0
  33. package/package.json +4 -3
  34. package/src/resources/caption-file.test.ts +124 -0
  35. package/src/resources/caption-file.ts +49 -24
  36. package/src/resources/image-file.test.ts +138 -0
  37. package/src/resources/image-file.ts +28 -25
  38. package/src/resources/isobmff-file.test.ts +108 -0
  39. package/src/resources/isobmff-file.ts +19 -22
  40. package/src/resources/isobmff-track.test.ts +152 -0
  41. package/src/resources/isobmff-track.ts +22 -31
  42. package/src/resources/renders.test.ts +112 -0
  43. package/src/resources/renders.ts +19 -20
  44. package/src/resources/test-av-file.txt +1 -0
  45. package/src/resources/unprocessed-file.test.ts +312 -0
  46. package/src/resources/unprocessed-file.ts +41 -44
  47. package/src/resources/url-token.test.ts +46 -0
@@ -6,9 +6,12 @@ import debug from "debug";
6
6
  import { AudioStreamSchema, VideoStreamSchema } from "@editframe/assets";
7
7
 
8
8
  import type { Client } from "../client.ts";
9
+ import { uploadChunks } from "../uploadChunks.ts";
9
10
 
10
11
  const log = debug("ef:api:isobmff-track");
11
12
 
13
+ const MAX_TRACK_SIZE = 1024 * 1024 * 1024; // 1GB
14
+
12
15
  export const CreateISOBMFFTrackPayload = z.discriminatedUnion("type", [
13
16
  z.object({
14
17
  file_id: z.string(),
@@ -17,7 +20,7 @@ export const CreateISOBMFFTrackPayload = z.discriminatedUnion("type", [
17
20
  probe_info: AudioStreamSchema,
18
21
  duration_ms: z.number().int(),
19
22
  codec_name: z.string(),
20
- byte_size: z.number().int(),
23
+ byte_size: z.number().int().max(MAX_TRACK_SIZE),
21
24
  }),
22
25
  z.object({
23
26
  file_id: z.string(),
@@ -26,12 +29,12 @@ export const CreateISOBMFFTrackPayload = z.discriminatedUnion("type", [
26
29
  probe_info: VideoStreamSchema,
27
30
  duration_ms: z.number().int(),
28
31
  codec_name: z.string(),
29
- byte_size: z.number().int(),
32
+ byte_size: z.number().int().max(MAX_TRACK_SIZE),
30
33
  }),
31
34
  ]);
32
35
 
33
36
  export interface CreateISOBMFFTrackResult {
34
- last_received_byte: number;
37
+ next_byte: number;
35
38
  byte_size: number;
36
39
  track_id: number;
37
40
  file_id: string;
@@ -42,6 +45,7 @@ export const createISOBMFFTrack = async (
42
45
  payload: z.infer<typeof CreateISOBMFFTrackPayload>,
43
46
  ) => {
44
47
  log("Creating isobmff track", payload);
48
+ CreateISOBMFFTrackPayload.parse(payload);
45
49
  const response = await client.authenticatedFetch(
46
50
  "/api/video2/isobmff_tracks",
47
51
  {
@@ -51,16 +55,13 @@ export const createISOBMFFTrack = async (
51
55
  );
52
56
 
53
57
  log("ISOBMFF track created", response);
54
- switch (response.status) {
55
- case 200: {
56
- return (await response.json()) as CreateISOBMFFTrackResult;
57
- }
58
- default: {
59
- console.error("Failed to create track");
60
- console.error(await response.json());
61
- return;
62
- }
58
+ if (response.ok) {
59
+ return (await response.json()) as CreateISOBMFFTrackResult;
63
60
  }
61
+
62
+ throw new Error(
63
+ `Failed to create isobmff track ${response.status} ${response.statusText}`,
64
+ );
64
65
  };
65
66
 
66
67
  export const uploadISOBMFFTrack = async (
@@ -68,25 +69,15 @@ export const uploadISOBMFFTrack = async (
68
69
  fileId: string,
69
70
  trackId: number,
70
71
  fileStream: Readable,
72
+ trackSize: number,
71
73
  ) => {
72
- log("Uploading isobmff track", fileId, trackId);
73
- const trackIndex = await client.authenticatedFetch(
74
- `/api/video2/isobmff_tracks/${fileId}/${trackId}/upload`,
75
- {
76
- method: "POST",
77
- body: fileStream,
78
- },
79
- );
74
+ log("Uploading fragment track", fileId);
80
75
 
81
- log("ISOBMFF track uploaded", trackIndex);
82
- switch (trackIndex.status) {
83
- case 200: {
84
- return trackIndex.json();
85
- }
86
- default: {
87
- console.error("Failed to upload track");
88
- console.error(trackIndex.status, trackIndex.statusText);
89
- return;
90
- }
91
- }
76
+ await uploadChunks(client, {
77
+ url: `/api/video2/isobmff_tracks/${fileId}/${trackId}/upload`,
78
+ fileStream,
79
+ fileSize: trackSize,
80
+ });
81
+
82
+ log("Fragment track upload complete");
92
83
  };
@@ -0,0 +1,112 @@
1
+ import { test, expect, beforeAll, afterEach, afterAll, describe } from "vitest";
2
+ import { http, HttpResponse } from "msw";
3
+ import { setupServer } from "msw/node";
4
+
5
+ import { Client } from "../client.ts";
6
+ import { readableFromBuffers } from "../readableFromBuffers.ts";
7
+ import { createRender, uploadRender } from "./renders.ts";
8
+
9
+ const server = setupServer();
10
+ const client = new Client("ef_TEST_TOKEN", "http://localhost");
11
+
12
+ describe("Renders", () => {
13
+ beforeAll(() => server.listen());
14
+ afterEach(() => server.resetHandlers());
15
+ afterAll(() => server.close());
16
+
17
+ describe("createRender", () => {
18
+ test("throws if server returns an error", async () => {
19
+ server.use(
20
+ http.post("http://localhost/api/video2/renders", () =>
21
+ HttpResponse.text("Internal Server Error", { status: 500 }),
22
+ ),
23
+ );
24
+
25
+ await expect(
26
+ createRender(client, createTestRender()),
27
+ ).rejects.toThrowError(
28
+ "Failed to create render 500 Internal Server Error",
29
+ );
30
+ });
31
+
32
+ test("returns json data from the http response", async () => {
33
+ server.use(
34
+ http.post("http://localhost/api/video2/renders", () =>
35
+ HttpResponse.json(
36
+ { testResponse: "test" },
37
+ { status: 200, statusText: "OK" },
38
+ ),
39
+ ),
40
+ );
41
+
42
+ const response = await createRender(client, createTestRender());
43
+
44
+ expect(response).toEqual({ testResponse: "test" });
45
+ });
46
+ });
47
+
48
+ describe("uploadRender", () => {
49
+ test("throws if file size exceeds limit", async () => {
50
+ await expect(
51
+ uploadRender(
52
+ client,
53
+ "test-id",
54
+ readableFromBuffers(Buffer.from("test")),
55
+ 1024 * 1024 * 17,
56
+ ),
57
+ ).rejects.toThrowError(
58
+ new Error("File size exceeds limit of 16777216 bytes"),
59
+ );
60
+ });
61
+
62
+ test("throws if server returns an error", async () => {
63
+ server.use(
64
+ http.post("http://localhost/api/video2/renders/test-id/upload", () =>
65
+ HttpResponse.text("Internal Server Error", { status: 500 }),
66
+ ),
67
+ );
68
+
69
+ await expect(
70
+ uploadRender(
71
+ client,
72
+ "test-id",
73
+ readableFromBuffers(Buffer.from("test")),
74
+ 1024 * 1024 * 2,
75
+ ),
76
+ ).rejects.toThrowError(
77
+ "Failed to upload render 500 Internal Server Error",
78
+ );
79
+ });
80
+
81
+ test("returns json data from the http response", async () => {
82
+ server.use(
83
+ http.post("http://localhost/api/video2/renders/test-id/upload", () =>
84
+ HttpResponse.json(
85
+ { testResponse: "test" },
86
+ { status: 200, statusText: "OK" },
87
+ ),
88
+ ),
89
+ );
90
+
91
+ const response = await uploadRender(
92
+ client,
93
+ "test-id",
94
+ readableFromBuffers(Buffer.from("test")),
95
+ 1024 * 1024 * 2,
96
+ );
97
+
98
+ expect(response).toEqual({ testResponse: "test" });
99
+ });
100
+ });
101
+ });
102
+
103
+ const createTestRender = () =>
104
+ ({
105
+ id: "test-id",
106
+ fps: 30,
107
+ width: 1920,
108
+ height: 1080,
109
+ work_slice_ms: 100,
110
+ duration_ms: 1000,
111
+ strategy: "v1",
112
+ }) as const;
@@ -6,6 +6,7 @@ import debug from "debug";
6
6
  import type { Client } from "../client.ts";
7
7
 
8
8
  const log = debug("ef:api:renders");
9
+ const FILE_SIZE_LIMIT = 1024 * 1024 * 16; // 16MiB
9
10
 
10
11
  export const CreateRenderPayload = z.object({
11
12
  id: z.string().uuid(),
@@ -33,25 +34,27 @@ export const createRender = async (
33
34
  });
34
35
 
35
36
  log("Render created", response);
36
- switch (response.status) {
37
- case 200: {
38
- return (await response.json()) as CreateRenderResult;
39
- }
40
- default: {
41
- console.error("Failed to create render");
42
- console.error(await response.json());
43
- return;
44
- }
37
+ if (response.ok) {
38
+ return (await response.json()) as CreateRenderResult;
45
39
  }
40
+
41
+ throw new Error(
42
+ `Failed to create render ${response.status} ${response.statusText}`,
43
+ );
46
44
  };
47
45
 
48
46
  export const uploadRender = async (
49
47
  client: Client,
50
48
  fileId: string,
51
49
  fileStream: Readable,
50
+ folderSize: number,
52
51
  ) => {
53
52
  log("Uploading render", fileId);
54
- const fileIndex = await client.authenticatedFetch(
53
+ log("Folder size", folderSize, "bytes");
54
+ if (folderSize > FILE_SIZE_LIMIT) {
55
+ throw new Error(`File size exceeds limit of ${FILE_SIZE_LIMIT} bytes`);
56
+ }
57
+ const response = await client.authenticatedFetch(
55
58
  `/api/video2/renders/${fileId}/upload`,
56
59
  {
57
60
  method: "POST",
@@ -59,15 +62,11 @@ export const uploadRender = async (
59
62
  },
60
63
  );
61
64
 
62
- log("Render uploaded", fileIndex);
63
- switch (fileIndex.status) {
64
- case 200: {
65
- return fileIndex.json();
66
- }
67
- default: {
68
- console.error("Failed to upload render");
69
- console.error(fileIndex.status, fileIndex.statusText);
70
- return;
71
- }
65
+ if (response.ok) {
66
+ return response.json();
72
67
  }
68
+
69
+ throw new Error(
70
+ `Failed to upload render ${response.status} ${response.statusText}`,
71
+ );
73
72
  };
@@ -0,0 +1 @@
1
+ test
@@ -0,0 +1,312 @@
1
+ import { join } from "node:path";
2
+
3
+ import { test, expect, beforeAll, afterEach, afterAll, describe } from "vitest";
4
+ import { http, HttpResponse } from "msw";
5
+ import { setupServer } from "msw/node";
6
+ import { ZodError } from "zod";
7
+
8
+ import { Client } from "../client.ts";
9
+ import {
10
+ createUnprocessedFile,
11
+ processAVFile,
12
+ processAVFileBuffer,
13
+ updateUnprocessedFile,
14
+ uploadUnprocessedFile,
15
+ } from "./unprocessed-file.ts";
16
+ import { readableFromBuffers } from "../readableFromBuffers.ts";
17
+
18
+ const server = setupServer();
19
+ const client = new Client("ef_TEST_TOKEN", "http://localhost");
20
+
21
+ const TEST_AV_FILE = join(__dirname, "test-av-file.txt");
22
+
23
+ describe("Unprocessed File", () => {
24
+ beforeAll(() => server.listen());
25
+ afterEach(() => server.resetHandlers());
26
+ afterAll(() => server.close());
27
+
28
+ describe("createUnprocessedFile", () => {
29
+ test("Throws when file is too large", async () => {
30
+ await expect(
31
+ createUnprocessedFile(client, {
32
+ id: "test-file",
33
+ filename: "test-file",
34
+ processes: [],
35
+ byte_size: 1024 * 1024 * 1025,
36
+ }),
37
+ ).rejects.toThrowError(
38
+ new ZodError([
39
+ {
40
+ code: "too_big",
41
+ maximum: 1073741824,
42
+ type: "number",
43
+ inclusive: true,
44
+ exact: false,
45
+ message: "Number must be less than or equal to 1073741824",
46
+ path: ["byte_size"],
47
+ },
48
+ ]),
49
+ );
50
+ });
51
+
52
+ test("Throws when server returns an error", async () => {
53
+ server.use(
54
+ http.post("http://localhost/api/v1/unprocessed_files", () =>
55
+ HttpResponse.text("Internal Server Error", { status: 500 }),
56
+ ),
57
+ );
58
+
59
+ await expect(
60
+ createUnprocessedFile(client, {
61
+ id: "test-file",
62
+ filename: "test-file",
63
+ processes: [],
64
+ byte_size: 1024 * 1024,
65
+ }),
66
+ ).rejects.toThrowError(
67
+ "Failed to create unprocessed file 500 Internal Server Error",
68
+ );
69
+ });
70
+
71
+ test("Returns json data from the http response", async () => {
72
+ server.use(
73
+ http.post("http://localhost/api/v1/unprocessed_files", () =>
74
+ HttpResponse.json(
75
+ { testResponse: "test" },
76
+ { status: 200, statusText: "OK" },
77
+ ),
78
+ ),
79
+ );
80
+
81
+ const result = await createUnprocessedFile(client, {
82
+ id: "test-file",
83
+ filename: "test-file",
84
+ processes: [],
85
+ byte_size: 1024 * 1024,
86
+ });
87
+
88
+ expect(result).toEqual({ testResponse: "test" });
89
+ });
90
+ });
91
+
92
+ describe("updateUnprocessedFile", () => {
93
+ test("Throws when server responds with an error", async () => {
94
+ server.use(
95
+ http.post("http://localhost/api/v1/unprocessed_files/test-file", () =>
96
+ HttpResponse.text("Internal Server Error", { status: 500 }),
97
+ ),
98
+ );
99
+
100
+ await expect(
101
+ updateUnprocessedFile(client, "test-file", {
102
+ processes: [],
103
+ }),
104
+ ).rejects.toThrowError(
105
+ "Failed to update unprocessed file 500 Internal Server Error",
106
+ );
107
+ });
108
+
109
+ test("Returns json data from the http response", async () => {
110
+ server.use(
111
+ http.post("http://localhost/api/v1/unprocessed_files/test-file", () =>
112
+ HttpResponse.json(
113
+ { testResponse: "test" },
114
+ { status: 200, statusText: "OK" },
115
+ ),
116
+ ),
117
+ );
118
+
119
+ const result = await updateUnprocessedFile(client, "test-file", {
120
+ processes: [],
121
+ });
122
+
123
+ expect(result).toEqual({ testResponse: "test" });
124
+ });
125
+ });
126
+
127
+ describe("uploadUnprocessedFile", () => {
128
+ test("Throws when server responds with an error", async () => {
129
+ server.use(
130
+ http.post(
131
+ "http://localhost/api/v1/unprocessed_files/test-file/upload",
132
+ () => HttpResponse.text("Internal Server Error", { status: 500 }),
133
+ ),
134
+ );
135
+
136
+ await expect(
137
+ uploadUnprocessedFile(
138
+ client,
139
+ "test-file",
140
+ readableFromBuffers(Buffer.from("test")),
141
+ 4,
142
+ ),
143
+ ).rejects.toThrowError(
144
+ "Failed to upload chunk 0 for /api/v1/unprocessed_files/test-file/upload 500 Internal Server Error",
145
+ );
146
+ });
147
+
148
+ test("Succeeds when server returns a success", async () => {
149
+ server.use(
150
+ http.post(
151
+ "http://localhost/api/v1/unprocessed_files/test-file/upload",
152
+ () => HttpResponse.json({}, { status: 201 }),
153
+ ),
154
+ );
155
+
156
+ await expect(
157
+ uploadUnprocessedFile(
158
+ client,
159
+ "test-file",
160
+ readableFromBuffers(Buffer.from("test")),
161
+ 4,
162
+ ),
163
+ ).resolves.toBeUndefined();
164
+ });
165
+ });
166
+
167
+ describe("processAVFileBuffer", () => {
168
+ test("Throws when server responds with an error when creating file", async () => {
169
+ server.use(
170
+ http.post("http://localhost/api/v1/unprocessed_files", () =>
171
+ HttpResponse.text("Internal Server Error", { status: 500 }),
172
+ ),
173
+ );
174
+
175
+ await expect(
176
+ processAVFileBuffer(client, Buffer.from("test"), "test-file"),
177
+ ).rejects.toThrowError(
178
+ "Failed to create unprocessed file 500 Internal Server Error",
179
+ );
180
+ });
181
+
182
+ test("Throws when server responds with an error when uploading file", async () => {
183
+ server.use(
184
+ http.post("http://localhost/api/v1/unprocessed_files", () =>
185
+ HttpResponse.json({}, { status: 200 }),
186
+ ),
187
+ http.post(
188
+ "http://localhost/api/v1/unprocessed_files/098f6bcd-4621-d373-cade-4e832627b4f6/upload",
189
+ () => HttpResponse.text("Internal Server Error", { status: 500 }),
190
+ ),
191
+ );
192
+
193
+ await expect(
194
+ processAVFileBuffer(client, Buffer.from("test"), "test-file"),
195
+ ).rejects.toThrowError(
196
+ "Failed to upload chunk 0 for /api/v1/unprocessed_files/098f6bcd-4621-d373-cade-4e832627b4f6/upload 500 Internal Server Error",
197
+ );
198
+ });
199
+
200
+ test("Throws when server responds with an error when updating file", async () => {
201
+ server.use(
202
+ http.post("http://localhost/api/v1/unprocessed_files", () =>
203
+ HttpResponse.json({}, { status: 200 }),
204
+ ),
205
+ http.post(
206
+ "http://localhost/api/v1/unprocessed_files/098f6bcd-4621-d373-cade-4e832627b4f6/upload",
207
+ () => HttpResponse.json({ test }, { status: 201 }),
208
+ ),
209
+ http.post(
210
+ "http://localhost/api/v1/unprocessed_files/098f6bcd-4621-d373-cade-4e832627b4f6",
211
+ () => HttpResponse.text("Internal Server Error", { status: 500 }),
212
+ ),
213
+ );
214
+
215
+ await expect(
216
+ processAVFileBuffer(client, Buffer.from("test"), "test-file"),
217
+ ).rejects.toThrowError(
218
+ "Failed to update unprocessed file 500 Internal Server Error",
219
+ );
220
+ });
221
+
222
+ test("Returns json data when upload is successful", async () => {
223
+ server.use(
224
+ http.post("http://localhost/api/v1/unprocessed_files", () =>
225
+ HttpResponse.json({}, { status: 200 }),
226
+ ),
227
+ http.post(
228
+ "http://localhost/api/v1/unprocessed_files/098f6bcd-4621-d373-cade-4e832627b4f6/upload",
229
+ () => HttpResponse.json({}, { status: 201 }),
230
+ ),
231
+ http.post(
232
+ "http://localhost/api/v1/unprocessed_files/098f6bcd-4621-d373-cade-4e832627b4f6",
233
+ () => HttpResponse.json({ test: "response" }, { status: 200 }),
234
+ ),
235
+ );
236
+
237
+ await expect(
238
+ processAVFileBuffer(client, Buffer.from("test"), "test-file"),
239
+ ).resolves.toEqual({ test: "response" });
240
+ });
241
+ });
242
+
243
+ describe("processAVFile", () => {
244
+ test("Throws when server responds with an error when creating file", async () => {
245
+ server.use(
246
+ http.post("http://localhost/api/v1/unprocessed_files", () =>
247
+ HttpResponse.text("Internal Server Error", { status: 500 }),
248
+ ),
249
+ );
250
+
251
+ await expect(processAVFile(client, TEST_AV_FILE)).rejects.toThrowError(
252
+ "Failed to create unprocessed file 500 Internal Server Error",
253
+ );
254
+ });
255
+
256
+ test("Throws when server responds with an error when uploading file", async () => {
257
+ server.use(
258
+ http.post("http://localhost/api/v1/unprocessed_files", () =>
259
+ HttpResponse.json({}, { status: 200 }),
260
+ ),
261
+ http.post(
262
+ "http://localhost/api/v1/unprocessed_files/098f6bcd-4621-d373-cade-4e832627b4f6/upload",
263
+ () => HttpResponse.text("Internal Server Error", { status: 500 }),
264
+ ),
265
+ );
266
+
267
+ await expect(processAVFile(client, TEST_AV_FILE)).rejects.toThrowError(
268
+ "Failed to upload chunk 0 for /api/v1/unprocessed_files/098f6bcd-4621-d373-cade-4e832627b4f6/upload 500 Internal Server Error",
269
+ );
270
+ });
271
+
272
+ test("Throws when server responds with an error when updating file", async () => {
273
+ server.use(
274
+ http.post("http://localhost/api/v1/unprocessed_files", () =>
275
+ HttpResponse.json({}, { status: 200 }),
276
+ ),
277
+ http.post(
278
+ "http://localhost/api/v1/unprocessed_files/098f6bcd-4621-d373-cade-4e832627b4f6/upload",
279
+ () => HttpResponse.json({ test }, { status: 201 }),
280
+ ),
281
+ http.post(
282
+ "http://localhost/api/v1/unprocessed_files/098f6bcd-4621-d373-cade-4e832627b4f6",
283
+ () => HttpResponse.text("Internal Server Error", { status: 500 }),
284
+ ),
285
+ );
286
+
287
+ await expect(processAVFile(client, TEST_AV_FILE)).rejects.toThrowError(
288
+ "Failed to update unprocessed file 500 Internal Server Error",
289
+ );
290
+ });
291
+
292
+ test("Returns json data when upload is successful", async () => {
293
+ server.use(
294
+ http.post("http://localhost/api/v1/unprocessed_files", () =>
295
+ HttpResponse.json({}, { status: 200 }),
296
+ ),
297
+ http.post(
298
+ "http://localhost/api/v1/unprocessed_files/098f6bcd-4621-d373-cade-4e832627b4f6/upload",
299
+ () => HttpResponse.json({}, { status: 201 }),
300
+ ),
301
+ http.post(
302
+ "http://localhost/api/v1/unprocessed_files/098f6bcd-4621-d373-cade-4e832627b4f6",
303
+ () => HttpResponse.json({ test: "response" }, { status: 200 }),
304
+ ),
305
+ );
306
+
307
+ await expect(processAVFile(client, TEST_AV_FILE)).resolves.toEqual({
308
+ test: "response",
309
+ });
310
+ });
311
+ });
312
+ });