Skip to content

Commit 2c068f5

Browse files
committed
address crisbeto@'s feedback
1 parent 16a71c2 commit 2c068f5

File tree

13 files changed

+262
-293
lines changed

13 files changed

+262
-293
lines changed

.github/CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@
178178
/src/e2e-app/button-toggle/** @jelbourn
179179
/src/e2e-app/card/** @jelbourn
180180
/src/e2e-app/checkbox/** @jelbourn @devversion
181+
/src/e2e-app/component-harness/** @mmalerba
181182
/src/e2e-app/dialog/** @jelbourn @crisbeto
182183
/src/e2e-app/e2e-app/** @jelbourn
183184
/src/e2e-app/example-viewer/** @andrewseguin

src/cdk-experimental/testing/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ ng_module(
1111
deps = [
1212
"@npm//@angular/core",
1313
"@npm//protractor",
14+
"//src/cdk/testing",
1415
],
1516
)
1617

src/cdk-experimental/testing/component-harness.ts

Lines changed: 36 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -68,21 +68,21 @@ export interface Locator {
6868

6969
/**
7070
* Search the first matched test element.
71-
* @param css Selector of the test elements.
71+
* @param selector The CSS selector of the test elements.
7272
* @param options Optional, extra searching options
7373
*/
74-
find(css: string, options?: Options): Promise<TestElement|null>;
74+
querySelector(selector: string, options?: Options): Promise<TestElement|null>;
7575

7676
/**
77-
* Search all matched test elements under current root by css selector.
78-
* @param css Selector of the test elements.
77+
* Search all matched test elements under current root by CSS selector.
78+
* @param selector The CSS selector of the test elements.
7979
*/
80-
findAll(css: string): Promise<TestElement[]>;
80+
querySelectorAll(selector: string): Promise<TestElement[]>;
8181

8282
/**
8383
* Load the first matched Component Harness.
8484
* @param componentHarness Type of user customized harness.
85-
* @param root Css root selector of the new component harness.
85+
* @param root CSS root selector of the new component harness.
8686
* @param options Optional, extra searching options
8787
*/
8888
load<T extends ComponentHarness>(
@@ -92,7 +92,7 @@ export interface Locator {
9292
/**
9393
* Load all Component Harnesses under current root.
9494
* @param componentHarness Type of user customized harness.
95-
* @param root Css root selector of the new component harnesses.
95+
* @param root CSS root selector of the new component harnesses.
9696
*/
9797
loadAll<T extends ComponentHarness>(
9898
componentHarness: ComponentHarnessType<T>, root: string): Promise<T[]>;
@@ -115,33 +115,33 @@ export class ComponentHarness {
115115
}
116116

117117
/**
118-
* Generate a function to find the first matched test element by css
118+
* Generate a function to find the first matched test element by CSS
119119
* selector.
120-
* @param css Css selector of the test element.
120+
* @param selector The CSS selector of the test element.
121121
*/
122-
protected find(css: string): () => Promise<TestElement>;
122+
protected find(selector: string): () => Promise<TestElement>;
123123

124124
/**
125-
* Generate a function to find the first matched test element by css
125+
* Generate a function to find the first matched test element by CSS
126126
* selector.
127-
* @param css Css selector of the test element.
127+
* @param selector The CSS selector of the test element.
128128
* @param options Extra searching options
129129
*/
130-
protected find(css: string, options: OptionsWithAllowNullSet):
130+
protected find(selector: string, options: OptionsWithAllowNullSet):
131131
() => Promise<TestElement|null>;
132132

133133
/**
134-
* Generate a function to find the first matched test element by css
134+
* Generate a function to find the first matched test element by CSS
135135
* selector.
136-
* @param css Css selector of the test element.
136+
* @param selector The CSS selector of the test element.
137137
* @param options Extra searching options
138138
*/
139-
protected find(css: string, options: Options): () => Promise<TestElement>;
139+
protected find(selector: string, options: Options): () => Promise<TestElement>;
140140

141141
/**
142142
* Generate a function to find the first matched Component Harness.
143143
* @param componentHarness Type of user customized harness.
144-
* @param root Css root selector of the new component harness.
144+
* @param root CSS root selector of the new component harness.
145145
*/
146146
protected find<T extends ComponentHarness>(
147147
componentHarness: ComponentHarnessType<T>,
@@ -150,7 +150,7 @@ export class ComponentHarness {
150150
/**
151151
* Generate a function to find the first matched Component Harness.
152152
* @param componentHarness Type of user customized harness.
153-
* @param root Css root selector of the new component harness.
153+
* @param root CSS root selector of the new component harness.
154154
* @param options Extra searching options
155155
*/
156156
protected find<T extends ComponentHarness>(
@@ -160,53 +160,53 @@ export class ComponentHarness {
160160
/**
161161
* Generate a function to find the first matched Component Harness.
162162
* @param componentHarness Type of user customized harness.
163-
* @param root Css root selector of the new component harness.
163+
* @param root CSS root selector of the new component harness.
164164
* @param options Extra searching options
165165
*/
166166
protected find<T extends ComponentHarness>(
167167
componentHarness: ComponentHarnessType<T>, root: string,
168168
options: Options): () => Promise<T>;
169169

170170
protected find<T extends ComponentHarness>(
171-
cssOrComponentHarness: string|ComponentHarnessType<T>,
172-
cssOrOptions?: string|Options,
171+
selectorOrComponentHarness: string|ComponentHarnessType<T>,
172+
selectorOrOptions?: string|Options,
173173
options?: Options): () => Promise<TestElement|T|null> {
174-
if (typeof cssOrComponentHarness === 'string') {
175-
const css = cssOrComponentHarness;
176-
return () => this.locator.find(css, cssOrOptions as Options);
174+
if (typeof selectorOrComponentHarness === 'string') {
175+
const selector = selectorOrComponentHarness;
176+
return () => this.locator.querySelector(selector, selectorOrOptions as Options);
177177
} else {
178-
const componentHarness = cssOrComponentHarness;
179-
const css = cssOrOptions as string;
180-
return () => this.locator.load(componentHarness, css, options);
178+
const componentHarness = selectorOrComponentHarness;
179+
const selector = selectorOrOptions as string;
180+
return () => this.locator.load(componentHarness, selector, options);
181181
}
182182
}
183183

184184
/**
185-
* Generate a function to find all matched test elements by css selector.
186-
* @param css Css root selector of elements. It will locate
185+
* Generate a function to find all matched test elements by CSS selector.
186+
* @param selector The CSS root selector of elements. It will locate
187187
* elements under the current root.
188188
*/
189-
protected findAll(css: string): () => Promise<TestElement[]>;
189+
protected findAll(selector: string): () => Promise<TestElement[]>;
190190

191191
/**
192192
* Generate a function to find all Component Harnesses under current
193193
* component harness.
194194
* @param componentHarness Type of user customized harness.
195-
* @param root Css root selector of the new component harnesses. It will
195+
* @param root CSS root selector of the new component harnesses. It will
196196
* locate harnesses under the current root.
197197
*/
198198
protected findAll<T extends ComponentHarness>(
199199
componentHarness: ComponentHarnessType<T>,
200200
root: string): () => Promise<T[]>;
201201

202202
protected findAll<T extends ComponentHarness>(
203-
cssOrComponentHarness: string|ComponentHarnessType<T>,
203+
selectorOrComponentHarness: string|ComponentHarnessType<T>,
204204
root?: string): () => Promise<TestElement[]|T[]> {
205-
if (typeof cssOrComponentHarness === 'string') {
206-
const css = cssOrComponentHarness;
207-
return () => this.locator.findAll(css);
205+
if (typeof selectorOrComponentHarness === 'string') {
206+
const selector = selectorOrComponentHarness;
207+
return () => this.locator.querySelectorAll(selector);
208208
} else {
209-
const componentHarness = cssOrComponentHarness;
209+
const componentHarness = selectorOrComponentHarness;
210210
return () => this.locator.loadAll(componentHarness, root as string);
211211
}
212212
}

src/cdk-experimental/testing/protractor.ts

Lines changed: 50 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
// package? It depends on protractor which we don't want to put in the deps for cdk-experimental.
1111

1212
import {browser, by, element as protractorElement, ElementFinder} from 'protractor';
13-
import {promise as wdpromise} from 'selenium-webdriver';
1413

1514
import {
1615
ComponentHarness,
@@ -28,33 +27,29 @@ import {
2827
* loading harness, using the load function that accepts extra searching
2928
* options.
3029
* @param componentHarness: Type of user defined harness.
31-
* @param rootSelector: Optional. Css selector to specify the root of component.
30+
* @param rootSelector: Optional. CSS selector to specify the root of component.
3231
* Set to 'body' by default
3332
*/
3433
export async function load<T extends ComponentHarness>(
35-
componentHarness: ComponentHarnessType<T>,
36-
rootSelector: string): Promise<T>;
34+
componentHarness: ComponentHarnessType<T>,
35+
rootSelector: string): Promise<T>;
3736

3837
/**
3938
* Component harness factory for protractor.
4039
* @param componentHarness: Type of user defined harness.
41-
* @param rootSelector: Optional. Css selector to specify the root of component.
40+
* @param rootSelector: Optional. CSS selector to specify the root of component.
4241
* Set to 'body' by default.
4342
* @param options Optional. Extra searching options
4443
*/
4544
export async function load<T extends ComponentHarness>(
46-
componentHarness: ComponentHarnessType<T>, rootSelector?: string,
47-
options?: Options): Promise<T|null>;
45+
componentHarness: ComponentHarnessType<T>, rootSelector?: string,
46+
options?: Options): Promise<T|null>;
4847

4948
export async function load<T extends ComponentHarness>(
50-
componentHarness: ComponentHarnessType<T>, rootSelector = 'body',
51-
options?: Options): Promise<T|null> {
49+
componentHarness: ComponentHarnessType<T>, rootSelector = 'body',
50+
options?: Options): Promise<T|null> {
5251
const root = await getElement(rootSelector, undefined, options);
53-
if (root === null) {
54-
return null;
55-
}
56-
const locator = new ProtractorLocator(root);
57-
return new componentHarness(locator);
52+
return root && new componentHarness(new ProtractorLocator(root));
5853
}
5954

6055
/**
@@ -69,7 +64,7 @@ export function getElementFinder(testElement: TestElement): ElementFinder {
6964
}
7065

7166
class ProtractorLocator implements Locator {
72-
private _root: ProtractorElement;
67+
private readonly _root: ProtractorElement;
7368

7469
constructor(private _rootFinder: ElementFinder) {
7570
this._root = new ProtractorElement(this._rootFinder);
@@ -79,16 +74,13 @@ class ProtractorLocator implements Locator {
7974
return this._root;
8075
}
8176

82-
async find(css: string, options?: Options): Promise<TestElement|null> {
83-
const finder = await getElement(css, this._rootFinder, options);
84-
if (finder === null) {
85-
return null;
86-
}
87-
return new ProtractorElement(finder);
77+
async querySelector(selector: string, options?: Options): Promise<TestElement|null> {
78+
const finder = await getElement(selector, this._rootFinder, options);
79+
return finder && new ProtractorElement(finder);
8880
}
8981

90-
async findAll(css: string): Promise<TestElement[]> {
91-
const elementFinders = this._rootFinder.all(by.css(css));
82+
async querySelectorAll(selector: string): Promise<TestElement[]> {
83+
const elementFinders = this._rootFinder.all(by.css(selector));
9284
const res: TestElement[] = [];
9385
await elementFinders.each(el => {
9486
if (el) {
@@ -99,20 +91,15 @@ class ProtractorLocator implements Locator {
9991
}
10092

10193
async load<T extends ComponentHarness>(
102-
componentHarness: ComponentHarnessType<T>, css: string,
103-
options?: Options): Promise<T|null> {
104-
const root = await getElement(css, this._rootFinder, options);
105-
if (root === null) {
106-
return null;
107-
}
108-
const locator = new ProtractorLocator(root);
109-
return new componentHarness(locator);
94+
componentHarness: ComponentHarnessType<T>, selector: string,
95+
options?: Options): Promise<T|null> {
96+
const root = await getElement(selector, this._rootFinder, options);
97+
return root && new componentHarness(new ProtractorLocator(root));
11098
}
11199

112100
async loadAll<T extends ComponentHarness>(
113-
componentHarness: ComponentHarnessType<T>,
114-
rootSelector: string,
115-
): Promise<T[]> {
101+
componentHarness: ComponentHarnessType<T>,
102+
rootSelector: string): Promise<T[]> {
116103
const roots = this._rootFinder.all(by.css(rootSelector));
117104
const res: T[] = [];
118105
await roots.each(el => {
@@ -128,77 +115,66 @@ class ProtractorLocator implements Locator {
128115
class ProtractorElement implements TestElement {
129116
constructor(readonly element: ElementFinder) {}
130117

131-
blur(): Promise<void> {
132-
return toPromise<void>(this.element['blur']());
118+
async blur(): Promise<void> {
119+
return this.element['blur']();
133120
}
134121

135-
clear(): Promise<void> {
136-
return toPromise<void>(this.element.clear());
122+
async clear(): Promise<void> {
123+
return this.element.clear();
137124
}
138125

139-
click(): Promise<void> {
140-
return toPromise<void>(this.element.click());
126+
async click(): Promise<void> {
127+
return this.element.click();
141128
}
142129

143-
focus(): Promise<void> {
144-
return toPromise<void>(this.element['focus']());
130+
async focus(): Promise<void> {
131+
return this.element['focus']();
145132
}
146133

147-
getCssValue(property: string): Promise<string> {
148-
return toPromise<string>(this.element.getCssValue(property));
134+
async getCssValue(property: string): Promise<string> {
135+
return this.element.getCssValue(property);
149136
}
150137

151138
async hover(): Promise<void> {
152-
return toPromise<void>(browser.actions()
153-
.mouseMove(await this.element.getWebElement())
154-
.perform());
139+
return browser.actions()
140+
.mouseMove(await this.element.getWebElement())
141+
.perform();
155142
}
156143

157-
sendKeys(keys: string): Promise<void> {
158-
return toPromise<void>(this.element.sendKeys(keys));
144+
async sendKeys(keys: string): Promise<void> {
145+
return this.element.sendKeys(keys);
159146
}
160147

161-
text(): Promise<string> {
162-
return toPromise(this.element.getText());
148+
async text(): Promise<string> {
149+
return this.element.getText();
163150
}
164151

165-
getAttribute(name: string): Promise<string|null> {
166-
return toPromise(this.element.getAttribute(name));
152+
async getAttribute(name: string): Promise<string|null> {
153+
return this.element.getAttribute(name);
167154
}
168155
}
169156

170-
function toPromise<T>(p: wdpromise.Promise<T>): Promise<T> {
171-
return new Promise<T>((resolve, reject) => {
172-
p.then(resolve, reject);
173-
});
174-
}
175-
176157
/**
177-
* Get an element finder based on the css selector and root element.
158+
* Get an element finder based on the CSS selector and root element.
178159
* Note that it will check whether the element is present only when
179160
* Options.allowNull is set. This is for performance purpose.
180-
* @param css the css selector
161+
* @param selector The CSS selector
181162
* @param root Optional Search element under the root element. If not set,
182163
* search element globally. If options.global is set, root is ignored.
183164
* @param options Optional, extra searching options
184165
*/
185-
async function getElement(css: string, root?: ElementFinder, options?: Options):
166+
async function getElement(selector: string, root?: ElementFinder, options?: Options):
186167
Promise<ElementFinder|null> {
187168
const useGlobalRoot = options && !!options.global;
188-
const elem = root === undefined || useGlobalRoot ? protractorElement(by.css(css)) :
189-
root.element(by.css(css));
169+
const elem = root === undefined || useGlobalRoot ?
170+
protractorElement(by.css(selector)) : root.element(by.css(selector));
190171
const allowNull = options !== undefined && options.allowNull !== undefined ?
191-
options.allowNull :
192-
undefined;
193-
if (allowNull !== undefined) {
194-
// Only check isPresent when allowNull is set
195-
if (!(await elem.isPresent())) {
196-
if (allowNull) {
197-
return null;
198-
}
199-
throw new Error('Cannot find element based on the css selector: ' + css);
172+
options.allowNull : undefined;
173+
if (allowNull !== undefined && !(await elem.isPresent())) {
174+
if (allowNull) {
175+
return null;
200176
}
201-
return elem;
177+
throw new Error('Cannot find element based on the CSS selector: ' + selector);
202178
}
203179
return elem;
204180
}

0 commit comments

Comments
 (0)