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');
+ });
+});