@globisnv/cypress-core 0.0.10 → 1.1.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/biome.json +11 -0
- package/dist/blueprints/GLO_consignment.js +1 -0
- package/dist/blueprints/GLO_consignmentCustoms.d.ts +24 -0
- package/dist/blueprints/GLO_consignmentCustoms.js +24 -0
- package/dist/blueprints/GLO_consignmentCustomsSettings.d.ts +11 -0
- package/dist/blueprints/GLO_consignmentCustomsSettings.js +11 -0
- package/dist/blueprints/GLO_customsDeclaration.d.ts +22 -0
- package/dist/blueprints/GLO_customsDeclaration.js +22 -0
- package/dist/blueprints/GLO_customsDeclarationDetail.d.ts +20 -0
- package/dist/blueprints/GLO_customsDeclarationDetail.js +20 -0
- package/dist/blueprints/GLO_customsDeclarationDocument.d.ts +9 -0
- package/dist/blueprints/GLO_customsDeclarationDocument.js +9 -0
- package/dist/blueprints/GLO_dangerousGoods.d.ts +10 -0
- package/dist/blueprints/GLO_dangerousGoods.js +9 -0
- package/dist/blueprints/GLO_logisticContract.d.ts +14 -0
- package/dist/blueprints/GLO_logisticContract.js +53 -11
- package/dist/blueprints/GLO_logisticContractCustomsDefinition.d.ts +22 -0
- package/dist/blueprints/GLO_logisticContractCustomsDefinition.js +22 -0
- package/dist/blueprints/GLO_logisticContractDetail.d.ts +11 -1
- package/dist/blueprints/GLO_logisticContractDetail.js +33 -8
- package/dist/blueprints/GLO_logisticContractDetailCustoms.d.ts +11 -0
- package/dist/blueprints/GLO_logisticContractDetailCustoms.js +11 -0
- package/dist/blueprints/GLO_logisticContractDetailHandling.d.ts +1 -0
- package/dist/blueprints/GLO_logisticContractDetailHandling.js +1 -0
- package/dist/blueprints/GLO_logisticContractDetailItem.js +1 -1
- package/dist/blueprints/GLO_logisticContractItem.d.ts +9 -0
- package/dist/blueprints/GLO_logisticContractItem.js +31 -4
- package/dist/blueprints/GLO_logisticLocationType.d.ts +4 -0
- package/dist/blueprints/GLO_logisticLocationType.js +4 -0
- package/dist/blueprints/GLO_planBloc.d.ts +6 -0
- package/dist/blueprints/GLO_planBloc.js +6 -0
- package/dist/blueprints/GLO_priceEntry.d.ts +1 -0
- package/dist/blueprints/GLO_priceEntry.js +1 -0
- package/dist/blueprints/GLO_purchaseOrderLine.js +4 -0
- package/dist/blueprints/GLO_relations.js +4 -4
- package/dist/blueprints/GLO_stopSchedule.d.ts +11 -0
- package/dist/blueprints/GLO_stopSchedule.js +11 -0
- package/dist/blueprints/GLO_transportScenario.d.ts +4 -0
- package/dist/blueprints/GLO_transportScenario.js +4 -0
- package/dist/blueprints/GLO_transportScenarioExecution.d.ts +6 -0
- package/dist/blueprints/GLO_transportScenarioExecution.js +5 -0
- package/dist/blueprints/GLO_transportScenarioRegion.d.ts +5 -0
- package/dist/blueprints/GLO_transportScenarioRegion.js +5 -0
- package/dist/blueprints/GLO_zoneTypeEntityType.d.ts +4 -0
- package/dist/blueprints/GLO_zoneTypeEntityType.js +4 -0
- package/dist/commands/GLO_commands.js +72 -39
- package/dist/commands/GLT_commands.js +2 -2
- package/dist/config.js +4 -2
- package/dist/websocketDetector.js +148 -114
- package/package.json +9 -6
- package/template/.gitattributes +12 -0
- package/template/package.json +5 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { open } from '../tsHelper.js';
|
|
1
|
+
import { close, open } from '../tsHelper.js';
|
|
2
2
|
export const GLO_enterLogisticContractItem = (obj) => {
|
|
3
3
|
const formName = 'ng$logistic_contract_item_dtl';
|
|
4
4
|
const generalFormName = 'ng$logistic_contract_item_dtl_general';
|
|
@@ -33,8 +33,35 @@ export const GLO_enterLogisticContractItem = (obj) => {
|
|
|
33
33
|
cy.GLO_checkLoadingIndicator();
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
// Tab Billing
|
|
37
|
+
enterBillingTab(obj);
|
|
38
|
+
};
|
|
39
|
+
// Billing tab
|
|
40
|
+
const enterBillingTab = (obj) => {
|
|
41
|
+
const formName = 'ng$logistic_contract_item_dtl';
|
|
42
|
+
const invoicingFormName = 'ng$logistic_contract_item_dtl_invoicing';
|
|
43
|
+
if (obj.flagProformaInvoice === undefined &&
|
|
44
|
+
obj.flagDirectInvoice === undefined &&
|
|
45
|
+
obj.flagSummaryInvoice === undefined &&
|
|
46
|
+
obj.flagAutomatedInvoice === undefined &&
|
|
47
|
+
obj.automatedInvoiceDays === undefined &&
|
|
48
|
+
!obj.invoicePeriodicity &&
|
|
49
|
+
!obj.invoicePeriodicityQuantity &&
|
|
50
|
+
!obj.dayOfMonthOfInvoice &&
|
|
51
|
+
!obj.transactionDateType &&
|
|
52
|
+
!obj.invoiceGroup) {
|
|
53
|
+
return;
|
|
39
54
|
}
|
|
55
|
+
cy.GLO_selectTab([formName, 'tabs_70'], 'Billing', open);
|
|
56
|
+
cy.GLO_checkbox([invoicingFormName, 'flag_proforma_invoice'], obj.flagProformaInvoice);
|
|
57
|
+
cy.GLO_checkbox([invoicingFormName, 'flag_summary_invoice'], obj.flagSummaryInvoice);
|
|
58
|
+
cy.GLO_checkbox([invoicingFormName, 'flag_direct_invoice'], obj.flagDirectInvoice);
|
|
59
|
+
cy.GLO_checkbox([invoicingFormName, 'flag_automated_invoice'], obj.flagAutomatedInvoice);
|
|
60
|
+
cy.GLO_addInput([invoicingFormName, 'automated_invoice_days'], obj.automatedInvoiceDays);
|
|
61
|
+
cy.GLO_addInput([invoicingFormName, 'invoice_periodicity'], obj.invoicePeriodicity);
|
|
62
|
+
cy.GLO_addInput([invoicingFormName, 'invoice_periodicity_quantity'], obj.invoicePeriodicityQuantity);
|
|
63
|
+
cy.GLO_addInput([invoicingFormName, 'day_of_month_of_invoice'], obj.dayOfMonthOfInvoice);
|
|
64
|
+
cy.GLO_addInput([invoicingFormName, 'transaction_date_type'], obj.transactionDateType);
|
|
65
|
+
cy.GLO_addInput([invoicingFormName, 'invoice_group'], obj.invoiceGroup);
|
|
66
|
+
cy.GLO_selectTab([formName, 'tabs_70'], 'Billing', close);
|
|
40
67
|
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export const GLO_enterPlanBloc = (obj) => {
|
|
2
|
+
const formName = 'ng$plan_bloc_dtl';
|
|
3
|
+
cy.GLO_addInput([formName, 'plan_bloc_code'], obj.planBlocCode);
|
|
4
|
+
cy.GLO_addInput([formName, 'plan_bloc_name'], obj.planBlocName);
|
|
5
|
+
cy.GLO_addInput([formName, 'sec_company_id'], obj.company);
|
|
6
|
+
};
|
|
@@ -5,6 +5,7 @@ export const GLO_enterPriceEntry = (obj) => {
|
|
|
5
5
|
cy.GLO_addDate(input, [formName, 'valid_till'], obj.validTill);
|
|
6
6
|
cy.GLO_addInput([formName, 'currency_id'], obj.currency);
|
|
7
7
|
cy.GLO_addInput([formName, 'result_value'], obj.result);
|
|
8
|
+
cy.GLO_addInput([formName, 'result_value_per'], obj.resultPer);
|
|
8
9
|
cy.GLO_addInput(['result_value_per_unit_id'], obj.perType);
|
|
9
10
|
cy.GLO_addInput([formName, 'min_amount'], obj.minAmount);
|
|
10
11
|
cy.GLO_addInput([formName, 'max_amount'], obj.maxAmount);
|
|
@@ -9,7 +9,11 @@ export const GLO_enterPurchaseOrderLine = (obj) => {
|
|
|
9
9
|
if (obj.quantity || obj.generalPrice || obj.inputQtyPerUnitId) {
|
|
10
10
|
cy.GLO_selectTab([formName, detailTabsName], 'General', open);
|
|
11
11
|
cy.GLO_addInput([`${formName}_general`, 'input_qty_per_unit_id'], obj.inputQtyPerUnitId);
|
|
12
|
+
if (obj.inputQtyPerUnitId)
|
|
13
|
+
cy.GLO_checkLoadingIndicator();
|
|
12
14
|
cy.GLO_addInput([`${formName}_general`, 'input_qty'], obj.quantity);
|
|
15
|
+
if (obj.quantity)
|
|
16
|
+
cy.GLO_checkLoadingIndicator();
|
|
13
17
|
cy.GLO_addInput([`${formName}_general`, 'quantity'], obj.quantityBase);
|
|
14
18
|
cy.GLO_checkField([`${formName}_general`, 'quantity'], obj.quantityBase);
|
|
15
19
|
cy.GLO_addInput([`${formName}_general`, 'price'], obj.generalPrice);
|
|
@@ -14,8 +14,8 @@ export const GLO_enterRelation = (obj, formName = formNameString) => {
|
|
|
14
14
|
cy.GLO_addInput([formName, 'postal_code_general'], obj.postalCodeGeneral);
|
|
15
15
|
cy.GLO_checkLoadingIndicator();
|
|
16
16
|
cy.get('body').then(($body) => {
|
|
17
|
-
if ($body.find('.svy-dialog').length > 0) {
|
|
18
|
-
if ($body.find('.svy-dialog [row-index]').length === 0) {
|
|
17
|
+
if ($body.find('.svy-dialog.active').length > 0) {
|
|
18
|
+
if ($body.find('.svy-dialog.active [row-index]').length === 0) {
|
|
19
19
|
cy.GLO_log('No cities found for this postal code, allowing manual input');
|
|
20
20
|
cy.GLO_clickButton(['ng$svy_nav_selection', 'btn_cancel']);
|
|
21
21
|
return;
|
|
@@ -43,8 +43,8 @@ export const GLO_enterRelation = (obj, formName = formNameString) => {
|
|
|
43
43
|
cy.GLO_addInput([formName, 'city_general'], obj.cityGeneral);
|
|
44
44
|
cy.GLO_checkLoadingIndicator();
|
|
45
45
|
cy.get('body').then(($body) => {
|
|
46
|
-
if ($body.find('.svy-dialog').length > 0) {
|
|
47
|
-
if ($body.find('.svy-dialog [row-index]').length === 0)
|
|
46
|
+
if ($body.find('.svy-dialog.active').length > 0) {
|
|
47
|
+
if ($body.find('.svy-dialog.active [row-index]').length === 0)
|
|
48
48
|
cy.GLO_clickButton(['ng$svy_nav_selection', 'btn_cancel']);
|
|
49
49
|
else
|
|
50
50
|
cy.GLO_dblClickRowInGrid(span, ['ng$postalcode_sel', 'grid'], obj.cityGeneral, undefined, skipCheck);
|
|
@@ -1,4 +1,15 @@
|
|
|
1
|
+
export type objStopScheduleDay = {
|
|
2
|
+
/** 1 = Monday, 7 = Sunday. */
|
|
3
|
+
day: number;
|
|
4
|
+
amFrom?: string;
|
|
5
|
+
amTill?: string;
|
|
6
|
+
pmFrom?: string;
|
|
7
|
+
pmTill?: string;
|
|
8
|
+
};
|
|
1
9
|
export type objStopSchedule = {
|
|
2
10
|
code?: string;
|
|
11
|
+
every?: number;
|
|
12
|
+
unit?: string;
|
|
13
|
+
days?: objStopScheduleDay[];
|
|
3
14
|
};
|
|
4
15
|
export declare const GLO_enterStopSchedule: (obj: objStopSchedule) => void;
|
|
@@ -1,4 +1,15 @@
|
|
|
1
|
+
import { check } from '../tsHelper.js';
|
|
1
2
|
export const GLO_enterStopSchedule = (obj) => {
|
|
2
3
|
const formName = 'ng$delivery_schedule$logistic_contract_detail_stop_dtl';
|
|
3
4
|
cy.GLO_addInput([formName, 'schedule_code'], obj.code);
|
|
5
|
+
cy.GLO_addInput([formName, 'every'], obj.every);
|
|
6
|
+
cy.GLO_addInput([formName, 'unit'], obj.unit);
|
|
7
|
+
// The times are named per weekday, the checkbox drops the flag prefix
|
|
8
|
+
obj.days?.forEach((day) => {
|
|
9
|
+
cy.GLO_checkbox([formName, `day${day.day}`], check);
|
|
10
|
+
cy.GLO_addInput([formName, `amfrom${day.day}`], day.amFrom);
|
|
11
|
+
cy.GLO_addInput([formName, `amto${day.day}`], day.amTill);
|
|
12
|
+
cy.GLO_addInput([formName, `pmfrom${day.day}`], day.pmFrom);
|
|
13
|
+
cy.GLO_addInput([formName, `pmto${day.day}`], day.pmTill);
|
|
14
|
+
});
|
|
4
15
|
};
|
|
@@ -33,13 +33,13 @@ const isGridRowSelector = (baseSelector, index) => {
|
|
|
33
33
|
// rendered-but-scrolled-past rows as hidden (measured: 14 of 21 rendered rows drop out of `:visible`
|
|
34
34
|
// after scrolling a grid to the bottom). Filter on the container, which is what both were after.
|
|
35
35
|
const isInOpenContainer = (_, el) => !el.closest('[hidden]');
|
|
36
|
-
const pickByRowIndex = (chain, index, log = false) => {
|
|
36
|
+
const pickByRowIndex = (chain, index, log = false, timeout = defaultTimeout) => {
|
|
37
37
|
if (log)
|
|
38
38
|
Cypress.log({ name: 'idx', message: String(index) });
|
|
39
39
|
return chain.filter((i, el) => {
|
|
40
40
|
const rowIndexEl = el.closest('[row-index]');
|
|
41
41
|
return rowIndexEl ? rowIndexEl.getAttribute('row-index') === String(index) : i === index;
|
|
42
|
-
});
|
|
42
|
+
}, { timeout });
|
|
43
43
|
};
|
|
44
44
|
Cypress.Commands.add('GLO_getElement', (selectorArg, options = {}) => {
|
|
45
45
|
const arr = selectorArg;
|
|
@@ -60,12 +60,12 @@ Cypress.Commands.add('GLO_getElement', (selectorArg, options = {}) => {
|
|
|
60
60
|
const elementInCrumb = Cypress.$(`div[formslist] ${selector}`).length > 0;
|
|
61
61
|
if (elementInCrumb) {
|
|
62
62
|
const result = cy.get(`div[formslist]:not([hidden]) ${selector}`, getOpts);
|
|
63
|
-
return pickByRowIndex(result, index ?? 0, hasIndex);
|
|
63
|
+
return pickByRowIndex(result, index ?? 0, hasIndex, getOpts.timeout);
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
66
|
const result = cy.get(selector, getOpts);
|
|
67
67
|
// Ponytail: sync DOM check — if element absent, skip filter so cy.get + should('not.exist') chain works
|
|
68
|
-
return hasIndex || Cypress.$(selector).length > 0 ? pickByRowIndex(result, index ?? 0, hasIndex) : result;
|
|
68
|
+
return hasIndex || Cypress.$(selector).length > 0 ? pickByRowIndex(result, index ?? 0, hasIndex, getOpts.timeout) : result;
|
|
69
69
|
});
|
|
70
70
|
Cypress.Commands.add('GLO_getVisible', (elementName, timeOut = defaultTimeout) => {
|
|
71
71
|
return cy.get(elementName, { timeout: timeOut }).filter(':visible', { timeout: timeOut });
|
|
@@ -115,7 +115,7 @@ Cypress.Commands.add('GLO_defaultlogin', (company, usernameENV = 'username', pas
|
|
|
115
115
|
}
|
|
116
116
|
cy.GLO_checkLoadingIndicator();
|
|
117
117
|
cy.get('body').then(($body) => {
|
|
118
|
-
if ($body.find('.svy-message-dialog .window-title').text() === 'Locked record') {
|
|
118
|
+
if ($body.find('.svy-message-dialog.active .window-title').text() === 'Locked record') {
|
|
119
119
|
// biome-ignore plugin: wait for locked record dialog choice to register
|
|
120
120
|
cy.wait(15000);
|
|
121
121
|
cy.GLO_dialogChoice('!globis.label.yes!');
|
|
@@ -136,7 +136,7 @@ const fillInUserAndPasswordDefault = (usernameENV, passwordENV) => {
|
|
|
136
136
|
.type(Cypress.expose(usernameENV));
|
|
137
137
|
cy.env([passwordENV]).then((envVars) => {
|
|
138
138
|
cy.GLO_getElement(['ng2$svy_nav_login', 'txtPass'])
|
|
139
|
-
.find('input')
|
|
139
|
+
.find('input:visible', { timeout: 30000 })
|
|
140
140
|
.eq(0)
|
|
141
141
|
.clear()
|
|
142
142
|
.type(envVars[passwordENV], { log: false });
|
|
@@ -227,10 +227,21 @@ Cypress.Commands.add('GLO_oktaLogin', (company, urlType, skipvNavCheck) => {
|
|
|
227
227
|
cy.task('log', 'End navbar check');
|
|
228
228
|
});
|
|
229
229
|
Cypress.Commands.add('GLO_logout', () => {
|
|
230
|
-
cy.
|
|
231
|
-
|
|
232
|
-
.
|
|
233
|
-
|
|
230
|
+
cy.document({ log: false }).then((doc) => {
|
|
231
|
+
cy.GLO_getElement(['ng$main_form2', 'navbar_top']).find('.lucide-LogOut').click();
|
|
232
|
+
cy.GLO_getVisible('.window-footer button.svy-btn-primary', 30000)
|
|
233
|
+
.contains(/^(Yes|Ja)$/)
|
|
234
|
+
.click();
|
|
235
|
+
// The confirm click triggers the app's own client-side redirect (not a cy.visit); a full
|
|
236
|
+
// page reload swaps the Document object as soon as navigation starts, so also wait for
|
|
237
|
+
// readyState to reach 'complete' — otherwise this resolves the instant the reload begins,
|
|
238
|
+
// not once it's actually finished. Checking readyState (not the destination URL) survives
|
|
239
|
+
// moving to a stateless auth flow with no login screen.
|
|
240
|
+
cy.document({ log: false, timeout: 30000 }).should((newDoc) => {
|
|
241
|
+
expect(newDoc).not.to.equal(doc);
|
|
242
|
+
expect(newDoc.readyState).to.equal('complete');
|
|
243
|
+
});
|
|
244
|
+
});
|
|
234
245
|
});
|
|
235
246
|
Cypress.Commands.add('GLO_servoyLogin', (company) => {
|
|
236
247
|
if (cypressWebsocketLoader) {
|
|
@@ -241,13 +252,13 @@ Cypress.Commands.add('GLO_servoyLogin', (company) => {
|
|
|
241
252
|
}
|
|
242
253
|
cy.GLO_checkLoadingIndicator();
|
|
243
254
|
cy.GLO_getElement(['ng2$svy_nav_login', 'txtUser'], { timeout: 30000 })
|
|
244
|
-
.find('input')
|
|
255
|
+
.find('input:visible', { timeout: 30000 })
|
|
245
256
|
.eq(0)
|
|
246
257
|
.clear()
|
|
247
258
|
.type(Cypress.expose('username'));
|
|
248
259
|
cy.env(['password']).then(({ password }) => {
|
|
249
260
|
cy.GLO_getElement(['ng2$svy_nav_login', 'txtPass'])
|
|
250
|
-
.find('input')
|
|
261
|
+
.find('input:visible', { timeout: 30000 })
|
|
251
262
|
.eq(0)
|
|
252
263
|
.clear()
|
|
253
264
|
.type(password, { log: false });
|
|
@@ -272,13 +283,13 @@ Cypress.Commands.add('GLO_clearData', (formulaName) => {
|
|
|
272
283
|
cy.GLO_log('Delete records completed');
|
|
273
284
|
});
|
|
274
285
|
Cypress.Commands.add('GLO_clickButton', (selector, buttonType) => {
|
|
275
|
-
cy.
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
286
|
+
// Chain .click() directly onto the query (no .then()/cy.wrap() snapshot) so Cypress's
|
|
287
|
+
// retry-ability re-runs GLO_getElement fresh on every attempt. A snapshotted jQuery handle
|
|
288
|
+
// goes stale and never recovers if Angular destroys/recreates the node once real data loads
|
|
289
|
+
// (e.g. a dialog opened via keyboard shortcut, before its websocket round-trip completes).
|
|
290
|
+
const target = buttonType ? cy.GLO_getElement(selector).find(`.${buttonType}`) : cy.GLO_getElement(selector);
|
|
291
|
+
target.click({ timeout: 10000 });
|
|
292
|
+
cy.GLO_checkLoadingIndicator();
|
|
282
293
|
});
|
|
283
294
|
Cypress.Commands.add('GLO_clickButtonText', (textButton) => {
|
|
284
295
|
clickButtonTextHelper(textButton, '.dx-button-content');
|
|
@@ -682,12 +693,12 @@ Cypress.Commands.add('GLO_closeDashboard', () => {
|
|
|
682
693
|
if (testFailed)
|
|
683
694
|
return;
|
|
684
695
|
cy.get('.navigation-item-close', { timeout: 10000 }).click();
|
|
685
|
-
cy.GLO_getVisible('.svy-message-dialog', 30000).should('exist');
|
|
686
|
-
cy.get('.svy-message-dialog').should(($dialog) => {
|
|
696
|
+
cy.GLO_getVisible('.svy-message-dialog.active', 30000).should('exist');
|
|
697
|
+
cy.get('.svy-message-dialog.active').should(($dialog) => {
|
|
687
698
|
expect($dialog.find('.window-title').text().trim()).to.match(/^(Confirm|Bevestigen)$/);
|
|
688
699
|
expect($dialog.find('.window-body').text().trim()).to.match(/^(Close all programs\?|Sluit alle programma's\?)$/);
|
|
689
700
|
});
|
|
690
|
-
cy.get('.svy-message-dialog')
|
|
701
|
+
cy.get('.svy-message-dialog.active')
|
|
691
702
|
.find('.svy-btn-primary')
|
|
692
703
|
.contains(/^(Yes|Ja)$/)
|
|
693
704
|
.should('exist')
|
|
@@ -763,22 +774,23 @@ Cypress.Commands.add('GLO_dialogChoice', (confirmation) => {
|
|
|
763
774
|
cy.wait(500);
|
|
764
775
|
cy.get('body').then(($body) => {
|
|
765
776
|
let CSSSearchStr;
|
|
766
|
-
if ($body.find('.svy-message-dialog').length > 0) {
|
|
767
|
-
CSSSearchStr = '.svy-message-dialog button';
|
|
777
|
+
if ($body.find('.svy-message-dialog.active').length > 0) {
|
|
778
|
+
CSSSearchStr = '.svy-message-dialog.active button';
|
|
768
779
|
}
|
|
769
780
|
else if ($body.find('.servoycore-dialog-body').length > 0) {
|
|
770
781
|
// Previous version
|
|
771
782
|
CSSSearchStr = '.servoycore-dialog-body button';
|
|
772
783
|
}
|
|
773
|
-
else if ($body.find('.svy-dialog.window').length > 0) {
|
|
784
|
+
else if ($body.find('.svy-dialog.window.active').length > 0) {
|
|
774
785
|
// Another variant
|
|
775
|
-
CSSSearchStr = '.svy-dialog.window globiscomponents-button';
|
|
786
|
+
CSSSearchStr = '.svy-dialog.window.active globiscomponents-button';
|
|
776
787
|
}
|
|
777
788
|
else {
|
|
778
789
|
cy.GLO_log('Popup not found, skipping dialog option');
|
|
779
790
|
return;
|
|
780
791
|
}
|
|
781
|
-
|
|
792
|
+
const $errorTitle = $body.find('.svy-message-dialog.active .window-title.type-error, .svy-dialog.window.active .window-title.type-error');
|
|
793
|
+
if ($errorTitle.length > 0 && $errorTitle.is(':visible')) {
|
|
782
794
|
cy.GLO_log('Error dialog, failing test. use GLO_dialogRequiredCheck.');
|
|
783
795
|
cy.wrap(null).should(() => {
|
|
784
796
|
throw new Error('Error dialog, failing test. use GLO_dialogRequiredCheck.');
|
|
@@ -805,7 +817,7 @@ Cypress.Commands.add('GLO_dialogChoice', (confirmation) => {
|
|
|
805
817
|
});
|
|
806
818
|
});
|
|
807
819
|
Cypress.Commands.add('GLO_addInputDialog', (text) => {
|
|
808
|
-
cy.get('.svy-message-dialog .window-body form', { timeout: 15000 }).then(($form) => {
|
|
820
|
+
cy.get('.svy-message-dialog.active .window-body form', { timeout: 15000 }).then(($form) => {
|
|
809
821
|
const inputType = $form.children().first().prop('tagName').toLowerCase();
|
|
810
822
|
if (inputType === 'input') {
|
|
811
823
|
cy.wrap($form).find('input').clear().type(text);
|
|
@@ -989,7 +1001,7 @@ Cypress.Commands.add('GLO_switchCompany', (companyName) => {
|
|
|
989
1001
|
cy.GLO_getElement(['ng$main_form2', 'navbar_top']).find('#userroles-dropdown').click();
|
|
990
1002
|
cy.get('.dx-submenu').find(span).contains('Switch company').click();
|
|
991
1003
|
cy.GLO_checkLoadingIndicator();
|
|
992
|
-
cy.get('.svy-dialog').find('.dx-dropdowneditor-icon').click();
|
|
1004
|
+
cy.get('.svy-dialog.active').find('.dx-dropdowneditor-icon').click();
|
|
993
1005
|
cy.GLO_getVisible('.dx-scrollview-content').contains(companyName).click();
|
|
994
1006
|
cy.GLO_clickButton(['ng$login_companies_dlg', 'btn_save']);
|
|
995
1007
|
});
|
|
@@ -1199,12 +1211,12 @@ const selectFromPopupWindow = (value, columnId, equals = noEqualBool) => {
|
|
|
1199
1211
|
const loadingColumnId = () => columnId
|
|
1200
1212
|
? cy.wrap(columnId)
|
|
1201
1213
|
: cy
|
|
1202
|
-
.get('.window-body
|
|
1214
|
+
.get('.svy-dialog.active .window-body .ag-center-cols-container [row-index="0"] [role="gridcell"]', { timeout: 30000 })
|
|
1203
1215
|
.filter((_, el) => Cypress.$(el).text().trim().length > 0)
|
|
1204
1216
|
.first()
|
|
1205
1217
|
.invoke('attr', 'col-id');
|
|
1206
1218
|
// So we dont have to repeat the whole command everywhere, just looks better in code below.
|
|
1207
|
-
const searchData = () => loadingColumnId().then((colId) => cy.get(`.window-body [row-index] [col-id="${colId}"]`, { timeout: loadTimeout }).should(($els) => {
|
|
1219
|
+
const searchData = () => loadingColumnId().then((colId) => cy.get(`.svy-dialog.active .window-body [row-index] [col-id="${colId}"]`, { timeout: loadTimeout }).should(($els) => {
|
|
1208
1220
|
assert.equal($els.toArray().filter((item) => (item.textContent || '').trim() === '').length, 0, 'Grid cells should not have empty values');
|
|
1209
1221
|
assert.isTrue(Cypress.$('.ag-loading').length === 0 && Cypress.$('loading-indicator').length === 0, '(Grid) loadingindicator is not visible');
|
|
1210
1222
|
}));
|
|
@@ -1238,7 +1250,7 @@ const selectFromPopupWindow = (value, columnId, equals = noEqualBool) => {
|
|
|
1238
1250
|
searchData()
|
|
1239
1251
|
.then(($els) => Array.from($els, (el) => el.textContent.trim()))
|
|
1240
1252
|
.as('beforeSearch');
|
|
1241
|
-
cy.GLO_getVisible('.window-body').within(() => {
|
|
1253
|
+
cy.GLO_getVisible('.svy-dialog.active .window-body').within(() => {
|
|
1242
1254
|
cy.GLO_getVisible(`.ag-header-cell[col-id="${columnId}"]`)
|
|
1243
1255
|
.invoke('attr', 'aria-colindex')
|
|
1244
1256
|
.then((ariaColIndex) => {
|
|
@@ -1257,13 +1269,13 @@ const selectFromPopupWindow = (value, columnId, equals = noEqualBool) => {
|
|
|
1257
1269
|
}
|
|
1258
1270
|
});
|
|
1259
1271
|
}
|
|
1260
|
-
cy.GLO_getVisible('.window-body').within(() => {
|
|
1272
|
+
cy.GLO_getVisible('.svy-dialog.active .window-body').within(() => {
|
|
1261
1273
|
dblClickRowInGrid(span, value, columnId, equals);
|
|
1262
1274
|
});
|
|
1263
1275
|
}
|
|
1264
1276
|
else {
|
|
1265
1277
|
cy.log('Value already exists in the grid, skipping search.');
|
|
1266
|
-
cy.GLO_getVisible('.window-body').within(() => {
|
|
1278
|
+
cy.GLO_getVisible('.svy-dialog.active .window-body').within(() => {
|
|
1267
1279
|
dblClickRowInGrid(span, value, columnId, equals);
|
|
1268
1280
|
});
|
|
1269
1281
|
}
|
|
@@ -1291,7 +1303,7 @@ Cypress.Commands.add('GLO_popupWindow', (selector, value, columnId, equals = noE
|
|
|
1291
1303
|
cy.GLO_checkLoadingIndicator();
|
|
1292
1304
|
}
|
|
1293
1305
|
cy.get('body').then(($body) => {
|
|
1294
|
-
if ($body.find('.window-body').
|
|
1306
|
+
if ($body.find('.svy-dialog.active .window-body').length > 0) {
|
|
1295
1307
|
selectFromPopupWindow(value, columnId, equals);
|
|
1296
1308
|
}
|
|
1297
1309
|
else {
|
|
@@ -1680,7 +1692,12 @@ Cypress.Commands.add('GLO_readFile', (fileName, fileType) => {
|
|
|
1680
1692
|
cy.readFile(`${Cypress.config('downloadsFolder')}/${fileName}.${fileType}`);
|
|
1681
1693
|
});
|
|
1682
1694
|
Cypress.Commands.add('GLO_dialogRequiredCheck', (confirmation, title, content, contentMatchType = 'exact') => {
|
|
1683
|
-
|
|
1695
|
+
// Cypress 16's :visible no longer excludes a dialog covered by another one stacked on top
|
|
1696
|
+
// of it (native checkVisibility() doesn't check occlusion), so when two dialogs are open
|
|
1697
|
+
// both can match here. The framework itself already marks the topmost/interactive one with
|
|
1698
|
+
// an "active" class (moved off the covered dialog onto whichever opens on top of it), so
|
|
1699
|
+
// scope to that instead of relying on :visible alone to disambiguate.
|
|
1700
|
+
cy.GLO_getVisible('.svy-message-dialog.active, .svy-dialog.active', 120000).within(($dialog) => {
|
|
1684
1701
|
if ($dialog.find('.window-title.type-error:visible').length > 0) {
|
|
1685
1702
|
if (typeof title === 'undefined' && typeof content === 'undefined') {
|
|
1686
1703
|
cy.GLO_log('Error dialog, failing test. Explicit definition of the title or content required.');
|
|
@@ -1770,9 +1787,21 @@ Cypress.Commands.add('GLO_fillInfieldInGrid', (selector, rowFilter, columnId, va
|
|
|
1770
1787
|
if (!value)
|
|
1771
1788
|
return;
|
|
1772
1789
|
if (typeof rowFilter === 'string') {
|
|
1773
|
-
cy.GLO_getAllRowsInGrid()
|
|
1790
|
+
cy.GLO_getAllRowsInGrid()
|
|
1791
|
+
.filter((_, el) => Cypress.$(el)
|
|
1792
|
+
.find('[role="gridcell"]')
|
|
1793
|
+
.toArray()
|
|
1794
|
+
.some((cell) => cell.textContent?.trim() === rowFilter))
|
|
1795
|
+
.find(`[col-id="${columnId}"]`)
|
|
1796
|
+
.click();
|
|
1774
1797
|
cy.wait(500); // Else both click and dblclick fire too fast
|
|
1775
|
-
cy.GLO_getAllRowsInGrid()
|
|
1798
|
+
cy.GLO_getAllRowsInGrid()
|
|
1799
|
+
.filter((_, el) => Cypress.$(el)
|
|
1800
|
+
.find('[role="gridcell"]')
|
|
1801
|
+
.toArray()
|
|
1802
|
+
.some((cell) => cell.textContent?.trim() === rowFilter))
|
|
1803
|
+
.find(`[col-id="${columnId}"]`)
|
|
1804
|
+
.dblclick();
|
|
1776
1805
|
}
|
|
1777
1806
|
else {
|
|
1778
1807
|
cy.GLO_getElement(selector).within(() => {
|
|
@@ -2177,7 +2206,11 @@ Cypress.Commands.add('GLO_extendedFilter', (filter, clearExistingFilters) => {
|
|
|
2177
2206
|
const id = $el[0].getAttribute('aria-controls');
|
|
2178
2207
|
if (!id)
|
|
2179
2208
|
throw new Error('Missing aria-controls');
|
|
2180
|
-
cy.get(`[id="${id}"]`, { timeout: 30000 })
|
|
2209
|
+
cy.get(`[id="${id}"]`, { timeout: 30000 })
|
|
2210
|
+
.should('be.visible')
|
|
2211
|
+
.should('not.have.class', 'dx-empty-collection')
|
|
2212
|
+
.find('.dx-item')
|
|
2213
|
+
.should('have.length.greaterThan', 0);
|
|
2181
2214
|
cy.get(`[id="${id}"] .dx-scrollview-content`).children().contains(value).click();
|
|
2182
2215
|
});
|
|
2183
2216
|
switch (dropDownType) {
|
|
@@ -40,7 +40,7 @@ Cypress.Commands.add('GLT_goHome', (formname) => {
|
|
|
40
40
|
cy.GLO_checkLoadingIndicator();
|
|
41
41
|
});
|
|
42
42
|
Cypress.Commands.add('GLT_closePopup', () => {
|
|
43
|
-
cy.get('.svy-dialog .window-header .svy-dialog-close').click();
|
|
43
|
+
cy.get('.svy-dialog.active .window-header .svy-dialog-close').click();
|
|
44
44
|
cy.get('.svy-dialog', { timeout: 60000 }).should('not.exist');
|
|
45
45
|
});
|
|
46
46
|
Cypress.Commands.add('GLT_clickButtonInButtonBar', (formName, title) => {
|
|
@@ -130,7 +130,7 @@ Cypress.Commands.add('GLT_getTreeListRows', (formName, elementName, filters) =>
|
|
|
130
130
|
return processLevel(null, 0);
|
|
131
131
|
});
|
|
132
132
|
Cypress.Commands.add('GLT_addInputDialog', (text) => {
|
|
133
|
-
cy.get('.svy-dialog .window-body, .svy-message-dialog .window-body', { timeout: 15000 })
|
|
133
|
+
cy.get('.svy-dialog.active .window-body, .svy-message-dialog.active .window-body', { timeout: 15000 })
|
|
134
134
|
.should(($el) => {
|
|
135
135
|
expect($el.find('input').length + $el.find('select').length, 'input or select present').to.be.greaterThan(0);
|
|
136
136
|
})
|
package/dist/config.js
CHANGED
|
@@ -27,7 +27,9 @@ const browserSettings = (browser, launchOptions) => {
|
|
|
27
27
|
export function defineGlobisConfig(overrides = {}) {
|
|
28
28
|
const wsMetricsBuffer = [];
|
|
29
29
|
return defineConfig({
|
|
30
|
-
|
|
30
|
+
// Cypress 16's HTTP/2 support is still an unfinished epic (1/14 done), causing ETIMEDOUT
|
|
31
|
+
// hangs against our Servoy backend. Remove once resolved: https://github.com/cypress-io/cypress/issues/33846
|
|
32
|
+
forceHttp1: true,
|
|
31
33
|
e2e: {
|
|
32
34
|
videosFolder: 'cypress/videos',
|
|
33
35
|
screenshotsFolder: 'cypress/screenshots',
|
|
@@ -37,7 +39,7 @@ export function defineGlobisConfig(overrides = {}) {
|
|
|
37
39
|
videoCompression: false,
|
|
38
40
|
responseTimeout: 120000,
|
|
39
41
|
modifyObstructiveCode: false,
|
|
40
|
-
|
|
42
|
+
keystrokeDelay: 10,
|
|
41
43
|
numTestsKeptInMemory: Number(process.env.numTestsKeptInMemory ?? 0),
|
|
42
44
|
scrollBehavior: 'center',
|
|
43
45
|
...overrides.e2e,
|