Skip to content

Commit efc539f

Browse files
committed
feat(paginator): add test harness
Sets up a test harness for `mat-paginator`.
1 parent 527f1b5 commit efc539f

File tree

10 files changed

+328
-0
lines changed

10 files changed

+328
-0
lines changed

src/material/config.bzl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ entryPoints = [
3030
"menu",
3131
"menu/testing",
3232
"paginator",
33+
"paginator/testing",
3334
"progress-bar",
3435
"progress-bar/testing",
3536
"progress-spinner",
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package(default_visibility = ["//visibility:public"])
2+
3+
load("//tools:defaults.bzl", "ng_test_library", "ng_web_test_suite", "ts_library")
4+
5+
ts_library(
6+
name = "testing",
7+
srcs = glob(
8+
["**/*.ts"],
9+
exclude = ["**/*.spec.ts"],
10+
),
11+
module_name = "@angular/material/paginator/testing",
12+
deps = [
13+
"//src/cdk/testing",
14+
"//src/material/select/testing",
15+
],
16+
)
17+
18+
filegroup(
19+
name = "source-files",
20+
srcs = glob(["**/*.ts"]),
21+
)
22+
23+
ng_test_library(
24+
name = "harness_tests_lib",
25+
srcs = ["shared.spec.ts"],
26+
deps = [
27+
":testing",
28+
"//src/cdk/testing",
29+
"//src/cdk/testing/private",
30+
"//src/cdk/testing/testbed",
31+
"//src/material/paginator",
32+
"@npm//@angular/platform-browser",
33+
],
34+
)
35+
36+
ng_test_library(
37+
name = "unit_tests_lib",
38+
srcs = glob(
39+
["**/*.spec.ts"],
40+
exclude = ["shared.spec.ts"],
41+
),
42+
deps = [
43+
":harness_tests_lib",
44+
":testing",
45+
"//src/material/paginator",
46+
],
47+
)
48+
49+
ng_web_test_suite(
50+
name = "unit_tests",
51+
deps = [":unit_tests_lib"],
52+
)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
9+
export * from './public-api';
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
9+
import {BaseHarnessFilters} from '@angular/cdk/testing';
10+
11+
/** A set of criteria that can be used to filter a list of `MatPaginatorHarness` instances. */
12+
export interface PaginatorHarnessFilters extends BaseHarnessFilters {
13+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import {MatPaginatorModule} from '@angular/material/paginator';
2+
import {runHarnessTests} from './shared.spec';
3+
import {MatPaginatorHarness} from './paginator-harness';
4+
5+
describe('Non-MDC-based MatPaginatorHarness', () => {
6+
runHarnessTests(MatPaginatorModule, MatPaginatorHarness);
7+
});
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
9+
import {ComponentHarness, HarnessPredicate} from '@angular/cdk/testing';
10+
import {MatSelectHarness} from '@angular/material/select/testing';
11+
import {PaginatorHarnessFilters} from './paginator-harness-filters';
12+
13+
14+
/** Harness for interacting with a standard mat-paginator in tests. */
15+
export class MatPaginatorHarness extends ComponentHarness {
16+
/** Selector used to find paginator instances. */
17+
static hostSelector = '.mat-paginator';
18+
private _nextButton = this.locatorFor('.mat-paginator-navigation-next');
19+
private _previousButton = this.locatorFor('.mat-paginator-navigation-previous');
20+
private _firstPageButton = this.locatorForOptional('.mat-paginator-navigation-first');
21+
private _lastPageButton = this.locatorForOptional('.mat-paginator-navigation-last');
22+
23+
/**
24+
* Gets a `HarnessPredicate` that can be used to search for a `MatPaginatorHarness` that meets
25+
* certain criteria.
26+
* @param options Options for filtering which paginator instances are considered a match.
27+
* @return a `HarnessPredicate` configured with the given options.
28+
*/
29+
static with(options: PaginatorHarnessFilters = {}): HarnessPredicate<MatPaginatorHarness> {
30+
return new HarnessPredicate(MatPaginatorHarness, options);
31+
}
32+
33+
/** Goes to the next page in the paginator. */
34+
async goToNextPage(): Promise<void> {
35+
return (await this._nextButton()).click();
36+
}
37+
38+
/** Goes to the previous page in the paginator. */
39+
async goToPreviousPage(): Promise<void> {
40+
return (await this._previousButton()).click();
41+
}
42+
43+
/** Goes to the first page in the paginator. */
44+
async goToFirstPage(): Promise<void> {
45+
const button = await this._firstPageButton();
46+
47+
// The first page button isn't enabled by default so we need to check for it.
48+
if (!button) {
49+
throw Error('Could not find first page button inside paginator. ' +
50+
'Make sure that `showFirstLastButtons` is enabled.');
51+
}
52+
53+
return button.click();
54+
}
55+
56+
/** Goes to the last page in the paginator. */
57+
async goToLastPage(): Promise<void> {
58+
const button = await this._lastPageButton();
59+
60+
// The last page button isn't enabled by default so we need to check for it.
61+
if (!button) {
62+
throw Error('Could not find last page button inside paginator. ' +
63+
'Make sure that `showFirstLastButtons` is enabled.');
64+
}
65+
66+
return button.click();
67+
}
68+
69+
/**
70+
* Sets the page size of the paginator.
71+
* @param size Page size that should be select.
72+
*/
73+
async setPageSize(size: number): Promise<void> {
74+
const select = await this.locatorForOptional(MatSelectHarness.with({
75+
ancestor: '.mat-paginator-page-size'
76+
}))();
77+
78+
// The select is only available if the `pageSizeOptions` are
79+
// set to an array with more than one item.
80+
if (!select) {
81+
throw Error('Cannot find page size selector in paginator. ' +
82+
'Make sure that the `pageSizeOptions` have been configured.');
83+
}
84+
85+
return select.clickOptions({text: `${size}`});
86+
}
87+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
9+
export * from './paginator-harness';
10+
export * from './paginator-harness-filters';
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
import {HarnessLoader} from '@angular/cdk/testing';
2+
import {TestbedHarnessEnvironment} from '@angular/cdk/testing/testbed';
3+
import {Component, ViewChild} from '@angular/core';
4+
import {NoopAnimationsModule} from '@angular/platform-browser/animations';
5+
import {ComponentFixture, TestBed} from '@angular/core/testing';
6+
import {MatPaginatorModule, PageEvent, MatPaginator} from '@angular/material/paginator';
7+
import {MatPaginatorHarness} from './paginator-harness';
8+
import {expectAsyncError} from '@angular/cdk/testing/private';
9+
10+
/** Shared tests to run on both the original and MDC-based paginator. */
11+
export function runHarnessTests(
12+
paginatorModule: typeof MatPaginatorModule, paginatorHarness: typeof MatPaginatorHarness) {
13+
let fixture: ComponentFixture<PaginatorHarnessTest>;
14+
let loader: HarnessLoader;
15+
let instance: PaginatorHarnessTest;
16+
17+
beforeEach(async () => {
18+
await TestBed.configureTestingModule({
19+
imports: [paginatorModule, NoopAnimationsModule],
20+
declarations: [PaginatorHarnessTest],
21+
}).compileComponents();
22+
23+
fixture = TestBed.createComponent(PaginatorHarnessTest);
24+
fixture.detectChanges();
25+
loader = TestbedHarnessEnvironment.loader(fixture);
26+
instance = fixture.componentInstance;
27+
});
28+
29+
it('should load all paginator harnesses', async () => {
30+
const paginators = await loader.getAllHarnesses(paginatorHarness);
31+
expect(paginators.length).toBe(1);
32+
});
33+
34+
it('should be able to go to the next page', async () => {
35+
const paginator = await loader.getHarness(paginatorHarness);
36+
37+
expect(instance.pageIndex).toBe(0);
38+
await paginator.goToNextPage();
39+
expect(instance.pageIndex).toBe(1);
40+
});
41+
42+
it('should be able to go to the previous page', async () => {
43+
const paginator = await loader.getHarness(paginatorHarness);
44+
45+
instance.pageIndex = 5;
46+
fixture.detectChanges();
47+
48+
await paginator.goToPreviousPage();
49+
expect(instance.pageIndex).toBe(4);
50+
});
51+
52+
it('should be able to go to the first page', async () => {
53+
const paginator = await loader.getHarness(paginatorHarness);
54+
55+
instance.pageIndex = 5;
56+
fixture.detectChanges();
57+
58+
await paginator.goToFirstPage();
59+
expect(instance.pageIndex).toBe(0);
60+
});
61+
62+
it('should be able to go to the last page', async () => {
63+
const paginator = await loader.getHarness(paginatorHarness);
64+
65+
expect(instance.pageIndex).toBe(0);
66+
await paginator.goToLastPage();
67+
expect(instance.pageIndex).toBe(49);
68+
});
69+
70+
it('should be able to set the page size', async () => {
71+
const paginator = await loader.getHarness(paginatorHarness);
72+
73+
expect(instance.pageSize).toBe(10);
74+
await paginator.setPageSize(25);
75+
expect(instance.pageSize).toBe(25);
76+
});
77+
78+
it('should throw an error if the first page button is not available', async () => {
79+
const paginator = await loader.getHarness(paginatorHarness);
80+
81+
instance.showFirstLastButtons = false;
82+
fixture.detectChanges();
83+
84+
await expectAsyncError(() => paginator.goToFirstPage(),
85+
/Error: Could not find first page button inside paginator/);
86+
});
87+
88+
it('should throw an error if the last page button is not available', async () => {
89+
const paginator = await loader.getHarness(paginatorHarness);
90+
91+
instance.showFirstLastButtons = false;
92+
fixture.detectChanges();
93+
94+
await expectAsyncError(() => paginator.goToLastPage(),
95+
/Error: Could not find last page button inside paginator/);
96+
});
97+
98+
it('should throw an error if the page size selector is not available', async () => {
99+
const paginator = await loader.getHarness(paginatorHarness);
100+
101+
instance.pageSizeOptions = [];
102+
fixture.detectChanges();
103+
104+
await expectAsyncError(() => paginator.setPageSize(10),
105+
/Error: Cannot find page size selector in paginator/);
106+
});
107+
}
108+
109+
@Component({
110+
template: `
111+
<mat-paginator
112+
(page)="handlePageEvent($event)"
113+
[length]="length"
114+
[pageSize]="pageSize"
115+
[showFirstLastButtons]="showFirstLastButtons"
116+
[pageSizeOptions]="pageSizeOptions"
117+
[pageIndex]="pageIndex">
118+
</mat-paginator>
119+
`
120+
})
121+
class PaginatorHarnessTest {
122+
@ViewChild(MatPaginator) paginator: MatPaginator;
123+
length = 500;
124+
pageSize = 10;
125+
pageIndex = 0;
126+
pageSizeOptions = [5, 10, 25];
127+
showFirstLastButtons = true;
128+
129+
handlePageEvent(event: PageEvent) {
130+
this.length = event.length;
131+
this.pageSize = event.pageSize;
132+
this.pageIndex = event.pageIndex;
133+
}
134+
}
135+

test/karma-system-config.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,8 @@ System.config({
136136
'@angular/material/menu/testing': 'dist/packages/material/menu/testing/index.js',
137137
'@angular/material/menu/testing/shared.spec': 'dist/packages/material/menu/testing/shared.spec.js',
138138
'@angular/material/paginator': 'dist/packages/material/paginator/index.js',
139+
'@angular/material/paginator/testing': 'dist/packages/material/paginator/testing/index.js',
140+
'@angular/material/paginator/testing/shared.spec': 'dist/packages/material/paginator/testing/shared.spec.js',
139141
'@angular/material/progress-bar': 'dist/packages/material/progress-bar/index.js',
140142
'@angular/material/progress-bar/testing': 'dist/packages/material/progress-bar/testing/index.js',
141143
'@angular/material/progress-bar/testing/shared.spec': 'dist/packages/material/progress-bar/testing/shared.spec.js',
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
export declare class MatPaginatorHarness extends ComponentHarness {
2+
goToFirstPage(): Promise<void>;
3+
goToLastPage(): Promise<void>;
4+
goToNextPage(): Promise<void>;
5+
goToPreviousPage(): Promise<void>;
6+
setPageSize(size: number): Promise<void>;
7+
static hostSelector: string;
8+
static with(options?: PaginatorHarnessFilters): HarnessPredicate<MatPaginatorHarness>;
9+
}
10+
11+
export interface PaginatorHarnessFilters extends BaseHarnessFilters {
12+
}

0 commit comments

Comments
 (0)