@aj-archipelago/cortex 1.3.58 → 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 (40) hide show
  1. package/helper-apps/cortex-file-handler/INTERFACE.md +20 -9
  2. package/helper-apps/cortex-file-handler/package-lock.json +2 -2
  3. package/helper-apps/cortex-file-handler/package.json +1 -1
  4. package/helper-apps/cortex-file-handler/scripts/setup-azure-container.js +17 -17
  5. package/helper-apps/cortex-file-handler/scripts/setup-test-containers.js +35 -35
  6. package/helper-apps/cortex-file-handler/src/blobHandler.js +1010 -909
  7. package/helper-apps/cortex-file-handler/src/constants.js +98 -98
  8. package/helper-apps/cortex-file-handler/src/docHelper.js +27 -27
  9. package/helper-apps/cortex-file-handler/src/fileChunker.js +224 -214
  10. package/helper-apps/cortex-file-handler/src/helper.js +93 -93
  11. package/helper-apps/cortex-file-handler/src/index.js +584 -550
  12. package/helper-apps/cortex-file-handler/src/localFileHandler.js +86 -86
  13. package/helper-apps/cortex-file-handler/src/redis.js +186 -90
  14. package/helper-apps/cortex-file-handler/src/services/ConversionService.js +301 -273
  15. package/helper-apps/cortex-file-handler/src/services/FileConversionService.js +55 -55
  16. package/helper-apps/cortex-file-handler/src/services/storage/AzureStorageProvider.js +174 -154
  17. package/helper-apps/cortex-file-handler/src/services/storage/GCSStorageProvider.js +239 -223
  18. package/helper-apps/cortex-file-handler/src/services/storage/LocalStorageProvider.js +161 -159
  19. package/helper-apps/cortex-file-handler/src/services/storage/StorageFactory.js +73 -71
  20. package/helper-apps/cortex-file-handler/src/services/storage/StorageProvider.js +46 -45
  21. package/helper-apps/cortex-file-handler/src/services/storage/StorageService.js +256 -213
  22. package/helper-apps/cortex-file-handler/src/start.js +4 -1
  23. package/helper-apps/cortex-file-handler/src/utils/filenameUtils.js +59 -25
  24. package/helper-apps/cortex-file-handler/tests/FileConversionService.test.js +119 -116
  25. package/helper-apps/cortex-file-handler/tests/blobHandler.test.js +257 -257
  26. package/helper-apps/cortex-file-handler/tests/cleanup.test.js +676 -0
  27. package/helper-apps/cortex-file-handler/tests/conversionResilience.test.js +124 -124
  28. package/helper-apps/cortex-file-handler/tests/fileChunker.test.js +249 -208
  29. package/helper-apps/cortex-file-handler/tests/fileUpload.test.js +439 -380
  30. package/helper-apps/cortex-file-handler/tests/getOperations.test.js +299 -263
  31. package/helper-apps/cortex-file-handler/tests/postOperations.test.js +265 -239
  32. package/helper-apps/cortex-file-handler/tests/start.test.js +1230 -1201
  33. package/helper-apps/cortex-file-handler/tests/storage/AzureStorageProvider.test.js +110 -105
  34. package/helper-apps/cortex-file-handler/tests/storage/GCSStorageProvider.test.js +201 -175
  35. package/helper-apps/cortex-file-handler/tests/storage/LocalStorageProvider.test.js +128 -125
  36. package/helper-apps/cortex-file-handler/tests/storage/StorageFactory.test.js +78 -73
  37. package/helper-apps/cortex-file-handler/tests/storage/StorageService.test.js +99 -99
  38. package/helper-apps/cortex-file-handler/tests/testUtils.helper.js +74 -70
  39. package/package.json +1 -1
  40. package/pathways/translate_subtitle.js +15 -8
@@ -1,13 +1,13 @@
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 XLSX from 'xlsx';
9
- import { port } from '../src/start.js';
10
- import { cleanupHashAndFile, createTestMediaFile } 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 XLSX from "xlsx";
9
+ import { port } from "../src/start.js";
10
+ import { cleanupHashAndFile, createTestMediaFile } from "./testUtils.helper.js";
11
11
 
12
12
  const __filename = fileURLToPath(import.meta.url);
13
13
  const __dirname = path.dirname(__filename);
