cypress-ag-grid 3.3.2 → 3.3.4

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.
@@ -0,0 +1,56 @@
1
+ import { filterOperator } from "../../../src/agGrid/filterOperator.enum";
2
+
3
+ const agGridSelector = "#myGrid2";
4
+
5
+ export function runAgGridElementsSuite({ pagePath, versionLabel }) {
6
+ describe(`ag-grid get elements scenario (${versionLabel})`, () => {
7
+ beforeEach(() => {
8
+ cy.visit(pagePath);
9
+ cy.contains(".example-version", `AG Grid ${versionLabel}`).should("be.visible");
10
+ cy.get(".ag-cell", { timeout: 10000 }).should("be.visible");
11
+ });
12
+
13
+ it("able to update grid cell value", () => {
14
+ cy.get(agGridSelector).agGridColumnFilterTextFloating({
15
+ searchCriteria: {
16
+ columnName: "Make",
17
+ filterValue: "Porsche",
18
+ operator: filterOperator.equals,
19
+ },
20
+ hasApplyButton: true,
21
+ });
22
+
23
+ const expectedTableBeforeEditing = [
24
+ { Year: "2020", Make: "Porsche", Model: "Boxter", Price: "72000" },
25
+ { Year: "2020", Make: "Porsche", Model: "Boxter", Price: "99000" },
26
+ ];
27
+
28
+ cy.get(agGridSelector)
29
+ .getAgGridData()
30
+ .then((tableData) => {
31
+ cy.agGridValidateRowsSubset(tableData, expectedTableBeforeEditing);
32
+ });
33
+
34
+ cy.get(agGridSelector)
35
+ .getAgGridElements()
36
+ .then((tableElements) => {
37
+ const porscheRow = tableElements.find(
38
+ (row) => row.Price.innerText === "72000"
39
+ );
40
+ const priceCell = porscheRow.Price;
41
+ cy.wrap(priceCell).dblclick().type("66000{enter}");
42
+ });
43
+
44
+ const expectedTableAfterEditing = [
45
+ { Year: "2020", Make: "Porsche", Model: "Boxter", Price: "66000" },
46
+ { Year: "2020", Make: "Porsche", Model: "Boxter", Price: "99000" },
47
+ ];
48
+
49
+ cy.get(agGridSelector)
50
+ .getAgGridData()
51
+ .then((tableData) => {
52
+ cy.agGridValidateRowsSubset(tableData, expectedTableAfterEditing);
53
+ });
54
+ });
55
+ });
56
+ }
@@ -1,21 +1,21 @@
1
1
  [
2
- { "Year": "2020", "Make": "Toyota", "Model": "Celica", "Condition": "fair", "Price": "35000" },
3
- { "Year": "2020", "Make": "Ford", "Model": "Mondeo", "Condition": "excellent", "Price": "32000" },
4
- { "Year": "2020", "Make": "Porsche", "Model": "Boxter", "Condition": "good", "Price": "72000" },
5
- { "Year": "2020", "Make": "BMW", "Model": "3-series", "Condition": "fair", "Price": "45000" },
6
- { "Year": "2020", "Make": "Mercedes", "Model": "GLC300", "Condition": "good", "Price": "53000" },
7
- { "Year": "2020", "Make": "Honda", "Model": "Civic", "Condition": "poor", "Price": "22000" },
8
- { "Year": "2020", "Make": "Honda", "Model": "Accord", "Condition": "poor", "Price": "32000" },
9
- { "Year": "2020", "Make": "Ford", "Model": "Taurus", "Condition": "excellent", "Price": "19000" },
10
- { "Year": "2020", "Make": "Hyundai", "Model": "Elantra", "Condition": "good", "Price": "22000" },
11
- { "Year": "2020", "Make": "Toyota", "Model": "Celica", "Condition": "poor", "Price": "5000" },
12
- { "Year": "2020", "Make": "Ford", "Model": "Mondeo", "Condition": "good", "Price": "25000" },
13
- { "Year": "2020", "Make": "Porsche", "Model": "Boxter", "Condition": "good", "Price": "99000" },
14
- { "Year": "2020", "Make": "BMW", "Model": "3-series", "Condition": "poor", "Price": "32000" },
15
- { "Year": "2020", "Make": "Mercedes", "Model": "GLC300", "Condition": "excellent", "Price": "35000" },
16
- { "Year": "2011", "Make": "Honda", "Model": "Civic", "Condition": "good", "Price": "9000" },
17
- { "Year": "2020", "Make": "Honda", "Model": "Accord", "Condition": "good", "Price": "34000" },
18
- { "Year": "1990", "Make": "Ford", "Model": "Taurus", "Condition": "excellent", "Price": "900" },
19
- { "Year": "2020", "Make": "Hyundai", "Model": "Elantra", "Condition": "fair", "Price": "3000" },
20
- { "Year": "2020", "Make": "BMW", "Model": "2002", "Condition": "excellent", "Price": "88001" }
21
- ]
2
+ { "Year": "2020", "Make": "Toyota", "Model": "Celica", "Condition": "fair", "Mileage": "12000", "Price": "35000" },
3
+ { "Year": "2020", "Make": "Ford", "Model": "Mondeo", "Condition": "excellent", "Mileage": "8000", "Price": "32000" },
4
+ { "Year": "2020", "Make": "Porsche", "Model": "Boxter", "Condition": "good", "Mileage": "30000", "Price": "72000" },
5
+ { "Year": "2020", "Make": "BMW", "Model": "3-series", "Condition": "fair", "Mileage": "18000", "Price": "45000" },
6
+ { "Year": "2020", "Make": "Mercedes", "Model": "GLC300", "Condition": "good", "Mileage": "24000", "Price": "53000" },
7
+ { "Year": "2020", "Make": "Honda", "Model": "Civic", "Condition": "poor", "Mileage": "40000", "Price": "22000" },
8
+ { "Year": "2020", "Make": "Honda", "Model": "Accord", "Condition": "poor", "Mileage": "42000", "Price": "32000" },
9
+ { "Year": "2020", "Make": "Ford", "Model": "Taurus", "Condition": "excellent", "Mileage": "5000", "Price": "19000" },
10
+ { "Year": "2020", "Make": "Hyundai", "Model": "Elantra", "Condition": "good", "Mileage": "28000", "Price": "22000" },
11
+ { "Year": "2020", "Make": "Toyota", "Model": "Celica", "Condition": "poor", "Mileage": "60000", "Price": "5000" },
12
+ { "Year": "2020", "Make": "Ford", "Model": "Mondeo", "Condition": "good", "Mileage": "15000", "Price": "25000" },
13
+ { "Year": "2020", "Make": "Porsche", "Model": "Boxter", "Condition": "good", "Mileage": "1000", "Price": "99000" },
14
+ { "Year": "2020", "Make": "BMW", "Model": "3-series", "Condition": "poor", "Mileage": "52000", "Price": "32000" },
15
+ { "Year": "2020", "Make": "Mercedes", "Model": "GLC300", "Condition": "excellent", "Mileage": "9000", "Price": "35000" },
16
+ { "Year": "2011", "Make": "Honda", "Model": "Civic", "Condition": "good", "Mileage": "70000", "Price": "9000" },
17
+ { "Year": "2020", "Make": "Honda", "Model": "Accord", "Condition": "good", "Mileage": "22000", "Price": "34000" },
18
+ { "Year": "1990", "Make": "Ford", "Model": "Taurus", "Condition": "excellent", "Mileage": "90000", "Price": "900" },
19
+ { "Year": "2020", "Make": "Hyundai", "Model": "Elantra", "Condition": "fair", "Mileage": "3500", "Price": "3000" },
20
+ { "Year": "2020", "Make": "BMW", "Model": "2002", "Condition": "excellent", "Mileage": "4500", "Price": "88001" }
21
+ ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cypress-ag-grid",
3
- "version": "3.3.2",
3
+ "version": "3.3.4",
4
4
  "description": "Cypress plugin to interact with ag grid",
