diff --git a/src/app/examples/grid-graphql-nopage.component.html b/src/app/examples/grid-graphql-nopage.component.html
index d9ac319a1..42b954a06 100644
--- a/src/app/examples/grid-graphql-nopage.component.html
+++ b/src/app/examples/grid-graphql-nopage.component.html
@@ -13,7 +13,7 @@
{{title}}
-
+
diff --git a/src/app/modules/angular-slickgrid/components/__tests__/angular-slickgrid-constructor.spec.ts b/src/app/modules/angular-slickgrid/components/__tests__/angular-slickgrid-constructor.spec.ts
index 94f35c64c..375ddc306 100644
--- a/src/app/modules/angular-slickgrid/components/__tests__/angular-slickgrid-constructor.spec.ts
+++ b/src/app/modules/angular-slickgrid/components/__tests__/angular-slickgrid-constructor.spec.ts
@@ -172,6 +172,7 @@ const mockDataView = {
beginUpdate: jest.fn(),
endUpdate: jest.fn(),
getItem: jest.fn(),
+ getItemCount: jest.fn(),
getItems: jest.fn(),
getLength: jest.fn(),
getItemMetadata: jest.fn(),
diff --git a/src/app/modules/angular-slickgrid/components/angular-slickgrid.component.ts b/src/app/modules/angular-slickgrid/components/angular-slickgrid.component.ts
index efc0b1b42..33acc2e27 100644
--- a/src/app/modules/angular-slickgrid/components/angular-slickgrid.component.ts
+++ b/src/app/modules/angular-slickgrid/components/angular-slickgrid.component.ts
@@ -772,7 +772,7 @@ export class AngularSlickgridComponent implements AfterViewInit, OnDestroy, OnIn
startTime: new Date(),
endTime: new Date(),
itemCount: itemCount,
- totalItemCount: Array.isArray(this.dataset) ? this.dataset.length : 0
+ totalItemCount: this.dataView && this.dataView.getItemCount() || 0
};
// when using local (in-memory) dataset, we'll display a warning message when filtered data is empty
diff --git a/src/app/modules/angular-slickgrid/filter-conditions/filterUtilities.ts b/src/app/modules/angular-slickgrid/filter-conditions/filterUtilities.ts
index 302c64022..9baf37a89 100644
--- a/src/app/modules/angular-slickgrid/filter-conditions/filterUtilities.ts
+++ b/src/app/modules/angular-slickgrid/filter-conditions/filterUtilities.ts
@@ -73,13 +73,13 @@ export const testFilterCondition = (operator: OperatorString, value1: any, value
return ((value2 && Array.isArray(value2 as string[])) ? (!value2.includes(value1)) : false);
case 'IN_CONTAINS':
if (value2 && Array.isArray(value2) && typeof value1 === 'string') {
- return value2.some(item => value1.split(',').includes(item));
+ return value2.some(item => value1.split(/[\s,]+/).includes(item));
}
return false;
case 'NIN_CONTAINS':
case 'NOT_IN_CONTAINS':
if (value2 && Array.isArray(value2) && typeof value1 === 'string') {
- return !value2.some(item => value1.split(',').includes(item));
+ return !value2.some(item => value1.split(/[\s,]+/).includes(item));
}
return false;
}
diff --git a/src/app/modules/angular-slickgrid/formatters/decimalFormatter.ts b/src/app/modules/angular-slickgrid/formatters/decimalFormatter.ts
index 6e8aa2e26..9004bfb7f 100644
--- a/src/app/modules/angular-slickgrid/formatters/decimalFormatter.ts
+++ b/src/app/modules/angular-slickgrid/formatters/decimalFormatter.ts
@@ -26,4 +26,3 @@ export const decimalFormatter: Formatter = (row: number, cell: number, value: an
}
return value;
};
-
diff --git a/src/app/modules/angular-slickgrid/services/filter.service.ts b/src/app/modules/angular-slickgrid/services/filter.service.ts
index a836df12e..f648a03f3 100644
--- a/src/app/modules/angular-slickgrid/services/filter.service.ts
+++ b/src/app/modules/angular-slickgrid/services/filter.service.ts
@@ -23,7 +23,7 @@ import {
SlickEventHandler,
} from './../models/index';
import { executeBackendCallback, refreshBackendDataset } from './backend-utilities';
-import { deepCopy, getDescendantProperty, mapOperatorByFieldType } from './utilities';
+import { deepCopy, getDescendantProperty, mapOperatorByFieldType, sanitizeHtmlToText } from './utilities';
import { FilterConditions, getParsedSearchTermsByFieldType } from './../filter-conditions';
import { FilterFactory } from '../filters/filterFactory';
import { SharedService } from './shared.service';
@@ -472,11 +472,13 @@ export class FilterService {
}
// when using localization (i18n), we should use the formatter output to search as the new cell value
+ // we will also sanitize/remove HTML tags out of the text (which might be added by multiple-select)
if (columnDef && columnDef.params && columnDef.params.useFormatterOuputToFilter) {
const dataView = grid.getData();
const idPropName = this._gridOptions.datasetIdPropertyName || 'id';
const rowIndex = (dataView && typeof dataView.getIdxById === 'function') ? dataView.getIdxById(item[idPropName]) : 0;
cellValue = (columnDef && typeof columnDef.formatter === 'function') ? columnDef.formatter(rowIndex || 0, columnIndex, cellValue, columnDef, item, this._grid) : '';
+ cellValue = sanitizeHtmlToText(cellValue); // also remove any html tag
}
// make sure cell value is always a string
diff --git a/test/cypress/integration/example27.spec.js b/test/cypress/integration/example27.spec.js
new file mode 100644
index 000000000..35d34f8eb
--- /dev/null
+++ b/test/cypress/integration/example27.spec.js
@@ -0,0 +1,157 @@
+///
+
+describe('Example 27 - GraphQL Basic API without Pagination', () => {
+ const GRID_ROW_HEIGHT = 35;
+ const fullPreTitles = ['Country', 'Language', 'Continent'];
+ const fullTitles = ['Code', 'Name', 'Native', 'Phone Area Code', 'Currency', 'Emoji', 'Names', 'Native', 'Codes', 'Name', 'Code'];
+
+ it('should display Example title', () => {
+ cy.visit(`${Cypress.config('baseExampleUrl')}/graphql-nopage`);
+ cy.get('h2').should('contain', 'Example 27: GraphQL Basic API without Pagination');
+ });
+
+ it('should display a processing alert which will change to done', () => {
+ cy.get('[data-test=status]').should('contain', 'processing');
+ cy.get('[data-test=status]').should('contain', 'done');
+ });
+
+ it('should have exact Column Pre-Header & Column Header Titles in the grid', () => {
+ cy.get('#grid27')
+ .find('.slick-header-columns:nth(0)')
+ .children()
+ .each(($child, index) => expect($child.text()).to.eq(fullPreTitles[index]));
+
+ cy.get('#grid27')
+ .find('.slick-header-columns:nth(1)')
+ .children()
+ .each(($child, index) => expect($child.text()).to.eq(fullTitles[index]));
+ });
+
+ it('should expect first 3 rows to be an exact match of data provided by the external GraphQL API', () => {
+ cy.get('.right-footer.metrics')
+ .contains('250 of 250 items');
+
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 0}px"] > .slick-cell:nth(0)`).should('contain', 'AD');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 0}px"] > .slick-cell:nth(1)`).should('contain', 'Andorra');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 0}px"] > .slick-cell:nth(2)`).should('contain', 'Andorra');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 0}px"] > .slick-cell:nth(3)`).should('contain', '376');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 0}px"] > .slick-cell:nth(4)`).should('contain', 'EUR');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 0}px"] > .slick-cell:nth(6)`).should('contain', 'Catalan');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 0}px"] > .slick-cell:nth(7)`).should('contain', 'Català');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 0}px"] > .slick-cell:nth(8)`).should('contain', 'ca');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 0}px"] > .slick-cell:nth(9)`).should('contain', 'Europe');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 0}px"] > .slick-cell:nth(10)`).should('contain', 'EU');
+
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 1}px"] > .slick-cell:nth(0)`).should('contain', 'AE');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 1}px"] > .slick-cell:nth(1)`).should('contain', 'United Arab Emirates');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 1}px"] > .slick-cell:nth(2)`).should('contain', 'دولة الإمارات العربية المتحدة');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 1}px"] > .slick-cell:nth(3)`).should('contain', '971');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 1}px"] > .slick-cell:nth(4)`).should('contain', 'AED');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 1}px"] > .slick-cell:nth(6)`).should('contain', 'Arabic');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 1}px"] > .slick-cell:nth(7)`).should('contain', 'العربية');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 1}px"] > .slick-cell:nth(8)`).should('contain', 'ar');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 1}px"] > .slick-cell:nth(9)`).should('contain', 'Asia');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 1}px"] > .slick-cell:nth(10)`).should('contain', 'AS');
+
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 2}px"] > .slick-cell:nth(0)`).should('contain', 'AF');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 2}px"] > .slick-cell:nth(1)`).should('contain', 'Afghanistan');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 2}px"] > .slick-cell:nth(2)`).should('contain', 'افغانستان');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 2}px"] > .slick-cell:nth(3)`).should('contain', '93');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 2}px"] > .slick-cell:nth(4)`).should('contain', 'AFN');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 2}px"] > .slick-cell:nth(6)`).should('contain', 'Pashto, Uzbek, Turkmen');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 2}px"] > .slick-cell:nth(7)`).should('contain', 'پښتو, Ўзбек, Туркмен / تركمن');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 2}px"] > .slick-cell:nth(8)`).should('contain', 'ps, uz, tk');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 2}px"] > .slick-cell:nth(9)`).should('contain', 'Asia');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 2}px"] > .slick-cell:nth(10)`).should('contain', 'AS');
+ });
+
+ it('should sort by country name and expect first 2 rows as Afghanistan and Albania', () => {
+ cy.get(`.slick-header-columns:nth(1) .slick-header-column:nth-child(2)`).contains('Name').click();
+
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 0}px"] > .slick-cell:nth(0)`).should('contain', 'AF');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 0}px"] > .slick-cell:nth(1)`).should('contain', 'Afghanistan');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 0}px"] > .slick-cell:nth(2)`).should('contain', 'افغانستان');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 0}px"] > .slick-cell:nth(3)`).should('contain', '93');
+
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 1}px"] > .slick-cell:nth(0)`).should('contain', 'AL');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 1}px"] > .slick-cell:nth(1)`).should('contain', 'Albania');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 1}px"] > .slick-cell:nth(2)`).should('contain', 'Shqipëria');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 1}px"] > .slick-cell:nth(3)`).should('contain', '355');
+ });
+
+ it('should filter by Language Codes "fr, de" and expect 2 rows of data in the grid', () => {
+ cy.get('.search-filter.filter-languageCode')
+ .type('fr, de');
+
+ cy.get('.right-footer.metrics')
+ .contains('2 of 250 items');
+
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 0}px"] > .slick-cell:nth(0)`).should('contain', 'BE');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 0}px"] > .slick-cell:nth(1)`).should('contain', 'Belgium');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 0}px"] > .slick-cell:nth(2)`).should('contain', 'België');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 0}px"] > .slick-cell:nth(3)`).should('contain', '32');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 0}px"] > .slick-cell:nth(4)`).should('contain', 'EUR');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 0}px"] > .slick-cell:nth(6)`).should('contain', 'Dutch, French, German');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 0}px"] > .slick-cell:nth(7)`).should('contain', 'Nederlands, Français, Deutsch');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 0}px"] > .slick-cell:nth(8)`).should('contain', 'nl, fr, de');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 0}px"] > .slick-cell:nth(9)`).should('contain', 'Europe');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 0}px"] > .slick-cell:nth(10)`).should('contain', 'EU');
+
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 1}px"] > .slick-cell:nth(0)`).should('contain', 'LU');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 1}px"] > .slick-cell:nth(1)`).should('contain', 'Luxembourg');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 1}px"] > .slick-cell:nth(2)`).should('contain', 'Luxembourg');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 1}px"] > .slick-cell:nth(3)`).should('contain', '352');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 1}px"] > .slick-cell:nth(4)`).should('contain', 'EUR');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 1}px"] > .slick-cell:nth(6)`).should('contain', 'French, German, Luxembourgish');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 1}px"] > .slick-cell:nth(7)`).should('contain', 'Français, Deutsch, Lëtzebuergesch');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 1}px"] > .slick-cell:nth(8)`).should('contain', 'fr, de, lb');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 1}px"] > .slick-cell:nth(9)`).should('contain', 'Europe');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 1}px"] > .slick-cell:nth(10)`).should('contain', 'EU');
+ });
+
+ it('should Clear all Filters and expect all rows to be back', () => {
+ cy.get('#grid27')
+ .find('button.slick-gridmenu-button')
+ .trigger('click')
+ .click();
+
+ cy.get(`.slick-gridmenu:visible`)
+ .find('.slick-gridmenu-item')
+ .first()
+ .find('span')
+ .contains('Clear all Filters')
+ .click();
+
+ cy.get('.right-footer.metrics')
+ .contains('250 of 250 items');
+ });
+
+ it('should filter Language Native with "Aymar" and expect only 1 row in the grid', () => {
+ cy.get('div.ms-filter.filter-languageNative')
+ .trigger('click');
+
+ cy.get('.ms-search:visible')
+ .type('Aymar');
+
+ cy.get('.ms-drop:visible')
+ .contains('Aymar')
+ .click();
+
+ cy.get('.ms-ok-button:visible')
+ .click();
+
+ cy.get('.right-footer.metrics')
+ .contains('1 of 250 items');
+
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 0}px"] > .slick-cell:nth(0)`).should('contain', 'BO');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 0}px"] > .slick-cell:nth(1)`).should('contain', 'Bolivia');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 0}px"] > .slick-cell:nth(2)`).should('contain', 'Bolivia');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 0}px"] > .slick-cell:nth(3)`).should('contain', '591');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 0}px"] > .slick-cell:nth(4)`).should('contain', 'BOB,BOV');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 0}px"] > .slick-cell:nth(6)`).should('contain', 'Spanish, Aymara, Quechua');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 0}px"] > .slick-cell:nth(7)`).should('contain', 'Español, Aymar, Runa Simi');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 0}px"] > .slick-cell:nth(8)`).should('contain', 'es, ay, qu');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 0}px"] > .slick-cell:nth(9)`).should('contain', 'South America');
+ cy.get(`[style="top:${GRID_ROW_HEIGHT * 0}px"] > .slick-cell:nth(10)`).should('contain', 'SA');
+ });
+});