@aj-archipelago/cortex 1.3.57 → 1.3.59

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/README.md +6 -0
  2. package/config.js +22 -0
  3. package/helper-apps/cortex-file-handler/INTERFACE.md +20 -9
  4. package/helper-apps/cortex-file-handler/package-lock.json +2 -2
  5. package/helper-apps/cortex-file-handler/package.json +1 -1
  6. package/helper-apps/cortex-file-handler/scripts/setup-azure-container.js +17 -17
  7. package/helper-apps/cortex-file-handler/scripts/setup-test-containers.js +35 -35
  8. package/helper-apps/cortex-file-handler/src/blobHandler.js +1010 -909
  9. package/helper-apps/cortex-file-handler/src/constants.js +98 -98
  10. package/helper-apps/cortex-file-handler/src/docHelper.js +27 -27
  11. package/helper-apps/cortex-file-handler/src/fileChunker.js +224 -214
  12. package/helper-apps/cortex-file-handler/src/helper.js +93 -93
  13. package/helper-apps/cortex-file-handler/src/index.js +584 -550
  14. package/helper-apps/cortex-file-handler/src/localFileHandler.js +86 -86
  15. package/helper-apps/cortex-file-handler/src/redis.js +186 -90
  16. package/helper-apps/cortex-file-handler/src/services/ConversionService.js +301 -273
  17. package/helper-apps/cortex-file-handler/src/services/FileConversionService.js +55 -55
  18. package/helper-apps/cortex-file-handler/src/services/storage/AzureStorageProvider.js +174 -154
  19. package/helper-apps/cortex-file-handler/src/services/storage/GCSStorageProvider.js +239 -223
  20. package/helper-apps/cortex-file-handler/src/services/storage/LocalStorageProvider.js +161 -159
  21. package/helper-apps/cortex-file-handler/src/services/storage/StorageFactory.js +73 -71
  22. package/helper-apps/cortex-file-handler/src/services/storage/StorageProvider.js +46 -45
  23. package/helper-apps/cortex-file-handler/src/services/storage/StorageService.js +256 -213
  24. package/helper-apps/cortex-file-handler/src/start.js +4 -1
  25. package/helper-apps/cortex-file-handler/src/utils/filenameUtils.js +59 -25
  26. package/helper-apps/cortex-file-handler/tests/FileConversionService.test.js +119 -116
  27. package/helper-apps/cortex-file-handler/tests/blobHandler.test.js +257 -257
  28. package/helper-apps/cortex-file-handler/tests/cleanup.test.js +676 -0
  29. package/helper-apps/cortex-file-handler/tests/conversionResilience.test.js +124 -124
  30. package/helper-apps/cortex-file-handler/tests/fileChunker.test.js +249 -208
  31. package/helper-apps/cortex-file-handler/tests/fileUpload.test.js +439 -380
  32. package/helper-apps/cortex-file-handler/tests/getOperations.test.js +299 -263
  33. package/helper-apps/cortex-file-handler/tests/postOperations.test.js +265 -239
  34. package/helper-apps/cortex-file-handler/tests/start.test.js +1230 -1201
  35. package/helper-apps/cortex-file-handler/tests/storage/AzureStorageProvider.test.js +110 -105
  36. package/helper-apps/cortex-file-handler/tests/storage/GCSStorageProvider.test.js +201 -175
  37. package/helper-apps/cortex-file-handler/tests/storage/LocalStorageProvider.test.js +128 -125
  38. package/helper-apps/cortex-file-handler/tests/storage/StorageFactory.test.js +78 -73
  39. package/helper-apps/cortex-file-handler/tests/storage/StorageService.test.js +99 -99
  40. package/helper-apps/cortex-file-handler/tests/testUtils.helper.js +74 -70
  41. package/package.json +1 -1
  42. package/pathways/translate_apptek.js +33 -0
  43. package/pathways/translate_subtitle.js +15 -8
  44. package/server/plugins/apptekTranslatePlugin.js +46 -91
  45. package/tests/apptekTranslatePlugin.test.js +0 -2
  46. package/tests/integration/apptekTranslatePlugin.integration.test.js +159 -93
  47. package/tests/translate_apptek.test.js +16 -0
