Skip to content

Commit

Permalink
fix(runtime): support watch for components with custom tag names (#5767)
Browse files Browse the repository at this point in the history
* fix(runtime): support watch for components with custom tag names

* add unit test

* Update src/runtime/initialize-component.ts

Co-authored-by: Alice Pote <alice.writes.wrongs@gmail.com>

---------

Co-authored-by: Alice Pote <alice.writes.wrongs@gmail.com>
  • Loading branch information
christian-bromann and alicewriteswrongs committed May 15, 2024
1 parent 3538d06 commit f561e0f
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 2 deletions.
16 changes: 15 additions & 1 deletion src/runtime/initialize-component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,24 @@ export const initializeComponent = async (
// sync constructor component
Cstr = elm.constructor as any;

/**
* Instead of using e.g. `cmpMeta.$tagName$` we use `elm.localName` to get the tag name of the component.
* This is because we can't guarantee that the component class is actually registered with the tag name
* defined in the component class as users can very well also do this:
*
* ```html
* <script type="module">
* import { MyComponent } from 'my-stencil-component-library';
* customElements.define('my-other-component', MyComponent);
* </script>
* ```
*/
const cmpTag = elm.localName;

// wait for the CustomElementRegistry to mark the component as ready before setting `isWatchReady`. Otherwise,
// watchers may fire prematurely if `customElements.get()`/`customElements.whenDefined()` resolves _before_
// Stencil has completed instantiating the component.
customElements.whenDefined(cmpMeta.$tagName$).then(() => (hostRef.$flags$ |= HOST_FLAGS.isWatchReady));
customElements.whenDefined(cmpTag).then(() => (hostRef.$flags$ |= HOST_FLAGS.isWatchReady));
}

if (BUILD.style && Cstr && Cstr.style) {
Expand Down
3 changes: 2 additions & 1 deletion test/wdio/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ const testRequiresManualSetup =
window.__wdioSpec__.includes('custom-elements-output-tag-class-different') ||
window.__wdioSpec__.includes('custom-elements-delegates-focus') ||
window.__wdioSpec__.includes('custom-elements-output') ||
window.__wdioSpec__.includes('global-script');
window.__wdioSpec__.includes('global-script') ||
window.__wdioSpec__.endsWith('custom-tag-name.test.tsx');

/**
* setup all components defined in tests except for those where we want ot manually setup
Expand Down
25 changes: 25 additions & 0 deletions test/wdio/watch-native-attributes/custom-tag-name.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { h } from '@stencil/core';
import { render } from '@wdio/browser-runner/stencil';

import { WatchNativeAttributes } from '../test-components/watch-native-attributes.js';

describe('watch native attributes', () => {
beforeEach(() => {
customElements.define('some-custom-element', WatchNativeAttributes);
render({
template: () => <some-custom-element aria-label="myStartingLabel"></some-custom-element>,
});
});

it('triggers the callback for the watched attribute', async () => {
const $cmp = $('some-custom-element');
await $cmp.waitForExist();

await expect($cmp).toHaveText('Label: myStartingLabel\nCallback triggered: false');

const cmp = document.querySelector('some-custom-element');
cmp.setAttribute('aria-label', 'myNewLabel');

await expect($cmp).toHaveText('Label: myNewLabel\nCallback triggered: true');
});
});

0 comments on commit f561e0f

Please sign in to comment.