Skip to content

Commit 5194bea

Browse files
crisbetommalerba
authored andcommitted
fix(material-experimental): unit tests getting wrong root element and add API for getting property value (#16706)
Based on the discussion in #16697 (comment), these changes fix a couple of things that I ran into while doing the `mat-autocomplete` test harness in #16620. * Fixes querying for elements outside the harness not working, because the wrong root node was set. * Adds an API to retrieve the value of a property on a DOM node.
1 parent f6116ee commit 5194bea

File tree

10 files changed

+48
-30
lines changed

10 files changed

+48
-30
lines changed

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,8 @@ export class ProtractorElement implements TestElement {
123123
}
124124

125125
async getAttribute(name: string): Promise<string|null> {
126-
return this.element.getAttribute(name);
126+
return browser.executeScript(
127+
`return arguments[0].getAttribute(arguments[1])`, this.element, name);
127128
}
128129

129130
async hasClass(name: string): Promise<boolean> {
@@ -136,4 +137,8 @@ export class ProtractorElement implements TestElement {
136137
const {x: left, y: top} = await this.element.getLocation();
137138
return {width, height, left, top};
138139
}
140+
141+
async getProperty(name: string): Promise<any> {
142+
return browser.executeScript(`return arguments[0][arguments[1]]`, this.element, name);
143+
}
139144
}

src/cdk-experimental/testing/test-element.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,4 +101,7 @@ export interface TestElement {
101101

102102
/** Gets the dimensions of the element. */
103103
getDimensions(): Promise<ElementDimensions>;
104+
105+
/** Gets the value of a property of an element. */
106+
getProperty(name: string): Promise<any>;
104107
}

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

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -120,14 +120,7 @@ export class UnitTestElement implements TestElement {
120120

121121
async getAttribute(name: string): Promise<string|null> {
122122
await this._stabilize();
123-
let value = this.element.getAttribute(name);
124-
// If cannot find attribute in the element, also try to find it in property,
125-
// this is useful for input/textarea tags.
126-
if (value === null && name in this.element) {
127-
// We need to cast the element so we can access its properties via string indexing.
128-
return (this.element as unknown as {[key: string]: string|null})[name];
129-
}
130-
return value;
123+
return this.element.getAttribute(name);
131124
}
132125

133126
async hasClass(name: string): Promise<boolean> {
@@ -139,4 +132,9 @@ export class UnitTestElement implements TestElement {
139132
await this._stabilize();
140133
return this.element.getBoundingClientRect();
141134
}
135+
136+
async getProperty(name: string): Promise<any> {
137+
await this._stabilize();
138+
return (this.element as any)[name];
139+
}
142140
}

src/cdk-experimental/testing/tests/protractor.e2e.spec.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -179,10 +179,10 @@ describe('ProtractorHarnessEnvironment', () => {
179179
it('should be able to clear', async () => {
180180
const input = await harness.input();
181181
await input.sendKeys('Yi');
182-
expect(await input.getAttribute('value')).toBe('Yi');
182+
expect(await input.getProperty('value')).toBe('Yi');
183183

184184
await input.clear();
185-
expect(await input.getAttribute('value')).toBe('');
185+
expect(await input.getProperty('value')).toBe('');
186186
});
187187

188188
it('should be able to click', async () => {
@@ -204,7 +204,7 @@ describe('ProtractorHarnessEnvironment', () => {
204204
const value = await harness.value();
205205
await input.sendKeys('Yi');
206206

207-
expect(await input.getAttribute('value')).toBe('Yi');
207+
expect(await input.getProperty('value')).toBe('Yi');
208208
expect(await value.text()).toBe('Input: Yi');
209209
});
210210

@@ -236,7 +236,7 @@ describe('ProtractorHarnessEnvironment', () => {
236236
`;
237237
const memo = await harness.memo();
238238
await memo.sendKeys(memoStr);
239-
expect(await memo.getAttribute('value')).toBe(memoStr);
239+
expect(await memo.getProperty('value')).toBe(memoStr);
240240
});
241241

242242
it('should be able to getCssValue', async () => {
@@ -254,6 +254,12 @@ describe('ProtractorHarnessEnvironment', () => {
254254
expect(await (await browser.switchTo().activeElement()).getText())
255255
.not.toBe(await button.text());
256256
});
257+
258+
it('should be able to get the value of a property', async () => {
259+
const input = await harness.input();
260+
await input.sendKeys('Hello');
261+
expect(await input.getProperty('value')).toBe('Hello');
262+
});
257263
});
258264

259265
describe('HarnessPredicate', () => {

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

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -199,10 +199,10 @@ describe('TestbedHarnessEnvironment', () => {
199199
it('should be able to clear', async () => {
200200
const input = await harness.input();
201201
await input.sendKeys('Yi');
202-
expect(await input.getAttribute('value')).toBe('Yi');
202+
expect(await input.getProperty('value')).toBe('Yi');
203203

204204
await input.clear();
205-
expect(await input.getAttribute('value')).toBe('');
205+
expect(await input.getProperty('value')).toBe('');
206206
});
207207

208208
it('should be able to click', async () => {
@@ -224,7 +224,7 @@ describe('TestbedHarnessEnvironment', () => {
224224
const value = await harness.value();
225225
await input.sendKeys('Yi');
226226

227-
expect(await input.getAttribute('value')).toBe('Yi');
227+
expect(await input.getProperty('value')).toBe('Yi');
228228
expect(await value.text()).toBe('Input: Yi');
229229
});
230230

@@ -255,7 +255,7 @@ describe('TestbedHarnessEnvironment', () => {
255255
`;
256256
const memo = await harness.memo();
257257
await memo.sendKeys(memoStr);
258-
expect(await memo.getAttribute('value')).toBe(memoStr);
258+
expect(await memo.getProperty('value')).toBe(memoStr);
259259
});
260260

261261
it('should be able to getCssValue', async () => {
@@ -271,6 +271,12 @@ describe('TestbedHarnessEnvironment', () => {
271271
await button.blur();
272272
expect(activeElementText()).not.toBe(await button.text());
273273
});
274+
275+
it('should be able to get the value of a property', async () => {
276+
const input = await harness.input();
277+
await input.sendKeys('Hello');
278+
expect(await input.getProperty('value')).toBe('Hello');
279+
});
274280
});
275281

276282
describe('HarnessPredicate', () => {

src/material-experimental/mdc-checkbox/harness/checkbox-harness.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,13 @@ export class MatCheckboxHarness extends ComponentHarness {
4141

4242
/** Gets a boolean promise indicating if the checkbox is checked. */
4343
async isChecked(): Promise<boolean> {
44-
const checked = (await this._input()).getAttribute('checked');
44+
const checked = (await this._input()).getProperty('checked');
4545
return coerceBooleanProperty(await checked);
4646
}
4747

4848
/** Gets a boolean promise indicating if the checkbox is in an indeterminate state. */
4949
async isIndeterminate(): Promise<boolean> {
50-
const indeterminate = (await this._input()).getAttribute('indeterminate');
50+
const indeterminate = (await this._input()).getProperty('indeterminate');
5151
return coerceBooleanProperty(await indeterminate);
5252
}
5353

@@ -59,7 +59,7 @@ export class MatCheckboxHarness extends ComponentHarness {
5959

6060
/** Gets a boolean promise indicating if the checkbox is required. */
6161
async isRequired(): Promise<boolean> {
62-
const required = (await this._input()).getAttribute('required');
62+
const required = (await this._input()).getProperty('required');
6363
return coerceBooleanProperty(await required);
6464
}
6565

@@ -76,7 +76,7 @@ export class MatCheckboxHarness extends ComponentHarness {
7676

7777
/** Gets a promise for the checkbox's value. */
7878
async getValue(): Promise<string|null> {
79-
return (await this._input()).getAttribute('value');
79+
return (await this._input()).getProperty('value');
8080
}
8181

8282
/** Gets a promise for the checkbox's aria-label. */

src/material-experimental/mdc-checkbox/harness/mdc-checkbox-harness.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,13 @@ export class MatCheckboxHarness extends ComponentHarness {
4141

4242
/** Gets a boolean promise indicating if the checkbox is checked. */
4343
async isChecked(): Promise<boolean> {
44-
const checked = (await this._input()).getAttribute('checked');
44+
const checked = (await this._input()).getProperty('checked');
4545
return coerceBooleanProperty(await checked);
4646
}
4747

4848
/** Gets a boolean promise indicating if the checkbox is in an indeterminate state. */
4949
async isIndeterminate(): Promise<boolean> {
50-
const indeterminate = (await this._input()).getAttribute('indeterminate');
50+
const indeterminate = (await this._input()).getProperty('indeterminate');
5151
return coerceBooleanProperty(await indeterminate);
5252
}
5353

@@ -76,7 +76,7 @@ export class MatCheckboxHarness extends ComponentHarness {
7676

7777
/** Gets a promise for the checkbox's value. */
7878
async getValue(): Promise<string|null> {
79-
return (await this._input()).getAttribute('value');
79+
return (await this._input()).getProperty('value');
8080
}
8181

8282
/** Gets a promise for the checkbox's aria-label. */

src/material-experimental/mdc-radio/harness/radio-harness.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export class MatRadioGroupHarness extends ComponentHarness {
5757

5858
/** Gets the id of the radio-group. */
5959
async getId(): Promise<string|null> {
60-
return (await this.host()).getAttribute('id');
60+
return (await this.host()).getProperty('id');
6161
}
6262

6363
/** Gets the selected radio-button in a radio-group. */
@@ -174,7 +174,7 @@ export class MatRadioButtonHarness extends ComponentHarness {
174174

175175
/** Whether the radio-button is checked. */
176176
async isChecked(): Promise<boolean> {
177-
const checked = (await this._input()).getAttribute('checked');
177+
const checked = (await this._input()).getProperty('checked');
178178
return coerceBooleanProperty(await checked);
179179
}
180180

@@ -197,7 +197,7 @@ export class MatRadioButtonHarness extends ComponentHarness {
197197

198198
/** Gets a promise for the radio-button's id. */
199199
async getId(): Promise<string|null> {
200-
return (await this.host()).getAttribute('id');
200+
return (await this.host()).getProperty('id');
201201
}
202202

203203
/**
@@ -208,7 +208,7 @@ export class MatRadioButtonHarness extends ComponentHarness {
208208
* intentionally have the `[object Object]` as return value.
209209
*/
210210
async getValue(): Promise<string|null> {
211-
return (await this._input()).getAttribute('value');
211+
return (await this._input()).getProperty('value');
212212
}
213213

214214
/** Gets a promise for the radio-button's label text. */

src/material-experimental/mdc-slide-toggle/harness/mdc-slide-toggle-harness.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export class MatSlideToggleHarness extends ComponentHarness {
3636

3737
/** Gets a boolean promise indicating if the slide-toggle is checked. */
3838
async isChecked(): Promise<boolean> {
39-
const checked = (await this._input()).getAttribute('checked');
39+
const checked = (await this._input()).getProperty('checked');
4040
return coerceBooleanProperty(await checked);
4141
}
4242

src/material-experimental/mdc-slide-toggle/harness/slide-toggle-harness.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export class MatSlideToggleHarness extends ComponentHarness {
3636

3737
/** Gets a boolean promise indicating if the slide-toggle is checked. */
3838
async isChecked(): Promise<boolean> {
39-
const checked = (await this._input()).getAttribute('checked');
39+
const checked = (await this._input()).getProperty('checked');
4040
return coerceBooleanProperty(await checked);
4141
}
4242

0 commit comments

Comments
 (0)