Skip to content

Commit 44accd6

Browse files
authored
feat(tooltip/testing): add test harness for mat-tooltip (#19144)
This is redo of #16676. Adds a test harness for `mat-tooltip`, as well as an API to move the pointer away from an element, as an opposite to `TestElement.hover`.
1 parent 45435c9 commit 44accd6

File tree

18 files changed

+253
-5
lines changed

18 files changed

+253
-5
lines changed

src/cdk/testing/protractor/protractor-element.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,12 @@ export class ProtractorElement implements TestElement {
9999
.perform();
100100
}
101101

102+
async mouseAway(): Promise<void> {
103+
return browser.actions()
104+
.mouseMove(await this.element.getWebElement(), {x: -1, y: -1})
105+
.perform();
106+
}
107+
102108
async sendKeys(...keys: (string | TestKey)[]): Promise<void>;
103109
async sendKeys(modifiers: ModifierKeys, ...keys: (string | TestKey)[]): Promise<void>;
104110
async sendKeys(...modifiersAndKeys: any[]): Promise<void> {

src/cdk/testing/test-element.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ export interface TestElement {
8686
/** Hovers the mouse over the element. */
8787
hover(): Promise<void>;
8888

89+
/** Moves the mouse away from the element. */
90+
mouseAway(): Promise<void>;
91+
8992
/**
9093
* Sends the given string to the input as a series of key presses. Also fires input events
9194
* and attempts to add the string to the Element's value.

src/cdk/testing/testbed/unit-test-element.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,12 @@ export class UnitTestElement implements TestElement {
119119
await this._stabilize();
120120
}
121121

122+
async mouseAway(): Promise<void> {
123+
await this._stabilize();
124+
dispatchMouseEvent(this.element, 'mouseleave');
125+
await this._stabilize();
126+
}
127+
122128
async sendKeys(...keys: (string | TestKey)[]): Promise<void>;
123129
async sendKeys(modifiers: ModifierKeys, ...keys: (string | TestKey)[]): Promise<void>;
124130
async sendKeys(...modifiersAndKeys: any[]): Promise<void> {

src/cdk/testing/tests/test-main-component.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ import {
2424
templateUrl: 'test-main-component.html',
2525
host: {
2626
'[class.hovering]': '_isHovering',
27-
'(mouseenter)': 'onMouseOver()',
28-
'(mouseout)': 'onMouseOut()',
27+
'(mouseenter)': 'onMouseEnter()',
28+
'(mouseleave)': 'onMouseLeave()',
2929
},
3030
encapsulation: ViewEncapsulation.None,
3131
changeDetection: ChangeDetectionStrategy.OnPush,
@@ -50,11 +50,11 @@ export class TestMainComponent implements OnDestroy {
5050

5151
private _fakeOverlayElement: HTMLElement;
5252

53-
onMouseOver() {
53+
onMouseEnter() {
5454
this._isHovering = true;
5555
}
5656

57-
onMouseOut() {
57+
onMouseLeave() {
5858
this._isHovering = false;
5959
}
6060

src/cdk/testing/tests/testbed.spec.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,18 @@ describe('TestbedHarnessEnvironment', () => {
338338
expect(classAttr).toContain('hovering');
339339
});
340340

341+
it('should be able to stop hovering', async () => {
342+
const host = await harness.host();
343+
let classAttr = await host.getAttribute('class');
344+
expect(classAttr).not.toContain('hovering');
345+
await host.hover();
346+
classAttr = await host.getAttribute('class');
347+
expect(classAttr).toContain('hovering');
348+
await host.mouseAway();
349+
classAttr = await host.getAttribute('class');
350+
expect(classAttr).not.toContain('hovering');
351+
});
352+
341353
it('should be able to getAttribute', async () => {
342354
const memoStr = `
343355
This is an example that shows how to use component harness

src/material/config.bzl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ entryPoints = [
5858
"tabs/testing",
5959
"toolbar",
6060
"tooltip",
61+
"tooltip/testing",
6162
"tree",
6263
"form-field/testing",
6364
"form-field/testing/control",
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
load("//tools:defaults.bzl", "ng_test_library", "ng_web_test_suite", "ts_library")
2+
3+
package(default_visibility = ["//visibility:public"])
4+
5+
ts_library(
6+
name = "testing",
7+
srcs = glob(
8+
["**/*.ts"],
9+
exclude = ["**/*.spec.ts"],
10+
),
11+
module_name = "@angular/material/tooltip/testing",
12+
deps = [
13+
"//src/cdk/testing",
14+
],
15+
)
16+
17+
filegroup(
18+
name = "source-files",
19+
srcs = glob(["**/*.ts"]),
20+
)
21+
22+
ng_test_library(
23+
name = "harness_tests_lib",
24+
srcs = ["shared.spec.ts"],
25+
deps = [
26+
":testing",
27+
"//src/cdk/testing",
28+
"//src/cdk/testing/testbed",
29+
"//src/material/tooltip",
30+
"@npm//@angular/platform-browser",
31+
],
32+
)
33+
34+
ng_test_library(
35+
name = "unit_tests_lib",
36+
srcs = glob(
37+
["**/*.spec.ts"],
38+
exclude = ["shared.spec.ts"],
39+
),
40+
deps = [
41+
":harness_tests_lib",
42+
":testing",
43+
"//src/material/tooltip",
44+
],
45+
)
46+
47+
ng_web_test_suite(
48+
name = "unit_tests",
49+
deps = [":unit_tests_lib"],
50+
)

src/material/tooltip/testing/index.ts

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: 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 './tooltip-harness';
10+
export * from './tooltip-harness-filters';
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import {HarnessLoader} from '@angular/cdk/testing';
2+
import {TestbedHarnessEnvironment} from '@angular/cdk/testing/testbed';
3+
import {Component} from '@angular/core';
4+
import {ComponentFixture, TestBed} from '@angular/core/testing';
5+
import {MatTooltipModule} from '@angular/material/tooltip';
6+
import {MatTooltipHarness} from '@angular/material/tooltip/testing/tooltip-harness';
7+
import {NoopAnimationsModule} from '@angular/platform-browser/animations';
8+
9+
/** Shared tests to run on both the original and MDC-based tooltips. */
10+
export function runHarnessTests(
11+
tooltipModule: typeof MatTooltipModule, tooltipHarness: typeof MatTooltipHarness) {
12+
let fixture: ComponentFixture<TooltipHarnessTest>;
13+
let loader: HarnessLoader;
14+
15+
beforeEach(async () => {
16+
await TestBed.configureTestingModule({
17+
imports: [tooltipModule, NoopAnimationsModule],
18+
declarations: [TooltipHarnessTest],
19+
}).compileComponents();
20+
21+
fixture = TestBed.createComponent(TooltipHarnessTest);
22+
fixture.detectChanges();
23+
loader = TestbedHarnessEnvironment.loader(fixture);
24+
});
25+
26+
it('should load all tooltip harnesses', async () => {
27+
const tooltips = await loader.getAllHarnesses(tooltipHarness);
28+
expect(tooltips.length).toBe(2);
29+
});
30+
31+
it('should be able to show a tooltip', async () => {
32+
const tooltip = await loader.getHarness(tooltipHarness.with({selector: '#one'}));
33+
expect(await tooltip.isOpen()).toBe(false);
34+
await tooltip.show();
35+
expect(await tooltip.isOpen()).toBe(true);
36+
});
37+
38+
it('should be able to hide a tooltip', async () => {
39+
const tooltip = await loader.getHarness(tooltipHarness.with({selector: '#one'}));
40+
expect(await tooltip.isOpen()).toBe(false);
41+
await tooltip.show();
42+
expect(await tooltip.isOpen()).toBe(true);
43+
await tooltip.hide();
44+
expect(await tooltip.isOpen()).toBe(false);
45+
});
46+
47+
it('should be able to get the text of a tooltip', async () => {
48+
const tooltip = await loader.getHarness(tooltipHarness.with({selector: '#one'}));
49+
await tooltip.show();
50+
expect(await tooltip.getTooltipText()).toBe('Tooltip message');
51+
});
52+
53+
it('should return empty when getting the tooltip text while closed', async () => {
54+
const tooltip = await loader.getHarness(tooltipHarness.with({selector: '#one'}));
55+
expect(await tooltip.getTooltipText()).toBe('');
56+
});
57+
}
58+
59+
@Component({
60+
template: `
61+
<button [matTooltip]="message" id="one">Trigger 1</button>
62+
<button matTooltip="Static message" id="two">Trigger 2</button>
63+
`
64+
})
65+
class TooltipHarnessTest {
66+
message = 'Tooltip message';
67+
}

0 commit comments

Comments
 (0)