@@ -15,293 +15,329 @@ const baseUrl = `http://localhost:${port}/api/CortexFileHandler`;
15
15
 
16
16
  // Helper function to create test files
17
17
  async function createTestFile(content, extension) {
18
- const testDir = path.join(__dirname, 'test-files');
19
- if (!fs.existsSync(testDir)) {
20
- fs.mkdirSync(testDir, { recursive: true });
21
- }
22
- // Use a shorter filename to avoid filesystem limits
23
- const filename = path.join(testDir, `test-${uuidv4().slice(0, 8)}.${extension}`);
24
- fs.writeFileSync(filename, content);
25
- return filename;
18
+ const testDir = path.join(__dirname, "test-files");
19
+ if (!fs.existsSync(testDir)) {
20
+ fs.mkdirSync(testDir, { recursive: true });
21
+ }
22
+ // Use a shorter filename to avoid filesystem limits
23
+ const filename = path.join(
24
+ testDir,
25
+ `test-${uuidv4().slice(0, 8)}.${extension}`,
26
+ );
27
+ fs.writeFileSync(filename, content);
28
+ return filename;
26
29
  }
27
30
 
28
31
  // Helper function to upload file
29
32
  async function uploadFile(filePath, requestId = null, hash = null) {
30
- const form = new FormData();
31
- form.append('file', fs.createReadStream(filePath));
32
- if (requestId) form.append('requestId', requestId);
33
- if (hash) form.append('hash', hash);
34
-
35
- const response = await axios.post(baseUrl, form, {
36
- headers: {
37
- ...form.getHeaders(),
38
- 'Content-Type': 'multipart/form-data',
39
- },
40
- validateStatus: (status) => true,
41
- timeout: 30000,
42
- maxContentLength: Infinity,
43
- maxBodyLength: Infinity,
44
- });
33
+ const form = new FormData();
34
+ form.append("file", fs.createReadStream(filePath));
35
+ if (requestId) form.append("requestId", requestId);
36
+ if (hash) form.append("hash", hash);
37
+
38
+ const response = await axios.post(baseUrl, form, {
39
+ headers: {
40
+ ...form.getHeaders(),
41
+ "Content-Type": "multipart/form-data",
42
+ },
43
+ validateStatus: (status) => true,
44
+ timeout: 30000,
45
+ maxContentLength: Infinity,
46
+ maxBodyLength: Infinity,
47
+ });
45
48
 
46
- return response;
49
+ return response;
47
50
  }
48
51
 
49
52
  // Setup: Create test directory
50
53
  test.before(async (t) => {
51
- const testDir = path.join(__dirname, 'test-files');
52
- await fs.promises.mkdir(testDir, { recursive: true });
53
- t.context = { testDir };
54
+ const testDir = path.join(__dirname, "test-files");
55
+ await fs.promises.mkdir(testDir, { recursive: true });
56
+ t.context = { testDir };
54
57
  });
55
58
 
56
59
  // Test: Document processing with save=true
