-
Notifications
You must be signed in to change notification settings - Fork 77
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
test(common): add prop theme utility for E2E #9027
test(common): add prop theme utility for E2E #9027
Conversation
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.
Looking good! 😎
* Helper to test custom theming of a component's associated tokens. | ||
* | ||
* @example | ||
* describe("default", () => { |
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 the default
name intentional? All other utils use a name closer to the test subject.
{ | ||
selector: string; | ||
shadowSelector?: string; | ||
targetProp: 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.
Can you type this as keyof CSSStyleDeclaration
?
): void { | ||
it("is theme-able", async () => { | ||
const page = await simplePageSetup(componentTagOrHTML); | ||
const expectChecklist: Record< |
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.
Can we add explicit types for these objects?
} | ||
>, | ||
): void { | ||
it("is theme-able", async () => { |
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 this be themeable?
targetProps[token] = [targetProp, themedTokenValue, state]; | ||
} | ||
|
||
// let all page.find calls resolve |
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 isn't quite accurate, find
does not rely on waitForChanges
.
await page.mouse.down(); | ||
} | ||
if (stateName === "focus") { | ||
await page.mouse.up(); |
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 this also call mouse.down
or does this depend on press
being specified before? If it's the latter, it might be prone to being missed.
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.
thanks for the catch
for (const [targetProp, themedTokenValue, state] of props) { | ||
if (state) { | ||
if (typeof state === "string") { | ||
await target[state](); |
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.
Can we use a type to hint at which E2EElement
methods are used here?
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.
refactored this so it's simplified and more clear
* | ||
* @param page - the e2e page | ||
* @param target - the element to get the computed style from | ||
* @param selector - the selector of the target element |
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.
selector
can be removed as there is no matching prop in the function signature.
export async function assertThemedProps( | ||
page: E2EPage, | ||
target: E2EElement, | ||
props: [string, string, string | Record<string, { attribute: string; value: string }> | undefined][], |
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 the type accurate? I'm not sure I spot where the 3rd item (Record<string, { attribute: string; value: string }>
is provided in themed
. The doc mentions a second value, but there isn't a mention of the third one.
On a related note, can we use an object vs a tuple? It's not clear from the type itself what the tuple contains. Alternatively, props
could be renamed to make this clearer. It's slightly misleading as it has both the prop and value.
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.
yeah this was silly. Refactored to be much more simple and clear.
for (let i = 0; i < shadowSelectors.length; i++) { | ||
const s = shadowSelectors[i]; | ||
|
||
if (i === 0) { |
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 not sure I follow this. Could you shed some light on how this works?
Also, has custom deep piercing been working smoothly? I recall this wasn't working before due to a Stencil bug that was recently fixed.
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 uses the Stencil bug work around that you posted. It does expect a certain pattern to the shadowSelector but it does work.
[shadowSelector] [wrapper-class] [sub-element] >>> [wrapper-class] [sub-element] >>> [shadowSelector]
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.
Approving to get component E2E testing moving along. Any updates to the helper shouldn't impact the rest (famous last words 🌻💀🌻).
for (const token in tokens) { | ||
let selectors = tokens[token]; | ||
|
||
if (!isArray(selectors)) { |
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.
Can you use Array.isArray
instead of adding a custom function for this?
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.
no. The custom type guard is required. See microsoft/TypeScript#19892
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.
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.
That doesn't work for me. It says it doesn't know if it's a string or an array.
* @param options.state - the state to apply to the target element | ||
* @param options.expectedValue - the expected value of the targetProp | ||
*/ | ||
export async function assertThemedProps(page: E2EPage, options: TestTarget): 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.
Does this need to be exported?
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.
why wouldn't we export it? It might be useful in other contexts and costs us nothing to export.
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.
It's not used at the moment and bypasses the current way we're recommending component tokens to be tested via themed
.
* @param token - the token as a CSS variable | ||
* @returns string - the new value for the token | ||
*/ | ||
export function assignTestTokenThemeValues(token: string): 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.
Can we move this into commonTests
? #9056 should help split up helpers by test topic.
Related Issue: #7180
Summary
Our chromium tests do a good job of ensuring the component token updates to styles do not break the existing UI but custom style application of tokens should be considered a data change, not a style change and therefor should be tested with Unit tests. These E2E tests are faster, less resource heavy, and less prone to human error.
However, E2E token tests are harder to set up. To facilitate ease-of-use for other developers this PR introduces a new commonTest utility called themed. This utility expects a calcite-component followed by an object of component token names as keys and each value being an object with a selector, shadowSelector, targetProp, and optional state. The state key will accept a string or an object for more selector specificity which is required when testing a "press"/"active" state.