Skip to content

Commit

Permalink
fix(material-experimental): unit tests getting wrong root element and…
Browse files Browse the repository at this point in the history
… add API for getting property value

Based on the discussion in angular#16697 (comment), these changes fix a couple of things that I ran into while doing the `mat-autocomplete` test harness in angular#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.
  • Loading branch information
crisbeto committed Aug 22, 2019
1 parent fa81811 commit 8dd52a8
Show file tree
Hide file tree
Showing 10 changed files with 43 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ export class ProtractorElement implements TestElement {
}

async getAttribute(name: string): Promise<string|null> {
return this.element.getAttribute(name);
return browser.executeScript(`return arguments[0].getAttribute('${name}')`, this.element);
}

async hasClass(name: string): Promise<boolean> {
Expand All @@ -136,4 +136,8 @@ export class ProtractorElement implements TestElement {
const {x: left, y: top} = await this.element.getLocation();
return {width, height, left, top};
}

async getPropertyValue(name: string): Promise<any> {
return browser.executeScript(`return arguments[0]['${name}']`, this.element);
}
}
3 changes: 3 additions & 0 deletions src/cdk-experimental/testing/test-element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,4 +101,7 @@ export interface TestElement {

/** Gets the dimensions of the element. */
getDimensions(): Promise<ElementDimensions>;

/** Gets the value of a property of an element. */
getPropertyValue(name: string): Promise<any>;
}
14 changes: 6 additions & 8 deletions src/cdk-experimental/testing/testbed/unit-test-element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,14 +120,7 @@ export class UnitTestElement implements TestElement {

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

async hasClass(name: string): Promise<boolean> {
Expand All @@ -139,4 +132,9 @@ export class UnitTestElement implements TestElement {
await this._stabilize();
return this.element.getBoundingClientRect();
}

async getPropertyValue(name: string): Promise<any> {
await this._stabilize();
return (this.element as any)[name];
}
}
14 changes: 10 additions & 4 deletions src/cdk-experimental/testing/tests/protractor.e2e.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,10 +179,10 @@ describe('ProtractorHarnessEnvironment', () => {
it('should be able to clear', async () => {
const input = await harness.input();
await input.sendKeys('Yi');
expect(await input.getAttribute('value')).toBe('Yi');
expect(await input.getPropertyValue('value')).toBe('Yi');

await input.clear();
expect(await input.getAttribute('value')).toBe('');
expect(await input.getPropertyValue('value')).toBe('');
});

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

expect(await input.getAttribute('value')).toBe('Yi');
expect(await input.getPropertyValue('value')).toBe('Yi');
expect(await value.text()).toBe('Input: Yi');
});

Expand Down Expand Up @@ -236,7 +236,7 @@ describe('ProtractorHarnessEnvironment', () => {
`;
const memo = await harness.memo();
await memo.sendKeys(memoStr);
expect(await memo.getAttribute('value')).toBe(memoStr);
expect(await memo.getPropertyValue('value')).toBe(memoStr);
});

it('should be able to getCssValue', async () => {
Expand All @@ -254,6 +254,12 @@ describe('ProtractorHarnessEnvironment', () => {
expect(await (await browser.switchTo().activeElement()).getText())
.not.toBe(await button.text());
});

it('should be able to get the value of a property', async () => {
const input = await harness.input();
await input.sendKeys('Hello');
expect(await input.getPropertyValue('value')).toBe('Hello');
});
});

describe('HarnessPredicate', () => {
Expand Down
14 changes: 10 additions & 4 deletions src/cdk-experimental/testing/tests/testbed.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,10 +199,10 @@ describe('TestbedHarnessEnvironment', () => {
it('should be able to clear', async () => {
const input = await harness.input();
await input.sendKeys('Yi');
expect(await input.getAttribute('value')).toBe('Yi');
expect(await input.getPropertyValue('value')).toBe('Yi');

await input.clear();
expect(await input.getAttribute('value')).toBe('');
expect(await input.getPropertyValue('value')).toBe('');
});

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

expect(await input.getAttribute('value')).toBe('Yi');
expect(await input.getPropertyValue('value')).toBe('Yi');
expect(await value.text()).toBe('Input: Yi');
});

Expand Down Expand Up @@ -255,7 +255,7 @@ describe('TestbedHarnessEnvironment', () => {
`;
const memo = await harness.memo();
await memo.sendKeys(memoStr);
expect(await memo.getAttribute('value')).toBe(memoStr);
expect(await memo.getPropertyValue('value')).toBe(memoStr);
});

it('should be able to getCssValue', async () => {
Expand All @@ -271,6 +271,12 @@ describe('TestbedHarnessEnvironment', () => {
await button.blur();
expect(activeElementText()).not.toBe(await button.text());
});

it('should be able to get the value of a property', async () => {
const input = await harness.input();
await input.sendKeys('Hello');
expect(await input.getPropertyValue('value')).toBe('Hello');
});
});

describe('HarnessPredicate', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export class MatCheckboxHarness extends ComponentHarness {

/** Gets a boolean promise indicating if the checkbox is checked. */
async isChecked(): Promise<boolean> {
const checked = (await this._input()).getAttribute('checked');
const checked = (await this._input()).getPropertyValue('checked');
return coerceBooleanProperty(await checked);
}

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

/** Gets a boolean promise indicating if the checkbox is required. */
async isRequired(): Promise<boolean> {
const required = (await this._input()).getAttribute('required');
const required = (await this._input()).getPropertyValue('required');
return coerceBooleanProperty(await required);
}

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

/** Gets a promise for the checkbox's value. */
async getValue(): Promise<string|null> {
return (await this._input()).getAttribute('value');
return (await this._input()).getPropertyValue('value');
}

/** Gets a promise for the checkbox's aria-label. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export class MatCheckboxHarness extends ComponentHarness {

/** Gets a boolean promise indicating if the checkbox is checked. */
async isChecked(): Promise<boolean> {
const checked = (await this._input()).getAttribute('checked');
const checked = (await this._input()).getPropertyValue('checked');
return coerceBooleanProperty(await checked);
}

Expand Down Expand Up @@ -76,7 +76,7 @@ export class MatCheckboxHarness extends ComponentHarness {

/** Gets a promise for the checkbox's value. */
async getValue(): Promise<string|null> {
return (await this._input()).getAttribute('value');
return (await this._input()).getPropertyValue('value');
}

/** Gets a promise for the checkbox's aria-label. */
Expand Down
4 changes: 2 additions & 2 deletions src/material-experimental/mdc-radio/harness/radio-harness.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ export class MatRadioButtonHarness extends ComponentHarness {

/** Whether the radio-button is checked. */
async isChecked(): Promise<boolean> {
const checked = (await this._input()).getAttribute('checked');
const checked = (await this._input()).getPropertyValue('checked');
return coerceBooleanProperty(await checked);
}

Expand Down Expand Up @@ -208,7 +208,7 @@ export class MatRadioButtonHarness extends ComponentHarness {
* intentionally have the `[object Object]` as return value.
*/
async getValue(): Promise<string|null> {
return (await this._input()).getAttribute('value');
return (await this._input()).getPropertyValue('value');
}

/** Gets a promise for the radio-button's label text. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export class MatSlideToggleHarness extends ComponentHarness {

/** Gets a boolean promise indicating if the slide-toggle is checked. */
async isChecked(): Promise<boolean> {
const checked = (await this._input()).getAttribute('checked');
const checked = (await this._input()).getPropertyValue('checked');
return coerceBooleanProperty(await checked);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export class MatSlideToggleHarness extends ComponentHarness {

/** Gets a boolean promise indicating if the slide-toggle is checked. */
async isChecked(): Promise<boolean> {
const checked = (await this._input()).getAttribute('checked');
const checked = (await this._input()).getPropertyValue('checked');
return coerceBooleanProperty(await checked);
}

Expand Down

0 comments on commit 8dd52a8

Please sign in to comment.