chore(ct): revert adapters imports and template
This commit is contained in:
parent
d83f9ee4a9
commit
69a6db45fd
13
packages/playwright-ct-angular/index.d.ts
vendored
13
packages/playwright-ct-angular/index.d.ts
vendored
|
|
@ -17,24 +17,18 @@
|
|||
import type { Locator } from 'playwright/test';
|
||||
import type { JsonObject } from '@playwright/experimental-ct-core/types/component';
|
||||
import type { TestType } from '@playwright/experimental-ct-core';
|
||||
import type { Provider, Type } from '@angular/core';
|
||||
import type { Type } from '@angular/core';
|
||||
|
||||
export type ComponentEvents = Record<string, Function>;
|
||||
|
||||
export interface MountOptions<HooksConfig extends JsonObject, Component> {
|
||||
props?: Partial<Component> | Record<string, unknown>, // TODO: filter props and handle signals
|
||||
providers?: Provider[],
|
||||
on?: ComponentEvents;
|
||||
hooksConfig?: HooksConfig;
|
||||
}
|
||||
|
||||
export interface MountTemplateOptions<HooksConfig extends JsonObject, Component> extends MountOptions<HooksConfig, Component> {
|
||||
imports?: Type<unknown>[];
|
||||
}
|
||||
|
||||
export interface MountResult<Component> extends Locator {
|
||||
unmount(): Promise<void>;
|
||||
|
||||
update(options: {
|
||||
props?: Partial<Component>,
|
||||
on?: Partial<ComponentEvents>,
|
||||
|
|
@ -42,11 +36,6 @@ export interface MountResult<Component> extends Locator {
|
|||
}
|
||||
|
||||
export interface ComponentFixtures {
|
||||
mount<HooksConfig extends JsonObject, Component = unknown>(
|
||||
template: string,
|
||||
options?: MountTemplateOptions<HooksConfig, Component>
|
||||
): Promise<MountResult<Component>>;
|
||||
|
||||
mount<HooksConfig extends JsonObject, Component = unknown>(
|
||||
component: Type<Component>,
|
||||
options?: MountOptions<HooksConfig, Component>
|
||||
|
|
|
|||
|
|
@ -17,10 +17,7 @@
|
|||
// @ts-check
|
||||
// This file is injected into the registry as text, no dependencies are allowed.
|
||||
|
||||
/**
|
||||
* @typedef {{type: string} & import('./index').MountTemplateOptions} TemplateInfo
|
||||
* @typedef {{type: import('@angular/core').Type<unknown>} & import('./index').MountOptions | TemplateInfo} ComponentInfo
|
||||
*/
|
||||
/** @typedef {import('../playwright-ct-core/types/component').ObjectComponent} ObjectComponent */
|
||||
|
||||
import 'zone.js';
|
||||
import {
|
||||
|
|
@ -33,13 +30,75 @@ import {
|
|||
platformBrowserDynamicTesting,
|
||||
} from '@angular/platform-browser-dynamic/testing';
|
||||
|
||||
/** @type {WeakMap<import('@angular/core/testing').ComponentFixture, Record<string, import('rxjs').Subscription>>} */
|
||||
const __pwOutputSubscriptionRegistry = new WeakMap();
|
||||
|
||||
/** @type {Map<string, import('@angular/core/testing').ComponentFixture>} */
|
||||
const __pwFixtureRegistry = new Map();
|
||||
|
||||
getTestBed().initTestEnvironment(
|
||||
BrowserDynamicTestingModule,
|
||||
platformBrowserDynamicTesting(),
|
||||
);
|
||||
|
||||
/**
|
||||
* @param {ObjectComponent} component
|
||||
*/
|
||||
async function __pwRenderComponent(component) {
|
||||
const componentMetadata = reflectComponentType(component.type);
|
||||
if (!componentMetadata?.isStandalone)
|
||||
throw new Error('Only standalone components are supported');
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
imports: [component.type],
|
||||
});
|
||||
|
||||
await TestBed.compileComponents();
|
||||
|
||||
const fixture = TestBed.createComponent(component.type);
|
||||
fixture.nativeElement.id = 'root';
|
||||
|
||||
__pwUpdateProps(fixture, component.props);
|
||||
__pwUpdateEvents(fixture, component.on);
|
||||
|
||||
fixture.autoDetectChanges();
|
||||
|
||||
return fixture;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('@angular/core/testing').ComponentFixture} fixture
|
||||
*/
|
||||
function __pwUpdateProps(fixture, props = {}) {
|
||||
for (const [name, value] of Object.entries(props))
|
||||
fixture.componentRef.setInput(name, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('@angular/core/testing').ComponentFixture} fixture
|
||||
*/
|
||||
function __pwUpdateEvents(fixture, events = {}) {
|
||||
const outputSubscriptionRecord =
|
||||
__pwOutputSubscriptionRegistry.get(fixture) ?? {};
|
||||
for (const [name, listener] of Object.entries(events)) {
|
||||
/* Unsubscribe previous listener. */
|
||||
outputSubscriptionRecord[name]?.unsubscribe();
|
||||
|
||||
const subscription = fixture.componentInstance[
|
||||
name
|
||||
].subscribe((/** @type {unknown} */ event) => listener(event));
|
||||
|
||||
/* Store new subscription. */
|
||||
outputSubscriptionRecord[name] = subscription;
|
||||
}
|
||||
|
||||
/* Update output subscription registry. */
|
||||
__pwOutputSubscriptionRegistry.set(fixture, outputSubscriptionRecord);
|
||||
}
|
||||
|
||||
window.playwrightMount = async (component, rootElement, hooksConfig) => {
|
||||
__pwAssertIsNotJsx(component);
|
||||
if (component.__pw_type === 'jsx')
|
||||
throw new Error('JSX mount notation is not supported');
|
||||
|
||||
for (const hook of window.__pw_hooks_before_mount || [])
|
||||
await hook({ hooksConfig, TestBed });
|
||||
|
|
@ -66,116 +125,16 @@ window.playwrightUnmount = async rootElement => {
|
|||
fixture.nativeElement.replaceChildren();
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {{type: import('@angular/core').Type<unknown>} & import('./index').MountOptions | {type: string} & import('./index').MountTemplateOptions} component
|
||||
*/
|
||||
window.playwrightUpdate = async (rootElement, component) => {
|
||||
__pwAssertIsNotJsx(component);
|
||||
if (component.__pw_type === 'jsx')
|
||||
throw new Error('JSX mount notation is not supported');
|
||||
|
||||
const fixture = __pwFixtureRegistry.get(rootElement.id);
|
||||
if (!fixture)
|
||||
throw new Error('Component was not mounted');
|
||||
|
||||
__pwUpdateProps(fixture, component);
|
||||
__pwUpdateProps(fixture, component.props);
|
||||
__pwUpdateEvents(fixture, component.on);
|
||||
|
||||
fixture.detectChanges();
|
||||
};
|
||||
|
||||
/** @type {WeakMap<import('@angular/core/testing').ComponentFixture, Record<string, import('rxjs').Subscription>>} */
|
||||
const __pwOutputSubscriptionRegistry = new WeakMap();
|
||||
|
||||
/** @type {Map<string, import('@angular/core/testing').ComponentFixture>} */
|
||||
const __pwFixtureRegistry = new Map();
|
||||
|
||||
/**
|
||||
* @param {ComponentInfo} component
|
||||
*/
|
||||
async function __pwRenderComponent(component) {
|
||||
/** @type {import('@angular/core').Type<unknown>} */
|
||||
let componentClass;
|
||||
|
||||
if (__pwIsTemplate(component)) {
|
||||
const templateInfo = /** @type {TemplateInfo} */(component);
|
||||
componentClass = defineComponent({
|
||||
standalone: true,
|
||||
selector: 'pw-template-component',
|
||||
imports: templateInfo.imports,
|
||||
template: templateInfo.type,
|
||||
})(class {});
|
||||
} else {
|
||||
componentClass = /** @type {import('@angular/core').Type<unknown>} */(component.type);
|
||||
}
|
||||
|
||||
const componentMetadata = reflectComponentType(componentClass);
|
||||
if (!componentMetadata?.isStandalone)
|
||||
throw new Error('Only standalone components are supported');
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
imports: [componentClass],
|
||||
providers: component.providers,
|
||||
});
|
||||
|
||||
await TestBed.compileComponents();
|
||||
|
||||
const fixture = TestBed.createComponent(componentClass);
|
||||
fixture.nativeElement.id = 'root';
|
||||
|
||||
__pwUpdateProps(fixture, component);
|
||||
__pwUpdateEvents(fixture, component.on);
|
||||
|
||||
fixture.autoDetectChanges();
|
||||
|
||||
return fixture;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('@angular/core/testing').ComponentFixture} fixture
|
||||
* @param {ComponentInfo} componentInfo
|
||||
*/
|
||||
function __pwUpdateProps(fixture, componentInfo) {
|
||||
if (!componentInfo.props)
|
||||
return;
|
||||
|
||||
if (__pwIsTemplate(componentInfo)) {
|
||||
Object.assign(fixture.componentInstance, componentInfo.props);
|
||||
} else {
|
||||
for (const [name, value] of Object.entries(componentInfo.props))
|
||||
fixture.componentRef.setInput(name, value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('@angular/core/testing').ComponentFixture} fixture
|
||||
*/
|
||||
function __pwUpdateEvents(fixture, events = {}) {
|
||||
const outputSubscriptionRecord =
|
||||
__pwOutputSubscriptionRegistry.get(fixture) ?? {};
|
||||
for (const [name, listener] of Object.entries(events)) {
|
||||
/* Unsubscribe previous listener. */
|
||||
outputSubscriptionRecord[name]?.unsubscribe();
|
||||
|
||||
const subscription = fixture.componentInstance[
|
||||
name
|
||||
].subscribe((/** @type {unknown} */ event) => listener(event));
|
||||
|
||||
/* Store new subscription. */
|
||||
outputSubscriptionRecord[name] = subscription;
|
||||
}
|
||||
|
||||
/* Update output subscription registry. */
|
||||
__pwOutputSubscriptionRegistry.set(fixture, outputSubscriptionRecord);
|
||||
}
|
||||
|
||||
function __pwAssertIsNotJsx(component) {
|
||||
if (component.__pw_type === 'jsx')
|
||||
throw new Error('JSX mount notation is not supported');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ComponentInfo} component
|
||||
*/
|
||||
function __pwIsTemplate(component) {
|
||||
return typeof component.type === 'string';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
import { InjectComponent, TOKEN } from "@/components/inject.component";
|
||||
import { expect, test } from "@playwright/experimental-ct-angular";
|
||||
import { InjectComponent, TOKEN } from '@/components/inject.component';
|
||||
import { expect, test } from '@playwright/experimental-ct-angular';
|
||||
import type { HooksConfig } from 'playwright';
|
||||
|
||||
test('inject a token', async ({ mount }) => {
|
||||
const component = await mount(InjectComponent, {
|
||||
providers: [{ provide: TOKEN, useValue: { text: 'has been overwritten' }}]
|
||||
const component = await mount<HooksConfig>(InjectComponent, {
|
||||
hooksConfig: { injectToken: true },
|
||||
});
|
||||
await expect(component).toHaveText('has been overwritten');
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,44 +0,0 @@
|
|||
import { ButtonComponent } from "@/components/button.component";
|
||||
import { expect, test } from "@playwright/experimental-ct-angular"
|
||||
|
||||
test('render a template', async ({ mount }) => {
|
||||
const component = await mount('<h1>{{ 1 + 1 }}</h1>');
|
||||
|
||||
await expect(component).toHaveText('2');
|
||||
})
|
||||
|
||||
test('render a template with child components', async ({ mount }) => {
|
||||
const component = await mount('<app-button title="Click"/>', {
|
||||
imports: [ButtonComponent]
|
||||
});
|
||||
|
||||
await expect(component.getByRole('button')).toContainText('Click');
|
||||
})
|
||||
|
||||
test('render a template with inputs', async ({ mount }) => {
|
||||
const component = await mount('<app-button [title]="title"/>', {
|
||||
imports: [ButtonComponent],
|
||||
props: {
|
||||
title: 'Click',
|
||||
}
|
||||
});
|
||||
|
||||
await expect(component.getByRole('button')).toContainText('Click');
|
||||
})
|
||||
|
||||
test('render a template with outputs', async ({ mount }) => {
|
||||
let _message: string;
|
||||
const component = await mount('<app-button (submit)="onSubmit($event)"/>', {
|
||||
imports: [ButtonComponent],
|
||||
props: {
|
||||
title: 'Click',
|
||||
onSubmit(message: string) {
|
||||
_message = message;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
await component.getByRole('button').click();
|
||||
|
||||
await expect(async () => {expect(_message).toBe('hello')}).toPass();
|
||||
})
|
||||
Loading…
Reference in a new issue