@globisnv/cypress-core 1.1.1 → 2.0.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.
@@ -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) });
@@ -756,7 +759,7 @@ const navItem = (topBottom, programName, tabNumber, mode) => {
756
759
  throw new Error(`Incorrect type for GLO_${mode}Program. Available types: top, bottom`);
757
760
  const location = topBottom === top ? 0 : 1;
758
761
  const regex = new RegExp(`^${Cypress._.escapeRegExp(programName)}$`);
759
- cy.get('drag-scroll')
762
+ cy.get('[navigation] > [nodelist]')
760
763
  .eq(location)
761
764
  .within(() => {
762
765
  const items = cy
@@ -1072,13 +1075,13 @@ Cypress.Commands.add('GLO_selectProgram', (topBottom, programName, tabnumber) =>
1072
1075
  navItem(topBottom, programName, tabnumber, 'select');
1073
1076
  });
1074
1077
  Cypress.Commands.add('GLO_getRowInGrid', (rowFilter) => {
1075
- const rows = cy.get('.ag-center-cols-container [row-index]').filter(isInOpenContainer);
1078
+ const rows = cy.get(gridDataRows).filter(isInOpenContainer);
1076
1079
  return typeof rowFilter === 'number' ? rows.eq(rowFilter) : rows.filter(`:contains("${rowFilter}")`).first();
1077
1080
  });
1078
1081
  Cypress.Commands.add('GLO_selectRowInGrid', (rowFilter) => {
1079
1082
  let found = false;
1080
1083
  if (typeof rowFilter === 'number') {
1081
- cy.get(`[row-id="root_${rowFilter}"]`).filter(isInOpenContainer).find('[data-ref="eInput"]').click();
1084
+ cy.get(`[row-id="root_${rowFilter}"]`).filter(isInOpenContainer).find('.ag-grid-pinned-left-cells [data-ref="eInput"]').click();
1082
1085
  return;
1083
1086
  }
1084
1087
  // Convert to array if it's a string
@@ -1092,15 +1095,8 @@ Cypress.Commands.add('GLO_selectRowInGrid', (rowFilter) => {
1092
1095
  const matches = filters.every((filterValue) => cellTexts.some((val) => val.includes(filterValue)));
1093
1096
  if (matches) {
1094
1097
  found = true;
1095
- const rowId = $row.attr('row-id');
1096
- // No isInOpenContainer here: `.ag-root` is the grid of $row, which already passed that
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
- });
1098
+ // AG Grid 36 renders the pinned-left selection checkbox inside the row itself.
1099
+ cy.wrap($row).find('.ag-grid-pinned-left-cells [data-ref="eInput"]').click();
1104
1100
  return false; // Stop after the first match
1105
1101
  }
1106
1102
  })
@@ -1150,7 +1146,7 @@ const dblClickRowInGrid = (type, value, columnId, equals) => {
1150
1146
  cy.get('[row-index]:visible')
1151
1147
  .find(`[col-id="${columnId}"]`)
1152
1148
  .filter(filterSelector, { timeout: 10000 })
1153
- .parentsUntil('.ag-center-cols-container')
1149
+ .parentsUntil('.ag-grid-scrolling-container')
1154
1150
  .filter('[row-index]')
1155
1151
  .first()
1156
1152
  .then(saveValues);
@@ -1173,7 +1169,7 @@ const dblClickRowInGrid = (type, value, columnId, equals) => {
1173
1169
  cy.get('[row-index]:visible')
1174
1170
  .find(columnId ? `[col-id="${columnId}"] ${span}` : span)
1175
1171
  .contains(regex, { timeout: 10000 })
1176
- .parentsUntil('.ag-center-cols-container')
1172
+ .parentsUntil('.ag-grid-scrolling-container')
1177
1173
  .filter('[row-index]')
1178
1174
  .first()
1179
1175
  .then(saveValues);
@@ -1198,13 +1194,13 @@ const dblClickRowInGrid = (type, value, columnId, equals) => {
1198
1194
  }
1199
1195
  // The actual dblClick on the row
1200
1196
  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();
1197
+ columnId ? cy.get(selector).find(`[col-id="${columnId}"]`).dblclick() : cy.get(selector).find('.ag-grid-scrolling-cells [aria-colindex]').eq(1).dblclick();
1202
1198
  });
1203
1199
  };
1204
1200
  Cypress.Commands.add('GLO_clickRowInGrid', (value, columnId) => {
1205
1201
  if (value === undefined)
1206
1202
  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();
1203
+ columnId ? cy.GLO_getRowInGrid(value).find(`[col-id="${columnId}"]`).click() : cy.GLO_getRowInGrid(value).find('.ag-grid-scrolling-cells').children().first().click();
1208
1204
  cy.GLO_checkLoadingIndicator();
1209
1205
  });
1210
1206
  // Shared popup-window search + grid selection logic used by GLO_popupWindow.
@@ -1217,7 +1213,9 @@ const selectFromPopupWindow = (value, columnId, equals = noEqualBool) => {
1217
1213
  const loadingColumnId = () => columnId
1218
1214
  ? cy.wrap(columnId)
1219
1215
  : cy
1220
- .get('.svy-dialog.active .window-body .ag-center-cols-container [row-index="0"] [role="gridcell"]', { timeout: 30000 })
1216
+ .get('.svy-dialog.active .window-body .ag-grid-scrolling-container [row-index="0"]:not(.ag-full-width-row) .ag-grid-scrolling-cells [role="gridcell"]', {
1217
+ timeout: 30000
1218
+ })
1221
1219
  .filter((_, el) => Cypress.$(el).text().trim().length > 0)
1222
1220
  .first()
1223
1221
  .invoke('attr', 'col-id');
@@ -1481,13 +1479,15 @@ Cypress.Commands.add('GLO_checkNumberOfRowsInGrid', (selector, numberToValidate,
1481
1479
  const pollInterval = 5000;
1482
1480
  const HEADER_ROWS = 2;
1483
1481
  const getAriaRowcount = ($grid) => parseInt($grid.find('[role="grid"]').attr('aria-rowcount') || '0', 10);
1484
- // Column header row + filter row, counted in the center viewport only (the pinned-left and
1485
- // pinned-right containers repeat those same header rows).
1486
- const headerRowCount = ($grid) => $grid.find('.ag-header-viewport .ag-header-row').length || HEADER_ROWS;
1482
+ // Column header row + filter row (AG Grid 36 renders each header row once, pinned cells included).
1483
+ const headerRowCount = ($grid) => $grid.find('.ag-header .ag-header-row').length || HEADER_ROWS;
1484
+ // Rows aria-rowcount counts that are not data rows: header rows plus pinned top/bottom rows (e.g. a totals
1485
+ // row), which AG Grid 36 includes in aria-rowcount. Pinned rows are never virtualised, so the DOM count is exact.
1486
+ const nonDataRowCount = ($grid) => headerRowCount($grid) + $grid.find('.ag-row-pinned').length;
1487
1487
  const isLazyLoaded = ($grid) => {
1488
1488
  const ariaRowcount = getAriaRowcount($grid);
1489
- const renderedRows = $grid.find('.ag-center-cols-container [row-index]').length;
1490
- return renderedRows > 0 && (ariaRowcount === -1 || ariaRowcount > renderedRows + headerRowCount($grid));
1489
+ const renderedRows = $grid.find(gridDataRows).length;
1490
+ return renderedRows > 0 && (ariaRowcount === -1 || ariaRowcount > renderedRows + nonDataRowCount($grid));
1491
1491
  };
1492
1492
  // When a client-side column filter is active, the tab-/datacontrol-counter still shows the
1493
1493
  // unfiltered foundset total, so we must count the rendered (filtered) rows instead.
@@ -1509,12 +1509,12 @@ Cypress.Commands.add('GLO_checkNumberOfRowsInGrid', (selector, numberToValidate,
1509
1509
  const total = parseInt(parts[1].trim(), 10);
1510
1510
  return Number.isNaN(total) ? null : total;
1511
1511
  };
1512
- // AG Grid publishes the displayed row total (header rows included, pinned "sum" rows
1513
- // excluded) in aria-rowcount, so a virtualised grid still reports rows the viewport never
1514
- // rendered. Verified on ng$consignment_dtl_general.grid: 25 goods -> aria-rowcount 27 with
1515
- // 2 header rows, while only 12 rows exist in the DOM.
1512
+ // AG Grid publishes the displayed row total (header and pinned rows included) in aria-rowcount,
1513
+ // so a virtualised grid still reports rows the viewport never rendered. Verified on
1514
+ // ng$consignment_dtl_general.grid: 25 goods -> aria-rowcount 27 with 2 header rows, while only
1515
+ // 12 rows exist in the DOM.
1516
1516
  const getCountFromAriaRowcount = ($grid) => {
1517
- const total = getAriaRowcount($grid) - headerRowCount($grid);
1517
+ const total = getAriaRowcount($grid) - nonDataRowCount($grid);
1518
1518
  return total >= 0 ? total : null; // An aria-rowcount of -1 means the total is unknown (infinite row model)
1519
1519
  };
1520
1520
  // Form-level counters (#txtCount navigator, tab "(n)" label) only match a grid on list
@@ -1558,7 +1558,7 @@ Cypress.Commands.add('GLO_checkNumberOfRowsInGrid', (selector, numberToValidate,
1558
1558
  runChainAssertion(tabCount);
1559
1559
  }
1560
1560
  else {
1561
- runChainAssertion($grid.find('.ag-center-cols-container [row-index]'));
1561
+ runChainAssertion($grid.find(gridDataRows));
1562
1562
  }
1563
1563
  });
1564
1564
  }
@@ -1569,7 +1569,7 @@ Cypress.Commands.add('GLO_checkNumberOfRowsInGrid', (selector, numberToValidate,
1569
1569
  const log = Cypress.log({ name: 'checkNumberOfRowsInGrid', message: `Polling rows (${lengthCondition} ${numberToValidate})…`, autoEnd: false, timeout: 0 });
1570
1570
  const checkStatus = (resolve, reject) => {
1571
1571
  cy.GLO_getElement(selector, { timeout: timeOut, log: false }).then(($grid) => {
1572
- const $rows = $grid.find('.ag-center-cols-container [row-index]');
1572
+ const $rows = $grid.find(gridDataRows);
1573
1573
  let actual = $rows.length;
1574
1574
  let passed = false;
1575
1575
  try {
@@ -1768,7 +1768,7 @@ Cypress.Commands.add('GLO_selectRows', (selector, rowNumber) => {
1768
1768
  }
1769
1769
  };
1770
1770
  cy.GLO_getElement(selector)
1771
- .find('.ag-body-viewport')
1771
+ .find('.ag-grid-scrolling-rows')
1772
1772
  .within(() => {
1773
1773
  cy.GLO_clickRowInGrid(0); // Always click the first row
1774
1774
  if (rowNumber !== undefined) {
@@ -1783,7 +1783,7 @@ Cypress.Commands.add('GLO_selectRows', (selector, rowNumber) => {
1783
1783
  });
1784
1784
  Cypress.Commands.add('GLO_sortGrid', (selector, headerText) => {
1785
1785
  cy.GLO_getElement(selector)
1786
- .find('.ag-header-viewport .ag-header-row.ag-header-row-column')
1786
+ .find('.ag-header .ag-header-row.ag-header-row-column')
1787
1787
  .within(() => {
1788
1788
  cy.get('.ag-header-cell').contains(headerText).click();
1789
1789
  });
@@ -1966,14 +1966,15 @@ Cypress.Commands.add('GLO_getAllRowsInGrid', (selector, timeOut = defaultTimeout
1966
1966
  const deadline = Date.now() + timeOut;
1967
1967
  return cy
1968
1968
  .GLO_getElement(selector, { timeout: timeOut })
1969
- .find('.ag-center-cols-container [row-index]', { timeout: timeOut + 500 })
1969
+ .find(gridDataRows, { timeout: timeOut + 500 })
1970
1970
  .should(($rows) => {
1971
1971
  if ($rows.length === 0 && Date.now() < deadline)
1972
1972
  throw new Error('GLO_getAllRowsInGrid: waiting for rows');
1973
1973
  });
1974
1974
  }
1975
1975
  else {
1976
- return cy.get('.ag-center-cols-container [row-index] [role="gridcell"]', { timeout: timeOut }).parent().filter(isInOpenContainer);
1976
+ // AG Grid 36 nests cells in pinned/scrolling wrappers, so a cell's parent is no longer the row.
1977
+ return cy.get(`${gridDataRows}:has([role="gridcell"])`, { timeout: timeOut }).filter(isInOpenContainer);
1977
1978
  }
1978
1979
  });
1979
1980
  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-body-viewport')
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-body-viewport label', value).click();
27
+ return cy.contains('.ag-grid-scrolling-rows label', value).click();
28
28
  }
29
29
  return cy
30
- .get('.ag-center-cols-container [role="row"][tabindex="0"]')
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-center-cols-container').POR_isNotEmpty();
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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@globisnv/cypress-core",
3
- "version": "1.1.1",
3
+ "version": "2.0.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.2"
18
+ "minVersion": "11.0.3"
19
19
  },
20
20
  "exports": {
21
21
  ".": "./dist/index.js",