@globisnv/cypress-core 0.0.4 → 0.0.6
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.
|
@@ -181,14 +181,10 @@ Cypress.Commands.add('GLO_oktaLogin', (company, urlType, skipvNavCheck) => {
|
|
|
181
181
|
const target = globisUrlTypes.includes(urlType) ? 'globis_online' : 'online';
|
|
182
182
|
url = url.replace(target, urlType);
|
|
183
183
|
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
cy.on('window:before:load', (win) => {
|
|
189
|
-
attachWebSocketSpy(win);
|
|
190
|
-
});
|
|
191
|
-
}
|
|
184
|
+
// Stateless Okta login redirects server side before any Servoy client boots, so there is no
|
|
185
|
+
// websocket to wait for on the first visit — the connection is only asserted after the Okta
|
|
186
|
+
// round trip (see waitForWebSocketAfterOkta). The spy itself is attached globally on every
|
|
187
|
+
// AUT page load (see websocketDetector.ts), which covers this server-side redirect too.
|
|
192
188
|
cy.visit(url);
|
|
193
189
|
cy.task('log', 'Redirect to okta url');
|
|
194
190
|
cy.origin(Cypress.expose('oktaUrl'), () => {
|
|
@@ -354,6 +350,52 @@ Cypress.Commands.add('GLO_searchDataControl', (elementName) => {
|
|
|
354
350
|
cy.GLO_checkLoadingIndicator();
|
|
355
351
|
});
|
|
356
352
|
});
|
|
353
|
+
const loadingCheckTimeout = 1200000;
|
|
354
|
+
const progressBarSelector = '[data-cy="ng$main_form2.progress"] dx-progress-bar';
|
|
355
|
+
/** Modal overlays that park the Servoy server thread until the user answers. */
|
|
356
|
+
const blockingDialogSelector = '.svy-message-dialog, .servoycore-dialog-body, .svy-dialog';
|
|
357
|
+
/**
|
|
358
|
+
* Polls the full screen progress bar away. A process that asks the user something halfway - a formula
|
|
359
|
+
* showing a select dialog, for instance - keeps the bar in the DOM while its thread is parked on that
|
|
360
|
+
* dialog, so a visible dialog resolves the poll and lets the test answer it. The dialog handler calls
|
|
361
|
+
* the loading check again afterwards, which re-enters this same poll.
|
|
362
|
+
*/
|
|
363
|
+
const waitForProgressBar = () => {
|
|
364
|
+
const pollInterval = 1000;
|
|
365
|
+
const maxAttempts = Math.ceil(loadingCheckTimeout / pollInterval);
|
|
366
|
+
let attempts = 0;
|
|
367
|
+
const log = Cypress.log({ name: 'checkLoadingIndicator', message: 'Waiting for the progress bar…', autoEnd: false, timeout: 0 });
|
|
368
|
+
const checkStatus = (resolve, reject) => {
|
|
369
|
+
cy.get('body', { log: false }).then(($body) => {
|
|
370
|
+
if (!$body.find(progressBarSelector).length) {
|
|
371
|
+
log.end();
|
|
372
|
+
resolve();
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
if ($body.find(blockingDialogSelector).filter(':visible').length) {
|
|
376
|
+
log.set({ message: 'Progress bar still shown, but a dialog is waiting for input: continuing' });
|
|
377
|
+
log.end();
|
|
378
|
+
resolve();
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
attempts += 1;
|
|
382
|
+
if (attempts > maxAttempts) {
|
|
383
|
+
log.end();
|
|
384
|
+
reject(new Error(`Timed out after ${Math.round((maxAttempts * pollInterval) / 1000)}s waiting for the progress bar to disappear`));
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
// biome-ignore plugin: wait for next poll interval before checking again
|
|
388
|
+
cy.wait(pollInterval, { log: false }).then(() => {
|
|
389
|
+
log.set({ message: `Still waiting for the progress bar ${attempts}/${maxAttempts}` });
|
|
390
|
+
checkStatus(resolve, reject);
|
|
391
|
+
});
|
|
392
|
+
});
|
|
393
|
+
};
|
|
394
|
+
const promise = new Cypress.Promise((resolve, reject) => {
|
|
395
|
+
checkStatus(resolve, reject);
|
|
396
|
+
});
|
|
397
|
+
cy.then(() => promise);
|
|
398
|
+
};
|
|
357
399
|
Cypress.Commands.add('GLO_checkLoadingIndicator', () => {
|
|
358
400
|
if (cypressWebsocketLoader) {
|
|
359
401
|
cy.WS_loadingCheck();
|
|
@@ -361,8 +403,8 @@ Cypress.Commands.add('GLO_checkLoadingIndicator', () => {
|
|
|
361
403
|
else {
|
|
362
404
|
// biome-ignore plugin: wait before checking loading indicator
|
|
363
405
|
cy.wait(1000);
|
|
364
|
-
cy.get('loading-indicator', { timeout:
|
|
365
|
-
|
|
406
|
+
cy.get('loading-indicator', { timeout: loadingCheckTimeout }).should('not.exist');
|
|
407
|
+
waitForProgressBar();
|
|
366
408
|
}
|
|
367
409
|
});
|
|
368
410
|
Cypress.Commands.add('GLO_clickDatacontrolBrowserButton', (buttonName, skipCheck = noSkipCheck) => {
|
|
@@ -1502,7 +1544,7 @@ Cypress.Commands.add('GLO_checkNumberOfRowsInGrid', (selector, numberToValidate,
|
|
|
1502
1544
|
let lastError;
|
|
1503
1545
|
const log = Cypress.log({ name: 'checkNumberOfRowsInGrid', message: `Polling rows (${lengthCondition} ${numberToValidate})…`, autoEnd: false, timeout: 0 });
|
|
1504
1546
|
const checkStatus = (resolve, reject) => {
|
|
1505
|
-
cy.GLO_getElement(selector, { timeout: timeOut }).then(($grid) => {
|
|
1547
|
+
cy.GLO_getElement(selector, { timeout: timeOut, log: false }).then(($grid) => {
|
|
1506
1548
|
const $rows = $grid.find('.ag-center-cols-container [row-index]');
|
|
1507
1549
|
let actual = $rows.length;
|
|
1508
1550
|
let passed = false;
|
|
@@ -2313,7 +2355,7 @@ Cypress.Commands.add('GLO_extendedFilter', (filter, clearExistingFilters) => {
|
|
|
2313
2355
|
cy.GLO_checkLoadingIndicator();
|
|
2314
2356
|
});
|
|
2315
2357
|
Cypress.Commands.add('GLO_selectNamedSearch', (searchName) => {
|
|
2316
|
-
cy.
|
|
2358
|
+
cy.GLO_getVisible('#txtSearch .dx-icon-search').click();
|
|
2317
2359
|
cy.GLO_getVisible('.dx-submenu', 10000).contains(searchName).click();
|
|
2318
2360
|
cy.GLO_checkLoadingIndicator();
|
|
2319
2361
|
});
|
|
@@ -3,8 +3,8 @@ import * as http from 'node:http';
|
|
|
3
3
|
import * as https from 'node:https';
|
|
4
4
|
import { URL } from 'node:url';
|
|
5
5
|
import { Sha256 } from '@aws-crypto/sha256-js';
|
|
6
|
-
import { fromContainerMetadata } from '@
|
|
7
|
-
import { SignatureV4 } from '@
|
|
6
|
+
import { fromContainerMetadata } from '@smithy/credential-provider-imds';
|
|
7
|
+
import { SignatureV4 } from '@smithy/signature-v4';
|
|
8
8
|
import { compress } from 'snappyjs';
|
|
9
9
|
// ─── Minimal Prometheus remote-write protobuf encoder ─────────────────────────
|
|
10
10
|
// WriteRequest { repeated TimeSeries timeseries = 1 }
|
package/dist/tsHelper.d.ts
CHANGED
|
@@ -143,7 +143,7 @@ export declare function parseLocalizedNumber(value: string | number | undefined)
|
|
|
143
143
|
* will fall back to a random generated 4-character UUID if not found.
|
|
144
144
|
* @returns {string} CYP + build number or random 4-character UUID
|
|
145
145
|
*/
|
|
146
|
-
export declare const getOrCreateUuid: (
|
|
146
|
+
export declare const getOrCreateUuid: (createNew?: 'createNew') => string;
|
|
147
147
|
/**
|
|
148
148
|
* Returns the ISO 8601 week number for the given date.
|
|
149
149
|
*
|
package/dist/tsHelper.js
CHANGED
|
@@ -153,12 +153,13 @@ export function parseLocalizedNumber(value) {
|
|
|
153
153
|
* will fall back to a random generated 4-character UUID if not found.
|
|
154
154
|
* @returns {string} CYP + build number or random 4-character UUID
|
|
155
155
|
*/
|
|
156
|
-
export const getOrCreateUuid = (
|
|
157
|
-
const
|
|
156
|
+
export const getOrCreateUuid = (createNew) => {
|
|
157
|
+
const id = createNew === 'createNew' ? getUUID(3) : undefined;
|
|
158
|
+
const envKey = id !== undefined ? `BUILD_UUID_${id}` : 'BUILD_UUID';
|
|
158
159
|
let uuid = Cypress.expose(envKey);
|
|
159
160
|
if (!uuid) {
|
|
160
161
|
const buildNumber = Cypress.expose('BUILD_NUMBER');
|
|
161
|
-
const suffix =
|
|
162
|
+
const suffix = id !== undefined ? `-${id}` : '';
|
|
162
163
|
uuid = buildNumber ? `CYP${buildNumber}${suffix}` : `CYP${getUUID(4)}${suffix}`;
|
|
163
164
|
Cypress.expose({ [envKey]: uuid });
|
|
164
165
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { cypressWebsocketDebug, extraParams } from './tsHelper.js';
|
|
1
|
+
import { cypressWebsocketDebug, cypressWebsocketLoader, extraParams } from './tsHelper.js';
|
|
2
2
|
/** Module-level flag controlling auto-dismissal of Info dialogs. Disabled by default; set via WS_toggleDialogHandler or env wsEnableDialogHandler=true. */
|
|
3
3
|
let wsDialogHandlerEnabled = extraParams.wsEnableDialogHandler === 'true';
|
|
4
4
|
// ─── Cypress action tracking for metric labels ────────────────────────────────
|
|
@@ -71,13 +71,16 @@ after(() => {
|
|
|
71
71
|
Cypress.log({ name: 'WSMetrics', displayName: '📊 WSMetrics', message: msg });
|
|
72
72
|
});
|
|
73
73
|
});
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
74
|
+
// Attaches to every AUT page load, not just the one triggered by the WS_visitWithSpy call below —
|
|
75
|
+
// GLO_logout redirects to the login page itself (app-triggered, not via cy.visit), and that load
|
|
76
|
+
// needs the spy too or its websocket connects unpatched (same problem GLO_oktaLogin's redirect has).
|
|
77
|
+
if (cypressWebsocketLoader) {
|
|
78
|
+
Cypress.on('window:before:load', (win) => {
|
|
79
|
+
attachWebSocketSpy(win);
|
|
79
80
|
});
|
|
80
|
-
|
|
81
|
+
}
|
|
82
|
+
Cypress.Commands.add('WS_visitWithSpy', (url) => {
|
|
83
|
+
cy.visit(url);
|
|
81
84
|
cy.window().then((win) => {
|
|
82
85
|
cy.wrap(win.wsMessages).as('wsMessages');
|
|
83
86
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@globisnv/cypress-core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
4
4
|
"description": "Core building blocks for Globis Cypress E2E tests",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|
|
@@ -48,8 +48,8 @@
|
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
50
|
"@aws-crypto/sha256-js": "^5.2.0",
|
|
51
|
-
"@
|
|
52
|
-
"@
|
|
51
|
+
"@smithy/credential-provider-imds": "^4.5.2",
|
|
52
|
+
"@smithy/signature-v4": "^5.7.3",
|
|
53
53
|
"snappyjs": "^0.7.0",
|
|
54
54
|
"uuid": "^14.0.1"
|
|
55
55
|
},
|