@globisnv/cypress-core 1.1.1 → 2.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/README.md
CHANGED
|
@@ -34,6 +34,7 @@ See [Cutting a release](#cutting-a-release) for how a bump actually gets publish
|
|
|
34
34
|
|
|
35
35
|
| Core version | Minimum globis-online version |
|
|
36
36
|
| --- | --- |
|
|
37
|
+
| `2.0.0` | `11.0.3` |
|
|
37
38
|
| `0.0.1` | `11.0.2` |
|
|
38
39
|
|
|
39
40
|
The floor is recorded in `package.json` under `globisOnline.minVersion` (machine-readable, in case tooling wants to check it later) and here in this table (human-readable, updated on every release alongside `CHANGELOG.md`). `globis-cypress` stays pinned to the latest core version — since it's Globis's own suite, it's the first thing to catch a globis-online release breaking something, before any customer repo would.
|
|
@@ -150,6 +150,20 @@ declare global {
|
|
|
150
150
|
* @example - cy.GLO_clickDatacontrolViewerButton('salesorder', 'btnAdd');
|
|
151
151
|
*/
|
|
152
152
|
GLO_clickDatacontrolViewerButton(pageName: string, buttonName: baseDatacontrolViewerButtonType, skipCheck?: skipCheckFlag): void;
|
|
153
|
+
/**
|
|
154
|
+
* Command to check the counter badges of a button within the main program datacontrol bar.
|
|
155
|
+
*
|
|
156
|
+
* The grey badge counts the attachments with a physical file or the closed notifications, the red badge the
|
|
157
|
+
* attachments without a physical file or the open notifications. A badge is hidden at 0, so passing 0 checks that it does not exist.
|
|
158
|
+
*
|
|
159
|
+
* @param {datacontrolCounterButtonType} buttonName - The datacontrol button with the counters.
|
|
160
|
+
* @param {number} greyCount - The expected grey count, 0 when there should be no grey badge.
|
|
161
|
+
* @param {number} redCount - The expected red count, 0 when there should be no red badge.
|
|
162
|
+
* @param {number} [timeOut = defaultTimeout] - The time to wait for the counters to update.
|
|
163
|
+
*
|
|
164
|
+
* @example - cy.GLO_checkDatacontrolCounter('btnAttachment', 3, 1);
|
|
165
|
+
*/
|
|
166
|
+
GLO_checkDatacontrolCounter(buttonName: datacontrolCounterButtonType, greyCount: number, redCount: number, timeOut?: number): void;
|
|
153
167
|
/**
|
|
154
168
|
* Command to click a button based on its displayed text.
|
|
155
169
|
*
|
|
@@ -33,6 +33,9 @@ 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
|
+
// Data rows of an AG Grid 36 body. Group rows (full-width) share the scrolling container with the data rows,
|
|
37
|
+
// so they are excluded to keep row indexes and counts about data rows only.
|
|
38
|
+
const gridDataRows = '.ag-grid-scrolling-container [row-index]:not(.ag-full-width-row)';
|
|
36
39
|
const pickByRowIndex = (chain, index, log = false, timeout = defaultTimeout) => {
|
|
37
40
|
if (log)
|
|
38
41
|
Cypress.log({ name: 'idx', message: String(index) });
|
|
@@ -469,6 +472,21 @@ Cypress.Commands.add('GLO_clickDatacontrolViewerButton', (pageName, buttonName,
|
|
|
469
472
|
cy.GLO_getElement([`ng$${pageName}_tab`, 'datacontrol_viewer']).find('[title="Save record"][disabled="true"]', { timeout: 60000 });
|
|
470
473
|
});
|
|
471
474
|
});
|
|
475
|
+
Cypress.Commands.add('GLO_checkDatacontrolCounter', (buttonName, greyCount, redCount, timeOut = defaultTimeout) => {
|
|
476
|
+
const button = `globiscomponents-data-control[name="datacontrol"]:visible #${buttonName}`;
|
|
477
|
+
// Without the button in view a 'not.exist' check below would pass for the wrong reason.
|
|
478
|
+
cy.get(button, { timeout: timeOut }).should('exist');
|
|
479
|
+
const checkBadge = (selector, count) => {
|
|
480
|
+
if (count > 0) {
|
|
481
|
+
cy.get(selector, { timeout: timeOut }).should('have.text', count.toString());
|
|
482
|
+
}
|
|
483
|
+
else {
|
|
484
|
+
cy.get(selector, { timeout: timeOut }).should('not.exist');
|
|
485
|
+
}
|
|
486
|
+
};
|
|
487
|
+
checkBadge(`${button} [counter-muted]`, greyCount);
|
|
488
|
+
checkBadge(`${button} [counter]:not([counter-muted])`, redCount);
|
|
489
|
+
});
|
|
472
490
|
Cypress.Commands.add('GLO_selectCompany', (companyName) => {
|
|
473
491
|
cy.GLO_addInput(['ng2$svy_nav_login', 'company'], companyName);
|
|
474
492
|
cy.get('[data-cy="ng2$svy_nav_login.btnLogin"]').click();
|
|
@@ -756,7 +774,7 @@ const navItem = (topBottom, programName, tabNumber, mode) => {
|
|
|
756
774
|
throw new Error(`Incorrect type for GLO_${mode}Program. Available types: top, bottom`);
|
|
757
775
|
const location = topBottom === top ? 0 : 1;
|
|
758
776
|
const regex = new RegExp(`^${Cypress._.escapeRegExp(programName)}$`);
|
|
759
|
-
cy.get('
|
|
777
|
+
cy.get('[navigation] > [nodelist]')
|
|
760
778
|
.eq(location)
|
|
761
779
|
.within(() => {
|
|
762
780
|
const items = cy
|
|
@@ -1072,13 +1090,13 @@ Cypress.Commands.add('GLO_selectProgram', (topBottom, programName, tabnumber) =>
|
|
|
1072
1090
|
navItem(topBottom, programName, tabnumber, 'select');
|
|
1073
1091
|
});
|
|
1074
1092
|
Cypress.Commands.add('GLO_getRowInGrid', (rowFilter) => {
|
|
1075
|
-
const rows = cy.get(
|
|
1093
|
+
const rows = cy.get(gridDataRows).filter(isInOpenContainer);
|
|
1076
1094
|
return typeof rowFilter === 'number' ? rows.eq(rowFilter) : rows.filter(`:contains("${rowFilter}")`).first();
|
|
1077
1095
|
});
|
|
1078
1096
|
Cypress.Commands.add('GLO_selectRowInGrid', (rowFilter) => {
|
|
1079
1097
|
let found = false;
|
|
1080
1098
|
if (typeof rowFilter === 'number') {
|
|
1081
|
-
cy.get(`[row-id="root_${rowFilter}"]`).filter(isInOpenContainer).find('[data-ref="eInput"]').click();
|
|
1099
|
+
cy.get(`[row-id="root_${rowFilter}"]`).filter(isInOpenContainer).find('.ag-grid-pinned-left-cells [data-ref="eInput"]').click();
|
|
1082
1100
|
return;
|
|
1083
1101
|
}
|
|
1084
1102
|
// Convert to array if it's a string
|
|
@@ -1092,15 +1110,8 @@ Cypress.Commands.add('GLO_selectRowInGrid', (rowFilter) => {
|
|
|
1092
1110
|
const matches = filters.every((filterValue) => cellTexts.some((val) => val.includes(filterValue)));
|
|
1093
1111
|
if (matches) {
|
|
1094
1112
|
found = true;
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
// filter above, so everything inside shares its ancestors. The re-query is only needed
|
|
1098
|
-
// because the checkbox lives in the pinned-left twin carrying the same row-id.
|
|
1099
|
-
cy.wrap($row)
|
|
1100
|
-
.closest('.ag-root')
|
|
1101
|
-
.within(() => {
|
|
1102
|
-
cy.get(`[row-id="${rowId}"]`).find('[data-ref="eInput"]').click();
|
|
1103
|
-
});
|
|
1113
|
+
// AG Grid 36 renders the pinned-left selection checkbox inside the row itself.
|
|
1114
|
+
cy.wrap($row).find('.ag-grid-pinned-left-cells [data-ref="eInput"]').click();
|
|
1104
1115
|
return false; // Stop after the first match
|
|
1105
1116
|
}
|
|
1106
1117
|
})
|
|
@@ -1150,7 +1161,7 @@ const dblClickRowInGrid = (type, value, columnId, equals) => {
|
|
|
1150
1161
|
cy.get('[row-index]:visible')
|
|
1151
1162
|
.find(`[col-id="${columnId}"]`)
|
|
1152
1163
|
.filter(filterSelector, { timeout: 10000 })
|
|
1153
|
-
.parentsUntil('.ag-
|
|
1164
|
+
.parentsUntil('.ag-grid-scrolling-container')
|
|
1154
1165
|
.filter('[row-index]')
|
|
1155
1166
|
.first()
|
|
1156
1167
|
.then(saveValues);
|
|
@@ -1173,7 +1184,7 @@ const dblClickRowInGrid = (type, value, columnId, equals) => {
|
|
|
1173
1184
|
cy.get('[row-index]:visible')
|
|
1174
1185
|
.find(columnId ? `[col-id="${columnId}"] ${span}` : span)
|
|
1175
1186
|
.contains(regex, { timeout: 10000 })
|
|
1176
|
-
.parentsUntil('.ag-
|
|
1187
|
+
.parentsUntil('.ag-grid-scrolling-container')
|
|
1177
1188
|
.filter('[row-index]')
|
|
1178
1189
|
.first()
|
|
1179
1190
|
.then(saveValues);
|
|
@@ -1198,13 +1209,13 @@ const dblClickRowInGrid = (type, value, columnId, equals) => {
|
|
|
1198
1209
|
}
|
|
1199
1210
|
// The actual dblClick on the row
|
|
1200
1211
|
cy.get('@COM_selectedRowSelector').then((selector) => {
|
|
1201
|
-
columnId ? cy.get(selector).find(`[col-id="${columnId}"]`).dblclick() : cy.get(selector).find('[aria-colindex]').eq(1).dblclick();
|
|
1212
|
+
columnId ? cy.get(selector).find(`[col-id="${columnId}"]`).dblclick() : cy.get(selector).find('.ag-grid-scrolling-cells [aria-colindex]').eq(1).dblclick();
|
|
1202
1213
|
});
|
|
1203
1214
|
};
|
|
1204
1215
|
Cypress.Commands.add('GLO_clickRowInGrid', (value, columnId) => {
|
|
1205
1216
|
if (value === undefined)
|
|
1206
1217
|
throw new Error('Value missing for GLO_clickRowInGrid');
|
|
1207
|
-
columnId ? cy.GLO_getRowInGrid(value).find(`[col-id="${columnId}"]`).click() : cy.GLO_getRowInGrid(value).children().first().click();
|
|
1218
|
+
columnId ? cy.GLO_getRowInGrid(value).find(`[col-id="${columnId}"]`).click() : cy.GLO_getRowInGrid(value).find('.ag-grid-scrolling-cells').children().first().click();
|
|
1208
1219
|
cy.GLO_checkLoadingIndicator();
|
|
1209
1220
|
});
|
|
1210
1221
|
// Shared popup-window search + grid selection logic used by GLO_popupWindow.
|
|
@@ -1217,7 +1228,9 @@ const selectFromPopupWindow = (value, columnId, equals = noEqualBool) => {
|
|
|
1217
1228
|
const loadingColumnId = () => columnId
|
|
1218
1229
|
? cy.wrap(columnId)
|
|
1219
1230
|
: cy
|
|
1220
|
-
.get('.svy-dialog.active .window-body .ag-
|
|
1231
|
+
.get('.svy-dialog.active .window-body .ag-grid-scrolling-container [row-index="0"]:not(.ag-full-width-row) .ag-grid-scrolling-cells [role="gridcell"]', {
|
|
1232
|
+
timeout: 30000
|
|
1233
|
+
})
|
|
1221
1234
|
.filter((_, el) => Cypress.$(el).text().trim().length > 0)
|
|
1222
1235
|
.first()
|
|
1223
1236
|
.invoke('attr', 'col-id');
|
|
@@ -1481,13 +1494,15 @@ Cypress.Commands.add('GLO_checkNumberOfRowsInGrid', (selector, numberToValidate,
|
|
|
1481
1494
|
const pollInterval = 5000;
|
|
1482
1495
|
const HEADER_ROWS = 2;
|
|
1483
1496
|
const getAriaRowcount = ($grid) => parseInt($grid.find('[role="grid"]').attr('aria-rowcount') || '0', 10);
|
|
1484
|
-
// Column header row + filter row
|
|
1485
|
-
|
|
1486
|
-
|
|
1497
|
+
// Column header row + filter row (AG Grid 36 renders each header row once, pinned cells included).
|
|
1498
|
+
const headerRowCount = ($grid) => $grid.find('.ag-header .ag-header-row').length || HEADER_ROWS;
|
|
1499
|
+
// Rows aria-rowcount counts that are not data rows: header rows plus pinned top/bottom rows (e.g. a totals
|
|
1500
|
+
// row), which AG Grid 36 includes in aria-rowcount. Pinned rows are never virtualised, so the DOM count is exact.
|
|
1501
|
+
const nonDataRowCount = ($grid) => headerRowCount($grid) + $grid.find('.ag-row-pinned').length;
|
|
1487
1502
|
const isLazyLoaded = ($grid) => {
|
|
1488
1503
|
const ariaRowcount = getAriaRowcount($grid);
|
|
1489
|
-
const renderedRows = $grid.find(
|
|
1490
|
-
return renderedRows > 0 && (ariaRowcount === -1 || ariaRowcount > renderedRows +
|
|
1504
|
+
const renderedRows = $grid.find(gridDataRows).length;
|
|
1505
|
+
return renderedRows > 0 && (ariaRowcount === -1 || ariaRowcount > renderedRows + nonDataRowCount($grid));
|
|
1491
1506
|
};
|
|
1492
1507
|
// When a client-side column filter is active, the tab-/datacontrol-counter still shows the
|
|
1493
1508
|
// unfiltered foundset total, so we must count the rendered (filtered) rows instead.
|
|
@@ -1509,12 +1524,12 @@ Cypress.Commands.add('GLO_checkNumberOfRowsInGrid', (selector, numberToValidate,
|
|
|
1509
1524
|
const total = parseInt(parts[1].trim(), 10);
|
|
1510
1525
|
return Number.isNaN(total) ? null : total;
|
|
1511
1526
|
};
|
|
1512
|
-
// AG Grid publishes the displayed row total (header rows included
|
|
1513
|
-
//
|
|
1514
|
-
//
|
|
1515
|
-
//
|
|
1527
|
+
// AG Grid publishes the displayed row total (header and pinned rows included) in aria-rowcount,
|
|
1528
|
+
// so a virtualised grid still reports rows the viewport never rendered. Verified on
|
|
1529
|
+
// ng$consignment_dtl_general.grid: 25 goods -> aria-rowcount 27 with 2 header rows, while only
|
|
1530
|
+
// 12 rows exist in the DOM.
|
|
1516
1531
|
const getCountFromAriaRowcount = ($grid) => {
|
|
1517
|
-
const total = getAriaRowcount($grid) -
|
|
1532
|
+
const total = getAriaRowcount($grid) - nonDataRowCount($grid);
|
|
1518
1533
|
return total >= 0 ? total : null; // An aria-rowcount of -1 means the total is unknown (infinite row model)
|
|
1519
1534
|
};
|
|
1520
1535
|
// Form-level counters (#txtCount navigator, tab "(n)" label) only match a grid on list
|
|
@@ -1558,7 +1573,7 @@ Cypress.Commands.add('GLO_checkNumberOfRowsInGrid', (selector, numberToValidate,
|
|
|
1558
1573
|
runChainAssertion(tabCount);
|
|
1559
1574
|
}
|
|
1560
1575
|
else {
|
|
1561
|
-
runChainAssertion($grid.find(
|
|
1576
|
+
runChainAssertion($grid.find(gridDataRows));
|
|
1562
1577
|
}
|
|
1563
1578
|
});
|
|
1564
1579
|
}
|
|
@@ -1569,7 +1584,7 @@ Cypress.Commands.add('GLO_checkNumberOfRowsInGrid', (selector, numberToValidate,
|
|
|
1569
1584
|
const log = Cypress.log({ name: 'checkNumberOfRowsInGrid', message: `Polling rows (${lengthCondition} ${numberToValidate})…`, autoEnd: false, timeout: 0 });
|
|
1570
1585
|
const checkStatus = (resolve, reject) => {
|
|
1571
1586
|
cy.GLO_getElement(selector, { timeout: timeOut, log: false }).then(($grid) => {
|
|
1572
|
-
const $rows = $grid.find(
|
|
1587
|
+
const $rows = $grid.find(gridDataRows);
|
|
1573
1588
|
let actual = $rows.length;
|
|
1574
1589
|
let passed = false;
|
|
1575
1590
|
try {
|
|
@@ -1768,7 +1783,7 @@ Cypress.Commands.add('GLO_selectRows', (selector, rowNumber) => {
|
|
|
1768
1783
|
}
|
|
1769
1784
|
};
|
|
1770
1785
|
cy.GLO_getElement(selector)
|
|
1771
|
-
.find('.ag-
|
|
1786
|
+
.find('.ag-grid-scrolling-rows')
|
|
1772
1787
|
.within(() => {
|
|
1773
1788
|
cy.GLO_clickRowInGrid(0); // Always click the first row
|
|
1774
1789
|
if (rowNumber !== undefined) {
|
|
@@ -1783,7 +1798,7 @@ Cypress.Commands.add('GLO_selectRows', (selector, rowNumber) => {
|
|
|
1783
1798
|
});
|
|
1784
1799
|
Cypress.Commands.add('GLO_sortGrid', (selector, headerText) => {
|
|
1785
1800
|
cy.GLO_getElement(selector)
|
|
1786
|
-
.find('.ag-header
|
|
1801
|
+
.find('.ag-header .ag-header-row.ag-header-row-column')
|
|
1787
1802
|
.within(() => {
|
|
1788
1803
|
cy.get('.ag-header-cell').contains(headerText).click();
|
|
1789
1804
|
});
|
|
@@ -1966,14 +1981,15 @@ Cypress.Commands.add('GLO_getAllRowsInGrid', (selector, timeOut = defaultTimeout
|
|
|
1966
1981
|
const deadline = Date.now() + timeOut;
|
|
1967
1982
|
return cy
|
|
1968
1983
|
.GLO_getElement(selector, { timeout: timeOut })
|
|
1969
|
-
.find(
|
|
1984
|
+
.find(gridDataRows, { timeout: timeOut + 500 })
|
|
1970
1985
|
.should(($rows) => {
|
|
1971
1986
|
if ($rows.length === 0 && Date.now() < deadline)
|
|
1972
1987
|
throw new Error('GLO_getAllRowsInGrid: waiting for rows');
|
|
1973
1988
|
});
|
|
1974
1989
|
}
|
|
1975
1990
|
else {
|
|
1976
|
-
|
|
1991
|
+
// AG Grid 36 nests cells in pinned/scrolling wrappers, so a cell's parent is no longer the row.
|
|
1992
|
+
return cy.get(`${gridDataRows}:has([role="gridcell"])`, { timeout: timeOut }).filter(isInOpenContainer);
|
|
1977
1993
|
}
|
|
1978
1994
|
});
|
|
1979
1995
|
Cypress.Commands.add('GLO_validateGridOrFail', (waitValue, failValue, rowNumber, columnId, timeOut = 600000, interval = 15000) => {
|
|
@@ -19,15 +19,15 @@ Cypress.Commands.add('GLS_mainNavigation', (value) => {
|
|
|
19
19
|
throw new Error(`Could not find menu item: ${value}`);
|
|
20
20
|
}
|
|
21
21
|
return cy
|
|
22
|
-
.get('.ag-
|
|
22
|
+
.get('.ag-grid-scrolling-rows')
|
|
23
23
|
.first()
|
|
24
24
|
.then(($viewport) => {
|
|
25
25
|
const $label = $viewport.find('label').filter((_i, el) => el.innerText.trim() === value);
|
|
26
26
|
if ($label.length > 0 && $label.is(':visible')) {
|
|
27
|
-
return cy.contains('.ag-
|
|
27
|
+
return cy.contains('.ag-grid-scrolling-rows label', value).click();
|
|
28
28
|
}
|
|
29
29
|
return cy
|
|
30
|
-
.get('.ag-
|
|
30
|
+
.get('.ag-grid-scrolling-container [role="row"][tabindex="0"]')
|
|
31
31
|
.first()
|
|
32
32
|
.focus()
|
|
33
33
|
.realPress('ArrowDown')
|
|
@@ -65,7 +65,7 @@ Cypress.Commands.add('POR_clickTopDropdownMenu', (linkText) => {
|
|
|
65
65
|
});
|
|
66
66
|
Cypress.Commands.add('POR_checkTableHasData', () => {
|
|
67
67
|
cy.GLO_getElement(['ep$consignment_lst', 'shipments_grid']).within(() => {
|
|
68
|
-
cy.get('.ag-
|
|
68
|
+
cy.get('.ag-grid-scrolling-container').POR_isNotEmpty();
|
|
69
69
|
});
|
|
70
70
|
});
|
|
71
71
|
Cypress.Commands.add('POR_isNotEmpty', { prevSubject: true }, (subject, className) => {
|
package/dist/types.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ type customValueTypeUndefined = customValueType | undefined;
|
|
|
11
11
|
type deleteRecordsType = 'DELETE_CYPRESS_RECORDS' | 'DELETE_LEAPWORK_RECORDS';
|
|
12
12
|
type viewModeButtonType = 'btnList' | 'btnDetail';
|
|
13
13
|
type datacontrolbuttonType = baseDatacontrolViewerButtonType | viewModeButtonType | 'btnPrev' | 'btnNext' | 'btnAll' | 'btnPivot' | 'btnAttachment' | 'btnAddMode' | 'btnEditMode' | 'btnDeleteMode' | 'btnDeeplink' | 'btnExtendedSearch' | 'btnCustomViews' | 'btnFilter' | 'btnClearAllFilters';
|
|
14
|
+
type datacontrolCounterButtonType = 'btnAttachment' | 'btnNotification';
|
|
14
15
|
type checkValueInGridType = string | string[] | number;
|
|
15
16
|
type selectMenuButtonLeftType = 'home' | 'settings' | 'help' | 'support' | 'excel' | 'info' | 'refresh' | 'query' | 'clients' | 'users' | 'theme';
|
|
16
17
|
type urlTypeType = 'online' | 'pos' | 'globgate' | 'globjob' | 'globscan' | 'portal' | 'carrier' | 'globtrace' | 'external_portal' | 'globtake' | 'globis_external_portal';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@globisnv/cypress-core",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Core building blocks for Globis Cypress E2E tests",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"access": "public"
|
|
16
16
|
},
|
|
17
17
|
"globisOnline": {
|
|
18
|
-
"minVersion": "11.0.
|
|
18
|
+
"minVersion": "11.0.3"
|
|
19
19
|
},
|
|
20
20
|
"exports": {
|
|
21
21
|
".": "./dist/index.js",
|