5
5
  "main": "src/index.js",
6
6
  "repository": {
@@ -18,12 +18,15 @@
18
18
  "cypress aggrid"
19
19
  ],
20
20
  "scripts": {
21
- "test": "npx cypress run --headless --spec cypress/e2e/*.cy.js",
21
+ "test": "npx cypress run --headless --spec \"cypress/e2e/*.cy.js\"",
22
+ "test:v33": "npx cypress run --headless --spec \"cypress/e2e/*.v33.cy.js\"",
23
+ "test:v34": "npx cypress run --headless --spec \"cypress/e2e/*.v34.cy.js\"",
24
+ "test:v35": "npx cypress run --headless --spec \"cypress/e2e/*.v35.cy.js\"",
22
25
  "test:watch": "npx cypress open"
23
26
  },
24
27
  "author": "Kerry McKeever <kerry@kerrymckeever.com>",
25
28
  "license": "MIT",
26
29
  "devDependencies": {
27
- "cypress": "^13.3.0"
30
+ "cypress": "^15.12.0"
28
31
  }
29
32
  }
@@ -22,8 +22,15 @@ export const agGridWaitForAnimation = async (agGridElement) => {
22
22
 
23
23
  const animations = agGridElement.get()[0].getAnimations({ subtree: true });
24
24
 
25
+ // Filter out infinite animations (e.g. loading spinners) whose .finished
26
+ // promise never resolves per the Web Animations API spec.
27
+ const finiteAnimations = animations.filter((animation) => {
28
+ const iterations = animation.effect?.getTiming?.()?.iterations;
29
+ return iterations !== Infinity;
30
+ });
31
+
25
32
  await Promise.all(
26
- animations.map(async (animation) => {
33
+ finiteAnimations.map(async (animation) => {
27
34
  try {
28
35
  await animation.finished;
29
36
  } catch (error) {
@@ -271,28 +278,54 @@ function getFilterColumnButtonElement(
271
278
  columnName,
272
279
  isFloatingFilter = false
273
280
  ) {
274
- let columnIndex;
275
- if (isFloatingFilter)
281
+ if (isFloatingFilter) {
276
282
  return getColumnHeaderElement(agGridElement, columnName)
277
283
  .parents(".ag-header-cell")
278
- .then(($ele) => {
279
- cy.wrap($ele)
280
- .invoke("attr", "aria-colindex")
281
- .then((colIndex) => {
282
- columnIndex = colIndex;
283
- })
284
- .then(() => {
285
- cy.wrap($ele)
286
- .parents(".ag-header-row-column")
287
- .siblings(".ag-header-row-column-filter")
288
- .find(`.ag-header-cell[aria-colindex=${columnIndex}]`)
289
- .find(".ag-floating-filter-button");
290
- });
284
+ .then(($headerCell) => {
285
+ const columnIndex = $headerCell.attr("aria-colindex");
286
+ const visibleHeaderCells = $headerCell
287
+ .closest(".ag-header")
288
+ .find(".ag-header-row-column .ag-header-cell:visible");
289
+ const headerPosition = visibleHeaderCells.index($headerCell);
290
+
291
+ return cy.get(agGridElement).then(($gridElement) => {
292
+ const usesV35FloatingFilterRow =
293
+ $gridElement.find(".ag-header-row-filter").length > 0;
294
+
295
+ let floatingFilterButton;
296
+
297
+ if (usesV35FloatingFilterRow) {
298
+ floatingFilterButton = $gridElement.find(
299
+ `.ag-header-row-filter .ag-header-cell[aria-colindex="${columnIndex}"] .ag-floating-filter-button:visible`
300
+ );
301
+
302
+ if (!floatingFilterButton.length && headerPosition > -1) {
303
+ floatingFilterButton = $gridElement
304
+ .find(".ag-header-row-filter .ag-floating-filter-button:visible")
305
+ .eq(headerPosition);
306
+ }
307
+ } else {
308
+ floatingFilterButton = $gridElement.find(
309
+ `.ag-header-row-column-filter .ag-header-cell[aria-colindex="${columnIndex}"] .ag-floating-filter-button-button:visible`
310
+ );
311
+
312
+ if (!floatingFilterButton.length && headerPosition > -1) {
313
+ floatingFilterButton = $gridElement
314
+ .find(
315
+ ".ag-header-row-column-filter .ag-floating-filter-button-button:visible"
316
+ )
317
+ .eq(headerPosition);
318
+ }
319
+ }
320
+
321
+ return cy.wrap(floatingFilterButton.first());
322
+ });
291
323
  });
292
- else
324
+ } else {
293
325
  return getColumnHeaderElement(agGridElement, columnName)
294
326
  .parent()
295
327
  .siblings(".ag-header-cell-filter-button");
328
+ }
296
329
  }
297
330
 
298
331
  /**
@@ -305,6 +338,9 @@ function filterBySearchTerm(agGridElement, options) {
305
338
  const filterValue = options.searchCriteria.filterValue;
306
339
  const operator = options.searchCriteria.operator;
307
340
  const searchInputIndex = options.searchCriteria.searchInputIndex || 0;
341
+ const operatorIndex =
342
+ options.searchCriteria.operatorIndex ??
343
+ (operator === filterOperator.inRange ? 0 : searchInputIndex);
308
344
  const isMultiFilter = options.searchCriteria.isMultiFilter;
309
345
  const noMenuTabs = options.noMenuTabs;
310
346
 
@@ -319,7 +355,7 @@ function filterBySearchTerm(agGridElement, options) {
319
355
  .find(".ag-filter")
320
356
  .find(".ag-picker-field-wrapper")
321
357
  .filter(":visible")
322
- .eq(searchInputIndex);
358
+ .eq(operatorIndex);
323
359
  cy.get(agGridElement).agGridWaitForAnimation();
324
360
  elem.click();
325
361
  cy.get(agGridElement)
@@ -510,19 +546,73 @@ function _filterBySearchTextColumnMenu(agGridElement, options) {
510
546
  export function filterBySearchTextColumnFloatingFilter(agGridElement, options) {
511
547
  // Check if there are multiple search criteria provided by attempting to access the columnName
512
548
  if (!options.searchCriteria.columnName) {
513
- options.searchCriteria.forEach((_searchCriteria) => {
514
- const _options = populateSearchCriteria(
515
- _searchCriteria,
516
- options.hasApplyButton,
517
- options.noMenuTabs
549
+ groupFloatingFilterSearchCriteria(
550
+ normalizeFloatingFilterSearchCriteria(options.searchCriteria)
551
+ ).forEach((searchCriteriaGroup) => {
552
+ const criteriaOptions = searchCriteriaGroup.map((_searchCriteria) =>
553
+ populateSearchCriteria(
554
+ _searchCriteria,
555
+ options.hasApplyButton,
556
+ options.noMenuTabs
557
+ )
518
558
  );
519
- _filterBySearchTextColumnFloatingFilter(agGridElement, _options);
559
+
560
+ if (criteriaOptions.length === 1) {
561
+ _filterBySearchTextColumnFloatingFilter(agGridElement, criteriaOptions[0]);
562
+ return;
563
+ }
564
+
565
+ _filterBySearchTextColumnFloatingFilterGroup(agGridElement, criteriaOptions);
520
566
  });
521
567
  } else {
522
568
  _filterBySearchTextColumnFloatingFilter(agGridElement, options);
523
569
  }
524
570
  }
525
571
 
572
+ function normalizeFloatingFilterSearchCriteria(searchCriteria) {
573
+ const betweenInputIndexes = new Map();
574
+
575
+ return searchCriteria.map((criteria) => {
576
+ if (
577
+ criteria.operator !== filterOperator.inRange ||
578
+ criteria.searchInputIndex !== undefined
579
+ ) {
580
+ return criteria;
581
+ }
582
+
583
+ const criteriaKey = `${criteria.columnName}::${criteria.operator}`;
584
+ const nextInputIndex = betweenInputIndexes.get(criteriaKey) || 0;
585
+ betweenInputIndexes.set(criteriaKey, nextInputIndex + 1);
586
+
587
+ return {
588
+ ...criteria,
589
+ searchInputIndex: nextInputIndex,
590
+ };
591
+ });
592
+ }
593
+
594
+ function groupFloatingFilterSearchCriteria(searchCriteria) {
595
+ const groupedCriteria = [];
596
+
597
+ searchCriteria.forEach((criteria) => {
598
+ const lastGroup = groupedCriteria[groupedCriteria.length - 1];
599
+
600
+ if (
601
+ criteria.operator === filterOperator.inRange &&
602
+ lastGroup &&
603
+ lastGroup[0].columnName === criteria.columnName &&
604
+ lastGroup[0].operator === criteria.operator
605
+ ) {
606
+ lastGroup.push(criteria);
607
+ return;
608
+ }
609
+
610
+ groupedCriteria.push([criteria]);
611
+ });
612
+
613
+ return groupedCriteria;
614
+ }
615
+
526
616
  function _filterBySearchTextColumnFloatingFilter(agGridElement, options) {
527
617
  cy.get(agGridElement).then((agGridElement) => {
528
618
  getFilterColumnButtonElement(
@@ -539,6 +629,37 @@ function _filterBySearchTextColumnFloatingFilter(agGridElement, options) {
539
629
  });
540
630
  }
541
631
 
632
+ function _filterBySearchTextColumnFloatingFilterGroup(
633
+ agGridElement,
634
+ criteriaOptions
635
+ ) {
636
+ cy.get(agGridElement).then((agGridElement) => {
637
+ getFilterColumnButtonElement(
638
+ agGridElement,
639
+ criteriaOptions[0].searchCriteria.columnName,
640
+ true
641
+ ).click();
642
+
643
+ criteriaOptions.forEach((criteriaOption, index) => {
644
+ const searchCriteria =
645
+ index === 0
646
+ ? criteriaOption.searchCriteria
647
+ : { ...criteriaOption.searchCriteria, operator: undefined };
648
+
649
+ filterBySearchTerm(agGridElement, {
650
+ ...criteriaOption,
651
+ searchCriteria,
652
+ });
653
+ });
654
+
655
+ applyColumnFilter(
656
+ agGridElement,
657
+ criteriaOptions[0].hasApplyButton,
658
+ criteriaOptions[0].noMenuTabs
659
+ );
660
+ });
661
+ }
662
+
542
663
  /**
543
664
  * * Performs a filter operation on the specified column and selects only the provided filterValue
544
665
  * @param agGridElement The get() selector for which ag grid table you wish to retrieve.
package/src/index.d.ts CHANGED
@@ -119,7 +119,11 @@ interface agGridColumnFilterSearchCriteriaOptionsWithOperator extends agGridColu
119
119
  operator?: string
120
120
  }
121
121
 
122
- interface agGridColumnFilterSearchCriteriaOptionsWithMultiFilter extends agGridColumnFilterSearchCriteriaOptionsWithOperator {
123
- /** Use if floating filter is multiselect checkboxes vs free form input */
124
- isMultiFilter?: boolean
125
- }
122
+ interface agGridColumnFilterSearchCriteriaOptionsWithMultiFilter extends agGridColumnFilterSearchCriteriaOptionsWithOperator {
123
+ /** Index of which visible filter input to use when the floating filter renders multiple inputs */
124
+ searchInputIndex?: number
125
+ /** Index of which visible operator dropdown to use when the floating filter renders multiple conditions */
126
+ operatorIndex?: number
127
+ /** Use if floating filter is multiselect checkboxes vs free form input */
128
+ isMultiFilter?: boolean
129
+ }