@aj-archipelago/cortex 1.3.62 → 1.3.63
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/.github/workflows/cortex-file-handler-test.yml +61 -0
- package/README.md +31 -7
- package/config/default.example.json +15 -0
- package/config.js +133 -12
- package/helper-apps/cortex-autogen2/DigiCertGlobalRootCA.crt.pem +22 -0
- package/helper-apps/cortex-autogen2/Dockerfile +31 -0
- package/helper-apps/cortex-autogen2/Dockerfile.worker +41 -0
- package/helper-apps/cortex-autogen2/README.md +183 -0
- package/helper-apps/cortex-autogen2/__init__.py +1 -0
- package/helper-apps/cortex-autogen2/agents.py +131 -0
- package/helper-apps/cortex-autogen2/docker-compose.yml +20 -0
- package/helper-apps/cortex-autogen2/function_app.py +55 -0
- package/helper-apps/cortex-autogen2/host.json +15 -0
- package/helper-apps/cortex-autogen2/main.py +126 -0
- package/helper-apps/cortex-autogen2/poetry.lock +3652 -0
- package/helper-apps/cortex-autogen2/pyproject.toml +36 -0
- package/helper-apps/cortex-autogen2/requirements.txt +20 -0
- package/helper-apps/cortex-autogen2/send_task.py +105 -0
- package/helper-apps/cortex-autogen2/services/__init__.py +1 -0
- package/helper-apps/cortex-autogen2/services/azure_queue.py +85 -0
- package/helper-apps/cortex-autogen2/services/redis_publisher.py +153 -0
- package/helper-apps/cortex-autogen2/task_processor.py +488 -0
- package/helper-apps/cortex-autogen2/tools/__init__.py +24 -0
- package/helper-apps/cortex-autogen2/tools/azure_blob_tools.py +175 -0
- package/helper-apps/cortex-autogen2/tools/azure_foundry_agents.py +601 -0
- package/helper-apps/cortex-autogen2/tools/coding_tools.py +72 -0
- package/helper-apps/cortex-autogen2/tools/download_tools.py +48 -0
- package/helper-apps/cortex-autogen2/tools/file_tools.py +545 -0
- package/helper-apps/cortex-autogen2/tools/search_tools.py +646 -0
- package/helper-apps/cortex-azure-cleaner/README.md +36 -0
- package/helper-apps/cortex-file-converter/README.md +93 -0
- package/helper-apps/cortex-file-converter/key_to_pdf.py +104 -0
- package/helper-apps/cortex-file-converter/list_blob_extensions.py +89 -0
- package/helper-apps/cortex-file-converter/process_azure_keynotes.py +181 -0
- package/helper-apps/cortex-file-converter/requirements.txt +1 -0
- package/helper-apps/cortex-file-handler/.env.test.azure.ci +7 -0
- package/helper-apps/cortex-file-handler/.env.test.azure.sample +1 -1
- package/helper-apps/cortex-file-handler/.env.test.gcs.ci +10 -0
- package/helper-apps/cortex-file-handler/.env.test.gcs.sample +2 -2
- package/helper-apps/cortex-file-handler/INTERFACE.md +41 -0
- package/helper-apps/cortex-file-handler/package.json +1 -1
- package/helper-apps/cortex-file-handler/scripts/setup-azure-container.js +41 -17
- package/helper-apps/cortex-file-handler/scripts/setup-test-containers.js +30 -15
- package/helper-apps/cortex-file-handler/scripts/test-azure.sh +32 -6
- package/helper-apps/cortex-file-handler/scripts/test-gcs.sh +24 -2
- package/helper-apps/cortex-file-handler/scripts/validate-env.js +128 -0
- package/helper-apps/cortex-file-handler/src/blobHandler.js +161 -51
- package/helper-apps/cortex-file-handler/src/constants.js +3 -0
- package/helper-apps/cortex-file-handler/src/fileChunker.js +10 -8
- package/helper-apps/cortex-file-handler/src/index.js +116 -9
- package/helper-apps/cortex-file-handler/src/redis.js +61 -1
- package/helper-apps/cortex-file-handler/src/services/ConversionService.js +11 -8
- package/helper-apps/cortex-file-handler/src/services/FileConversionService.js +2 -2
- package/helper-apps/cortex-file-handler/src/services/storage/AzureStorageProvider.js +88 -6
- package/helper-apps/cortex-file-handler/src/services/storage/GCSStorageProvider.js +58 -0
- package/helper-apps/cortex-file-handler/src/services/storage/StorageFactory.js +25 -5
- package/helper-apps/cortex-file-handler/src/services/storage/StorageProvider.js +9 -0
- package/helper-apps/cortex-file-handler/src/services/storage/StorageService.js +120 -16
- package/helper-apps/cortex-file-handler/src/start.js +27 -17
- package/helper-apps/cortex-file-handler/tests/FileConversionService.test.js +52 -1
- package/helper-apps/cortex-file-handler/tests/blobHandler.test.js +40 -0
- package/helper-apps/cortex-file-handler/tests/checkHashShortLived.test.js +553 -0
- package/helper-apps/cortex-file-handler/tests/cleanup.test.js +46 -52
- package/helper-apps/cortex-file-handler/tests/containerConversionFlow.test.js +451 -0
- package/helper-apps/cortex-file-handler/tests/containerNameParsing.test.js +229 -0
- package/helper-apps/cortex-file-handler/tests/containerParameterFlow.test.js +392 -0
- package/helper-apps/cortex-file-handler/tests/conversionResilience.test.js +7 -2
- package/helper-apps/cortex-file-handler/tests/deleteOperations.test.js +348 -0
- package/helper-apps/cortex-file-handler/tests/fileChunker.test.js +23 -2
- package/helper-apps/cortex-file-handler/tests/fileUpload.test.js +11 -5
- package/helper-apps/cortex-file-handler/tests/getOperations.test.js +58 -24
- package/helper-apps/cortex-file-handler/tests/postOperations.test.js +11 -4
- package/helper-apps/cortex-file-handler/tests/shortLivedUrlConversion.test.js +225 -0
- package/helper-apps/cortex-file-handler/tests/start.test.js +8 -12
- package/helper-apps/cortex-file-handler/tests/storage/StorageFactory.test.js +80 -0
- package/helper-apps/cortex-file-handler/tests/storage/StorageService.test.js +388 -22
- package/helper-apps/cortex-file-handler/tests/testUtils.helper.js +74 -0
- package/lib/cortexResponse.js +153 -0
- package/lib/entityConstants.js +21 -3
- package/lib/logger.js +21 -4
- package/lib/pathwayTools.js +28 -9
- package/lib/util.js +49 -0
- package/package.json +1 -1
- package/pathways/basePathway.js +1 -0
- package/pathways/bing_afagent.js +54 -1
- package/pathways/call_tools.js +2 -3
- package/pathways/chat_jarvis.js +1 -1
- package/pathways/google_cse.js +27 -0
- package/pathways/grok_live_search.js +18 -0
- package/pathways/system/entity/memory/sys_memory_lookup_required.js +1 -0
- package/pathways/system/entity/memory/sys_memory_required.js +1 -0
- package/pathways/system/entity/memory/sys_search_memory.js +1 -0
- package/pathways/system/entity/sys_entity_agent.js +56 -4
- package/pathways/system/entity/sys_generator_quick.js +1 -0
- package/pathways/system/entity/tools/sys_tool_bing_search_afagent.js +26 -0
- package/pathways/system/entity/tools/sys_tool_google_search.js +141 -0
- package/pathways/system/entity/tools/sys_tool_grok_x_search.js +237 -0
- package/pathways/system/entity/tools/sys_tool_image.js +1 -1
- package/pathways/system/rest_streaming/sys_claude_37_sonnet.js +21 -0
- package/pathways/system/rest_streaming/sys_claude_41_opus.js +21 -0
- package/pathways/system/rest_streaming/sys_claude_4_sonnet.js +21 -0
- package/pathways/system/rest_streaming/sys_google_gemini_25_flash.js +25 -0
- package/pathways/system/rest_streaming/{sys_google_gemini_chat.js → sys_google_gemini_25_pro.js} +6 -4
- package/pathways/system/rest_streaming/sys_grok_4.js +23 -0
- package/pathways/system/rest_streaming/sys_grok_4_fast_non_reasoning.js +23 -0
- package/pathways/system/rest_streaming/sys_grok_4_fast_reasoning.js +23 -0
- package/pathways/system/rest_streaming/sys_openai_chat.js +3 -0
- package/pathways/system/rest_streaming/sys_openai_chat_gpt41.js +22 -0
- package/pathways/system/rest_streaming/sys_openai_chat_gpt41_mini.js +21 -0
- package/pathways/system/rest_streaming/sys_openai_chat_gpt41_nano.js +21 -0
- package/pathways/system/rest_streaming/{sys_claude_35_sonnet.js → sys_openai_chat_gpt4_omni.js} +6 -4
- package/pathways/system/rest_streaming/sys_openai_chat_gpt4_omni_mini.js +21 -0
- package/pathways/system/rest_streaming/{sys_claude_3_haiku.js → sys_openai_chat_gpt5.js} +7 -5
- package/pathways/system/rest_streaming/sys_openai_chat_gpt5_chat.js +21 -0
- package/pathways/system/rest_streaming/sys_openai_chat_gpt5_mini.js +21 -0
- package/pathways/system/rest_streaming/sys_openai_chat_gpt5_nano.js +21 -0
- package/pathways/system/rest_streaming/{sys_openai_chat_o1.js → sys_openai_chat_o3.js} +6 -3
- package/pathways/system/rest_streaming/sys_openai_chat_o3_mini.js +3 -0
- package/pathways/system/workspaces/run_workspace_prompt.js +99 -0
- package/pathways/vision.js +1 -1
- package/server/graphql.js +1 -1
- package/server/modelExecutor.js +8 -0
- package/server/pathwayResolver.js +166 -16
- package/server/pathwayResponseParser.js +16 -8
- package/server/plugins/azureFoundryAgentsPlugin.js +1 -1
- package/server/plugins/claude3VertexPlugin.js +193 -45
- package/server/plugins/gemini15ChatPlugin.js +21 -0
- package/server/plugins/gemini15VisionPlugin.js +360 -0
- package/server/plugins/googleCsePlugin.js +94 -0
- package/server/plugins/grokVisionPlugin.js +365 -0
- package/server/plugins/modelPlugin.js +3 -1
- package/server/plugins/openAiChatPlugin.js +106 -13
- package/server/plugins/openAiVisionPlugin.js +42 -30
- package/server/resolver.js +28 -4
- package/server/rest.js +270 -53
- package/server/typeDef.js +1 -0
- package/tests/{mocks.js → helpers/mocks.js} +5 -2
- package/tests/{server.js → helpers/server.js} +2 -2
- package/tests/helpers/sseAssert.js +23 -0
- package/tests/helpers/sseClient.js +73 -0
- package/tests/helpers/subscriptionAssert.js +11 -0
- package/tests/helpers/subscriptions.js +113 -0
- package/tests/{sublong.srt → integration/features/translate/sublong.srt} +4543 -4543
- package/tests/integration/features/translate/translate_chunking_stream.test.js +100 -0
- package/tests/{translate_srt.test.js → integration/features/translate/translate_srt.test.js} +2 -2
- package/tests/integration/graphql/async/stream/agentic.test.js +477 -0
- package/tests/integration/graphql/async/stream/subscription_streaming.test.js +62 -0
- package/tests/integration/graphql/async/stream/sys_entity_start_streaming.test.js +71 -0
- package/tests/integration/graphql/async/stream/vendors/claude_streaming.test.js +56 -0
- package/tests/integration/graphql/async/stream/vendors/gemini_streaming.test.js +66 -0
- package/tests/integration/graphql/async/stream/vendors/grok_streaming.test.js +56 -0
- package/tests/integration/graphql/async/stream/vendors/openai_streaming.test.js +72 -0
- package/tests/integration/graphql/features/google/sysToolGoogleSearch.test.js +96 -0
- package/tests/integration/graphql/features/grok/grok.test.js +688 -0
- package/tests/integration/graphql/features/grok/grok_x_search_tool.test.js +354 -0
- package/tests/{main.test.js → integration/graphql/features/main.test.js} +1 -1
- package/tests/{call_tools.test.js → integration/graphql/features/tools/call_tools.test.js} +2 -2
- package/tests/{vision.test.js → integration/graphql/features/vision/vision.test.js} +1 -1
- package/tests/integration/graphql/subscriptions/connection.test.js +26 -0
- package/tests/{openai_api.test.js → integration/rest/oai/openai_api.test.js} +63 -238
- package/tests/integration/rest/oai/tool_calling_api.test.js +343 -0
- package/tests/integration/rest/oai/tool_calling_streaming.test.js +85 -0
- package/tests/integration/rest/vendors/claude_streaming.test.js +47 -0
- package/tests/integration/rest/vendors/claude_tool_calling_streaming.test.js +75 -0
- package/tests/integration/rest/vendors/gemini_streaming.test.js +47 -0
- package/tests/integration/rest/vendors/gemini_tool_calling_streaming.test.js +75 -0
- package/tests/integration/rest/vendors/grok_streaming.test.js +55 -0
- package/tests/integration/rest/vendors/grok_tool_calling_streaming.test.js +75 -0
- package/tests/{azureAuthTokenHelper.test.js → unit/core/azureAuthTokenHelper.test.js} +1 -1
- package/tests/{chunkfunction.test.js → unit/core/chunkfunction.test.js} +2 -2
- package/tests/{config.test.js → unit/core/config.test.js} +3 -3
- package/tests/{encodeCache.test.js → unit/core/encodeCache.test.js} +1 -1
- package/tests/{fastLruCache.test.js → unit/core/fastLruCache.test.js} +1 -1
- package/tests/{handleBars.test.js → unit/core/handleBars.test.js} +1 -1
- package/tests/{memoryfunction.test.js → unit/core/memoryfunction.test.js} +2 -2
- package/tests/unit/core/mergeResolver.test.js +952 -0
- package/tests/{parser.test.js → unit/core/parser.test.js} +3 -3
- package/tests/unit/core/pathwayResolver.test.js +187 -0
- package/tests/{requestMonitor.test.js → unit/core/requestMonitor.test.js} +1 -1
- package/tests/{requestMonitorDurationEstimator.test.js → unit/core/requestMonitorDurationEstimator.test.js} +1 -1
- package/tests/{truncateMessages.test.js → unit/core/truncateMessages.test.js} +3 -3
- package/tests/{util.test.js → unit/core/util.test.js} +1 -1
- package/tests/{apptekTranslatePlugin.test.js → unit/plugins/apptekTranslatePlugin.test.js} +3 -3
- package/tests/{azureFoundryAgents.test.js → unit/plugins/azureFoundryAgents.test.js} +136 -1
- package/tests/{claude3VertexPlugin.test.js → unit/plugins/claude3VertexPlugin.test.js} +32 -10
- package/tests/{claude3VertexToolConversion.test.js → unit/plugins/claude3VertexToolConversion.test.js} +3 -3
- package/tests/unit/plugins/googleCsePlugin.test.js +111 -0
- package/tests/unit/plugins/grokVisionPlugin.test.js +1392 -0
- package/tests/{modelPlugin.test.js → unit/plugins/modelPlugin.test.js} +3 -3
- package/tests/{multimodal_conversion.test.js → unit/plugins/multimodal_conversion.test.js} +4 -4
- package/tests/{openAiChatPlugin.test.js → unit/plugins/openAiChatPlugin.test.js} +13 -4
- package/tests/{openAiToolPlugin.test.js → unit/plugins/openAiToolPlugin.test.js} +35 -27
- package/tests/{tokenHandlingTests.test.js → unit/plugins/tokenHandlingTests.test.js} +5 -5
- package/tests/{translate_apptek.test.js → unit/plugins/translate_apptek.test.js} +3 -3
- package/tests/{streaming.test.js → unit/plugins.streaming/plugin_stream_events.test.js} +19 -58
- package/helper-apps/mogrt-handler/tests/test-files/test.gif +0 -1
- package/helper-apps/mogrt-handler/tests/test-files/test.mogrt +0 -1
- package/helper-apps/mogrt-handler/tests/test-files/test.mp4 +0 -1
- package/pathways/system/rest_streaming/sys_openai_chat_gpt4.js +0 -19
- package/pathways/system/rest_streaming/sys_openai_chat_gpt4_32.js +0 -19
- package/pathways/system/rest_streaming/sys_openai_chat_gpt4_turbo.js +0 -19
- package/pathways/system/workspaces/run_claude35_sonnet.js +0 -21
- package/pathways/system/workspaces/run_claude3_haiku.js +0 -20
- package/pathways/system/workspaces/run_gpt35turbo.js +0 -20
- package/pathways/system/workspaces/run_gpt4.js +0 -20
- package/pathways/system/workspaces/run_gpt4_32.js +0 -20
- package/tests/agentic.test.js +0 -256
- package/tests/pathwayResolver.test.js +0 -78
- package/tests/subscription.test.js +0 -387
- /package/tests/{subchunk.srt → integration/features/translate/subchunk.srt} +0 -0
- /package/tests/{subhorizontal.srt → integration/features/translate/subhorizontal.srt} +0 -0
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import test from "ava";
|
|
2
|
+
import {
|
|
3
|
+
AZURE_STORAGE_CONTAINER_NAMES,
|
|
4
|
+
DEFAULT_AZURE_STORAGE_CONTAINER_NAME,
|
|
5
|
+
isValidContainerName
|
|
6
|
+
} from "../src/blobHandler.js";
|
|
7
|
+
|
|
8
|
+
// Mock environment variables for testing
|
|
9
|
+
const originalEnv = process.env.AZURE_STORAGE_CONTAINER_NAME;
|
|
10
|
+
|
|
11
|
+
test.beforeEach(() => {
|
|
12
|
+
// Reset to original environment
|
|
13
|
+
process.env.AZURE_STORAGE_CONTAINER_NAME = originalEnv;
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
test.afterEach(() => {
|
|
17
|
+
// Restore original environment
|
|
18
|
+
process.env.AZURE_STORAGE_CONTAINER_NAME = originalEnv;
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test("parseContainerNames should handle single container name", (t) => {
|
|
22
|
+
// Set environment variable for single container
|
|
23
|
+
process.env.AZURE_STORAGE_CONTAINER_NAME = "single-container";
|
|
24
|
+
|
|
25
|
+
// We need to reload the module to pick up the new environment variable
|
|
26
|
+
// Since we can't easily reload ES modules, we'll test the logic directly
|
|
27
|
+
const parseContainerNames = () => {
|
|
28
|
+
const containerStr = process.env.AZURE_STORAGE_CONTAINER_NAME || "whispertempfiles";
|
|
29
|
+
return containerStr.split(',').map(name => name.trim());
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const result = parseContainerNames();
|
|
33
|
+
|
|
34
|
+
t.is(result.length, 1);
|
|
35
|
+
t.is(result[0], "single-container");
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
test("parseContainerNames should handle comma-separated container names", (t) => {
|
|
39
|
+
// Set environment variable for multiple containers
|
|
40
|
+
process.env.AZURE_STORAGE_CONTAINER_NAME = "container1,container2,container3";
|
|
41
|
+
|
|
42
|
+
const parseContainerNames = () => {
|
|
43
|
+
const containerStr = process.env.AZURE_STORAGE_CONTAINER_NAME || "whispertempfiles";
|
|
44
|
+
return containerStr.split(',').map(name => name.trim());
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const result = parseContainerNames();
|
|
48
|
+
|
|
49
|
+
t.is(result.length, 3);
|
|
50
|
+
t.is(result[0], "container1");
|
|
51
|
+
t.is(result[1], "container2");
|
|
52
|
+
t.is(result[2], "container3");
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test("parseContainerNames should handle comma-separated names with whitespace", (t) => {
|
|
56
|
+
// Set environment variable with spaces around commas
|
|
57
|
+
process.env.AZURE_STORAGE_CONTAINER_NAME = " container1 , container2 , container3 ";
|
|
58
|
+
|
|
59
|
+
const parseContainerNames = () => {
|
|
60
|
+
const containerStr = process.env.AZURE_STORAGE_CONTAINER_NAME || "whispertempfiles";
|
|
61
|
+
return containerStr.split(',').map(name => name.trim());
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const result = parseContainerNames();
|
|
65
|
+
|
|
66
|
+
t.is(result.length, 3);
|
|
67
|
+
t.is(result[0], "container1");
|
|
68
|
+
t.is(result[1], "container2");
|
|
69
|
+
t.is(result[2], "container3");
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
test("parseContainerNames should default to whispertempfiles when env var is not set", (t) => {
|
|
73
|
+
// Unset environment variable
|
|
74
|
+
delete process.env.AZURE_STORAGE_CONTAINER_NAME;
|
|
75
|
+
|
|
76
|
+
const parseContainerNames = () => {
|
|
77
|
+
const containerStr = process.env.AZURE_STORAGE_CONTAINER_NAME || "whispertempfiles";
|
|
78
|
+
return containerStr.split(',').map(name => name.trim());
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
const result = parseContainerNames();
|
|
82
|
+
|
|
83
|
+
t.is(result.length, 1);
|
|
84
|
+
t.is(result[0], "whispertempfiles");
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
test("parseContainerNames should handle empty string", (t) => {
|
|
88
|
+
// Set environment variable to empty string
|
|
89
|
+
process.env.AZURE_STORAGE_CONTAINER_NAME = "";
|
|
90
|
+
|
|
91
|
+
const parseContainerNames = () => {
|
|
92
|
+
const containerStr = process.env.AZURE_STORAGE_CONTAINER_NAME || "whispertempfiles";
|
|
93
|
+
return containerStr.split(',').map(name => name.trim());
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const result = parseContainerNames();
|
|
97
|
+
|
|
98
|
+
t.is(result.length, 1);
|
|
99
|
+
t.is(result[0], "whispertempfiles");
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
test("parseContainerNames should handle only commas", (t) => {
|
|
103
|
+
// Set environment variable to only commas
|
|
104
|
+
process.env.AZURE_STORAGE_CONTAINER_NAME = ",,,";
|
|
105
|
+
|
|
106
|
+
const parseContainerNames = () => {
|
|
107
|
+
const containerStr = process.env.AZURE_STORAGE_CONTAINER_NAME || "whispertempfiles";
|
|
108
|
+
return containerStr.split(',').map(name => name.trim());
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const result = parseContainerNames();
|
|
112
|
+
|
|
113
|
+
// Should result in 4 empty strings after trimming
|
|
114
|
+
t.is(result.length, 4);
|
|
115
|
+
t.is(result[0], "");
|
|
116
|
+
t.is(result[1], "");
|
|
117
|
+
t.is(result[2], "");
|
|
118
|
+
t.is(result[3], "");
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
test("DEFAULT_AZURE_STORAGE_CONTAINER_NAME should be the first container in the list", (t) => {
|
|
122
|
+
// Test with current module exports (these are loaded at import time)
|
|
123
|
+
// The default should be the first item in the array
|
|
124
|
+
t.is(DEFAULT_AZURE_STORAGE_CONTAINER_NAME, AZURE_STORAGE_CONTAINER_NAMES[0]);
|
|
125
|
+
|
|
126
|
+
// Additional validation that it's a non-empty string
|
|
127
|
+
t.truthy(DEFAULT_AZURE_STORAGE_CONTAINER_NAME);
|
|
128
|
+
t.is(typeof DEFAULT_AZURE_STORAGE_CONTAINER_NAME, 'string');
|
|
129
|
+
t.true(DEFAULT_AZURE_STORAGE_CONTAINER_NAME.length > 0);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
test("isValidContainerName should return true for valid container names", (t) => {
|
|
133
|
+
// Test with each container name from the current configuration
|
|
134
|
+
AZURE_STORAGE_CONTAINER_NAMES.forEach(containerName => {
|
|
135
|
+
t.true(isValidContainerName(containerName), `Container name '${containerName}' should be valid`);
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
test("isValidContainerName should return false for invalid container names", (t) => {
|
|
140
|
+
const invalidNames = [
|
|
141
|
+
"invalid-container",
|
|
142
|
+
"not-in-list",
|
|
143
|
+
"",
|
|
144
|
+
null,
|
|
145
|
+
undefined,
|
|
146
|
+
"container-that-does-not-exist"
|
|
147
|
+
];
|
|
148
|
+
|
|
149
|
+
invalidNames.forEach(containerName => {
|
|
150
|
+
t.false(isValidContainerName(containerName), `Container name '${containerName}' should be invalid`);
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
test("isValidContainerName should handle edge cases", (t) => {
|
|
155
|
+
// Test with various edge cases
|
|
156
|
+
t.false(isValidContainerName(null));
|
|
157
|
+
t.false(isValidContainerName(undefined));
|
|
158
|
+
t.false(isValidContainerName(""));
|
|
159
|
+
t.false(isValidContainerName(" ")); // whitespace only
|
|
160
|
+
t.false(isValidContainerName(123)); // number
|
|
161
|
+
t.false(isValidContainerName({})); // object
|
|
162
|
+
t.false(isValidContainerName([])); // array
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
test("container configuration should have at least one container", (t) => {
|
|
166
|
+
t.true(AZURE_STORAGE_CONTAINER_NAMES.length > 0, "Should have at least one container configured");
|
|
167
|
+
t.truthy(AZURE_STORAGE_CONTAINER_NAMES[0], "First container should not be empty");
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
test("all configured container names should be non-empty strings", (t) => {
|
|
171
|
+
AZURE_STORAGE_CONTAINER_NAMES.forEach((containerName, index) => {
|
|
172
|
+
t.is(typeof containerName, 'string', `Container at index ${index} should be a string`);
|
|
173
|
+
t.true(containerName.length > 0, `Container at index ${index} should not be empty`);
|
|
174
|
+
t.true(containerName.trim().length > 0, `Container at index ${index} should not be only whitespace`);
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
test("container names should not contain duplicates", (t) => {
|
|
179
|
+
const uniqueNames = new Set(AZURE_STORAGE_CONTAINER_NAMES);
|
|
180
|
+
t.is(uniqueNames.size, AZURE_STORAGE_CONTAINER_NAMES.length, "Container names should be unique");
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
// Integration test with actual environment simulation
|
|
184
|
+
test("complete container parsing workflow", (t) => {
|
|
185
|
+
const testCases = [
|
|
186
|
+
{
|
|
187
|
+
env: "single",
|
|
188
|
+
expected: ["single"],
|
|
189
|
+
description: "single container name"
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
env: "first,second",
|
|
193
|
+
expected: ["first", "second"],
|
|
194
|
+
description: "two container names"
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
env: "one, two, three",
|
|
198
|
+
expected: ["one", "two", "three"],
|
|
199
|
+
description: "three container names with spaces"
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
env: " leading , trailing ",
|
|
203
|
+
expected: ["leading", "trailing"],
|
|
204
|
+
description: "names with leading/trailing spaces"
|
|
205
|
+
}
|
|
206
|
+
];
|
|
207
|
+
|
|
208
|
+
testCases.forEach(({ env, expected, description }) => {
|
|
209
|
+
const parseContainerNames = () => {
|
|
210
|
+
return env.split(',').map(name => name.trim());
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
const containerNames = parseContainerNames();
|
|
214
|
+
const defaultContainer = containerNames[0];
|
|
215
|
+
|
|
216
|
+
// Test parsing
|
|
217
|
+
t.deepEqual(containerNames, expected, `Parsing should work for ${description}`);
|
|
218
|
+
|
|
219
|
+
// Test default is first
|
|
220
|
+
t.is(defaultContainer, expected[0], `Default should be first container for ${description}`);
|
|
221
|
+
|
|
222
|
+
// Test validation
|
|
223
|
+
expected.forEach(name => {
|
|
224
|
+
t.true(containerNames.includes(name), `${name} should be valid for ${description}`);
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
t.false(containerNames.includes("invalid"), `Invalid name should not be valid for ${description}`);
|
|
228
|
+
});
|
|
229
|
+
});
|
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
import test from "ava";
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import os from "os";
|
|
5
|
+
import { fileURLToPath } from "url";
|
|
6
|
+
import { v4 as uuidv4 } from "uuid";
|
|
7
|
+
import axios from "axios";
|
|
8
|
+
import FormData from "form-data";
|
|
9
|
+
import { port } from "../src/start.js";
|
|
10
|
+
import {
|
|
11
|
+
uploadBlob,
|
|
12
|
+
isValidContainerName,
|
|
13
|
+
AZURE_STORAGE_CONTAINER_NAMES,
|
|
14
|
+
DEFAULT_AZURE_STORAGE_CONTAINER_NAME,
|
|
15
|
+
} from "../src/blobHandler.js";
|
|
16
|
+
import CortexFileHandler from "../src/index.js";
|
|
17
|
+
import {
|
|
18
|
+
startTestServer,
|
|
19
|
+
stopTestServer,
|
|
20
|
+
setupTestDirectory,
|
|
21
|
+
cleanupHashAndFile,
|
|
22
|
+
getFolderNameFromUrl,
|
|
23
|
+
} from "./testUtils.helper.js";
|
|
24
|
+
|
|
25
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
26
|
+
const __dirname = path.dirname(__filename);
|
|
27
|
+
const baseUrl = `http://localhost:${port}/api/CortexFileHandler`;
|
|
28
|
+
|
|
29
|
+
// Helper function to create test files
|
|
30
|
+
async function createTestFile(content, extension) {
|
|
31
|
+
const testDir = path.join(__dirname, "test-files");
|
|
32
|
+
if (!fs.existsSync(testDir)) {
|
|
33
|
+
fs.mkdirSync(testDir, { recursive: true });
|
|
34
|
+
}
|
|
35
|
+
const filename = path.join(testDir, `${uuidv4()}.${extension}`);
|
|
36
|
+
fs.writeFileSync(filename, content);
|
|
37
|
+
return filename;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Mock context for testing
|
|
41
|
+
const mockContext = {
|
|
42
|
+
log: (message) => console.log(`[TEST] ${message}`),
|
|
43
|
+
res: null,
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// Setup: Create test directory and start server
|
|
47
|
+
test.before(async (t) => {
|
|
48
|
+
await startTestServer();
|
|
49
|
+
await setupTestDirectory(t);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
// Cleanup
|
|
53
|
+
test.after.always(async (t) => {
|
|
54
|
+
await stopTestServer();
|
|
55
|
+
|
|
56
|
+
// Clean up test directory
|
|
57
|
+
if (t.context?.testDir) {
|
|
58
|
+
await fs.promises.rm(t.context.testDir, { recursive: true, force: true });
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Clean up any remaining files in the test-files directory
|
|
62
|
+
const testFilesDir = path.join(__dirname, "test-files");
|
|
63
|
+
if (fs.existsSync(testFilesDir)) {
|
|
64
|
+
try {
|
|
65
|
+
await fs.promises.rm(testFilesDir, { recursive: true, force: true });
|
|
66
|
+
} catch (error) {
|
|
67
|
+
console.log("Error cleaning test files:", error);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// Test container parameter validation
|
|
73
|
+
test("should validate container names correctly", (t) => {
|
|
74
|
+
// Test with valid container names from configuration
|
|
75
|
+
AZURE_STORAGE_CONTAINER_NAMES.forEach(containerName => {
|
|
76
|
+
t.true(isValidContainerName(containerName), `${containerName} should be valid`);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// Test with invalid container names
|
|
80
|
+
const invalidNames = ["invalid-container", "", null, undefined, "nonexistent"];
|
|
81
|
+
invalidNames.forEach(name => {
|
|
82
|
+
t.false(isValidContainerName(name), `${name} should be invalid`);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// Test uploadBlob function with container parameter
|
|
87
|
+
test("uploadBlob should accept and use container parameter from function parameter", async (t) => {
|
|
88
|
+
if (!process.env.AZURE_STORAGE_CONNECTION_STRING) {
|
|
89
|
+
t.pass("Skipping test - Azure not configured");
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Create a test file
|
|
94
|
+
const testFile = await createTestFile("test content", "txt");
|
|
95
|
+
const testStream = fs.createReadStream(testFile);
|
|
96
|
+
|
|
97
|
+
// Mock request with container parameter in function call
|
|
98
|
+
const mockReq = {
|
|
99
|
+
headers: { "content-type": "application/octet-stream" },
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
const originalEnv = process.env.AZURE_STORAGE_CONTAINER_NAME;
|
|
103
|
+
process.env.AZURE_STORAGE_CONTAINER_NAME = "test1,test2,test3";
|
|
104
|
+
|
|
105
|
+
try {
|
|
106
|
+
// Call uploadBlob with container parameter
|
|
107
|
+
const result = await uploadBlob(
|
|
108
|
+
mockContext,
|
|
109
|
+
mockReq,
|
|
110
|
+
false, // saveToLocal
|
|
111
|
+
testFile, // filePath
|
|
112
|
+
null, // hash
|
|
113
|
+
"test2" // container parameter
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
t.truthy(result);
|
|
117
|
+
t.truthy(result.url || mockContext.res?.body?.url);
|
|
118
|
+
|
|
119
|
+
// Cleanup
|
|
120
|
+
const uploadedUrl = result.url || mockContext.res?.body?.url;
|
|
121
|
+
if (uploadedUrl) {
|
|
122
|
+
const folderName = getFolderNameFromUrl(uploadedUrl);
|
|
123
|
+
await cleanupHashAndFile(null, uploadedUrl, baseUrl);
|
|
124
|
+
}
|
|
125
|
+
} finally {
|
|
126
|
+
// Restore environment
|
|
127
|
+
if (originalEnv) {
|
|
128
|
+
process.env.AZURE_STORAGE_CONTAINER_NAME = originalEnv;
|
|
129
|
+
} else {
|
|
130
|
+
delete process.env.AZURE_STORAGE_CONTAINER_NAME;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Cleanup test file
|
|
134
|
+
if (fs.existsSync(testFile)) {
|
|
135
|
+
fs.unlinkSync(testFile);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
// Test uploadBlob function with container parameter in form data
|
|
141
|
+
test("uploadBlob should accept container parameter from form data", async (t) => {
|
|
142
|
+
if (!process.env.AZURE_STORAGE_CONNECTION_STRING) {
|
|
143
|
+
t.pass("Skipping test - Azure not configured");
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const originalEnv = process.env.AZURE_STORAGE_CONTAINER_NAME;
|
|
148
|
+
process.env.AZURE_STORAGE_CONTAINER_NAME = "test1,test2,test3";
|
|
149
|
+
|
|
150
|
+
try {
|
|
151
|
+
// Create a test file
|
|
152
|
+
const testContent = "test content for form data";
|
|
153
|
+
const testFile = await createTestFile(testContent, "txt");
|
|
154
|
+
|
|
155
|
+
// Create form data with container parameter
|
|
156
|
+
const form = new FormData();
|
|
157
|
+
form.append("file", fs.createReadStream(testFile), "test.txt");
|
|
158
|
+
form.append("container", "test3");
|
|
159
|
+
|
|
160
|
+
const response = await axios.post(baseUrl, form, {
|
|
161
|
+
headers: {
|
|
162
|
+
...form.getHeaders(),
|
|
163
|
+
"Content-Type": "multipart/form-data",
|
|
164
|
+
},
|
|
165
|
+
validateStatus: (status) => true,
|
|
166
|
+
timeout: 30000,
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
t.is(response.status, 200);
|
|
170
|
+
t.truthy(response.data.url);
|
|
171
|
+
|
|
172
|
+
// Cleanup
|
|
173
|
+
await cleanupHashAndFile(null, response.data.url, baseUrl);
|
|
174
|
+
} finally {
|
|
175
|
+
// Restore environment
|
|
176
|
+
if (originalEnv) {
|
|
177
|
+
process.env.AZURE_STORAGE_CONTAINER_NAME = originalEnv;
|
|
178
|
+
} else {
|
|
179
|
+
delete process.env.AZURE_STORAGE_CONTAINER_NAME;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
// Test invalid container name in form data
|
|
185
|
+
test("uploadBlob should reject invalid container names in form data", async (t) => {
|
|
186
|
+
if (!process.env.AZURE_STORAGE_CONNECTION_STRING) {
|
|
187
|
+
t.pass("Skipping test - Azure not configured");
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Create a test file
|
|
192
|
+
const testContent = "test content";
|
|
193
|
+
const testFile = await createTestFile(testContent, "txt");
|
|
194
|
+
|
|
195
|
+
try {
|
|
196
|
+
// Create form data with invalid container parameter
|
|
197
|
+
const form = new FormData();
|
|
198
|
+
form.append("file", fs.createReadStream(testFile), "test.txt");
|
|
199
|
+
form.append("container", "invalid-container-name");
|
|
200
|
+
|
|
201
|
+
const response = await axios.post(baseUrl, form, {
|
|
202
|
+
headers: {
|
|
203
|
+
...form.getHeaders(),
|
|
204
|
+
"Content-Type": "multipart/form-data",
|
|
205
|
+
},
|
|
206
|
+
validateStatus: (status) => true,
|
|
207
|
+
timeout: 30000,
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
t.is(response.status, 400);
|
|
211
|
+
t.truthy(response.data);
|
|
212
|
+
t.true(
|
|
213
|
+
response.data.includes("Invalid container name")
|
|
214
|
+
);
|
|
215
|
+
} finally {
|
|
216
|
+
// Cleanup test file
|
|
217
|
+
if (fs.existsSync(testFile)) {
|
|
218
|
+
fs.unlinkSync(testFile);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
// Test container parameter flow through index.js
|
|
224
|
+
test("CortexFileHandler should pass container parameter for remote file downloads", async (t) => {
|
|
225
|
+
if (!process.env.AZURE_STORAGE_CONNECTION_STRING) {
|
|
226
|
+
t.pass("Skipping test - Azure not configured");
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const originalEnv = process.env.AZURE_STORAGE_CONTAINER_NAME;
|
|
231
|
+
process.env.AZURE_STORAGE_CONTAINER_NAME = "test1,test2,test3";
|
|
232
|
+
|
|
233
|
+
try {
|
|
234
|
+
// Create a test file URL (this would typically be a remote URL)
|
|
235
|
+
const testUrl = "https://example.com/test.txt";
|
|
236
|
+
|
|
237
|
+
// Mock request for remote file with container parameter
|
|
238
|
+
const mockReq = {
|
|
239
|
+
query: {
|
|
240
|
+
fetch: testUrl,
|
|
241
|
+
container: "test2"
|
|
242
|
+
},
|
|
243
|
+
method: "GET"
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
// Since we can't easily test real remote downloads in unit tests,
|
|
247
|
+
// we'll test the parameter extraction and validation
|
|
248
|
+
const { container } = mockReq.query;
|
|
249
|
+
|
|
250
|
+
t.is(container, "test2");
|
|
251
|
+
t.true(isValidContainerName(container));
|
|
252
|
+
} finally {
|
|
253
|
+
// Restore environment
|
|
254
|
+
if (originalEnv) {
|
|
255
|
+
process.env.AZURE_STORAGE_CONTAINER_NAME = originalEnv;
|
|
256
|
+
} else {
|
|
257
|
+
delete process.env.AZURE_STORAGE_CONTAINER_NAME;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
// Test container parameter flow for document processing
|
|
263
|
+
test("CortexFileHandler should pass container parameter for document processing", async (t) => {
|
|
264
|
+
if (!process.env.AZURE_STORAGE_CONNECTION_STRING) {
|
|
265
|
+
t.pass("Skipping test - Azure not configured");
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
const originalEnv = process.env.AZURE_STORAGE_CONTAINER_NAME;
|
|
270
|
+
process.env.AZURE_STORAGE_CONTAINER_NAME = "test1,test2,test3";
|
|
271
|
+
|
|
272
|
+
try {
|
|
273
|
+
// Mock request for document processing with container parameter
|
|
274
|
+
const mockReq = {
|
|
275
|
+
body: {
|
|
276
|
+
params: {
|
|
277
|
+
uri: "https://example.com/test.pdf",
|
|
278
|
+
requestId: "test-request",
|
|
279
|
+
container: "test3"
|
|
280
|
+
}
|
|
281
|
+
},
|
|
282
|
+
query: {},
|
|
283
|
+
method: "GET"
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
// Extract parameters like index.js does
|
|
287
|
+
const {
|
|
288
|
+
uri,
|
|
289
|
+
requestId,
|
|
290
|
+
container,
|
|
291
|
+
} = mockReq.body?.params || mockReq.query;
|
|
292
|
+
|
|
293
|
+
t.is(uri, "https://example.com/test.pdf");
|
|
294
|
+
t.is(requestId, "test-request");
|
|
295
|
+
t.is(container, "test3");
|
|
296
|
+
t.true(isValidContainerName(container));
|
|
297
|
+
} finally {
|
|
298
|
+
// Restore environment
|
|
299
|
+
if (originalEnv) {
|
|
300
|
+
process.env.AZURE_STORAGE_CONTAINER_NAME = originalEnv;
|
|
301
|
+
} else {
|
|
302
|
+
delete process.env.AZURE_STORAGE_CONTAINER_NAME;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
// Test default container behavior
|
|
308
|
+
test("should use default container when no container specified", async (t) => {
|
|
309
|
+
if (!process.env.AZURE_STORAGE_CONNECTION_STRING) {
|
|
310
|
+
t.pass("Skipping test - Azure not configured");
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// Test that default container is first in the list
|
|
315
|
+
t.is(DEFAULT_AZURE_STORAGE_CONTAINER_NAME, AZURE_STORAGE_CONTAINER_NAMES[0]);
|
|
316
|
+
t.true(isValidContainerName(DEFAULT_AZURE_STORAGE_CONTAINER_NAME));
|
|
317
|
+
|
|
318
|
+
// Create a test file
|
|
319
|
+
const testContent = "test content for default container";
|
|
320
|
+
const testFile = await createTestFile(testContent, "txt");
|
|
321
|
+
|
|
322
|
+
try {
|
|
323
|
+
// Create form data without container parameter (should use default)
|
|
324
|
+
const form = new FormData();
|
|
325
|
+
form.append("file", fs.createReadStream(testFile), "test.txt");
|
|
326
|
+
|
|
327
|
+
const response = await axios.post(baseUrl, form, {
|
|
328
|
+
headers: {
|
|
329
|
+
...form.getHeaders(),
|
|
330
|
+
"Content-Type": "multipart/form-data",
|
|
331
|
+
},
|
|
332
|
+
validateStatus: (status) => true,
|
|
333
|
+
timeout: 30000,
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
t.is(response.status, 200);
|
|
337
|
+
t.truthy(response.data.url);
|
|
338
|
+
|
|
339
|
+
// Cleanup
|
|
340
|
+
await cleanupHashAndFile(null, response.data.url, baseUrl);
|
|
341
|
+
} finally {
|
|
342
|
+
// Cleanup test file
|
|
343
|
+
if (fs.existsSync(testFile)) {
|
|
344
|
+
fs.unlinkSync(testFile);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
// Test container parameter with media chunking
|
|
350
|
+
test("should pass container parameter for media file chunking", async (t) => {
|
|
351
|
+
if (!process.env.AZURE_STORAGE_CONNECTION_STRING) {
|
|
352
|
+
t.pass("Skipping test - Azure not configured");
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
const originalEnv = process.env.AZURE_STORAGE_CONTAINER_NAME;
|
|
357
|
+
process.env.AZURE_STORAGE_CONTAINER_NAME = "test1,test2,test3";
|
|
358
|
+
|
|
359
|
+
try {
|
|
360
|
+
// Mock request for media file processing with container parameter
|
|
361
|
+
const mockReq = {
|
|
362
|
+
body: {
|
|
363
|
+
params: {
|
|
364
|
+
uri: "https://example.com/test.mp3",
|
|
365
|
+
requestId: "test-media-request",
|
|
366
|
+
container: "test1"
|
|
367
|
+
}
|
|
368
|
+
},
|
|
369
|
+
query: {},
|
|
370
|
+
method: "GET"
|
|
371
|
+
};
|
|
372
|
+
|
|
373
|
+
// Extract parameters like index.js does
|
|
374
|
+
const {
|
|
375
|
+
uri,
|
|
376
|
+
requestId,
|
|
377
|
+
container,
|
|
378
|
+
} = mockReq.body?.params || mockReq.query;
|
|
379
|
+
|
|
380
|
+
t.is(uri, "https://example.com/test.mp3");
|
|
381
|
+
t.is(requestId, "test-media-request");
|
|
382
|
+
t.is(container, "test1");
|
|
383
|
+
t.true(isValidContainerName(container));
|
|
384
|
+
} finally {
|
|
385
|
+
// Restore environment
|
|
386
|
+
if (originalEnv) {
|
|
387
|
+
process.env.AZURE_STORAGE_CONTAINER_NAME = originalEnv;
|
|
388
|
+
} else {
|
|
389
|
+
delete process.env.AZURE_STORAGE_CONTAINER_NAME;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
});
|
|
@@ -8,7 +8,7 @@ import XLSX from "xlsx";
|
|
|
8
8
|
import { port } from "../src/start.js";
|
|
9
9
|
import { gcs, GCS_BUCKETNAME } from "../src/blobHandler.js";
|
|
10
10
|
import { getFileStoreMap, setFileStoreMap } from "../src/redis.js";
|
|
11
|
-
import { cleanupHashAndFile } from "./testUtils.helper.js";
|
|
11
|
+
import { cleanupHashAndFile, startTestServer, stopTestServer } from "./testUtils.helper.js";
|
|
12
12
|
import { gcsUrlExists } from "../src/blobHandler.js";
|
|
13
13
|
|
|
14
14
|
const baseUrl = `http://localhost:${port}/api/CortexFileHandler`;
|
|
@@ -47,13 +47,18 @@ function isGcsConfigured() {
|
|
|
47
47
|
return !!gcs;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
+
// Ensure server is ready before tests
|
|
50
51
|
test.before(async (t) => {
|
|
52
|
+
await startTestServer();
|
|
51
53
|
const dir = path.join(fs.mkdtempSync(path.join(process.cwd(), "conv-test-")));
|
|
52
54
|
t.context.tmpDir = dir;
|
|
53
55
|
});
|
|
54
56
|
|
|
55
57
|
test.after.always(async (t) => {
|
|
56
|
-
|
|
58
|
+
await stopTestServer();
|
|
59
|
+
if (t.context?.tmpDir) {
|
|
60
|
+
fs.rmSync(t.context.tmpDir, { recursive: true, force: true });
|
|
61
|
+
}
|
|
57
62
|
});
|
|
58
63
|
|
|
59
64
|
// 1. Remote-URL upload path should still return converted info
|