Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 45 additions & 7 deletions src/material/table/table-data-source.spec.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import {MatTableDataSource} from './table-data-source';
import {ComponentFixture, TestBed} from '@angular/core/testing';
import {ComponentFixture, fakeAsync, TestBed, tick} from '@angular/core/testing';
import {MatSort, MatSortModule} from '@angular/material/sort';
import {Component, ViewChild} from '@angular/core';

declare global {
interface Window {
ngDevMode?: object | null;
}
}

describe('MatTableDataSource', () => {
describe('sort', () => {
let dataSource: MatTableDataSource<any>;
let dataSource: MatTableDataSource<{'prop': string | number}>;
let fixture: ComponentFixture<MatSortApp>;
let sort: MatSort;

Expand All @@ -18,7 +24,7 @@ describe('MatTableDataSource', () => {
});

/** Test the data source's `sortData` function. */
function testSortWithValues(values: any[]) {
function testSortWithValues(values: (string | number)[]) {
// The data source and MatSort expect the list to contain objects with values, where
// the sort should be performed over a particular key.
// Map the values into an array of objects where each value is keyed by "prop"
Expand Down Expand Up @@ -73,13 +79,45 @@ describe('MatTableDataSource', () => {
});

it('should update filteredData even if the data source is disconnected', () => {
dataSource.data = [1, 2, 3, 4, 5];
expect(dataSource.filteredData).toEqual([1, 2, 3, 4, 5]);
dataSource.data = [{'prop': 1}, {'prop': 2}, {'prop': 3}];
expect(dataSource.filteredData).toEqual([{'prop': 1}, {'prop': 2}, {'prop': 3}]);

dataSource.disconnect();
dataSource.data = [5, 4, 3, 2, 1];
expect(dataSource.filteredData).toEqual([5, 4, 3, 2, 1]);
dataSource.data = [{'prop': 3}, {'prop': 2}, {'prop': 1}];
expect(dataSource.filteredData).toEqual([{'prop': 3}, {'prop': 2}, {'prop': 1}]);
});

it('should filter data', () => {
dataSource.data = [{'prop': 1}, {'prop': 'foo'}, {'prop': 'banana'}];
dataSource.filter = 'b';
expect(dataSource.filteredData).toEqual([{'prop': 'banana'}]);
});

it('does not warn in non-dev mode when filtering non-object data', fakeAsync(() => {
const warnSpy = spyOn(console, 'warn');
window.ngDevMode = null;
dataSource.data = [1, 2, 3, 4, 5] as unknown as {'prop': number}[];

dataSource.filter = '1';
tick();

expect(warnSpy).not.toHaveBeenCalled();
expect(dataSource.filteredData).toEqual([]);
}));

it('displays the warning in dev mode when filtering non-object data', fakeAsync(() => {
const warnSpy = spyOn(console, 'warn');
window.ngDevMode = {};
dataSource.data = [1, 2, 3, 4, 5] as unknown as {'prop': number}[];

dataSource.filter = '1';
tick();

expect(warnSpy).toHaveBeenCalledWith(
jasmine.stringContaining('requires data to be a non-null object'),
);
expect(dataSource.filteredData).toEqual([]);
}));
});
});

Expand Down
9 changes: 9 additions & 0 deletions src/material/table/table-data-source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,15 @@ export class MatTableDataSource<
* @returns Whether the filter matches against the data
*/
filterPredicate: (data: T, filter: string) => boolean = (data: T, filter: string): boolean => {
if (
(typeof ngDevMode === 'undefined' || ngDevMode) &&
(typeof data !== 'object' || data === null)
) {
console.warn(
'Default implementation of filterPredicate requires data to be a non-null object.',
);
}

// Transform the filter by converting it to lowercase and removing whitespace.
const transformedFilter = filter.trim().toLowerCase();
// Loops over the values in the array and returns true if any of them match the filter string
Expand Down
Loading