57
- test.serial('should process document with save=true', async (t) => {
58
- // Create a minimal XLSX workbook in-memory
59
- const workbook = XLSX.utils.book_new();
60
- const worksheet = XLSX.utils.aoa_to_sheet([
61
- ['Name', 'Score'],
62
- ['Alice', 10],
63
- ['Bob', 8],
64
- ]);
65
- XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1');
66
-
67
- // Write it to a temp file inside the test directory
68
- const filePath = path.join(t.context.testDir, `${uuidv4()}.xlsx`);
69
- XLSX.writeFile(workbook, filePath);
70
-
71
- const requestId = uuidv4();
72
- let response;
73
- let convertedUrl;
74
-
75
- try {
76
- // First upload the file
77
- response = await uploadFile(filePath, requestId);
78
- t.is(response.status, 200, 'Upload should succeed');
79
-
80
- // Then process with save=true
81
- const processResponse = await axios.get(baseUrl, {
82
- params: {
83
- uri: response.data.url,
84
- requestId,
85
- save: true
86
- },
87
- validateStatus: (status) => true
88
- });
89
-
90
- t.is(processResponse.status, 200, 'Document processing should succeed');
91
- t.truthy(processResponse.data.url, 'Should return converted file URL');
92
- t.true(processResponse.data.url.includes('.csv'), 'Should return a CSV URL');
93
-
94
- // Store the converted URL for cleanup
95
- convertedUrl = processResponse.data.url;
96
-
97
- // Verify the converted file is accessible immediately after conversion
98
- const fileResponse = await axios.get(convertedUrl, {
99
- validateStatus: (status) => true
100
- });
101
-
102
- t.is(fileResponse.status, 200, 'Converted file should be accessible');
103
- t.true(fileResponse.data.includes('Name,Score'), 'CSV should contain headers');
104
- t.true(fileResponse.data.includes('Alice,10'), 'CSV should contain data');
105
- } finally {
106
- // Clean up both the original and converted files
107
- if (response?.data?.url) {
108
- await cleanupHashAndFile(null, response.data.url, baseUrl);
109
- }
110
- if (convertedUrl) {
111
- await cleanupHashAndFile(null, convertedUrl, baseUrl);
112
- }
113
- // Clean up the local file last
114
- fs.unlinkSync(filePath);
60
+ test.serial("should process document with save=true", async (t) => {
61
+ // Create a minimal XLSX workbook in-memory
62
+ const workbook = XLSX.utils.book_new();
63
+ const worksheet = XLSX.utils.aoa_to_sheet([
64
+ ["Name", "Score"],
65
+ ["Alice", 10],
66
+ ["Bob", 8],
67
+ ]);
68
+ XLSX.utils.book_append_sheet(workbook, worksheet, "Sheet1");
69
+
70
+ // Write it to a temp file inside the test directory
71
+ const filePath = path.join(t.context.testDir, `${uuidv4()}.xlsx`);
72
+ XLSX.writeFile(workbook, filePath);
73
+
74
+ const requestId = uuidv4();
75
+ let response;
76
+ let convertedUrl;
77
+
78
+ try {
79
+ // First upload the file
80
+ response = await uploadFile(filePath, requestId);
81
+ t.is(response.status, 200, "Upload should succeed");
82
+
83
+ // Then process with save=true
84
+ const processResponse = await axios.get(baseUrl, {
85
+ params: {
86
+ uri: response.data.url,
87
+ requestId,
88
+ save: true,
89
+ },
90
+ validateStatus: (status) => true,
91
+ });
92
+
93
+ t.is(processResponse.status, 200, "Document processing should succeed");
94
+ t.truthy(processResponse.data.url, "Should return converted file URL");
95
+ t.true(
96
+ processResponse.data.url.includes(".csv"),
97
+ "Should return a CSV URL",
98
+ );
99
+
100
+ // Store the converted URL for cleanup
101
+ convertedUrl = processResponse.data.url;
102
+
103
+ // Verify the converted file is accessible immediately after conversion
104
+ const fileResponse = await axios.get(convertedUrl, {
105
+ validateStatus: (status) => true,
106
+ });
107
+
108
+ t.is(fileResponse.status, 200, "Converted file should be accessible");
109
+ t.true(
110
+ fileResponse.data.includes("Name,Score"),
111
+ "CSV should contain headers",
112
+ );
113
+ t.true(fileResponse.data.includes("Alice,10"), "CSV should contain data");
114
+ } finally {
115
+ // Clean up both the original and converted files
116
+ if (response?.data?.url) {
117
+ await cleanupHashAndFile(null, response.data.url, baseUrl);
115
118
  }
119
+ if (convertedUrl) {
120
+ await cleanupHashAndFile(null, convertedUrl, baseUrl);
121
+ }
122
+ // Clean up the local file last
123
+ fs.unlinkSync(filePath);
124
+ }
116
125
  });
117
126
 
118
127
  // Test: Document processing with save=false
119
- test.serial('should process document with save=false', async (t) => {
120
- const fileContent = 'Test document content';
121
- const filePath = await createTestFile(fileContent, 'txt');
122
- const requestId = uuidv4();
123
- let response;
124
-
125
- try {
126
- // First upload the file
127
- response = await uploadFile(filePath, requestId);
128
- t.is(response.status, 200, 'Upload should succeed');
129
-
130
- // Then process with save=false
131
- const processResponse = await axios.get(baseUrl, {
132
- params: {
133
- uri: response.data.url,
134
- requestId,
135
- save: false
136
- },
137
- validateStatus: (status) => true
138
- });
139
-
140
- t.is(processResponse.status, 200, 'Document processing should succeed');
141
- t.true(Array.isArray(processResponse.data), 'Should return array of chunks');
142
- t.true(processResponse.data.length > 0, 'Should return non-empty chunks');
143
- // ensure the first chunk contains the right content
144
- t.true(processResponse.data[0].includes(fileContent), 'First chunk should contain the right content');
145
- } finally {
146
- fs.unlinkSync(filePath);
147
- if (response?.data?.url) {
148
- await cleanupHashAndFile(null, response.data.url, baseUrl);
149
- }
128
+ test.serial("should process document with save=false", async (t) => {
129
+ const fileContent = "Test document content";
130
+ const filePath = await createTestFile(fileContent, "txt");
131
+ const requestId = uuidv4();
132
+ let response;
133
+
134
+ try {
135
+ // First upload the file
136
+ response = await uploadFile(filePath, requestId);
137
+ t.is(response.status, 200, "Upload should succeed");
138
+
139
+ // Then process with save=false
140
+ const processResponse = await axios.get(baseUrl, {
141
+ params: {
142
+ uri: response.data.url,
143
+ requestId,
144
+ save: false,
145
+ },
146
+ validateStatus: (status) => true,
147
+ });
148
+
149
+ t.is(processResponse.status, 200, "Document processing should succeed");
150
+ t.true(
151
+ Array.isArray(processResponse.data),
152
+ "Should return array of chunks",
153
+ );
154
+ t.true(processResponse.data.length > 0, "Should return non-empty chunks");
155
+ // ensure the first chunk contains the right content
156
+ t.true(
157
+ processResponse.data[0].includes(fileContent),
158
+ "First chunk should contain the right content",
159
+ );
160
+ } finally {
161
+ fs.unlinkSync(filePath);
162
+ if (response?.data?.url) {
163
+ await cleanupHashAndFile(null, response.data.url, baseUrl);
150
164
  }
165
+ }
151
166
  });
152
167
 
153
168
  // Test: Media file chunking
154
- test.serial('should chunk media file', async (t) => {
155
- // Create a proper 10-second test audio file (MP3)
156
- const testDir = path.join(__dirname, 'test-files');
157
- if (!fs.existsSync(testDir)) {
158
- fs.mkdirSync(testDir, { recursive: true });
159
- }
160
- const filePath = path.join(testDir, `test-${uuidv4()}.mp3`);
169
+ test.serial("should chunk media file", async (t) => {
170
+ // Create a proper 10-second test audio file (MP3)
171
+ const testDir = path.join(__dirname, "test-files");
172
+ if (!fs.existsSync(testDir)) {
173
+ fs.mkdirSync(testDir, { recursive: true });
174
+ }
175
+ const filePath = path.join(testDir, `test-${uuidv4()}.mp3`);
176
+
177
+ try {
178
+ await createTestMediaFile(filePath, 10);
179
+
180
+ const requestId = uuidv4();
181
+ let response;
161
182
 
162
183
  try {
163
- await createTestMediaFile(filePath, 10);
164
-
165
- const requestId = uuidv4();
166
- let response;
167
-
168
- try {
169
- // First upload the file
170
- response = await uploadFile(filePath, requestId);
171
- t.is(response.status, 200, 'Upload should succeed');
172
-
173
- // Then request chunking
174
- const chunkResponse = await axios.get(baseUrl, {
175
- params: {
176
- uri: response.data.url,
177
- requestId
178
- },
179
- validateStatus: (status) => true
180
- });
181
-
182
- t.is(chunkResponse.status, 200, 'Chunking should succeed');
183
- t.true(Array.isArray(chunkResponse.data), 'Should return array of chunks');
184
- t.true(chunkResponse.data.length > 0, 'Should return non-empty chunks');
185
-
186
- // Verify each chunk has required properties
187
- chunkResponse.data.forEach(chunk => {
188
- t.truthy(chunk.uri, 'Chunk should have URI');
189
- t.true(typeof chunk.offset === 'number', 'Chunk should have a numeric offset');
190
- });
191
- } finally {
192
- if (response?.data?.url) {
193
- await cleanupHashAndFile(null, response.data.url, baseUrl);
194
- }
195
- }
184
+ // First upload the file
185
+ response = await uploadFile(filePath, requestId);
186
+ t.is(response.status, 200, "Upload should succeed");
187
+
188
+ // Then request chunking
189
+ const chunkResponse = await axios.get(baseUrl, {
190
+ params: {
191
+ uri: response.data.url,
192
+ requestId,
193
+ },
194
+ validateStatus: (status) => true,
195
+ });
196
+
197
+ t.is(chunkResponse.status, 200, "Chunking should succeed");
198
+ t.true(
199
+ Array.isArray(chunkResponse.data),
200
+ "Should return array of chunks",
201
+ );
202
+ t.true(chunkResponse.data.length > 0, "Should return non-empty chunks");
203
+
204
+ // Verify each chunk has required properties
205
+ chunkResponse.data.forEach((chunk) => {
206
+ t.truthy(chunk.uri, "Chunk should have URI");
207
+ t.true(
208
+ typeof chunk.offset === "number",
209
+ "Chunk should have a numeric offset",
210
+ );
211
+ });
196
212
  } finally {
197
- // Clean up the test file
198
- if (fs.existsSync(filePath)) {
199
- fs.unlinkSync(filePath);
200
- }
213
+ if (response?.data?.url) {
214
+ await cleanupHashAndFile(null, response.data.url, baseUrl);
215
+ }
216
+ }
217
+ } finally {
218
+ // Clean up the test file
219
+ if (fs.existsSync(filePath)) {
220
+ fs.unlinkSync(filePath);
201
221
  }
222
+ }
202
223
  });
203
224
 
204
225
  // Test: Remote file fetching with fetch parameter
205
- test.serial('should fetch remote file', async (t) => {
206
- const requestId = uuidv4();
207
- const remoteUrl = 'https://example.com/test.txt';
208
-
209
- const response = await axios.get(baseUrl, {
210
- params: {
211
- fetch: remoteUrl,
212
- requestId
213
- },
214
- validateStatus: (status) => true
215
- });
216
-
217
- t.is(response.status, 400, 'Should reject invalid URL');
218
- t.is(response.data, 'Invalid or inaccessible URL', 'Should return correct error message');
226
+ test.serial("should fetch remote file", async (t) => {
227
+ const requestId = uuidv4();
228
+ const remoteUrl = "https://example.com/test.txt";
229
+
230
+ const response = await axios.get(baseUrl, {
231
+ params: {
232
+ fetch: remoteUrl,
233
+ requestId,
234
+ },
235
+ validateStatus: (status) => true,
236
+ });
237
+
238
+ t.is(response.status, 400, "Should reject invalid URL");
239
+ t.is(
240
+ response.data,
241
+ "Invalid or inaccessible URL",
242
+ "Should return correct error message",
243
+ );
219
244
  });
220
245
 
221
246
  // Test: Redis caching behavior for remote files
222
- test.serial('should cache remote files in Redis', async (t) => {
223
- const requestId = uuidv4();
224
- const hash = 'test-cache-' + uuidv4();
225
-
226
- // First request should cache the file
227
- const firstResponse = await axios.get(baseUrl, {
228
- params: {
229
- fetch: 'https://example.com/test.txt',
230
- requestId,
231
- hash,
232
- timeout: 10000
233
- },
234
- validateStatus: (status) => true
235
- });
236
-
237
- // Second request should return cached result
238
- const secondResponse = await axios.get(baseUrl, {
239
- params: {
240
- hash,
241
- checkHash: true
242
- },
243
- validateStatus: (status) => true
244
- });
245
-
246
- t.is(secondResponse.status, 404, 'Should return 404 for invalid URL');
247
+ test.serial("should cache remote files in Redis", async (t) => {
248
+ const requestId = uuidv4();
249
+ const hash = "test-cache-" + uuidv4();
250
+
251
+ // First request should cache the file
252
+ const firstResponse = await axios.get(baseUrl, {
253
+ params: {
254
+ fetch: "https://example.com/test.txt",
255
+ requestId,
256
+ hash,
257
+ timeout: 10000,
258
+ },
259
+ validateStatus: (status) => true,
260
+ });
261
+
262
+ // Second request should return cached result
263
+ const secondResponse = await axios.get(baseUrl, {
264
+ params: {
265
+ hash,
266
+ checkHash: true,
267
+ },
268
+ validateStatus: (status) => true,
269
+ });
270
+
271
+ t.is(secondResponse.status, 404, "Should return 404 for invalid URL");
247
272
  });
248
273
 
249
274
  // Test: Error cases for invalid URLs
250
- test.serial('should handle invalid URLs', async (t) => {
251
- const requestId = uuidv4();
252
- const invalidUrls = [
253
- 'not-a-url',
254
- 'http://',
255
- 'https://',
256
- 'ftp://invalid',
257
- 'file:///nonexistent'
258
- ];
259
-
260
- for (const url of invalidUrls) {
261
- const response = await axios.get(baseUrl, {
262
- params: {
263
- uri: url,
264
- requestId
265
- },
266
- validateStatus: (status) => true
267
- });
268
-
269
- t.is(response.status, 400, `Should reject invalid URL: ${url}`);
270
- t.true(response.data.includes('Invalid') || response.data.includes('Error'), 'Should return error message');
271
- }
275
+ test.serial("should handle invalid URLs", async (t) => {
276
+ const requestId = uuidv4();
277
+ const invalidUrls = [
278
+ "not-a-url",
279
+ "http://",
280
+ "https://",
281
+ "ftp://invalid",
282
+ "file:///nonexistent",
283
+ ];
284
+
285
+ for (const url of invalidUrls) {
286
+ const response = await axios.get(baseUrl, {
287
+ params: {
288
+ uri: url,
289
+ requestId,
290
+ },
291
+ validateStatus: (status) => true,
292
+ });
293
+
294
+ t.is(response.status, 400, `Should reject invalid URL: ${url}`);
295
+ t.true(
296
+ response.data.includes("Invalid") || response.data.includes("Error"),
297
+ "Should return error message",
298
+ );
299
+ }
272
300
  });
273
301
 
274
302
  // Test: Long filename handling
275
- test.serial('should handle long filenames', async (t) => {
276
- const fileContent = 'Test content';
277
- const filePath = await createTestFile(fileContent, 'txt');
278
- const requestId = uuidv4();
279
- let response;
280
-
281
- try {
282
- // First upload the file
283
- response = await uploadFile(filePath, requestId);
284
- t.is(response.status, 200, 'Upload should succeed');
285
-
286
- // Create a URL with a very long filename
287
- const longFilename = 'a'.repeat(1100) + '.txt';
288
- const longUrl = response.data.url.replace(/[^/]+$/, longFilename);
289
-
290
- // Try to process the file with the long filename
291
- const processResponse = await axios.get(baseUrl, {
292
- params: {
293
- uri: longUrl,
294
- requestId
295
- },
296
- validateStatus: (status) => true
297
- });
298
-
299
- t.is(processResponse.status, 400, 'Should reject URL with too long filename');
300
- t.is(processResponse.data, 'URL pathname is too long', 'Should return correct error message');
301
- } finally {
302
- fs.unlinkSync(filePath);
303
- if (response?.data?.url) {
304
- await cleanupHashAndFile(null, response.data.url, baseUrl);
305
- }
303
+ test.serial("should handle long filenames", async (t) => {
304
+ const fileContent = "Test content";
305
+ const filePath = await createTestFile(fileContent, "txt");
306
+ const requestId = uuidv4();
307
+ let response;
308
+
309
+ try {
310
+ // First upload the file
311
+ response = await uploadFile(filePath, requestId);
312
+ t.is(response.status, 200, "Upload should succeed");
313
+
314
+ // Create a URL with a very long filename
315
+ const longFilename = "a".repeat(1100) + ".txt";
316
+ const longUrl = response.data.url.replace(/[^/]+$/, longFilename);
317
+
318
+ // Try to process the file with the long filename
319
+ const processResponse = await axios.get(baseUrl, {
320
+ params: {
321
+ uri: longUrl,
322
+ requestId,
323
+ },
324
+ validateStatus: (status) => true,
325
+ });
326
+
327
+ t.is(
328
+ processResponse.status,
329
+ 400,
330
+ "Should reject URL with too long filename",
331
+ );
332
+ t.is(
333
+ processResponse.data,
334
+ "URL pathname is too long",
335
+ "Should return correct error message",
336
+ );
337
+ } finally {
338
+ fs.unlinkSync(filePath);
339
+ if (response?.data?.url) {
340
+ await cleanupHashAndFile(null, response.data.url, baseUrl);
306
341
  }
307
- });
342
+ }
343
+ });