Skip to content

Commit 0240846

Browse files
committed
feat(material-experimental): add button toggle test harness
Adds a test harness for `mat-button-toggle`.
1 parent 88631b9 commit 0240846

14 files changed

+477
-0
lines changed

.github/CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@
9494
/src/material-experimental/mdc-radio/** @mmalerba
9595
/src/material-experimental/mdc-slide-toggle/** @crisbeto
9696
/src/material-experimental/mdc-tabs/** @crisbeto
97+
/src/material-experimental/mdc-button-toggle/** @crisbeto
9798
/src/material-experimental/mdc-theming/** @mmalerba
9899
/src/material-experimental/mdc-typography/** @mmalerba
99100
/src/material-experimental/popover-edit/** @kseamon @andrewseguin
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
package(default_visibility = ["//visibility:public"])
2+
3+
load("@io_bazel_rules_sass//:defs.bzl", "sass_binary", "sass_library")
4+
load("//tools:defaults.bzl", "ng_e2e_test_library", "ng_module", "ng_test_library", "ng_web_test_suite", "ts_library")
5+
load("//src/e2e-app:test_suite.bzl", "e2e_test_suite")
6+
7+
ng_module(
8+
name = "mdc-button-toggle",
9+
srcs = glob(
10+
["**/*.ts"],
11+
exclude = [
12+
"**/*.spec.ts",
13+
"harness/**",
14+
],
15+
),
16+
assets = [
17+
# TODO: include scss assets
18+
] + glob(["**/*.html"]),
19+
module_name = "@angular/material-experimental/mdc-button-toggle",
20+
deps = [
21+
"//src/material/core",
22+
],
23+
)
24+
25+
ts_library(
26+
name = "harness",
27+
srcs = glob(
28+
["harness/**/*.ts"],
29+
exclude = ["**/*.spec.ts"],
30+
),
31+
deps = [
32+
"//src/cdk-experimental/testing",
33+
"//src/cdk/coercion",
34+
],
35+
)
36+
37+
sass_library(
38+
name = "mdc_button_toggle_scss_lib",
39+
srcs = glob(["**/_*.scss"]),
40+
deps = [
41+
"//src/material-experimental/mdc-helpers:mdc_helpers_scss_lib",
42+
"//src/material-experimental/mdc-helpers:mdc_scss_deps_lib",
43+
"//src/material/core:core_scss_lib",
44+
],
45+
)
46+
47+
sass_binary(
48+
name = "button_toggle_scss",
49+
src = "button-toggle.scss",
50+
include_paths = [
51+
"external/npm/node_modules",
52+
],
53+
deps = [
54+
"//src/material-experimental/mdc-helpers:mdc_helpers_scss_lib",
55+
"//src/material-experimental/mdc-helpers:mdc_scss_deps_lib",
56+
"//src/material/core:all_themes",
57+
],
58+
)
59+
60+
ng_test_library(
61+
name = "button_toggle_tests_lib",
62+
srcs = [
63+
"harness/button-toggle-harness.spec.ts",
64+
],
65+
deps = [
66+
":harness",
67+
":mdc-button-toggle",
68+
"//src/cdk-experimental/testing",
69+
"//src/cdk-experimental/testing/testbed",
70+
"//src/cdk/platform",
71+
"//src/cdk/testing",
72+
"//src/material/button-toggle",
73+
"@npm//@angular/platform-browser",
74+
],
75+
)
76+
77+
ng_web_test_suite(
78+
name = "unit_tests",
79+
deps = [
80+
":button_toggle_tests_lib",
81+
"//src/material-experimental:mdc_require_config.js",
82+
],
83+
)
84+
85+
ng_e2e_test_library(
86+
name = "e2e_test_sources",
87+
srcs = glob(["**/*.e2e.spec.ts"]),
88+
deps = [
89+
"//src/cdk/testing/e2e",
90+
],
91+
)
92+
93+
e2e_test_suite(
94+
name = "e2e_tests",
95+
deps = [
96+
":e2e_test_sources",
97+
"//src/cdk/testing/e2e",
98+
],
99+
)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<!-- TODO -->
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
@import '../mdc-helpers/mdc-helpers';
2+
3+
@mixin mat-button-toggle-theme-mdc($theme) {
4+
@include mat-using-mdc-theme($theme) {
5+
// TODO: implement MDC-based button toggle.
6+
}
7+
}
8+
9+
@mixin mat-buttont-toggle-typography-mdc($config) {
10+
@include mat-using-mdc-typography($config) {
11+
// TODO: implement MDC-based button toggle.
12+
}
13+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
// TODO: copy tests from existing mat-button-toggle, update as necessary to fix.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
// TODO: implement MDC-based button toggle
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
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 type ButtonToggleHarnessFilters = {
10+
label?: string | RegExp,
11+
name?: string,
12+
};
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
import {HarnessLoader} from '@angular/cdk-experimental/testing';
2+
import {TestbedHarnessEnvironment} from '@angular/cdk-experimental/testing/testbed';
3+
import {Component} from '@angular/core';
4+
import {ComponentFixture, TestBed} from '@angular/core/testing';
5+
import {MatButtonToggleModule} from '@angular/material/button-toggle';
6+
import {MatButtonToggleModule as MatMdcButtonToggleModule} from '../index';
7+
import {MatButtonToggleHarness} from './button-toggle-harness';
8+
import {MatButtonToggleHarness as MatMdcButtonToggleHarness} from './mdc-button-toggle-harness';
9+
10+
let fixture: ComponentFixture<ButtonToggleHarnessTest>;
11+
let loader: HarnessLoader;
12+
let harness: typeof MatButtonToggleHarness;
13+
14+
describe('MatButtonToggleHarness', () => {
15+
describe('non-MDC-based', () => {
16+
beforeEach(async () => {
17+
await TestBed.configureTestingModule({
18+
imports: [MatButtonToggleModule],
19+
declarations: [ButtonToggleHarnessTest],
20+
}).compileComponents();
21+
22+
fixture = TestBed.createComponent(ButtonToggleHarnessTest);
23+
fixture.detectChanges();
24+
loader = TestbedHarnessEnvironment.loader(fixture);
25+
harness = MatButtonToggleHarness;
26+
});
27+
28+
runTests();
29+
});
30+
31+
describe('MDC-based', () => {
32+
beforeEach(async () => {
33+
await TestBed.configureTestingModule({
34+
imports: [MatMdcButtonToggleModule],
35+
declarations: [ButtonToggleHarnessTest],
36+
}).compileComponents();
37+
38+
fixture = TestBed.createComponent(ButtonToggleHarnessTest);
39+
fixture.detectChanges();
40+
loader = TestbedHarnessEnvironment.loader(fixture);
41+
// Public APIs are the same as MatButtonToggleHarness, but cast is
42+
// necessary because of different private fields.
43+
harness = MatMdcButtonToggleHarness as any;
44+
});
45+
46+
// TODO: enable when the MDC-based harness is done.
47+
// runTests();
48+
});
49+
});
50+
51+
/** Shared tests to run on both the original and MDC-based toggles. */
52+
function runTests() {
53+
it('should load all button toggle harnesses', async () => {
54+
const toggles = await loader.getAllHarnesses(harness);
55+
expect(toggles.length).toBe(2);
56+
});
57+
58+
it('should load a button toggle with exact label', async () => {
59+
const toggles = await loader.getAllHarnesses(harness.with({label: 'First'}));
60+
expect(toggles.length).toBe(1);
61+
expect(await toggles[0].getText()).toBe('First');
62+
});
63+
64+
it('should load a button toggle with regex label match', async () => {
65+
const toggles = await loader.getAllHarnesses(harness.with({label: /^s/i}));
66+
expect(toggles.length).toBe(1);
67+
expect(await toggles[0].getText()).toBe('Second');
68+
});
69+
70+
it('should get checked state', async () => {
71+
const [checkedToggle, uncheckedToggle] = await loader.getAllHarnesses(harness);
72+
expect(await checkedToggle.isChecked()).toBe(true);
73+
expect(await uncheckedToggle.isChecked()).toBe(false);
74+
});
75+
76+
it('should get disabled state', async () => {
77+
const [enabledToggle, disabledToggle] = await loader.getAllHarnesses(harness);
78+
expect(await enabledToggle.isDisabled()).toBe(false);
79+
expect(await disabledToggle.isDisabled()).toBe(true);
80+
});
81+
82+
it('should get name', async () => {
83+
const toggle = await loader.getHarness(harness.with({label: 'First'}));
84+
expect(await toggle.getName()).toBe('first-name');
85+
});
86+
87+
it('should get aria-label', async () => {
88+
const toggle = await loader.getHarness(harness.with({label: 'First'}));
89+
expect(await toggle.getAriaLabel()).toBe('First toggle');
90+
});
91+
92+
it('should get aria-labelledby', async () => {
93+
const toggle = await loader.getHarness(harness.with({label: 'Second'}));
94+
expect(await toggle.getAriaLabelledby()).toBe('second-label');
95+
});
96+
97+
it('should get label text', async () => {
98+
const [firstToggle, secondToggle] = await loader.getAllHarnesses(harness);
99+
expect(await firstToggle.getText()).toBe('First');
100+
expect(await secondToggle.getText()).toBe('Second');
101+
});
102+
103+
it('should focus button', async () => {
104+
const toggle = await loader.getHarness(harness.with({label: 'First'}));
105+
expect(getActiveElementTagName()).not.toBe('button');
106+
await toggle.focus();
107+
expect(getActiveElementTagName()).toBe('button');
108+
});
109+
110+
it('should blur button', async () => {
111+
const toggle = await loader.getHarness(harness.with({label: 'First'}));
112+
await toggle.focus();
113+
expect(getActiveElementTagName()).toBe('button');
114+
await toggle.blur();
115+
expect(getActiveElementTagName()).not.toBe('button');
116+
});
117+
118+
it('should toggle', async () => {
119+
fixture.componentInstance.disabled = false;
120+
const [checkedToggle, uncheckedToggle] = await loader.getAllHarnesses(harness);
121+
await checkedToggle.toggle();
122+
await uncheckedToggle.toggle();
123+
expect(await checkedToggle.isChecked()).toBe(false);
124+
expect(await uncheckedToggle.isChecked()).toBe(true);
125+
});
126+
127+
it('should check toggle', async () => {
128+
fixture.componentInstance.disabled = false;
129+
const [checkedToggle, uncheckedToggle] = await loader.getAllHarnesses(harness);
130+
await checkedToggle.check();
131+
await uncheckedToggle.check();
132+
expect(await checkedToggle.isChecked()).toBe(true);
133+
expect(await uncheckedToggle.isChecked()).toBe(true);
134+
});
135+
136+
it('should uncheck toggle', async () => {
137+
fixture.componentInstance.disabled = false;
138+
const [checkedToggle, uncheckedToggle] = await loader.getAllHarnesses(harness);
139+
await checkedToggle.uncheck();
140+
await uncheckedToggle.uncheck();
141+
expect(await checkedToggle.isChecked()).toBe(false);
142+
expect(await uncheckedToggle.isChecked()).toBe(false);
143+
});
144+
145+
it('should not change disabled toggle', async () => {
146+
const disabledToggle = await loader.getHarness(harness.with({label: 'Second'}));
147+
expect(await disabledToggle.isChecked()).toBe(false);
148+
await disabledToggle.toggle();
149+
expect(await disabledToggle.isChecked()).toBe(false);
150+
});
151+
}
152+
153+
function getActiveElementTagName() {
154+
return document.activeElement ? document.activeElement.tagName.toLowerCase() : '';
155+
}
156+
157+
@Component({
158+
template: `
159+
<mat-button-toggle
160+
name="first-name"
161+
value="first-value"
162+
aria-label="First toggle"
163+
checked>First</mat-button-toggle>
164+
<mat-button-toggle
165+
[disabled]="disabled"
166+
aria-labelledby="second-label">Second</mat-button-toggle>
167+
<span id="second-label">Second toggle</span>
168+
`
169+
})
170+
class ButtonToggleHarnessTest {
171+
disabled = true;
172+
}
173+

0 commit comments

Comments
 (0)