vease 1.49.0-rc.5 → 1.49.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/.build/tests/e2e/utils/extension.js +3 -2
- package/.build/tests/e2e/utils/fixtures.js +3 -2
- package/.build/tests/e2e/utils/load.js +2 -1
- package/.build/tests/e2e/utils/navigate.js +24 -23
- package/.build/tests/e2e/utils/object_trees/main_object_tree.js +2 -1
- package/package.json +7 -7
- package/tests/e2e/utils/extension.ts +3 -2
- package/tests/e2e/utils/fixtures.ts +3 -2
- package/tests/e2e/utils/load.ts +2 -1
- package/tests/e2e/utils/navigate.ts +24 -23
- package/tests/e2e/utils/object_trees/main_object_tree.ts +2 -1
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { modalTransitionWait } from "./constants.js";
|
|
2
2
|
import { waitForLoadingScreen } from "./other.js";
|
|
3
3
|
import { navigateToExtensionsPage } from "./navigate.js";
|
|
4
|
+
import { consola } from "consola";
|
|
4
5
|
import path from "node:path";
|
|
5
6
|
//#region tests/e2e/utils/extension.ts
|
|
6
7
|
async function loadExtension(window, extensionFilePath) {
|
|
7
8
|
await waitForLoadingScreen(window);
|
|
8
9
|
try {
|
|
9
10
|
const inputFileExtension = path.extname(extensionFilePath);
|
|
10
|
-
|
|
11
|
+
consola.info("loadExtension", {
|
|
11
12
|
inputFileExtension,
|
|
12
13
|
extensionFilePath
|
|
13
14
|
});
|
|
@@ -23,7 +24,7 @@ async function loadExtension(window, extensionFilePath) {
|
|
|
23
24
|
await window.waitForTimeout(modalTransitionWait);
|
|
24
25
|
await waitForLoadingScreen(window);
|
|
25
26
|
} catch (error) {
|
|
26
|
-
|
|
27
|
+
consola.error("Failed to load extension:", error);
|
|
27
28
|
throw error;
|
|
28
29
|
}
|
|
29
30
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { navigateToApp } from "./navigate.js";
|
|
2
2
|
import { expect, test as test$1 } from "@playwright/test";
|
|
3
|
+
import { consola } from "consola";
|
|
3
4
|
import path from "node:path";
|
|
4
5
|
//#region tests/e2e/utils/fixtures.ts
|
|
5
6
|
const MILLISECONDS_PER_SECOND = 1e3;
|
|
@@ -22,13 +23,13 @@ const test = test$1.extend({
|
|
|
22
23
|
}, { scope: "worker" }],
|
|
23
24
|
logTestProgress: [async ({}, use, testInfo) => {
|
|
24
25
|
const name = `${path.basename(testInfo.file)} › ${testInfo.title}`;
|
|
25
|
-
|
|
26
|
+
consola.info(`\u001B[33m[START]\u001B[0m ${name}`);
|
|
26
27
|
const start = Date.now();
|
|
27
28
|
await use(void 0);
|
|
28
29
|
const statusColor = testInfo.status === "passed" ? "\x1B[32m" : "\x1B[31m";
|
|
29
30
|
const status = (testInfo.status ?? "done").toUpperCase();
|
|
30
31
|
const duration = ((Date.now() - start) / MILLISECONDS_PER_SECOND).toFixed(2);
|
|
31
|
-
|
|
32
|
+
consola.info(`\u001B[35m[END]\u001B[0m ${name} : ${statusColor}TEST ${status}\u001B[0m (${duration}s)`);
|
|
32
33
|
}, { auto: true }],
|
|
33
34
|
autoScreenshot: [async ({ window, screenshotMask }, use, testInfo) => {
|
|
34
35
|
await use(void 0);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { waitForActionSettled } from "./wait_for_action_settled.js";
|
|
2
2
|
import { expect } from "@playwright/test";
|
|
3
|
+
import { consola } from "consola";
|
|
3
4
|
import path from "node:path";
|
|
4
5
|
//#region tests/e2e/utils/load.ts
|
|
5
6
|
const __dirname = import.meta.dirname;
|
|
@@ -8,7 +9,7 @@ function getLayoutImportButton(window) {
|
|
|
8
9
|
return window.getByTestId("layoutImportButton");
|
|
9
10
|
}
|
|
10
11
|
async function loadVeaseTestDatas(window, inputDataFilenames, { loadTimeout = loadWorkflowTimeout, inputDataPath = path.join(__dirname, "..", "tests", "data") } = {}) {
|
|
11
|
-
|
|
12
|
+
consola.info(`Loading datas: ${inputDataFilenames.join(", ")} from ${inputDataPath}`);
|
|
12
13
|
const [firstInputDataFilename] = inputDataFilenames;
|
|
13
14
|
if (firstInputDataFilename === void 0) throw new Error("No input data filenames provided");
|
|
14
15
|
const inputFileExtension = path.extname(firstInputDataFilename);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { expect } from "@playwright/test";
|
|
2
2
|
import { isWindows } from "std-env";
|
|
3
|
+
import { consola } from "consola";
|
|
3
4
|
import path from "node:path";
|
|
4
5
|
import { execSync } from "node:child_process";
|
|
5
6
|
import fs from "node:fs";
|
|
@@ -32,11 +33,11 @@ const TIMEZONE = "UTC";
|
|
|
32
33
|
function findAppExecutable() {
|
|
33
34
|
const appExecutablePath = process.env.DESKTOP_EXECUTABLE_PATH;
|
|
34
35
|
if (appExecutablePath !== void 0 && appExecutablePath !== "" && fs.existsSync(appExecutablePath)) {
|
|
35
|
-
|
|
36
|
+
consola.debug({ appExecutablePath });
|
|
36
37
|
return path.join(appExecutablePath, executableName(packageJson.name));
|
|
37
38
|
}
|
|
38
39
|
const buildReleasePath = path.join(__dirname, "../../../release", "0.0.0");
|
|
39
|
-
|
|
40
|
+
consola.debug([buildReleasePath]);
|
|
40
41
|
const buildPath = findLatestBuild(buildReleasePath);
|
|
41
42
|
return parseElectronApp(buildPath).executable;
|
|
42
43
|
}
|
|
@@ -47,16 +48,16 @@ async function waitForAppReady(url, timeoutMs) {
|
|
|
47
48
|
const startTime = Date.now();
|
|
48
49
|
while (Date.now() - startTime < timeoutMs) {
|
|
49
50
|
const response = await getIsAppReady(url);
|
|
50
|
-
|
|
51
|
+
consola.info(`App ready check response: ${JSON.stringify(response)}`);
|
|
51
52
|
if (isAppReadyResponse(response) && response.isReady === true) return true;
|
|
52
53
|
await setTimeout(MILLISECONDS);
|
|
53
54
|
}
|
|
54
|
-
|
|
55
|
+
consola.info("Timed out waiting for app to become ready");
|
|
55
56
|
return false;
|
|
56
57
|
}
|
|
57
58
|
async function runDesktopBuild() {
|
|
58
59
|
const appInfo = findAppExecutable();
|
|
59
|
-
|
|
60
|
+
consola.debug({ appInfo });
|
|
60
61
|
process.env.CI = "e2e";
|
|
61
62
|
const electronApp = await _electron.launch({
|
|
62
63
|
args: [
|
|
@@ -82,15 +83,15 @@ async function runDesktopBuild() {
|
|
|
82
83
|
if (!stdout || !stderr) throw new Error("Electron app process has no stdout/stderr");
|
|
83
84
|
stdout.on("data", (data) => {
|
|
84
85
|
const line = data.toString();
|
|
85
|
-
|
|
86
|
+
consola.info(`stdout: ${line}`);
|
|
86
87
|
const match = urlRegex.exec(line);
|
|
87
88
|
if (match && resolveAppUrl) resolveAppUrl(`http://${match.groups?.host}`);
|
|
88
89
|
});
|
|
89
90
|
stderr.on("data", (data) => {
|
|
90
|
-
|
|
91
|
+
consola.info(`stderr: ${data.toString()}`);
|
|
91
92
|
});
|
|
92
93
|
electronApp.on("close", () => {
|
|
93
|
-
|
|
94
|
+
consola.info("electronApp close");
|
|
94
95
|
});
|
|
95
96
|
const firstWindow = await electronApp.firstWindow();
|
|
96
97
|
await (await electronApp.browserWindow(firstWindow)).evaluate((window, { width, height }) => {
|
|
@@ -107,27 +108,27 @@ async function runDesktopBuild() {
|
|
|
107
108
|
};
|
|
108
109
|
}
|
|
109
110
|
async function navigateToCloudApp(page, url, maxRetries) {
|
|
110
|
-
|
|
111
|
+
consola.info(`Navigating to: ${url}`);
|
|
111
112
|
const navigationTimeout = SECONDS_NAVIGATION_TIMEOUT * MILLISECONDS;
|
|
112
113
|
let lastError = void 0;
|
|
113
114
|
let succeeded = false;
|
|
114
115
|
for (let attempt = 1; attempt <= maxRetries; attempt += 1) try {
|
|
115
|
-
|
|
116
|
+
consola.info(`Navigation attempt ${attempt}/${maxRetries}`);
|
|
116
117
|
await page.goto(url, {
|
|
117
118
|
waitUntil: "domcontentloaded",
|
|
118
119
|
timeout: navigationTimeout
|
|
119
120
|
});
|
|
120
|
-
|
|
121
|
+
consola.info(`Attempt ${attempt} succeeded`);
|
|
121
122
|
succeeded = true;
|
|
122
123
|
break;
|
|
123
124
|
} catch (error) {
|
|
124
125
|
lastError = error;
|
|
125
126
|
const message = error instanceof Error ? error.message : String(error);
|
|
126
|
-
|
|
127
|
+
consola.info(`Attempt ${attempt} failed: ${message}`);
|
|
127
128
|
if (attempt < maxRetries) await setTimeout(MILLISECONDS);
|
|
128
129
|
}
|
|
129
130
|
if (!succeeded) throw new Error(`Failed to reach ${url} after ${maxRetries} attempts`, { cause: lastError });
|
|
130
|
-
|
|
131
|
+
consola.info("Navigated to", page.url());
|
|
131
132
|
}
|
|
132
133
|
async function signInToCloudApp(page) {
|
|
133
134
|
const eMailInput = page.getByTestId("eMailInput").getByRole("textbox");
|
|
@@ -138,7 +139,7 @@ async function signInToCloudApp(page) {
|
|
|
138
139
|
await page.waitForTimeout(signInTimeout);
|
|
139
140
|
await page.getByTestId("signInButton").click();
|
|
140
141
|
await page.getByTestId("loadAppButton").click();
|
|
141
|
-
|
|
142
|
+
consola.info(`Waiting up to ${WAIT_TIMES.cloud / MILLISECONDS} seconds for the app to load...`);
|
|
142
143
|
await expect(page.getByTestId("layoutImportButton")).toBeEnabled({ timeout: WAIT_TIMES.cloud });
|
|
143
144
|
await page.waitForFunction(() => document.readyState === "complete");
|
|
144
145
|
}
|
|
@@ -153,22 +154,22 @@ async function navigateToApp(mode, browser) {
|
|
|
153
154
|
permissions: ["clipboard-read", "clipboard-write"]
|
|
154
155
|
});
|
|
155
156
|
context.on("page", (newPage) => {
|
|
156
|
-
|
|
157
|
+
consola.info("NEW PAGE CREATED:", newPage.url());
|
|
157
158
|
newPage.on("close", () => {
|
|
158
|
-
|
|
159
|
+
consola.info("PAGE CLOSED:", newPage.url());
|
|
159
160
|
});
|
|
160
161
|
});
|
|
161
162
|
const page = await context.newPage();
|
|
162
|
-
|
|
163
|
+
consola.info(`Testing app in ${mode} mode`);
|
|
163
164
|
if (mode === "BROWSER") {
|
|
164
165
|
const nuxtPort = await runBrowser("preview:browser");
|
|
165
166
|
page.on("console", (msg) => {
|
|
166
|
-
|
|
167
|
+
consola.info(`Browser console: ${msg.text()}`);
|
|
167
168
|
});
|
|
168
169
|
const appUrl = `http://localhost:${nuxtPort}`;
|
|
169
170
|
await page.goto(appUrl);
|
|
170
|
-
|
|
171
|
-
|
|
171
|
+
consola.info("Navigated to", page.url());
|
|
172
|
+
consola.info(`Waiting for ${WAIT_TIMES.browser / MILLISECONDS} seconds for the app to load...`);
|
|
172
173
|
await waitForAppReady(appUrl, WAIT_TIMES.browser);
|
|
173
174
|
await page.waitForFunction(() => document.readyState === "complete");
|
|
174
175
|
return {
|
|
@@ -180,11 +181,11 @@ async function navigateToApp(mode, browser) {
|
|
|
180
181
|
};
|
|
181
182
|
} else if (mode === "CLOUD") {
|
|
182
183
|
page.on("console", (msg) => {
|
|
183
|
-
|
|
184
|
+
consola.info(`Browser console: ${msg.text()}`);
|
|
184
185
|
});
|
|
185
186
|
let prefix = "";
|
|
186
187
|
const branch = execSync("git branch --show-current", { encoding: "utf8" }).trim();
|
|
187
|
-
|
|
188
|
+
consola.info("Current branch:", branch);
|
|
188
189
|
if (branch === "next") prefix = "next.";
|
|
189
190
|
await navigateToCloudApp(page, `https://${prefix}vease.geode-solutions.com`, 10);
|
|
190
191
|
await signInToCloudApp(page);
|
|
@@ -196,7 +197,7 @@ async function navigateToApp(mode, browser) {
|
|
|
196
197
|
};
|
|
197
198
|
} else if (mode === "DESKTOP") {
|
|
198
199
|
const { electronApp, firstWindow } = await runDesktopBuild();
|
|
199
|
-
|
|
200
|
+
consola.info(`Waiting for ${WAIT_TIMES.desktop / MILLISECONDS} seconds for the app to load...`);
|
|
200
201
|
await firstWindow.waitForFunction(() => document.readyState === "complete");
|
|
201
202
|
return {
|
|
202
203
|
window: firstWindow,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { waitForActionSettled } from "../wait_for_action_settled.js";
|
|
2
2
|
import { moveMouseOutOfTheWay } from "../app_interaction.js";
|
|
3
3
|
import { clickCollapseOrExpandAll, collapseGeodeObjectTypeInTree, collapseTreeGroup, expandGeodeObjectTypeInTree, getTreeRowByTextAndParent } from "./common.js";
|
|
4
|
+
import { consola } from "consola";
|
|
4
5
|
//#region tests/e2e/utils/object_trees/main_object_tree.ts
|
|
5
6
|
const HIGHLIGHT_HOVER_ATTEMPTS = 3;
|
|
6
7
|
function getMainObjectTree(window) {
|
|
@@ -34,7 +35,7 @@ async function highlightData(window, geodeObjectType, dataName) {
|
|
|
34
35
|
await tooltipIdValue.waitFor({ state: "visible" });
|
|
35
36
|
await waitForActionSettled(window);
|
|
36
37
|
if (await tooltipIdValue.isVisible()) return;
|
|
37
|
-
|
|
38
|
+
consola.warn(`highlightData: hover on "${dataName}" was lost while the highlight rendered (attempt ${attempt}/${HIGHLIGHT_HOVER_ATTEMPTS})`);
|
|
38
39
|
await moveMouseOutOfTheWay(window);
|
|
39
40
|
await waitForActionSettled(window);
|
|
40
41
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vease",
|
|
3
|
-
"version": "1.49.0
|
|
3
|
+
"version": "1.49.0",
|
|
4
4
|
"description": "Desktop and cloud software for data visualization",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Desktop",
|
|
@@ -79,12 +79,12 @@
|
|
|
79
79
|
"@ai-sdk/vue": "4.0.93",
|
|
80
80
|
"@fontsource/michroma": "5.2.6",
|
|
81
81
|
"@fontsource/roboto": "5.2.10",
|
|
82
|
-
"@geode/cloud-api": "
|
|
83
|
-
"@geode/opengeodeweb-back": "
|
|
84
|
-
"@geode/opengeodeweb-front": "
|
|
85
|
-
"@geode/opengeodeweb-viewer": "
|
|
86
|
-
"@geode/vease-back": "
|
|
87
|
-
"@geode/vease-viewer": "
|
|
82
|
+
"@geode/cloud-api": "latest",
|
|
83
|
+
"@geode/opengeodeweb-back": "latest",
|
|
84
|
+
"@geode/opengeodeweb-front": "latest",
|
|
85
|
+
"@geode/opengeodeweb-viewer": "latest",
|
|
86
|
+
"@geode/vease-back": "latest",
|
|
87
|
+
"@geode/vease-viewer": "latest",
|
|
88
88
|
"@nuxtjs/mcp-toolkit": "0.18.1",
|
|
89
89
|
"ai": "7.0.93",
|
|
90
90
|
"bowser": "2.14.1",
|
|
@@ -3,6 +3,7 @@ import path from "node:path";
|
|
|
3
3
|
|
|
4
4
|
// Third party imports
|
|
5
5
|
import type { Page } from "@playwright/test";
|
|
6
|
+
import { consola } from "consola";
|
|
6
7
|
import { waitForLoadingScreen } from "./other";
|
|
7
8
|
|
|
8
9
|
// Local imports
|
|
@@ -13,7 +14,7 @@ async function loadExtension(window: Page, extensionFilePath: string): Promise<v
|
|
|
13
14
|
await waitForLoadingScreen(window);
|
|
14
15
|
try {
|
|
15
16
|
const inputFileExtension = path.extname(extensionFilePath);
|
|
16
|
-
|
|
17
|
+
consola.info("loadExtension", { inputFileExtension, extensionFilePath });
|
|
17
18
|
await navigateToExtensionsPage(window);
|
|
18
19
|
// Wait for modal transition
|
|
19
20
|
await window.waitForTimeout(modalTransitionWait);
|
|
@@ -30,7 +31,7 @@ async function loadExtension(window: Page, extensionFilePath: string): Promise<v
|
|
|
30
31
|
await window.waitForTimeout(modalTransitionWait);
|
|
31
32
|
await waitForLoadingScreen(window);
|
|
32
33
|
} catch (error) {
|
|
33
|
-
|
|
34
|
+
consola.error("Failed to load extension:", error);
|
|
34
35
|
throw error;
|
|
35
36
|
}
|
|
36
37
|
}
|
|
@@ -5,6 +5,7 @@ import path from "node:path";
|
|
|
5
5
|
import type { Locator, Page } from "@playwright/test";
|
|
6
6
|
// oxlint-disable-next-line eslint/no-duplicate-imports
|
|
7
7
|
import { test as base, expect } from "@playwright/test";
|
|
8
|
+
import { consola } from "consola";
|
|
8
9
|
|
|
9
10
|
// Local imports
|
|
10
11
|
import { navigateToApp } from "./navigate";
|
|
@@ -53,13 +54,13 @@ const test = base.extend<TestFixtures, WorkerFixtures>({
|
|
|
53
54
|
// oxlint-disable-next-line no-empty-pattern
|
|
54
55
|
async ({}, use, testInfo): Promise<void> => {
|
|
55
56
|
const name = `${path.basename(testInfo.file)} › ${testInfo.title}`;
|
|
56
|
-
|
|
57
|
+
consola.info(`\u001B[33m[START]\u001B[0m ${name}`);
|
|
57
58
|
const start = Date.now();
|
|
58
59
|
await use(undefined);
|
|
59
60
|
const statusColor = testInfo.status === "passed" ? "\u001B[32m" : "\u001B[31m";
|
|
60
61
|
const status = (testInfo.status ?? "done").toUpperCase();
|
|
61
62
|
const duration = ((Date.now() - start) / MILLISECONDS_PER_SECOND).toFixed(2);
|
|
62
|
-
|
|
63
|
+
consola.info(
|
|
63
64
|
`\u001B[35m[END]\u001B[0m ${name} : ${statusColor}TEST ${status}\u001B[0m (${duration}s)`,
|
|
64
65
|
);
|
|
65
66
|
},
|
package/tests/e2e/utils/load.ts
CHANGED
|
@@ -3,6 +3,7 @@ import path from "node:path";
|
|
|
3
3
|
|
|
4
4
|
// Third party imports
|
|
5
5
|
import { type Locator, type Page, expect } from "@playwright/test";
|
|
6
|
+
import { consola } from "consola";
|
|
6
7
|
|
|
7
8
|
// Local imports
|
|
8
9
|
import { waitForActionSettled } from "./wait_for_action_settled";
|
|
@@ -22,7 +23,7 @@ async function loadVeaseTestDatas(
|
|
|
22
23
|
inputDataPath = path.join(__dirname, "..", "tests", "data"),
|
|
23
24
|
}: { loadTimeout?: number; inputDataPath?: string } = {},
|
|
24
25
|
): Promise<void> {
|
|
25
|
-
|
|
26
|
+
consola.info(`Loading datas: ${inputDataFilenames.join(", ")} from ${inputDataPath}`);
|
|
26
27
|
const [firstInputDataFilename] = inputDataFilenames;
|
|
27
28
|
if (firstInputDataFilename === undefined) {
|
|
28
29
|
throw new Error("No input data filenames provided");
|
|
@@ -9,6 +9,7 @@ import { type Browser, type Page, expect } from "@playwright/test";
|
|
|
9
9
|
import { type ElectronApplication, _electron as electron } from "playwright";
|
|
10
10
|
import { findLatestBuild, parseElectronApp } from "electron-playwright-helpers";
|
|
11
11
|
import type { BrowserWindow } from "electron";
|
|
12
|
+
import { consola } from "consola";
|
|
12
13
|
import { isWindows } from "std-env";
|
|
13
14
|
import kill from "kill-port";
|
|
14
15
|
|
|
@@ -49,11 +50,11 @@ function findAppExecutable(): string {
|
|
|
49
50
|
appExecutablePath !== "" &&
|
|
50
51
|
fs.existsSync(appExecutablePath)
|
|
51
52
|
) {
|
|
52
|
-
|
|
53
|
+
consola.debug({ appExecutablePath });
|
|
53
54
|
return path.join(appExecutablePath, executableName(packageJson.name));
|
|
54
55
|
}
|
|
55
56
|
const buildReleasePath = path.join(__dirname, "../../../release", "0.0.0");
|
|
56
|
-
|
|
57
|
+
consola.debug([buildReleasePath]);
|
|
57
58
|
const buildPath = findLatestBuild(buildReleasePath);
|
|
58
59
|
return parseElectronApp(buildPath).executable;
|
|
59
60
|
}
|
|
@@ -71,14 +72,14 @@ async function waitForAppReady(url: string, timeoutMs: number): Promise<boolean>
|
|
|
71
72
|
while (Date.now() - startTime < timeoutMs) {
|
|
72
73
|
// oxlint-disable-next-line no-await-in-loop
|
|
73
74
|
const response = await getIsAppReady(url);
|
|
74
|
-
|
|
75
|
+
consola.info(`App ready check response: ${JSON.stringify(response)}`);
|
|
75
76
|
if (isAppReadyResponse(response) && response.isReady === true) {
|
|
76
77
|
return true;
|
|
77
78
|
}
|
|
78
79
|
// oxlint-disable-next-line no-await-in-loop
|
|
79
80
|
await setTimeout(MILLISECONDS);
|
|
80
81
|
}
|
|
81
|
-
|
|
82
|
+
consola.info("Timed out waiting for app to become ready");
|
|
82
83
|
return false;
|
|
83
84
|
}
|
|
84
85
|
|
|
@@ -88,7 +89,7 @@ async function runDesktopBuild(): Promise<{
|
|
|
88
89
|
}> {
|
|
89
90
|
// Find the latest build in the out directory
|
|
90
91
|
const appInfo = findAppExecutable();
|
|
91
|
-
|
|
92
|
+
consola.debug({ appInfo });
|
|
92
93
|
// Set the CI environment variable to true
|
|
93
94
|
//oxlint-disable-next-line id-length
|
|
94
95
|
process.env.CI = "e2e";
|
|
@@ -115,18 +116,18 @@ async function runDesktopBuild(): Promise<{
|
|
|
115
116
|
}
|
|
116
117
|
stdout.on("data", (data: Buffer) => {
|
|
117
118
|
const line = data.toString();
|
|
118
|
-
|
|
119
|
+
consola.info(`stdout: ${line}`);
|
|
119
120
|
const match = urlRegex.exec(line);
|
|
120
121
|
if (match && resolveAppUrl) {
|
|
121
122
|
resolveAppUrl(`http://${match.groups?.host}`);
|
|
122
123
|
}
|
|
123
124
|
});
|
|
124
125
|
stderr.on("data", (data: Buffer) => {
|
|
125
|
-
|
|
126
|
+
consola.info(`stderr: ${data.toString()}`);
|
|
126
127
|
});
|
|
127
128
|
|
|
128
129
|
electronApp.on("close", () => {
|
|
129
|
-
|
|
130
|
+
consola.info("electronApp close");
|
|
130
131
|
});
|
|
131
132
|
const firstWindow = await electronApp.firstWindow();
|
|
132
133
|
const browserWindow = await electronApp.browserWindow(firstWindow);
|
|
@@ -144,26 +145,26 @@ async function runDesktopBuild(): Promise<{
|
|
|
144
145
|
}
|
|
145
146
|
|
|
146
147
|
async function navigateToCloudApp(page: Page, url: string, maxRetries: number): Promise<void> {
|
|
147
|
-
|
|
148
|
+
consola.info(`Navigating to: ${url}`);
|
|
148
149
|
const navigationTimeout = SECONDS_NAVIGATION_TIMEOUT * MILLISECONDS;
|
|
149
150
|
let lastError: unknown = undefined;
|
|
150
151
|
let succeeded = false;
|
|
151
152
|
|
|
152
153
|
for (let attempt = 1; attempt <= maxRetries; attempt += 1) {
|
|
153
154
|
try {
|
|
154
|
-
|
|
155
|
+
consola.info(`Navigation attempt ${attempt}/${maxRetries}`);
|
|
155
156
|
// oxlint-disable-next-line no-await-in-loop
|
|
156
157
|
await page.goto(url, {
|
|
157
158
|
waitUntil: "domcontentloaded",
|
|
158
159
|
timeout: navigationTimeout,
|
|
159
160
|
});
|
|
160
|
-
|
|
161
|
+
consola.info(`Attempt ${attempt} succeeded`);
|
|
161
162
|
succeeded = true;
|
|
162
163
|
break;
|
|
163
164
|
} catch (error) {
|
|
164
165
|
lastError = error;
|
|
165
166
|
const message = error instanceof Error ? error.message : String(error);
|
|
166
|
-
|
|
167
|
+
consola.info(`Attempt ${attempt} failed: ${message}`);
|
|
167
168
|
if (attempt < maxRetries) {
|
|
168
169
|
// oxlint-disable-next-line no-await-in-loop
|
|
169
170
|
await setTimeout(MILLISECONDS);
|
|
@@ -176,7 +177,7 @@ async function navigateToCloudApp(page: Page, url: string, maxRetries: number):
|
|
|
176
177
|
cause: lastError,
|
|
177
178
|
});
|
|
178
179
|
}
|
|
179
|
-
|
|
180
|
+
consola.info("Navigated to", page.url());
|
|
180
181
|
}
|
|
181
182
|
|
|
182
183
|
async function signInToCloudApp(page: Page): Promise<void> {
|
|
@@ -193,7 +194,7 @@ async function signInToCloudApp(page: Page): Promise<void> {
|
|
|
193
194
|
|
|
194
195
|
const loadAppButton = page.getByTestId("loadAppButton");
|
|
195
196
|
await loadAppButton.click();
|
|
196
|
-
|
|
197
|
+
consola.info(`Waiting up to ${WAIT_TIMES.cloud / MILLISECONDS} seconds for the app to load...`);
|
|
197
198
|
await expect(page.getByTestId("layoutImportButton")).toBeEnabled({ timeout: WAIT_TIMES.cloud });
|
|
198
199
|
await page.waitForFunction(() => document.readyState === "complete");
|
|
199
200
|
}
|
|
@@ -209,22 +210,22 @@ async function navigateToApp(
|
|
|
209
210
|
permissions: ["clipboard-read", "clipboard-write"],
|
|
210
211
|
});
|
|
211
212
|
context.on("page", (newPage) => {
|
|
212
|
-
|
|
213
|
+
consola.info("NEW PAGE CREATED:", newPage.url());
|
|
213
214
|
newPage.on("close", () => {
|
|
214
|
-
|
|
215
|
+
consola.info("PAGE CLOSED:", newPage.url());
|
|
215
216
|
});
|
|
216
217
|
});
|
|
217
218
|
const page = await context.newPage();
|
|
218
|
-
|
|
219
|
+
consola.info(`Testing app in ${mode} mode`);
|
|
219
220
|
if (mode === "BROWSER") {
|
|
220
221
|
const nuxtPort = await runBrowser("preview:browser");
|
|
221
222
|
page.on("console", (msg) => {
|
|
222
|
-
|
|
223
|
+
consola.info(`Browser console: ${msg.text()}`);
|
|
223
224
|
});
|
|
224
225
|
const appUrl = `http://localhost:${nuxtPort}`;
|
|
225
226
|
await page.goto(appUrl);
|
|
226
|
-
|
|
227
|
-
|
|
227
|
+
consola.info("Navigated to", page.url());
|
|
228
|
+
consola.info(`Waiting for ${WAIT_TIMES.browser / MILLISECONDS} seconds for the app to load...`);
|
|
228
229
|
await waitForAppReady(appUrl, WAIT_TIMES.browser);
|
|
229
230
|
await page.waitForFunction(() => document.readyState === "complete");
|
|
230
231
|
|
|
@@ -237,14 +238,14 @@ async function navigateToApp(
|
|
|
237
238
|
};
|
|
238
239
|
} else if (mode === "CLOUD") {
|
|
239
240
|
page.on("console", (msg) => {
|
|
240
|
-
|
|
241
|
+
consola.info(`Browser console: ${msg.text()}`);
|
|
241
242
|
});
|
|
242
243
|
|
|
243
244
|
let prefix = "";
|
|
244
245
|
const branch = execSync("git branch --show-current", {
|
|
245
246
|
encoding: "utf8",
|
|
246
247
|
}).trim();
|
|
247
|
-
|
|
248
|
+
consola.info("Current branch:", branch);
|
|
248
249
|
if (branch === "next") {
|
|
249
250
|
prefix = "next.";
|
|
250
251
|
}
|
|
@@ -261,7 +262,7 @@ async function navigateToApp(
|
|
|
261
262
|
};
|
|
262
263
|
} else if (mode === "DESKTOP") {
|
|
263
264
|
const { electronApp, firstWindow } = await runDesktopBuild();
|
|
264
|
-
|
|
265
|
+
consola.info(`Waiting for ${WAIT_TIMES.desktop / MILLISECONDS} seconds for the app to load...`);
|
|
265
266
|
await firstWindow.waitForFunction(() => document.readyState === "complete");
|
|
266
267
|
return {
|
|
267
268
|
window: firstWindow,
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
expandGeodeObjectTypeInTree,
|
|
7
7
|
getTreeRowByTextAndParent,
|
|
8
8
|
} from "./common";
|
|
9
|
+
import { consola } from "consola";
|
|
9
10
|
import { moveMouseOutOfTheWay } from "@vease_tests/utils/app_interaction";
|
|
10
11
|
import { waitForActionSettled } from "@vease_tests/utils/wait_for_action_settled";
|
|
11
12
|
|
|
@@ -62,7 +63,7 @@ async function highlightData(
|
|
|
62
63
|
if (await tooltipIdValue.isVisible()) {
|
|
63
64
|
return;
|
|
64
65
|
}
|
|
65
|
-
|
|
66
|
+
consola.warn(
|
|
66
67
|
`highlightData: hover on "${dataName}" was lost while the highlight rendered (attempt ${attempt}/${HIGHLIGHT_HOVER_ATTEMPTS})`,
|
|
67
68
|
);
|
|
68
69
|
// oxlint-disable-next-line no-await-in-loop
|