diff --git a/packages/playwright-ct-angular/registerSource.mjs b/packages/playwright-ct-angular/registerSource.mjs index e23c99c7f8..997be15e4d 100644 --- a/packages/playwright-ct-angular/registerSource.mjs +++ b/packages/playwright-ct-angular/registerSource.mjs @@ -18,9 +18,15 @@ // This file is injected into the registry as text, no dependencies are allowed. import 'zone.js'; +import { + Component as defineComponent, + reflectComponentType +} from '@angular/core'; import { getTestBed, TestBed } from '@angular/core/testing'; -import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; -import { EventEmitter, reflectComponentType, Component as defineComponent } from '@angular/core'; +import { + BrowserDynamicTestingModule, + platformBrowserDynamicTesting, +} from '@angular/platform-browser-dynamic/testing'; import { Router } from '@angular/router'; /** @typedef {import('@playwright/experimental-ct-core/types/component').Component} Component */ @@ -34,6 +40,8 @@ const __pwLoaderRegistry = new Map(); const __pwRegistry = new Map(); /** @type {Map} */ const __pwFixtureRegistry = new Map(); +/** @type {WeakMap>} */ +const __pwOutputSubscriptionRegistry = new WeakMap(); getTestBed().initTestEnvironment( BrowserDynamicTestingModule, @@ -96,12 +104,22 @@ function __pwUpdateProps(fixture, props = {}) { * @param {import('@angular/core/testing').ComponentFixture} fixture */ function __pwUpdateEvents(fixture, events = {}) { - for (const [name, value] of Object.entries(events)) { - fixture.debugElement.children[0].componentInstance[name] = { - ...new EventEmitter(), - emit: event => value(event) - }; + const outputSubscriptionRecord = + __pwOutputSubscriptionRegistry.get(fixture) ?? {}; + for (const [name, listener] of Object.entries(events)) { + /* Unsubscribe previous listener. */ + outputSubscriptionRecord[name]?.unsubscribe(); + + const subscription = fixture.debugElement.children[0].componentInstance[ + name + ].subscribe((event) => listener(event)); + + /* Store new subscription. */ + outputSubscriptionRecord[name] = subscription; } + + /* Update output subscription registry. */ + __pwOutputSubscriptionRegistry.set(fixture, outputSubscriptionRecord); } function __pwUpdateSlots(Component, slots = {}, tagName) { @@ -211,8 +229,12 @@ window.playwrightMount = async (component, rootElement, hooksConfig) => { window.playwrightUnmount = async rootElement => { const fixture = __pwFixtureRegistry.get(rootElement.id); - if (!fixture) - throw new Error('Component was not mounted'); + if (!fixture) throw new Error('Component was not mounted'); + + /* Unsubscribe from all outputs. */ + for (const subscription of Object.values(__pwOutputSubscriptionRegistry.get(fixture) ?? {})) + subscription?.unsubscribe(); + __pwOutputSubscriptionRegistry.delete(fixture); fixture.destroy(); fixture.nativeElement.replaceChildren(); diff --git a/tests/components/ct-angular/tests/events.spec.ts b/tests/components/ct-angular/tests/events.spec.ts index 99c1ac484c..b11194ab90 100644 --- a/tests/components/ct-angular/tests/events.spec.ts +++ b/tests/components/ct-angular/tests/events.spec.ts @@ -19,8 +19,6 @@ test('emit an submit event when the button is clicked', async ({ mount }) => { test('replace existing listener when new listener is set', async ({ mount, }) => { - test.skip(true, '🚧 work in progress'); - let count = 0; const component = await mount(ButtonComponent, { @@ -50,7 +48,6 @@ test('unsubscribe from events when the component is unmounted', async ({ mount, page, }) => { - test.skip(true, '🚧 work in progress'); const component = await mount(OutputComponent, { on: { answerChange() {},