@geode/opengeodeweb-front 10.30.0-rc.8 → 10.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app/components/ObjectSelector.vue +26 -76
- package/app/components/Viewer/Generic/Model/BlocksOptions.vue +2 -2
- package/app/components/Viewer/Generic/Model/CornersOptions.vue +2 -2
- package/app/components/Viewer/Generic/Model/LinesOptions.vue +2 -2
- package/app/components/Viewer/Generic/Model/SurfacesOptions.vue +2 -2
- package/app/components/Viewer/ObjectTree/Base/CommonTreeView.vue +1 -0
- package/app/components/Viewer/ObjectTree/Base/TreeRow.vue +8 -0
- package/app/components/Viewer/ObjectTree/Views/GlobalObjects.vue +3 -0
- package/app/components/Viewer/Options/AttributeSelector.vue +13 -6
- package/app/components/Viewer/Options/ColoringTypeSelector.vue +7 -7
- package/app/composables/project_manager.js +14 -11
- package/app/stores/app.js +8 -7
- package/app/stores/back.js +2 -13
- package/app/stores/cloud.js +3 -0
- package/app/stores/infra.js +0 -5
- package/app/stores/viewer.js +0 -12
- package/app/utils/extension.js +4 -3
- package/app/utils/import_workflow.js +1 -9
- package/app/utils/log.js +18 -0
- package/internal/utils/api_fetch.js +26 -53
- package/internal/utils/upload_file.js +33 -29
- package/internal/utils/viewer_call.js +7 -2
- package/package.json +17 -16
- package/server/api/cloud/extensions/run.post.js +72 -0
- package/server/api/{microservice → local}/extensions/run.post.js +10 -46
- package/server/api/microservice/app/set_back_base_url.post.js +22 -0
- package/server/api/microservice/app/set_viewer_base_url.post.js +22 -0
- package/server/utils/cloud.js +107 -1
- package/server/utils/extension.js +50 -0
- package/server/utils/microservices.js +51 -26
- package/server/utils/path.js +10 -0
- package/server/utils/server_config.js +4 -10
- package/shared/scripts.js +47 -9
- package/shared/utils/fetch_raw.js +1 -0
- package/shared/utils/response_handlers/load.js +74 -0
- package/tests/unit/composables/project_manager.nuxt.test.js +12 -1
- package/tests/unit/composables/upload_file.nuxt.test.js +2 -2
- package/tests/unit/stores/cloud.nuxt.test.js +23 -26
- package/tests/unit/stores/infra.nuxt.test.js +12 -5
- package/tests/unit/utils/validate_schema.nuxt.test.js +1 -1
- package/app/utils/validate_schema.js +0 -13
- /package/server/api/{microservice → local}/extensions/kill.post.js +0 -0
- /package/server/api/serverless/{run_cloud.js → run_cloud.post.js} +0 -0
|
@@ -7,6 +7,7 @@ import path from "node:path";
|
|
|
7
7
|
import back_schemas from "@geode/opengeodeweb-back/opengeodeweb_back_schemas.json" with { type: "json" };
|
|
8
8
|
|
|
9
9
|
// Local imports
|
|
10
|
+
import { addNginxLocation, addSupervisorProgram } from "./cloud.js";
|
|
10
11
|
import { getAvailablePort, waitForReady } from "./scripts.js";
|
|
11
12
|
import { microservicesMetadatasPath, projectMicroservices } from "./cleanup.js";
|
|
12
13
|
import { executablePath } from "./path.js";
|
|
@@ -57,33 +58,11 @@ function isPortInUseError(errorMessage) {
|
|
|
57
58
|
}
|
|
58
59
|
|
|
59
60
|
async function runBack(execName, execPath, args = {}, attempts = 0) {
|
|
60
|
-
const { projectFolderPath } = args;
|
|
61
|
-
if (!projectFolderPath) {
|
|
62
|
-
throw new Error("projectFolderPath is required");
|
|
63
|
-
}
|
|
64
|
-
let { uploadFolderPath } = args;
|
|
65
|
-
if (!uploadFolderPath) {
|
|
66
|
-
uploadFolderPath = path.join(projectFolderPath, "uploads");
|
|
67
|
-
}
|
|
68
61
|
try {
|
|
69
62
|
const port = await getAvailablePort();
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
"--project_folder_path",
|
|
74
|
-
projectFolderPath,
|
|
75
|
-
"--upload_folder_path",
|
|
76
|
-
uploadFolderPath,
|
|
77
|
-
"--allowed_origins",
|
|
78
|
-
"http://localhost:*",
|
|
79
|
-
"--timeout",
|
|
80
|
-
"0",
|
|
81
|
-
];
|
|
82
|
-
if (process.env.NODE_ENV === "development" || !process.env.NODE_ENV) {
|
|
83
|
-
backArgs.push("--debug");
|
|
84
|
-
}
|
|
85
|
-
console.log("runBack", execPath, execName, backArgs);
|
|
86
|
-
await runScript(execPath, execName, backArgs, "Serving Flask app");
|
|
63
|
+
const executableArgs = backArgs(args, port);
|
|
64
|
+
console.log("runBack", execPath, execName, executableArgs);
|
|
65
|
+
await runScript(execPath, execName, executableArgs, "Serving Flask app");
|
|
87
66
|
return port;
|
|
88
67
|
} catch (error) {
|
|
89
68
|
if (!isPortInUseError(error)) {
|
|
@@ -129,6 +108,52 @@ async function runViewer(execName, execPath, args = {}, attempts = 0) {
|
|
|
129
108
|
}
|
|
130
109
|
}
|
|
131
110
|
|
|
111
|
+
function backArgs(args, port) {
|
|
112
|
+
const { projectFolderPath } = args;
|
|
113
|
+
if (!projectFolderPath) {
|
|
114
|
+
throw new Error("projectFolderPath is required");
|
|
115
|
+
}
|
|
116
|
+
const uploadFolderPath = args.uploadFolderPath || path.join(projectFolderPath, "uploads");
|
|
117
|
+
const executableArgs = [
|
|
118
|
+
"--port",
|
|
119
|
+
String(port),
|
|
120
|
+
"--project_folder_path",
|
|
121
|
+
projectFolderPath,
|
|
122
|
+
"--upload_folder_path",
|
|
123
|
+
uploadFolderPath,
|
|
124
|
+
"--allowed_origins",
|
|
125
|
+
"http://localhost:*",
|
|
126
|
+
"--timeout",
|
|
127
|
+
"0",
|
|
128
|
+
];
|
|
129
|
+
if (process.env.NODE_ENV === "development" || !process.env.NODE_ENV) {
|
|
130
|
+
executableArgs.push("--debug");
|
|
131
|
+
}
|
|
132
|
+
return executableArgs;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
async function runExtension(extensionId, execName, execPath, args = {}, attempts = 0) {
|
|
136
|
+
try {
|
|
137
|
+
const port = await getAvailablePort();
|
|
138
|
+
const executableArgs = backArgs(args, port);
|
|
139
|
+
const command = executablePath(execPath, execName);
|
|
140
|
+
console.log("runExtension", execPath, execName, executableArgs);
|
|
141
|
+
addSupervisorProgram(extensionId, command, executableArgs);
|
|
142
|
+
addNginxLocation(extensionId, port);
|
|
143
|
+
return port;
|
|
144
|
+
} catch (error) {
|
|
145
|
+
if (!isPortInUseError(error)) {
|
|
146
|
+
console.log("runBack error", error);
|
|
147
|
+
throw error;
|
|
148
|
+
}
|
|
149
|
+
if (attempts <= MAX_PORT_RETRIES) {
|
|
150
|
+
console.log("Retrying runExtension on conflicting port", port);
|
|
151
|
+
const port = await runExtension(extensionId, execName, execPath, args, attempts + 1);
|
|
152
|
+
return port;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
132
157
|
function addMicroserviceMetadatas(projectFolderPath, serviceObj) {
|
|
133
158
|
const microservices = projectMicroservices(projectFolderPath);
|
|
134
159
|
if (serviceObj.type === "back") {
|
|
@@ -147,4 +172,4 @@ function addMicroserviceMetadatas(projectFolderPath, serviceObj) {
|
|
|
147
172
|
);
|
|
148
173
|
}
|
|
149
174
|
|
|
150
|
-
export { addMicroserviceMetadatas, runBack, runViewer };
|
|
175
|
+
export { addMicroserviceMetadatas, runBack, runExtension, runViewer };
|
package/server/utils/path.js
CHANGED
|
@@ -138,8 +138,18 @@ async function extensionFrontendPath(unzippedExtensionPath, frontendFile, rootPa
|
|
|
138
138
|
throw new Error(`Failed to find ${unzippedfrontendFilePath}`);
|
|
139
139
|
}
|
|
140
140
|
|
|
141
|
+
function extensionBackendPath(unzippedExtensionPath, backendExecutableName) {
|
|
142
|
+
const backendExecutablePath = path.join(
|
|
143
|
+
unzippedExtensionPath,
|
|
144
|
+
executableName(backendExecutableName),
|
|
145
|
+
);
|
|
146
|
+
console.log("runExtensions", { backendExecutablePath });
|
|
147
|
+
return backendExecutablePath;
|
|
148
|
+
}
|
|
149
|
+
|
|
141
150
|
export {
|
|
142
151
|
createPath,
|
|
152
|
+
extensionBackendPath,
|
|
143
153
|
extensionFrontendPath,
|
|
144
154
|
extensionFolderPath,
|
|
145
155
|
executablePath,
|
|
@@ -1,30 +1,24 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createStorage, prefixStorage } from "unstorage";
|
|
2
|
+
|
|
3
|
+
const storage = createStorage();
|
|
4
|
+
const config = prefixStorage(storage, "config");
|
|
2
5
|
|
|
3
|
-
function getConfig() {
|
|
4
|
-
return useStorage("config");
|
|
5
|
-
}
|
|
6
6
|
function getAppBaseUrl() {
|
|
7
|
-
const config = getConfig();
|
|
8
7
|
return config.getItem("APP_BASE_URL");
|
|
9
8
|
}
|
|
10
9
|
function setAppBaseUrl(baseUrl) {
|
|
11
|
-
const config = getConfig();
|
|
12
10
|
return config.setItem("APP_BASE_URL", baseUrl);
|
|
13
11
|
}
|
|
14
12
|
function getBackBaseUrl() {
|
|
15
|
-
const config = getConfig();
|
|
16
13
|
return config.getItem("BACK_BASE_URL");
|
|
17
14
|
}
|
|
18
15
|
function setBackBaseUrl(baseUrl) {
|
|
19
|
-
const config = getConfig();
|
|
20
16
|
return config.setItem("BACK_BASE_URL", baseUrl);
|
|
21
17
|
}
|
|
22
18
|
function getViewerBaseUrl() {
|
|
23
|
-
const config = getConfig();
|
|
24
19
|
return config.getItem("VIEWER_BASE_URL");
|
|
25
20
|
}
|
|
26
21
|
function setViewerBaseUrl(baseUrl) {
|
|
27
|
-
const config = getConfig();
|
|
28
22
|
return config.setItem("VIEWER_BASE_URL", baseUrl);
|
|
29
23
|
}
|
|
30
24
|
|
package/shared/scripts.js
CHANGED
|
@@ -3,16 +3,54 @@
|
|
|
3
3
|
// Third party imports
|
|
4
4
|
|
|
5
5
|
// Local imports
|
|
6
|
+
import { fetchSchema } from "./utils/fetch_schema.js";
|
|
6
7
|
|
|
7
|
-
function setAppBaseUrl(
|
|
8
|
-
console.log(
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
function setAppBaseUrl(appBaseUrl) {
|
|
9
|
+
console.log("[API] setAppBaseUrl", appBaseUrl);
|
|
10
|
+
const schema = {
|
|
11
|
+
$id: "/api/microservice/app/set_app_base_url",
|
|
12
|
+
methods: ["POST"],
|
|
13
|
+
type: "object",
|
|
14
|
+
properties: {
|
|
15
|
+
baseUrl: { type: "string" },
|
|
13
16
|
},
|
|
14
|
-
|
|
15
|
-
|
|
17
|
+
required: ["baseUrl"],
|
|
18
|
+
additionalProperties: false,
|
|
19
|
+
};
|
|
20
|
+
const params = { baseUrl: appBaseUrl };
|
|
21
|
+
return fetchSchema({ schema, params, baseURL: appBaseUrl });
|
|
16
22
|
}
|
|
17
23
|
|
|
18
|
-
|
|
24
|
+
function setBackBaseUrl(appBaseUrl, backBaseUrl) {
|
|
25
|
+
console.log("[API] setBackBaseUrl", appBaseUrl, backBaseUrl);
|
|
26
|
+
const schema = {
|
|
27
|
+
$id: "/api/microservice/app/set_back_base_url",
|
|
28
|
+
methods: ["POST"],
|
|
29
|
+
type: "object",
|
|
30
|
+
properties: {
|
|
31
|
+
baseUrl: { type: "string" },
|
|
32
|
+
},
|
|
33
|
+
required: ["baseUrl"],
|
|
34
|
+
additionalProperties: false,
|
|
35
|
+
};
|
|
36
|
+
const params = { baseUrl: backBaseUrl };
|
|
37
|
+
return fetchSchema({ schema, params, baseURL: appBaseUrl });
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function setViewerBaseUrl(appBaseUrl, viewerBaseUrl) {
|
|
41
|
+
console.log("[API] setViewerBaseUrl", appBaseUrl, viewerBaseUrl);
|
|
42
|
+
const schema = {
|
|
43
|
+
$id: "/api/microservice/app/set_viewer_base_url",
|
|
44
|
+
methods: ["POST"],
|
|
45
|
+
type: "object",
|
|
46
|
+
properties: {
|
|
47
|
+
baseUrl: { type: "string" },
|
|
48
|
+
},
|
|
49
|
+
required: ["baseUrl"],
|
|
50
|
+
additionalProperties: false,
|
|
51
|
+
};
|
|
52
|
+
const params = { baseUrl: viewerBaseUrl };
|
|
53
|
+
return fetchSchema({ schema, params, baseURL: appBaseUrl });
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export { setAppBaseUrl, setBackBaseUrl, setViewerBaseUrl };
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
function getFileExtension(filename) {
|
|
2
|
+
return filename.slice(filename.lastIndexOf(".") + 1);
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
function selectGeodeObject(objectMap) {
|
|
6
|
+
const objectKeys = Object.keys(objectMap);
|
|
7
|
+
if (objectKeys.length === 0) {
|
|
8
|
+
return undefined;
|
|
9
|
+
}
|
|
10
|
+
if (objectKeys.length === 1 && objectMap[objectKeys[0]].is_loadable > 0) {
|
|
11
|
+
return objectKeys[0];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const highestLoadScore = Math.max(...objectKeys.map((key) => objectMap[key].is_loadable));
|
|
15
|
+
if (highestLoadScore <= 0) {
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const bestScoreObjects = objectKeys.filter(
|
|
20
|
+
(key) => objectMap[key].is_loadable === highestLoadScore,
|
|
21
|
+
);
|
|
22
|
+
if (bestScoreObjects.length === 1) {
|
|
23
|
+
return bestScoreObjects[0];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const highestPriority = Math.max(
|
|
27
|
+
...bestScoreObjects.map((key) => objectMap[key].object_priority ?? -Infinity),
|
|
28
|
+
);
|
|
29
|
+
const bestPriorityObjects = bestScoreObjects.filter(
|
|
30
|
+
(key) => objectMap[key].object_priority === highestPriority,
|
|
31
|
+
);
|
|
32
|
+
if (highestPriority !== -Infinity && bestPriorityObjects.length === 1) {
|
|
33
|
+
return bestPriorityObjects[0];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function intersectAllowedObjects(allowedObjectsList) {
|
|
40
|
+
const allKeys = [...new Set(allowedObjectsList.flatMap((object) => Object.keys(object)))];
|
|
41
|
+
const commonKeys = allKeys.filter((key) => allowedObjectsList.every((object) => key in object));
|
|
42
|
+
|
|
43
|
+
const mergedAllowedObjects = {};
|
|
44
|
+
for (const key of commonKeys) {
|
|
45
|
+
const loadScores = allowedObjectsList.map((object) => object[key].is_loadable);
|
|
46
|
+
const priorities = allowedObjectsList
|
|
47
|
+
.map((object) => object[key].object_priority)
|
|
48
|
+
.filter((priority) => priority !== undefined);
|
|
49
|
+
|
|
50
|
+
mergedAllowedObjects[key] = { is_loadable: Math.min(...loadScores) };
|
|
51
|
+
if (priorities.length > 0) {
|
|
52
|
+
mergedAllowedObjects[key].object_priority = Math.max(...priorities);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return { commonKeys, allKeys, mergedAllowedObjects };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function resolveAllowedObjects(filenames, allowedObjectsList) {
|
|
60
|
+
const { commonKeys, allKeys, mergedAllowedObjects } = intersectAllowedObjects(allowedObjectsList);
|
|
61
|
+
|
|
62
|
+
const multipleFilesNoCommon =
|
|
63
|
+
filenames.length > 1 && allKeys.length > 0 && commonKeys.length === 0;
|
|
64
|
+
|
|
65
|
+
const selectedGeodeObject = selectGeodeObject(mergedAllowedObjects);
|
|
66
|
+
|
|
67
|
+
return {
|
|
68
|
+
mergedAllowedObjects,
|
|
69
|
+
multipleFilesNoCommon,
|
|
70
|
+
selectedGeodeObject,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export { resolveAllowedObjects, getFileExtension };
|
|
@@ -8,6 +8,12 @@ import { exportProject, importProject } from "@ogw_front/composables/project_man
|
|
|
8
8
|
import { appMode } from "@ogw_shared/app_mode";
|
|
9
9
|
import { setupActivePinia } from "@ogw_tests/utils";
|
|
10
10
|
|
|
11
|
+
import { $fetch } from "ofetch";
|
|
12
|
+
|
|
13
|
+
vi.mock(import("ofetch"), () => ({
|
|
14
|
+
$fetch: vi.fn(),
|
|
15
|
+
}));
|
|
16
|
+
|
|
11
17
|
// Constants
|
|
12
18
|
const PANEL_WIDTH = 300;
|
|
13
19
|
const Z_SCALE = 1.5;
|
|
@@ -141,7 +147,12 @@ const hybridViewerStoreMock = {
|
|
|
141
147
|
};
|
|
142
148
|
|
|
143
149
|
// MOCKS
|
|
144
|
-
|
|
150
|
+
$fetch.mockImplementation((route, options) => {
|
|
151
|
+
const data = { snapshot: snapshotMock };
|
|
152
|
+
// oxlint-disable-next-line eslint/id-length
|
|
153
|
+
options.onResponse?.({ response: { ok: true, _data: data } });
|
|
154
|
+
return Promise.resolve(data);
|
|
155
|
+
});
|
|
145
156
|
vi.mock(import("@ogw_internal/utils/viewer_call"), () => ({
|
|
146
157
|
viewer_call: viewer_call_mock_fn,
|
|
147
158
|
}));
|
|
@@ -22,7 +22,7 @@ describe("upload_file", () => {
|
|
|
22
22
|
const backStore = useBackStore();
|
|
23
23
|
const file = "toto";
|
|
24
24
|
|
|
25
|
-
await expect(backStore.upload(file)).rejects.toThrow("file must be
|
|
25
|
+
await expect(backStore.upload(file)).rejects.toThrow("file must be an instance of File");
|
|
26
26
|
});
|
|
27
27
|
|
|
28
28
|
test("onResponse", async () => {
|
|
@@ -36,7 +36,7 @@ describe("upload_file", () => {
|
|
|
36
36
|
let response_value = "";
|
|
37
37
|
await backStore.upload(file, {
|
|
38
38
|
response_function: (response) => {
|
|
39
|
-
response_value = response.
|
|
39
|
+
response_value = response.test;
|
|
40
40
|
},
|
|
41
41
|
});
|
|
42
42
|
expect(feedbackStore.feedbacks).toHaveLength(ZERO);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Third party imports
|
|
2
2
|
import { beforeEach, describe, expect, expectTypeOf, test, vi } from "vitest";
|
|
3
|
-
import {
|
|
3
|
+
import { $fetch } from "ofetch";
|
|
4
4
|
|
|
5
5
|
// Local imports
|
|
6
6
|
import { Status } from "@ogw_front/utils/status";
|
|
@@ -8,9 +8,12 @@ import { setupActivePinia } from "@ogw_tests/utils";
|
|
|
8
8
|
import { useCloudStore } from "@ogw_front/stores/cloud";
|
|
9
9
|
import { useFeedbackStore } from "@ogw_front/stores/feedback";
|
|
10
10
|
|
|
11
|
+
vi.mock(import("ofetch"), () => ({
|
|
12
|
+
$fetch: vi.fn(),
|
|
13
|
+
}));
|
|
14
|
+
|
|
11
15
|
// CONSTANTS
|
|
12
16
|
const PROJECT = "project";
|
|
13
|
-
const STATUS_500 = 500;
|
|
14
17
|
|
|
15
18
|
function setupConfig() {
|
|
16
19
|
const config = useRuntimeConfig();
|
|
@@ -31,28 +34,23 @@ describe("cloud store", () => {
|
|
|
31
34
|
|
|
32
35
|
describe("actions", () => {
|
|
33
36
|
describe("launch", () => {
|
|
34
|
-
|
|
37
|
+
beforeEach(() => {
|
|
38
|
+
$fetch.mockReset();
|
|
39
|
+
});
|
|
35
40
|
|
|
36
41
|
test("successful launch", async () => {
|
|
37
42
|
setupConfig();
|
|
38
43
|
const cloudStore = useCloudStore();
|
|
39
44
|
const feedbackStore = useFeedbackStore();
|
|
40
45
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
46
|
+
$fetch.mockImplementation((route, options) => {
|
|
47
|
+
const data = { url: "test.com" };
|
|
48
|
+
// oxlint-disable-next-line eslint/id-length
|
|
49
|
+
options.onResponse?.({ response: { ok: true, _data: data } });
|
|
50
|
+
return Promise.resolve(data);
|
|
44
51
|
});
|
|
45
52
|
|
|
46
|
-
|
|
47
|
-
method: "POST",
|
|
48
|
-
handler: () => console.log("coucou from endpoint"),
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
postFakeCall.mockReturnValue({
|
|
52
|
-
url: "test.com",
|
|
53
|
-
});
|
|
54
|
-
const email = "noreply@example.com";
|
|
55
|
-
await cloudStore.launch(email);
|
|
53
|
+
await cloudStore.launch("noreply@example.com");
|
|
56
54
|
|
|
57
55
|
expect(cloudStore.status).toBe(Status.CONNECTED);
|
|
58
56
|
expect(feedbackStore.server_error).toBe(false);
|
|
@@ -63,19 +61,18 @@ describe("cloud store", () => {
|
|
|
63
61
|
const cloudStore = useCloudStore();
|
|
64
62
|
const feedbackStore = useFeedbackStore();
|
|
65
63
|
|
|
66
|
-
|
|
67
|
-
method: "POST",
|
|
68
|
-
handler: postFakeCall,
|
|
69
|
-
});
|
|
64
|
+
const error = createError({ statusCode: 500, statusMessage: "500 Internal Server Error" });
|
|
70
65
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
status:
|
|
74
|
-
statusMessage: "Internal Server Error",
|
|
66
|
+
$fetch.mockImplementation((route, options) => {
|
|
67
|
+
options.onResponseError?.({
|
|
68
|
+
response: { status: 500, name: "Error", description: "500 Internal Server Error" },
|
|
75
69
|
});
|
|
70
|
+
return Promise.reject(error);
|
|
76
71
|
});
|
|
77
|
-
|
|
78
|
-
await expect(cloudStore.launch(
|
|
72
|
+
|
|
73
|
+
await expect(cloudStore.launch("noreply@example.com")).rejects.toThrow(
|
|
74
|
+
"500 Internal Server Error",
|
|
75
|
+
);
|
|
79
76
|
|
|
80
77
|
expect(cloudStore.status).toBe(Status.NOT_CONNECTED);
|
|
81
78
|
expect(feedbackStore.server_error).toBe(true);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Third party imports
|
|
2
2
|
import { beforeEach, describe, expect, expectTypeOf, test, vi } from "vitest";
|
|
3
|
-
import {
|
|
3
|
+
import { $fetch } from "ofetch";
|
|
4
4
|
|
|
5
5
|
// Local imports
|
|
6
6
|
import { Status } from "@ogw_front/utils/status";
|
|
@@ -10,6 +10,10 @@ import { useBackStore } from "@ogw_front/stores/back";
|
|
|
10
10
|
import { useInfraStore } from "@ogw_front/stores/infra";
|
|
11
11
|
import { useViewerStore } from "@ogw_front/stores/viewer";
|
|
12
12
|
|
|
13
|
+
vi.mock(import("ofetch"), () => ({
|
|
14
|
+
$fetch: vi.fn(),
|
|
15
|
+
}));
|
|
16
|
+
|
|
13
17
|
// Mock navigator.locks API
|
|
14
18
|
const mockLockRequest = vi
|
|
15
19
|
.fn()
|
|
@@ -291,11 +295,14 @@ describe("infra store", () => {
|
|
|
291
295
|
|
|
292
296
|
infraStore.app_mode = appMode.CLOUD;
|
|
293
297
|
const url = "test.com";
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
298
|
+
$fetch.mockImplementation((route, options) => {
|
|
299
|
+
const data = { url };
|
|
300
|
+
// oxlint-disable-next-line eslint/id-length
|
|
301
|
+
options.onResponse?.({ response: { ok: true, _data: data } });
|
|
302
|
+
return Promise.resolve(data);
|
|
297
303
|
});
|
|
298
|
-
|
|
304
|
+
|
|
305
|
+
await infraStore.create_backend("noreply@example.com");
|
|
299
306
|
expect(infraStore.status).toBe(Status.CREATED);
|
|
300
307
|
expect(infraStore.domain_name).toBe(url);
|
|
301
308
|
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import Ajv from "ajv";
|
|
2
|
-
|
|
3
|
-
function validate_schema(schema, body) {
|
|
4
|
-
const ajv = new Ajv();
|
|
5
|
-
const list_keywords = ["methods", "route", "max_retry", "rpc"];
|
|
6
|
-
for (const keyword of list_keywords) {
|
|
7
|
-
ajv.addKeyword(keyword);
|
|
8
|
-
}
|
|
9
|
-
const valid = ajv.validate(schema, body);
|
|
10
|
-
return { valid, error: ajv.errorsText() };
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export { validate_schema };
|
|
File without changes
|
|
File without changes
|