Skip to content

feat(#10675): add e2e tests for UI Extensions (#10762)#11105

Open
jkuester wants to merge 9 commits into
medic:10224-ui-extensionsfrom
jkuester:10675-e2e
Open

feat(#10675): add e2e tests for UI Extensions (#10762)#11105
jkuester wants to merge 9 commits into
medic:10224-ui-extensionsfrom
jkuester:10675-e2e

Conversation

@jkuester
Copy link
Copy Markdown
Contributor

@jkuester jkuester commented May 22, 2026

Description

Closes #10675

The main goal of this PR was to add e2e tests. I ended up needing to fix a few more bugs along the way:

  • The app was not properly refreshing for online users when a UI Extension's .js file was modified:
    • I updated the changes feed watcher in app.component.ts to include UI Extension files (since these are not included in the service worker).
  • Changes to online-only extension properties were not being reflected in the app for Online users (even after reloading the app):
    • I updated the generate-service-worker.js code in api to include the properties for all extensions (even the online-only ones) in the hash value for the service worker. I think since the /ui-extensions endpoint was registered with the service worker glob, the browser was automatically caching the first response from that endpoint even for online users and was not busting the cache on changes to online-only extensions because the service-worker hash was never changing.
  • Loading resources in an extension (via the new getResource function) was failing for online users when refreshing the page because the extension loaded before the resource cache was warm.
    • I exposed an init method on the CustomResourceService so the CHTDatasourceService can wait for the cache to be warm.
  • Errors thrown from within the custom web component were not being captured in a feedback doc.
    • I updated the ui-extensions-tab.component.ts to listen for these errors and set them in the console.error when they come.

AI disclosure

I worked a lot with Claude on this, going back and forth on the different issues, etc. I have carefully pulled apart all of the code and confirmed it works as expected and does exactly what we want. Everything that is left here has either been heavily modified or reviewed by me.

Code review checklist

  • UI/UX backwards compatible: Test it works for the new design (enabled by default). And test it works in the old design, enable can_view_old_navigation permission to see the old design. Test it has appropriate design for RTL languages.
  • Readable: Concise, well named, follows the style guide
  • Documented: Configuration and user documentation on cht-docs
  • Tested: Unit and/or e2e where appropriate
  • Backwards compatible: Works with existing data and configuration or includes a migration. Any breaking changes documented in the release notes.
  • AI disclosure: Please disclose use of AI per the guidelines.

License

The software is provided under AGPL-3.0. Contributions to this project are accepted under the same license.

@jkuester jkuester changed the base branch from master to 10224-ui-extensions May 22, 2026 15:11
Comment thread webapp/src/ts/modules/ui-extensions/ui-extensions-tab.component.ts Dismissed
@jkuester jkuester requested a review from dianabarsan May 22, 2026 19:28
@jkuester
Copy link
Copy Markdown
Contributor Author

@dianabarsan this is the final PR for UI extensions before we are ready to go do master! 🎉

I am planning to send you the PR for master too once this gets merged. I wanted you to have a chance to look at the bug fixes here on their own, but if you would rather just see everything all at once, approve this PR and I will open the big one. 👍

Thank you! 🙏

@jkuester jkuester marked this pull request as ready for review May 22, 2026 19:31
Copy link
Copy Markdown
Member

@dianabarsan dianabarsan left a comment

Choose a reason for hiding this comment

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

Very lovely. Minor nits inline.

private registerErrorListener(extensionId: string) {
this.errorListener = (event: ErrorEvent | PromiseRejectionEvent) => {
const error = event instanceof PromiseRejectionEvent ? event.reason : event.error ?? event.message;
console.error(`Error in UI extension: "${extensionId}"`, error);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is it possible that another thing, other than Angular and the UI extension, triggers an error here? It yes, it will get logged and attributed to the ui extension, which could be misleading.

expect(await customElement.getText()).to.equal('Hello world');

const telemetries = await getTelemetry(`ui-extension:header-tab:render`, user.username);
expect(telemetries).to.have.lengthOf(2);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can you please add assertions about what the telemetries contain? Or at least a comment about why the header-tab has 2 and the sidebar-menu has 1.

const utils = require('@utils');
const commonPage = require('@page-objects/default/common/common.wdio.page');
const loginPage = require('@page-objects/default/login/login.wdio.page');
const { hamburguerMenuItemByOption, closeReloadModal } = require('@page-objects/default/common/common.wdio.page');
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

hamburguers are yummy :D :D but nothing to a hamburger

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants