Skip to content
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

E2E: refactor Support specs into one flow. #76960

Merged
merged 10 commits into from
May 17, 2023

Conversation

worldomonation
Copy link
Contributor

@worldomonation worldomonation commented May 16, 2023

Fixes #76916.

Proposed Changes

This PR is a semi-major refactor of how we think about Support related E2E specs. These specs were a near carbon copy of the ones that existed back in the Selenium framework days (prior to 2021).

Now that we have the ability to execute component testing with `react-testing-library, most of what's covered in the specs (even in revised form) should be tested at the component level.

However, to address the issue of permanent failure in #76916, I've decided to restructure the specs as a temporary bridge until they are moved into the component testing level.

Key changes:

  • merge all scenarios (invalid, valid) into one.
  • discontinue testing the support card present in /home.
  • discontinue parametrization of the overall suite, instead using the environment variables to run on the targeted environment.

Testing Instructions

Ensure the following build configurations are passing:

  • Calypso E2E (desktop)
  • Calypso E2E (mobile)
  • Pre-Release E2E

Pre-merge Checklist

  • Has the general commit checklist been followed? (PCYsg-hS-p2)
  • Have you written new tests for your changes?
  • Have you tested the feature in Simple (P9HQHe-k8-p2), Atomic (P9HQHe-jW-p2), and self-hosted Jetpack sites (PCYsg-g6b-p2)?
  • Have you checked for TypeScript, React or other console errors?
  • Have you used memoizing on expensive computations? More info in Memoizing with create-selector and Using memoizing selectors and Our Approach to Data
  • Have we added the "[Status] String Freeze" label as soon as any new strings were ready for translation (p4TIVU-5Jq-p2)?
  • For changes affecting Jetpack: Have we added the "[Status] Needs Privacy Updates" label if this pull request changes what data or activity we track or use (p4TIVU-ajp-p2)?

@github-actions
Copy link

github-actions bot commented May 16, 2023

@worldomonation worldomonation changed the title E2E: E2E: refactor Support specs into one flow. May 16, 2023
@worldomonation worldomonation self-assigned this May 16, 2023
@matticbot
Copy link
Contributor

This PR does not affect the size of JS and CSS bundles shipped to the user's browser.

Generated by performance advisor bot at iscalypsofastyet.com.

@worldomonation worldomonation marked this pull request as ready for review May 16, 2023 03:56
@worldomonation worldomonation requested a review from a team as a code owner May 16, 2023 03:56
@matticbot matticbot added the [Status] Needs Review The PR is ready for review. This also triggers e2e canary tests and wp-desktop tests automatically. label May 16, 2023
this.page.waitForSelector( selectors.resultsPlaceholderHelpCenter, { state: 'hidden' } ),
this.page.waitForSelector( selectors.resultsPlaceholder, { state: 'hidden' } ),
] );
this.root = this.page.getByLabel( 'Help Center' );
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a technique/style I learned from working on the Gutenberg Playwright migration, specifically this comment.

The idea is that, when using role-based selectors (as recommended by Playwright now), we trade legibility for some ambiguity in the locator structure. For instance, the following locator is easy to read and understand, but there is potential to match on multiple elements on a page.

page.getByRole('button', { name: 'home' });

By always selecting from a parent/root locator it is possible to understand the overall structure hierarchy.

Note: if I was following the Gutenberg code style, this would probably be named something like this.helpCenterinstead of this.root.

Comment on lines 44 to 45
expect( articles ).toBeTruthy();
expect( links ).toBeTruthy();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change in assertion is also from my experience with Gutenberg Playwright migration. In working on the PR, one thing that was repeated over the course of the PR is to not structure tests around implementation details.

In the case of Support testing, my thoughts are that the following constitute implementation detail:

  • how the results are presented;
  • the order in which the results are presented.

Additionally, we cannot control:

  • names of the returned resources;
  • how many results are returned.

Throw on top of this the fact that the reworked Support popover does not have a true "empty results" state anymore and it becomes apparent the existing component is no longer fit for purpose.

By removing the assertion for default state is shown or empty results are shown and instead testing that the query returned some sort of results for the expected categories, implementation detail testing is removed as much as possible.

Copy link
Member

@WunderBart WunderBart May 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case, I'd go for the isGreaterThan( 0 ) matcher instead of toBeTruthy(). The reason for that is that articles or links could be an array as well, and expect( [] ).toBeTruthy() would return true. Being a little bit more explicit here could potentially guard us against some false negatives in the future.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason for that is that articles or links could be an array as well, and expect( [] ).toBeTruthy() would return true.

Great point and something I have yet to come to grips with despite a couple of years of working in JS/TS ecosystem.

Assertions changed in 23ed24e76e93e4ec1b0598cbedc0e6ad2f89f4dd, but may change again if the loop stress test fails.

Copy link
Contributor Author

@worldomonation worldomonation May 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This spec has been removed because of a couple of reasons:

  • the support card present in /home serves up an older version of the inline help.
  • usage for the support card in /home is lower than the popover help.

For the second point, I compared the Tracks events for the two different Supports that are in production.

  • calypso_inlinehelp_show (new Support)
  • calypso_inlinehelp_article_open (legacy Support)

For the legacy Support, the calypso_inlinehelp_article_open stands in for the number of times a user interacts with the card and opens a link. It is not the perfect approximation, but there is no Tracks event exclusively for the user interacting with the card.

For a 7-day trailing period as of today, the popover has ~66k interactions while the card has just under half at ~31k interactions. So while not trivial, the card variant sees significantly fewer interactions.

@worldomonation worldomonation requested a review from a team May 16, 2023 06:16
@worldomonation
Copy link
Contributor Author

worldomonation commented May 16, 2023

Looks like the current solution failed in a loop at 69 (nice) iterations.

image

Copy link
Member

@WunderBart WunderBart left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a few non-blocking comments. Thanks! 🚀

Comment on lines 40 to 43
await Promise.all( [
// Waits for all placeholder CSS elements to be removed from the DOM.
this.waitForQueryComplete(),
this.page.waitForSelector( selectors.supportPopoverButton() ),
this.page.click( selectors.supportPopoverButton() ),
] );
Copy link
Member

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 understand this chain - why do we need to wait for the same selector we're about to click here? I think it's what internally happens with click() - before it clicks, it waits for the given selector to be clickable, so the click itself should be sufficient.

Copy link
Contributor Author

@worldomonation worldomonation May 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this was a mistake on my part. Can't think of reasons to explain this, all I can maybe come up with is that I mistyped a selector and forgot about it.

Edit: it looks like this was in place in the original file. Even more of a head scratcher.

Comment on lines 44 to 45
expect( articles ).toBeTruthy();
expect( links ).toBeTruthy();
Copy link
Member

@WunderBart WunderBart May 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case, I'd go for the isGreaterThan( 0 ) matcher instead of toBeTruthy(). The reason for that is that articles or links could be an array as well, and expect( [] ).toBeTruthy() would return true. Being a little bit more explicit here could potentially guard us against some false negatives in the future.

major refactor
- use locators and role-based locators where possible
- replace single-purpose methods with multi-purpose methods
test/e2e/specs/support/support__home.ts
- discontinue.

test/e2e/specs/support/support__showme-where.ts
- refactor to use the popover.

test/e2e/specs/support/support__popover-invalid.ts
- merge into one.

test/e2e/specs/support/support__popover-valid.ts
- merge into one.

test/e2e/specs/support/support__popover.ts
- merged spec that runs the "invalid" and "valid" choices.
- discontinue parametrization.
- rename step

packages/calypso-e2e/src/lib/components/support-component.ts
- add wait for the placeholder to disappear
- replace `this.root` with `this.helpCenter`.
- return named values instead of array of values
- add comment for the URL being matched.

test/e2e/specs/support/support__popover.ts
- change how the values being returned are referenced.
- change the assertions to check `greaterthan` and `tobe`.

test/e2e/specs/support/support__showme-where.ts
- add URL example
- wait for the results to populate first
this.page.waitForSelector( selectors.resultsPlaceholderHelpCenter, { state: 'hidden' } ),
this.page.waitForSelector( selectors.resultsPlaceholder, { state: 'hidden' } ),
] );
this.helpCenter = this.page.locator( '.components-card__body > .inline-help__search' );
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed: locator now points to the results field (in red) not the entire Inline Help modal.

This is because there is no selector to select the entire modal that is visible.

Screenshot 2023-05-17 at 3 48 52 PM

@worldomonation worldomonation merged commit aa68334 into trunk May 17, 2023
@worldomonation worldomonation deleted the fix/e2e-support-spec-76916 branch May 17, 2023 07:54
@github-actions github-actions bot removed the [Status] Needs Review The PR is ready for review. This also triggers e2e canary tests and wp-desktop tests automatically. label May 17, 2023
@worldomonation
Copy link
Contributor Author

The new solution wasn't perfect (failed at 94 iterations) but it was much better than the previous ones I had come up with, plus I didn't want to block #76734.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

Flaky E2E: Enter empty search keyword and expect no results to be shown
3 participants