diff --git a/src/runtime/initialize-component.ts b/src/runtime/initialize-component.ts index 12be231ad7c..9a8da6d0700 100644 --- a/src/runtime/initialize-component.ts +++ b/src/runtime/initialize-component.ts @@ -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 + * + * ``` + */ + 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) { diff --git a/test/wdio/setup.ts b/test/wdio/setup.ts index be3ab6eaa14..3a412b862d3 100644 --- a/test/wdio/setup.ts +++ b/test/wdio/setup.ts @@ -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 diff --git a/test/wdio/watch-native-attributes/custom-tag-name.test.tsx b/test/wdio/watch-native-attributes/custom-tag-name.test.tsx new file mode 100644 index 00000000000..b7473443d47 --- /dev/null +++ b/test/wdio/watch-native-attributes/custom-tag-name.test.tsx @@ -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: () => , + }); + }); + + 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'); + }); +});