import { Component, EventEmitter, Input, Output } from '@angular/core'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { NgxElementComponent } from './ngx-element.component'; import { LAZY_CMPS_PATH_TOKEN } from './tokens'; @Component({ selector: 'test-talk', standalone: true, template: `

{{ title }}

{{ description }}

{{ speaker }}` }) class TestTalkComponent { private _isTestMode = 'N'; @Input() set isTestMode(value: string) { this._isTestMode = value; } get isTestMode(): string { return this._isTestMode; } private _title = ''; @Input() set title(value: string) { this._title = value; if (this.isTestMode === 'Y') { this.tagClick.emit(`{"attrName": "title", "attrValue": "${value}"}`); } } get title(): string { return this._title; } private _description = ''; @Input() set description(value: string) { this._description = value; if (this.isTestMode === 'Y') { this.tagClick.emit(`{"attrName": "description", "attrValue": "${value}"}`); } } get description(): string { return this._description; } private _speaker = ''; @Input() set speaker(value: string) { this._speaker = value; if (this.isTestMode === 'Y') { this.tagClick.emit(`{"attrName": "speaker", "attrValue": "${value}"}`); } } get speaker(): string { return this._speaker; } @Output() tagClick = new EventEmitter(); } describe('NgxElementComponent', () => { let component: NgxElementComponent; let fixture: ComponentFixture; const inputsAttrs = { title: 'Angular Elements', description: 'How to write Angular and get Web Components', speaker: 'Bruno' }; beforeEach(async () => { await TestBed.configureTestingModule({ imports: [NgxElementComponent], providers: [ { provide: LAZY_CMPS_PATH_TOKEN, useValue: [ { selector: 'talk', loadComponent: () => Promise.resolve(TestTalkComponent) } ] } ] }).compileComponents(); fixture = TestBed.createComponent(NgxElementComponent); component = fixture.componentInstance; component.selector = 'talk'; fixture.detectChanges(); await fixture.whenStable(); fixture.detectChanges(); }); it('should create', () => { expect(component).toBeTruthy(); }); it('should render the lazy standalone component', () => { expect(component.componentRef).toBeTruthy(); component.setAttributes([{ name: 'title', value: inputsAttrs.title }]); component.componentRef?.changeDetectorRef.detectChanges(); fixture.detectChanges(); const instance = component.componentRef?.instance as { title?: string }; expect(instance.title).toBe(inputsAttrs.title); expect(component.container.length).toBeGreaterThan(0); expect(component.componentRef?.location.nativeElement.tagName.toLowerCase()).toBe('test-talk'); }); async function expectProxiedAttribute(attr: keyof typeof inputsAttrs): Promise { const nativeElement = fixture.nativeElement as HTMLElement; const eventPromise = new Promise((resolve) => { nativeElement.addEventListener( 'tagClick', (e: Event) => resolve((e as CustomEvent).detail), { once: true } ); }); nativeElement.setAttribute('data-is-test-mode', 'Y'); nativeElement.setAttribute(`data-${attr}`, inputsAttrs[attr]); const outputObject = JSON.parse(await eventPromise) as { attrName: string; attrValue: string; }; expect(outputObject.attrName).toBe(attr); expect(outputObject.attrValue).toBe(inputsAttrs[attr]); } it('should pass and receive the same "title" attr value', async () => { await expectProxiedAttribute('title'); }); it('should pass and receive the same "description" attr value', async () => { await expectProxiedAttribute('description'); }); it('should pass and receive the same "speaker" attr value', async () => { await expectProxiedAttribute('speaker'); }); });