@@ -1,12 +1,15 @@
1
- import test from 'ava';
2
- import fs from 'fs';
3
- import path from 'path';
4
- import { fileURLToPath } from 'url';
5
- import { v4 as uuidv4 } from 'uuid';
6
- import axios from 'axios';
7
- import FormData from 'form-data';
8
- import { port } from '../src/start.js';
9
- import { cleanupHashAndFile, getFolderNameFromUrl } from './testUtils.helper.js';
1
+ import test from "ava";
2
+ import fs from "fs";
3
+ import path from "path";
4
+ import { fileURLToPath } from "url";
5
+ import { v4 as uuidv4 } from "uuid";
6
+ import axios from "axios";
7
+ import FormData from "form-data";
8
+ import { port } from "../src/start.js";
9
+ import {
10
+ cleanupHashAndFile,
11
+ getFolderNameFromUrl,
12
+ } from "./testUtils.helper.js";
10
13
 
11
14
  const __filename = fileURLToPath(import.meta.url);
12
15
  const __dirname = path.dirname(__filename);
@@ -14,278 +17,301 @@ const baseUrl = `http://localhost:${port}/api/CortexFileHandler`;
14
17
 
15
18
  // Helper function to determine if GCS is configured
16
19
  function isGCSConfigured() {
17
- return (
18
- process.env.GCP_SERVICE_ACCOUNT_KEY_BASE64 ||
19
- process.env.GCP_SERVICE_ACCOUNT_KEY
20
- );
20
+ return (
21
+ process.env.GCP_SERVICE_ACCOUNT_KEY_BASE64 ||
22
+ process.env.GCP_SERVICE_ACCOUNT_KEY
23
+ );
21
24
  }
22
25
 
23
26
  // Helper function to create test files
24
27
  async function createTestFile(content, extension) {
25
- const testDir = path.join(__dirname, 'test-files');
26
- if (!fs.existsSync(testDir)) {
27
- fs.mkdirSync(testDir, { recursive: true });
28
- }
29
- const filename = path.join(testDir, `${uuidv4()}.${extension}`);
30
- fs.writeFileSync(filename, content);
31
- return filename;
28
+ const testDir = path.join(__dirname, "test-files");
29
+ if (!fs.existsSync(testDir)) {
30
+ fs.mkdirSync(testDir, { recursive: true });
31
+ }
32
+ const filename = path.join(testDir, `${uuidv4()}.${extension}`);
33
+ fs.writeFileSync(filename, content);
34
+ return filename;
32
35
  }
33
36
 
34
37
  // Helper function to upload file
35
38
  async function uploadFile(filePath, requestId = null, hash = null) {
36
- const form = new FormData();
37
- form.append('file', fs.createReadStream(filePath));
38
- if (requestId) form.append('requestId', requestId);
39
- if (hash) form.append('hash', hash);
40
-
41
- const response = await axios.post(baseUrl, form, {
42
- headers: {
43
- ...form.getHeaders(),
44
- 'Content-Type': 'multipart/form-data',
45
- },
46
- validateStatus: (status) => true,
47
- timeout: 30000,
48
- maxContentLength: Infinity,
49
- maxBodyLength: Infinity,
50
- });
39
+ const form = new FormData();
40
+ form.append("file", fs.createReadStream(filePath));
41
+ if (requestId) form.append("requestId", requestId);
42
+ if (hash) form.append("hash", hash);
51
43
 
52
- return response;
44
+ const response = await axios.post(baseUrl, form, {
45
+ headers: {
46
+ ...form.getHeaders(),
47
+ "Content-Type": "multipart/form-data",
48
+ },
49
+ validateStatus: (status) => true,
50
+ timeout: 30000,
51
+ maxContentLength: Infinity,
52
+ maxBodyLength: Infinity,
53
+ });
54
+
55
+ return response;
53
56
  }
