-
Notifications
You must be signed in to change notification settings - Fork 6.8k
feat(cdk-experimental/testing): Bring in component harness #16089
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
* Search all matched test elements under current root by css selector. | ||
* @param css Selector of the test elements. | ||
*/ | ||
findAll(css: string): Promise<TestElement[]>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we call these querySelector
and querySelectorAll
since it's what people are familiar with?
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed the Locator
methods to querySelector
/querySelectorAll
, it is a little bit different though because it returns a Promise
. The methods of the same name on ComponentHarness
are even more different because they return () => Promise
. I've left them as find
/findAll
for now, but open to renaming those as well
src/cdk-experimental/testing/test-app/harnesses/main-component-harness.ts
Outdated
Show resolved
Hide resolved
return toPromise<string>(this.element.getCssValue(property)); | ||
} | ||
|
||
async hover(): Promise<void> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How would we handle this if the consumer was running the test against a touch screen device?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it would be an issue necessarily. Protractor must have some way to handle mouseMove
on touch devices already, even if its to just do nothing. It would make sense to add a tap
action as well. I can do that in a follow-up PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAIK Protractor simulates real user input at the OS level so I'm not sure how it work. My main concern with hover
was for unit tests and it should be a bit easier to simulate it there though.
await this._stabilize(); | ||
} | ||
|
||
async getCssValue(property: string): Promise<string> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could be flaky between browsers, because some of the normalize things like color values. IIRC Edge or IE return all colors in RGBA, regardless of the format the color was set in.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we can add normalization logic here as we encounter things that need it. In the mean time, the harness author can always normalize on their end if needed.
Also what do you think about the name of this method? Should I change it to getComputedStyle
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't feel strongly about the name. We could call it getPropertyValue
which corresponds to the method on the CSSStyleDeclaration
that gets returned from getComputedStyle
.
this.element instanceof HTMLTextAreaElement)) { | ||
throw new Error('Attempting to clear an invalid element'); | ||
} | ||
this.element.focus(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moving focus here might a bit risky since it's not what would necessarily happen to a real user. E.g. an input "clear" button won't move focus into the input.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is that true? in Chrome with an <input type="search">
pressing the button also focuses.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I meant if it's a custom clear button, rather than the native browser one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, in that case the particular component that implements the clear button can choose to expose a clear
method in its harness API that clicks the custom button instead. This class is meant to be an implementation of the interface harness authors use to write their harnesses.
await this._stabilize(); | ||
(this.element as HTMLElement).focus(); | ||
const e = this.element as HTMLInputElement; | ||
for (const key of keys) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this logic come from somewhere? It would be good to reference back to it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not that I'm aware of, but Yi is the original author
f97a374
to
2e31b2d
Compare
0a679f2
to
0914d84
Compare
Co-Authored-By: Yi Qi <qiyi@google.com> Co-Authored-By: Rado Kirov <radokirov@google.com> Co-Authored-By: Thomas Shafer <tshafer@google.com> Co-Authored-By: Caitlin Mott <caitlinmott@google.com> Co-Authored-By: Craig Nishina <cnishina@google.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left a couple of nits, but aside from those it LGTM.
* Search all matched test elements under current root by CSS selector. | ||
* @param selector The CSS selector of the test elements. | ||
*/ | ||
querySelectorAll(selector: string): Promise<TestElement[]>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should querySelectorAll
accept options
as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm planning to address this when I make some API changes in the next PR. I think this is currently implemented like this because allowNull
doesn't really make sense for querySelectorAll
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, I'm good iterating on API/naming in follow-up PRs
Co-Authored-By: Yi Qi <qiyi@google.com> Co-Authored-By: Rado Kirov <radokirov@google.com> Co-Authored-By: Thomas Shafer <tshafer@google.com> Co-Authored-By: Caitlin Mott <caitlinmott@google.com> Co-Authored-By: Craig Nishina <cnishina@google.com>
…16089) Co-Authored-By: Yi Qi <qiyi@google.com> Co-Authored-By: Rado Kirov <radokirov@google.com> Co-Authored-By: Thomas Shafer <tshafer@google.com> Co-Authored-By: Caitlin Mott <caitlinmott@google.com> Co-Authored-By: Craig Nishina <cnishina@google.com>
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
This is the initial PR bringing in the the
ComponentHarness
from google3. Huge thanks to @qiyigg and @vikerman for getting this started, and to all who contributed to the code in google3.Main files
cdk-experimental/testing/component-harness.ts
contains classes and interfaces that define the test-environment-independent component harnessComponentHarness
the base class for all harnessesTestElement
an interface used by theComponentHarness
to interface with the DOMLocator
an interface used by theComponentHarness
to findTestElement
scdk-experimental/testing/testbed.ts
contains implementation specific to Angular'sTestBed
TestBed
compatible implementations ofTestElement
andLocator
load
method used to create instances ofComponentHarness
that are compatible withTestBed
@angular/core/testing
cdk-experimental/testing/protractor.ts
contains implementation specific to Protractor.TestElement
andLocator
load
method used to create instances ofComponentHarness
that are compatible withTestBed
protractor
andselenium-webdriver
cdk-experimental/testing/tests/*
contains tests for the component harness framework, including definitions for a couple simple components and corresponding harnesses to be used in the testsFuture work
focs
/blur
fakeAsync
testsload
)TestElement
(e.g.tap
)allowNull
behavior seems confusing, consider revising it