From 775785b5f7913ae07eb2be205f3a1b7f8884671a Mon Sep 17 00:00:00 2001 From: Andrew Beng Date: Thu, 20 Feb 2025 14:49:57 +0100 Subject: [PATCH 1/4] fix(vue): shift event listener logic from directive to onMounted --- packages/vue/src/runtime.ts | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/packages/vue/src/runtime.ts b/packages/vue/src/runtime.ts index 93b7085b..0c340d38 100644 --- a/packages/vue/src/runtime.ts +++ b/packages/vue/src/runtime.ts @@ -1,4 +1,4 @@ -import { defineComponent, getCurrentInstance, h, inject, ref, Ref, withDirectives } from 'vue'; +import { defineComponent, getCurrentInstance, h, inject, onMounted, ref, Ref, withDirectives } from 'vue'; export { defineStencilSSRComponent } from './ssr'; export interface InputProps { @@ -81,6 +81,18 @@ export const defineContainer = ( const containerRef = ref(); const classes = new Set(getComponentClasses(attrs.class)); + onMounted(() => { + /** + * we register the event emmiter for @Event definitions + * so we can use @event + */ + emitProps.forEach((eventName: string) => { + containerRef.value!.addEventListener(eventName, (e: Event) => { + emit(eventName, e); + }); + }); + }); + /** * This directive is responsible for updating any reactive * reference associated with v-model on the component. @@ -109,16 +121,6 @@ export const defineContainer = ( } }); }); - - /** - * we register the event emmiter for @Event definitions - * so we can use @event - */ - emitProps.forEach((eventName: string) => { - el.addEventListener(eventName, (e: Event) => { - emit(eventName, e); - }); - }); }, }; From f7c887fbb3e2b8e6a1fbb5302f06dc31638741ec Mon Sep 17 00:00:00 2001 From: Andrew Beng Date: Thu, 20 Feb 2025 14:54:17 +0100 Subject: [PATCH 2/4] fix(vue): remove lower case event naming --- packages/vue/src/runtime.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/vue/src/runtime.ts b/packages/vue/src/runtime.ts index 0c340d38..1692120c 100644 --- a/packages/vue/src/runtime.ts +++ b/packages/vue/src/runtime.ts @@ -107,7 +107,7 @@ export const defineContainer = ( created: (el: HTMLElement) => { const eventsNames = Array.isArray(modelUpdateEvent) ? modelUpdateEvent : [modelUpdateEvent]; eventsNames.forEach((eventName: string) => { - el.addEventListener(eventName.toLowerCase(), (e: Event) => { + el.addEventListener(eventName, (e: Event) => { /** * Only update the v-model binding if the event's target is the element we are * listening on. For example, Component A could emit ionChange, but it could also From c866328c811e53cf8f7e90cb187264382e3a017f Mon Sep 17 00:00:00 2001 From: Andrew Beng Date: Thu, 20 Feb 2025 14:55:57 +0100 Subject: [PATCH 3/4] tests(vue): for custom event handler and v-model directive --- example-project/vue-app/src/App.vue | 9 +++++++ .../vue-app/src/components/Input.vue | 24 ++++--------------- example-project/vue-app/tests/test.e2e.ts | 12 ++++++---- 3 files changed, 21 insertions(+), 24 deletions(-) diff --git a/example-project/vue-app/src/App.vue b/example-project/vue-app/src/App.vue index 548391f2..0f6bead6 100644 --- a/example-project/vue-app/src/App.vue +++ b/example-project/vue-app/src/App.vue @@ -2,6 +2,13 @@ import HelloWorld from './components/HelloWorld.vue' // @ts-ignore import Input from './components/Input.vue' +import { MyComponent } from 'component-library-vue' +import { ref } from 'vue' + +const isClicked = ref(false) +const handleCustomEvent = () => { + isClicked.value = true +} diff --git a/example-project/vue-app/src/components/Input.vue b/example-project/vue-app/src/components/Input.vue index 3a88e54a..a601bd4a 100644 --- a/example-project/vue-app/src/components/Input.vue +++ b/example-project/vue-app/src/components/Input.vue @@ -8,24 +8,10 @@ export default defineComponent({ MyInput, }, setup() { - const inputEvent = ref(''); - const changeEvent = ref(''); - - const handleInput = (ev) => { - console.log('handleInput', ev.target.value); - inputEvent.value = ev.target.value; - }; - - const handleChange = (ev) => { - console.log('handleChange', ev.target.value); - changeEvent.value = ev.detail.value; - }; + const inputValue = ref(''); return { - inputEvent, - changeEvent, - handleInput, - handleChange, + inputValue, }; }, }); @@ -40,13 +26,11 @@ export default defineComponent({ diff --git a/example-project/vue-app/tests/test.e2e.ts b/example-project/vue-app/tests/test.e2e.ts index 2bd001e7..1aaabfbd 100644 --- a/example-project/vue-app/tests/test.e2e.ts +++ b/example-project/vue-app/tests/test.e2e.ts @@ -7,9 +7,13 @@ describe('Stencil Vue Integration', () => { it('should allow to interact with input element', async () => { await $('my-input').$('input').setValue('Hello World'); - await expect(await $$('.inputResult p').map((p) => p.getText())).toEqual([ - 'Input Event: Hello World', - 'Change Event: Hello World' - ]); + await expect(await $('.inputResult p').getText()).toEqual( + 'Input Value: Hello World', + ); + }); + + it('should listen to custom events', async () => { + await $('my-component').$('div').click(); + await expect(await $('[data-testid="mycomponent-click"]').getText()).toEqual('MyComponent was clicked'); }); }); From 0442b87eb2d97c97c1dce24e449baffae9bccd61 Mon Sep 17 00:00:00 2001 From: Andrew Beng Date: Thu, 20 Feb 2025 16:01:50 +0100 Subject: [PATCH 4/4] test(vue): include coverage for custom event handler for input component --- example-project/vue-app/src/components/Input.vue | 12 +++++++++++- example-project/vue-app/tests/test.e2e.ts | 7 ++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/example-project/vue-app/src/components/Input.vue b/example-project/vue-app/src/components/Input.vue index a601bd4a..3b12afd4 100644 --- a/example-project/vue-app/src/components/Input.vue +++ b/example-project/vue-app/src/components/Input.vue @@ -9,9 +9,17 @@ export default defineComponent({ }, setup() { const inputValue = ref(''); + const changeEvent = ref(''); + + const handleChange = (ev) => { + console.log('handleChange', ev.target.value); + changeEvent.value = ev.detail.value; + }; return { inputValue, + changeEvent, + handleChange }; }, }); @@ -27,10 +35,12 @@ export default defineComponent({
-

Input Value: {{ inputValue }}

+

Input v-model: {{ inputValue }}

+

Change Event: {{ changeEvent }}

diff --git a/example-project/vue-app/tests/test.e2e.ts b/example-project/vue-app/tests/test.e2e.ts index 1aaabfbd..c707b47f 100644 --- a/example-project/vue-app/tests/test.e2e.ts +++ b/example-project/vue-app/tests/test.e2e.ts @@ -7,9 +7,10 @@ describe('Stencil Vue Integration', () => { it('should allow to interact with input element', async () => { await $('my-input').$('input').setValue('Hello World'); - await expect(await $('.inputResult p').getText()).toEqual( - 'Input Value: Hello World', - ); + await expect(await $$('.inputResult p').map((p) => p.getText())).toEqual([ + 'Input v-model: Hello World', + 'Change Event: Hello World' + ]); }); it('should listen to custom events', async () => {