54
57
 
55
58
  // Setup: Create test directory
56
59
  test.before(async (t) => {
57
- const testDir = path.join(__dirname, 'test-files');
58
- await fs.promises.mkdir(testDir, { recursive: true });
59
- t.context = { testDir };
60
+ const testDir = path.join(__dirname, "test-files");
61
+ await fs.promises.mkdir(testDir, { recursive: true });
62
+ t.context = { testDir };
60
63
  });
61
64
 
62
65
  // Test: Upload with hash and verify Redis storage
63
- test.serial('should store file metadata in Redis with hash', async (t) => {
64
- const fileContent = 'test content';
65
- const filePath = await createTestFile(fileContent, 'txt');
66
- const requestId = uuidv4();
67
- const hash = 'test-hash-' + uuidv4();
68
- let response;
69
-
70
- try {
71
- response = await uploadFile(filePath, requestId, hash);
72
- t.is(response.status, 200, 'Upload should succeed');
73
- t.truthy(response.data.url, 'Should have file URL');
74
- t.is(response.data.hash, hash, 'Should return correct hash');
75
-
76
- // Wait for Redis operations to complete
77
- await new Promise(resolve => setTimeout(resolve, 1000));
78
-
79
- // Verify hash exists in Redis
80
- const checkResponse = await axios.get(baseUrl, {
81
- params: {
82
- hash,
83
- checkHash: true,
84
- },
85
- validateStatus: (status) => true,
86
- });
87
-
88
- t.is(checkResponse.status, 200, 'Hash should exist in Redis');
89
- t.truthy(checkResponse.data.url, 'Hash check should return URL');
90
- t.is(checkResponse.data.url, response.data.url, 'Hash check should return correct URL');
91
- } finally {
92
- fs.unlinkSync(filePath);
93
- if (response?.data?.url) {
94
- await cleanupHashAndFile(hash, response.data.url, baseUrl);
95
- }
66
+ test.serial("should store file metadata in Redis with hash", async (t) => {
67
+ const fileContent = "test content";
68
+ const filePath = await createTestFile(fileContent, "txt");
69
+ const requestId = uuidv4();
70
+ const hash = "test-hash-" + uuidv4();
71
+ let response;
72
+
73
+ try {
74
+ response = await uploadFile(filePath, requestId, hash);
75
+ t.is(response.status, 200, "Upload should succeed");
76
+ t.truthy(response.data.url, "Should have file URL");
77
+ t.is(response.data.hash, hash, "Should return correct hash");
78
+
79
+ // Wait for Redis operations to complete
80
+ await new Promise((resolve) => setTimeout(resolve, 1000));
81
+
82
+ // Verify hash exists in Redis
83
+ const checkResponse = await axios.get(baseUrl, {
84
+ params: {
85
+ hash,
86
+ checkHash: true,
87
+ },
88
+ validateStatus: (status) => true,
89
+ });
90
+
91
+ t.is(checkResponse.status, 200, "Hash should exist in Redis");
92
+ t.truthy(checkResponse.data.url, "Hash check should return URL");
93
+ t.is(
94
+ checkResponse.data.url,
95
+ response.data.url,
96
+ "Hash check should return correct URL",
97
+ );
98
+ } finally {
99
+ fs.unlinkSync(filePath);
100
+ if (response?.data?.url) {
101
+ await cleanupHashAndFile(hash, response.data.url, baseUrl);
96
102
  }
103
+ }
97
104
  });
98
105
 
99
106
  // Test: Upload with GCS backup verification
100
- test.serial('should create GCS backup when configured', async (t) => {
101
- if (!isGCSConfigured()) {
102
- t.pass('Skipping test - GCS not configured');
103
- return;
104
- }
107
+ test.serial("should create GCS backup when configured", async (t) => {
108
+ if (!isGCSConfigured()) {
109
+ t.pass("Skipping test - GCS not configured");
110
+ return;
111
+ }
112
+
113
+ const fileContent = "test content";
114
+ const filePath = await createTestFile(fileContent, "txt");
115
+ const requestId = uuidv4();
116
+ let response;
105
117
 
106
- const fileContent = 'test content';
107
- const filePath = await createTestFile(fileContent, 'txt');
108
- const requestId = uuidv4();
109
- let response;
110
-
111
- try {
112
- response = await uploadFile(filePath, requestId);
113
- t.is(response.status, 200, 'Upload should succeed');
114
- t.truthy(response.data.url, 'Should have primary storage URL');
115
- t.truthy(response.data.gcs, 'Should have GCS backup URL');
116
- t.true(response.data.gcs.startsWith('gs://'), 'GCS URL should use gs:// protocol');
117
-
118
- // Verify file exists in both storages
119
- const primaryResponse = await axios.get(response.data.url);
120
- t.is(primaryResponse.status, 200, 'Primary file should be accessible');
121
- t.is(primaryResponse.data, fileContent, 'Primary file content should match');
122
-
123
- // GCS file should be accessible through the primary URL
124
- // since we can't directly access gs:// URLs
125
- const gcsResponse = await axios.get(response.data.url);
126
- t.is(gcsResponse.status, 200, 'GCS file should be accessible');
127
- t.is(gcsResponse.data, fileContent, 'GCS file content should match');
128
- } finally {
129
- fs.unlinkSync(filePath);
130
- if (response?.data?.url) {
131
- await cleanupHashAndFile(null, response.data.url, baseUrl);
132
- }
118
+ try {
119
+ response = await uploadFile(filePath, requestId);
120
+ t.is(response.status, 200, "Upload should succeed");
121
+ t.truthy(response.data.url, "Should have primary storage URL");
122
+ t.truthy(response.data.gcs, "Should have GCS backup URL");
123
+ t.true(
124
+ response.data.gcs.startsWith("gs://"),
125
+ "GCS URL should use gs:// protocol",
126
+ );
127
+
128
+ // Verify file exists in both storages
129
+ const primaryResponse = await axios.get(response.data.url);
130
+ t.is(primaryResponse.status, 200, "Primary file should be accessible");
131
+ t.is(
132
+ primaryResponse.data,
133
+ fileContent,
134
+ "Primary file content should match",
135
+ );
136
+
137
+ // GCS file should be accessible through the primary URL
138
+ // since we can't directly access gs:// URLs
139
+ const gcsResponse = await axios.get(response.data.url);
140
+ t.is(gcsResponse.status, 200, "GCS file should be accessible");
141
+ t.is(gcsResponse.data, fileContent, "GCS file content should match");
142
+ } finally {
143
+ fs.unlinkSync(filePath);
144
+ if (response?.data?.url) {
145
+ await cleanupHashAndFile(null, response.data.url, baseUrl);
133
146
  }
147
+ }
134
148
  });
135
149
 
136
150
  // Test: Upload with large file
137
- test.serial('should handle large file upload', async (t) => {
138
- const largeContent = 'x'.repeat(10 * 1024 * 1024); // 10MB
139
- const filePath = await createTestFile(largeContent, 'txt');
140
- const requestId = uuidv4();
141
- let response;
142
-
143
- try {
144
- response = await uploadFile(filePath, requestId);
145
- t.is(response.status, 200, 'Large file upload should succeed');
146
- t.truthy(response.data.url, 'Should have file URL');
147
-
148
- // Verify file content
149
- const fileResponse = await axios.get(response.data.url);
150
- t.is(fileResponse.status, 200, 'File should be accessible');
151
- t.is(fileResponse.data.length, largeContent.length, 'File size should match');
152
- } finally {
153
- fs.unlinkSync(filePath);
154
- if (response?.data?.url) {
155
- await cleanupHashAndFile(null, response.data.url, baseUrl);
156
- }
151
+ test.serial("should handle large file upload", async (t) => {
152
+ const largeContent = "x".repeat(10 * 1024 * 1024); // 10MB
153
+ const filePath = await createTestFile(largeContent, "txt");
154
+ const requestId = uuidv4();
155
+ let response;
156
+
157
+ try {
158
+ response = await uploadFile(filePath, requestId);
159
+ t.is(response.status, 200, "Large file upload should succeed");
160
+ t.truthy(response.data.url, "Should have file URL");
161
+
162
+ // Verify file content
163
+ const fileResponse = await axios.get(response.data.url);
164
+ t.is(fileResponse.status, 200, "File should be accessible");
165
+ t.is(
166
+ fileResponse.data.length,
167
+ largeContent.length,
168
+ "File size should match",
169
+ );
170
+ } finally {
171
+ fs.unlinkSync(filePath);
172
+ if (response?.data?.url) {
173
+ await cleanupHashAndFile(null, response.data.url, baseUrl);
157
174
  }
175
+ }
158
176
  });
159
177
 
160
178
  // Test: Upload with special characters in filename
161
- test('should handle special characters in filename', async (t) => {
162
- const fileContent = 'test content';
163
- const specialFilename = `test file with spaces and special chars !@#$%^&*()_+-=[]{}|;:,.<>?${uuidv4()}.txt`;
164
- const filePath = await createTestFile(fileContent, specialFilename);
165
- const requestId = uuidv4();
166
- let response;
167
-
168
- try {
169
- response = await uploadFile(filePath, requestId);
170
- t.is(response.status, 200, 'Upload should succeed');
171
- t.truthy(response.data.url, 'Should have file URL');
172
- t.truthy(response.data.filename, 'Should have filename in response');
173
-
174
- // Verify file is accessible
175
- const fileResponse = await axios.get(response.data.url);
176
- t.is(fileResponse.status, 200, 'File should be accessible');
177
- t.is(fileResponse.data, fileContent, 'File content should match');
178
- } finally {
179
- fs.unlinkSync(filePath);
180
- if (response?.data?.url) {
181
- await cleanupHashAndFile(null, response.data.url, baseUrl);
182
- }
179
+ test("should handle special characters in filename", async (t) => {
180
+ const fileContent = "test content";
181
+ const specialFilename = `test file with spaces and special chars !@#$%^&*()_+-=[]{}|;:,.<>?${uuidv4()}.txt`;
182
+ const filePath = await createTestFile(fileContent, specialFilename);
183
+ const requestId = uuidv4();
184
+ let response;
185
+
186
+ try {
187
+ response = await uploadFile(filePath, requestId);
188
+ t.is(response.status, 200, "Upload should succeed");
189
+ t.truthy(response.data.url, "Should have file URL");
190
+ t.truthy(response.data.filename, "Should have filename in response");
191
+
192
+ // Verify file is accessible
193
+ const fileResponse = await axios.get(response.data.url);
194
+ t.is(fileResponse.status, 200, "File should be accessible");
195
+ t.is(fileResponse.data, fileContent, "File content should match");
196
+ } finally {
197
+ fs.unlinkSync(filePath);
198
+ if (response?.data?.url) {
199
+ await cleanupHashAndFile(null, response.data.url, baseUrl);
183
200
  }
201
+ }
184
202
  });
185
203
 
186
204
  // Test: Upload with concurrent requests
187
- test.serial('should handle concurrent uploads', async (t) => {
188
- const requestId = uuidv4();
189
- const uploads = [];
190
- const numUploads = 5;
191
- let responses = []; // Move declaration outside try block
192
-
193
- // Create and upload multiple files concurrently
194
- for (let i = 0; i < numUploads; i++) {
195
- const fileContent = `test content ${i}`;
196
- const filePath = await createTestFile(fileContent, 'txt');
197
- uploads.push({
198
- filePath,
199
- promise: uploadFile(filePath, requestId)
200
- });
205
+ test.serial("should handle concurrent uploads", async (t) => {
206
+ const requestId = uuidv4();
207
+ const uploads = [];
208
+ const numUploads = 5;
209
+ let responses = []; // Move declaration outside try block
210
+
211
+ // Create and upload multiple files concurrently
212
+ for (let i = 0; i < numUploads; i++) {
213
+ const fileContent = `test content ${i}`;
214
+ const filePath = await createTestFile(fileContent, "txt");
215
+ uploads.push({
216
+ filePath,
217
+ promise: uploadFile(filePath, requestId),
218
+ });
219
+ }
220
+
221
+ try {
222
+ // Wait for all uploads to complete
223
+ responses = await Promise.all(uploads.map((u) => u.promise));
224
+
225
+ // Verify all uploads succeeded
226
+ responses.forEach((response, i) => {
227
+ t.is(response.status, 200, `Upload ${i} should succeed`);
228
+ t.truthy(response.data.url, `Upload ${i} should have URL`);
229
+ });
230
+
231
+ // Verify all files are accessible
232
+ for (const response of responses) {
233
+ const fileResponse = await axios.get(response.data.url);
234
+ t.is(fileResponse.status, 200, "File should be accessible");
201
235
  }
202
-
203
- try {
204
- // Wait for all uploads to complete
205
- responses = await Promise.all(uploads.map(u => u.promise));
206
-
207
- // Verify all uploads succeeded
208
- responses.forEach((response, i) => {
209
- t.is(response.status, 200, `Upload ${i} should succeed`);
210
- t.truthy(response.data.url, `Upload ${i} should have URL`);
211
- });
212
-
213
- // Verify all files are accessible
214
- for (const response of responses) {
215
- const fileResponse = await axios.get(response.data.url);
216
- t.is(fileResponse.status, 200, 'File should be accessible');
217
- }
218
- } finally {
219
- // Cleanup all files
220
- for (const upload of uploads) {
221
- fs.unlinkSync(upload.filePath);
222
- }
223
- // Cleanup uploaded files
224
- for (const response of responses) {
225
- if (response?.data?.url) {
226
- await cleanupHashAndFile(null, response.data.url, baseUrl);
227
- }
228
- }
236
+ } finally {
237
+ // Cleanup all files
238
+ for (const upload of uploads) {
239
+ fs.unlinkSync(upload.filePath);
229
240
  }
241
+ // Cleanup uploaded files
242
+ for (const response of responses) {
243
+ if (response?.data?.url) {
244
+ await cleanupHashAndFile(null, response.data.url, baseUrl);
245
+ }
246
+ }
247
+ }
230
248
  });
231
249
 
232
250
  // Test: Upload with missing file
233
- test.serial('should handle missing file in request', async (t) => {
234
- const form = new FormData();
235
- form.append('requestId', uuidv4());
236
-
237
- const response = await axios.post(baseUrl, form, {
238
- headers: {
239
- ...form.getHeaders(),
240
- 'Content-Type': 'multipart/form-data',
241
- },
242
- validateStatus: (status) => true,
243
- });
244
-
245
- t.is(response.status, 400, 'Should reject request without file');
246
- t.is(response.data, 'No file provided in request', 'Should return correct error message');
251
+ test.serial("should handle missing file in request", async (t) => {
252
+ const form = new FormData();
253
+ form.append("requestId", uuidv4());
254
+
255
+ const response = await axios.post(baseUrl, form, {
256
+ headers: {
257
+ ...form.getHeaders(),
258
+ "Content-Type": "multipart/form-data",
259
+ },
260
+ validateStatus: (status) => true,
261
+ });
262
+
263
+ t.is(response.status, 400, "Should reject request without file");
264
+ t.is(
265
+ response.data,
266
+ "No file provided in request",
267
+ "Should return correct error message",
268
+ );
247
269
  });
248
270
 
249
271
  // Test: Upload with empty file
250
- test.serial('should handle empty file upload', async (t) => {
251
- const filePath = await createTestFile('', 'txt');
252
- const requestId = uuidv4();
253
- let response;
254
-
255
- try {
256
- response = await uploadFile(filePath, requestId);
257
- t.is(response.status, 400, 'Should reject empty file');
258
- t.is(response.data, 'Invalid file: file is empty', 'Should return correct error message');
259
- } finally {
260
- fs.unlinkSync(filePath);
261
- }
272
+ test.serial("should handle empty file upload", async (t) => {
273
+ const filePath = await createTestFile("", "txt");
274
+ const requestId = uuidv4();
275
+ let response;
276
+
277
+ try {
278
+ response = await uploadFile(filePath, requestId);
279
+ t.is(response.status, 400, "Should reject empty file");
280
+ t.is(
281
+ response.data,
282
+ "Invalid file: file is empty",
283
+ "Should return correct error message",
284
+ );
285
+ } finally {
286
+ fs.unlinkSync(filePath);
287
+ }
262
288
  });
263
289
 
264
290
  // Test: Upload without requestId should generate one
265
- test.serial('should generate requestId when not provided', async (t) => {
266
- const fileContent = 'test content';
267
- const filePath = await createTestFile(fileContent, 'txt');
268
- let response;
269
-
270
- try {
271
- response = await uploadFile(filePath);
272
- t.is(response.status, 200, 'Upload should succeed without requestId');
273
- t.truthy(response.data.url, 'Should have file URL');
274
-
275
- // Extract requestId from the URL
276
- const urlParts = response.data.url.split('/');
277
- const requestId = urlParts[urlParts.length - 2]; // requestId is the second-to-last part of the URL
278
- t.truthy(requestId, 'URL should contain a requestId');
279
- t.true(requestId.length > 0, 'requestId should not be empty');
280
-
281
- // Verify file is accessible
282
- const fileResponse = await axios.get(response.data.url);
283
- t.is(fileResponse.status, 200, 'File should be accessible');
284
- t.is(fileResponse.data, fileContent, 'File content should match');
285
- } finally {
286
- fs.unlinkSync(filePath);
287
- if (response?.data?.url) {
288
- await cleanupHashAndFile(null, response.data.url, baseUrl);
289
- }
291
+ test.serial("should generate requestId when not provided", async (t) => {
292
+ const fileContent = "test content";
293
+ const filePath = await createTestFile(fileContent, "txt");
294
+ let response;
295
+
296
+ try {
297
+ response = await uploadFile(filePath);
298
+ t.is(response.status, 200, "Upload should succeed without requestId");
299
+ t.truthy(response.data.url, "Should have file URL");
300
+
301
+ // Extract requestId from the URL
302
+ const urlParts = response.data.url.split("/");
303
+ const requestId = urlParts[urlParts.length - 2]; // requestId is the second-to-last part of the URL
304
+ t.truthy(requestId, "URL should contain a requestId");
305
+ t.true(requestId.length > 0, "requestId should not be empty");
306
+
307
+ // Verify file is accessible
308
+ const fileResponse = await axios.get(response.data.url);
309
+ t.is(fileResponse.status, 200, "File should be accessible");
310
+ t.is(fileResponse.data, fileContent, "File content should match");
311
+ } finally {
312
+ fs.unlinkSync(filePath);
313
+ if (response?.data?.url) {
314
+ await cleanupHashAndFile(null, response.data.url, baseUrl);
290
315
  }
291
- });
316
+ }
317
+ });