mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
test(core): convert listener TemplateFixture tests to TestBed (#46509)
Converts listeners tests with hand-written generated code to TestBed fixtures. PR Close #46509
This commit is contained in:
committed by
Dylan Hunn
parent
779da7f9c4
commit
e42db01dc0
@@ -16,7 +16,99 @@ function getNoOfNativeListeners(): number {
|
||||
}
|
||||
|
||||
describe('event listeners', () => {
|
||||
describe('even handler', () => {
|
||||
describe('even handling statements', () => {
|
||||
it('should call function on event emit', () => {
|
||||
@Component({
|
||||
template: `<button (click)="onClick()">Click me</button>`,
|
||||
})
|
||||
class MyComp {
|
||||
counter = 0;
|
||||
|
||||
onClick() {
|
||||
this.counter++;
|
||||
}
|
||||
}
|
||||
|
||||
const fixture = TestBed.createComponent(MyComp);
|
||||
fixture.detectChanges();
|
||||
expect(fixture.componentInstance.counter).toEqual(0);
|
||||
|
||||
const button = fixture.nativeElement.querySelector('button');
|
||||
button.click();
|
||||
expect(fixture.componentInstance.counter).toEqual(1);
|
||||
});
|
||||
|
||||
it('should call function chain on event emit', () => {
|
||||
@Component({
|
||||
template: `<button (click)="onClick(); onClick2(); "> Click me </button>`,
|
||||
})
|
||||
class MyComp {
|
||||
counter = 0;
|
||||
counter2 = 0;
|
||||
onClick() {
|
||||
this.counter++;
|
||||
}
|
||||
onClick2() {
|
||||
this.counter2++;
|
||||
}
|
||||
}
|
||||
|
||||
const fixture = TestBed.createComponent(MyComp);
|
||||
fixture.detectChanges();
|
||||
expect(fixture.componentInstance.counter).toEqual(0);
|
||||
expect(fixture.componentInstance.counter2).toEqual(0);
|
||||
|
||||
const button = fixture.nativeElement.querySelector('button');
|
||||
button.click();
|
||||
expect(fixture.componentInstance.counter).toEqual(1);
|
||||
expect(fixture.componentInstance.counter2).toEqual(1);
|
||||
});
|
||||
|
||||
it('should evaluate expression on event emit', () => {
|
||||
@Component({
|
||||
template: `<button (click)="showing=!showing"> Click me </button>`,
|
||||
})
|
||||
class MyComp {
|
||||
showing = false;
|
||||
}
|
||||
|
||||
const fixture = TestBed.createComponent(MyComp);
|
||||
fixture.detectChanges();
|
||||
expect(fixture.componentInstance.showing).toBeFalse();
|
||||
|
||||
const button = fixture.nativeElement.querySelector('button');
|
||||
button.click();
|
||||
expect(fixture.componentInstance.showing).toBeTrue();
|
||||
|
||||
button.click();
|
||||
expect(fixture.componentInstance.showing).toBeFalse();
|
||||
});
|
||||
|
||||
it('should support listeners with specified set of args', () => {
|
||||
@Component({
|
||||
template: `<button (click)="onClick(data.a, data.b)"> Click me </button>`,
|
||||
})
|
||||
class MyComp {
|
||||
counter = 0;
|
||||
data = {a: 1, b: 2};
|
||||
|
||||
onClick(a: any, b: any) {
|
||||
this.counter += a + b;
|
||||
}
|
||||
}
|
||||
|
||||
const fixture = TestBed.createComponent(MyComp);
|
||||
fixture.detectChanges();
|
||||
expect(fixture.componentInstance.counter).toBe(0);
|
||||
|
||||
const button = fixture.nativeElement.querySelector('button');
|
||||
button.click();
|
||||
expect(fixture.componentInstance.counter).toBe(3);
|
||||
|
||||
button.click();
|
||||
expect(fixture.componentInstance.counter).toBe(6);
|
||||
});
|
||||
|
||||
it('should be able to access a property called $event using `this`', () => {
|
||||
let eventVariable: number|undefined;
|
||||
let eventObject: MouseEvent|undefined;
|
||||
@@ -110,6 +202,82 @@ describe('event listeners', () => {
|
||||
expect(instance.one.value).toBe('one!');
|
||||
expect(instance.two.value).toBe('two!');
|
||||
});
|
||||
|
||||
it('should support local refs in listeners', () => {
|
||||
@Component({
|
||||
selector: 'my-comp',
|
||||
standalone: true,
|
||||
template: ``,
|
||||
})
|
||||
class MyComp {
|
||||
}
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
imports: [MyComp],
|
||||
template: `
|
||||
<my-comp #comp></my-comp>
|
||||
<button (click)="onClick(comp)"></button>
|
||||
`,
|
||||
})
|
||||
class App {
|
||||
comp: MyComp|null = null;
|
||||
|
||||
onClick(comp: MyComp) {
|
||||
this.comp = comp;
|
||||
}
|
||||
}
|
||||
|
||||
const fixture = TestBed.createComponent(App);
|
||||
fixture.detectChanges();
|
||||
expect(fixture.componentInstance.comp).toBeNull();
|
||||
|
||||
const button = fixture.nativeElement.querySelector('button');
|
||||
button.click();
|
||||
expect(fixture.componentInstance.comp).toBeInstanceOf(MyComp);
|
||||
});
|
||||
});
|
||||
|
||||
describe('prevent default', () => {
|
||||
it('should call prevent default when a handler returns false', () => {
|
||||
@Component({
|
||||
template: `<button (click)="onClick($event)">Click</button>`,
|
||||
})
|
||||
class MyComp {
|
||||
handlerReturnValue: boolean|undefined;
|
||||
event: Event|undefined;
|
||||
|
||||
onClick(e: any) {
|
||||
this.event = e;
|
||||
|
||||
// stub preventDefault() to check whether it's called
|
||||
Object.defineProperty(
|
||||
this.event, 'preventDefault',
|
||||
{value: jasmine.createSpy('preventDefault'), writable: true});
|
||||
|
||||
return this.handlerReturnValue;
|
||||
}
|
||||
}
|
||||
|
||||
const fixture = TestBed.createComponent(MyComp);
|
||||
fixture.detectChanges();
|
||||
|
||||
const myComp = fixture.componentInstance;
|
||||
const button = fixture.nativeElement.querySelector('button');
|
||||
|
||||
myComp.handlerReturnValue = undefined;
|
||||
button.click();
|
||||
expect(myComp.event!.preventDefault).not.toHaveBeenCalled();
|
||||
|
||||
myComp.handlerReturnValue = true;
|
||||
button.click();
|
||||
expect(myComp.event!.preventDefault).not.toHaveBeenCalled();
|
||||
|
||||
// Returning `false` is what causes the renderer to call `event.preventDefault`.
|
||||
myComp.handlerReturnValue = false;
|
||||
button.click();
|
||||
expect(myComp.event!.preventDefault).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('coalescing', () => {
|
||||
@@ -490,7 +658,127 @@ describe('event listeners', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('global event listeners on special elements', () => {
|
||||
describe('host listeners', () => {
|
||||
it('should support host listeners on components', () => {
|
||||
const events: string[] = [];
|
||||
|
||||
@Component({
|
||||
template: ``,
|
||||
})
|
||||
class MyComp {
|
||||
@HostListener('click')
|
||||
onClick() {
|
||||
events.push('click!');
|
||||
}
|
||||
}
|
||||
|
||||
const fixture = TestBed.createComponent(MyComp);
|
||||
fixture.detectChanges();
|
||||
|
||||
const host = fixture.nativeElement;
|
||||
|
||||
host.click();
|
||||
expect(events).toEqual(['click!']);
|
||||
|
||||
host.click();
|
||||
expect(events).toEqual(['click!', 'click!']);
|
||||
});
|
||||
|
||||
it('should support global host listeners on components', () => {
|
||||
const events: string[] = [];
|
||||
|
||||
@Component({
|
||||
template: ``,
|
||||
})
|
||||
class MyComp {
|
||||
@HostListener('document:click')
|
||||
onClick() {
|
||||
events.push('global click!');
|
||||
}
|
||||
}
|
||||
|
||||
const fixture = TestBed.createComponent(MyComp);
|
||||
fixture.detectChanges();
|
||||
|
||||
const host = fixture.nativeElement;
|
||||
|
||||
host.click();
|
||||
expect(events).toEqual(['global click!']);
|
||||
|
||||
host.click();
|
||||
expect(events).toEqual(['global click!', 'global click!']);
|
||||
});
|
||||
|
||||
it('should support host listeners on directives', () => {
|
||||
const events: string[] = [];
|
||||
|
||||
@Directive({
|
||||
selector: '[hostListenerDir]',
|
||||
standalone: true,
|
||||
})
|
||||
class HostListenerDir {
|
||||
@HostListener('click')
|
||||
onClick() {
|
||||
events.push('click!');
|
||||
}
|
||||
}
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
imports: [HostListenerDir],
|
||||
template: `<button hostListenerDir>Click</button>`,
|
||||
})
|
||||
class MyComp {
|
||||
}
|
||||
|
||||
const fixture = TestBed.createComponent(MyComp);
|
||||
fixture.detectChanges();
|
||||
expect(events).toEqual([]);
|
||||
|
||||
const button = fixture.nativeElement.querySelector('button');
|
||||
button.click();
|
||||
expect(events).toEqual(['click!']);
|
||||
|
||||
button.click();
|
||||
expect(events).toEqual(['click!', 'click!']);
|
||||
});
|
||||
|
||||
it('should support global host listeners on directives', () => {
|
||||
const events: string[] = [];
|
||||
|
||||
@Directive({
|
||||
selector: '[hostListenerDir]',
|
||||
standalone: true,
|
||||
})
|
||||
class HostListenerDir {
|
||||
@HostListener('document:click')
|
||||
onClick() {
|
||||
events.push('click!');
|
||||
}
|
||||
}
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
imports: [HostListenerDir],
|
||||
template: `<button hostListenerDir>Click</button>`,
|
||||
})
|
||||
class MyComp {
|
||||
}
|
||||
|
||||
const fixture = TestBed.createComponent(MyComp);
|
||||
fixture.detectChanges();
|
||||
expect(events).toEqual([]);
|
||||
|
||||
const button = fixture.nativeElement.querySelector('button');
|
||||
button.click();
|
||||
expect(events).toEqual(['click!']);
|
||||
|
||||
button.click();
|
||||
expect(events).toEqual(['click!', 'click!']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('global host listeners on special element as directive hosts', () => {
|
||||
it('should bind global event listeners on an ng-container directive host', () => {
|
||||
let clicks = 0;
|
||||
|
||||
|
||||
@@ -1,514 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google LLC All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {HEADER_OFFSET} from '@angular/core/src/render3/interfaces/view';
|
||||
import {dispatchEvent} from '@angular/platform-browser/testing/src/browser_util';
|
||||
|
||||
import {ɵɵdefineComponent, ɵɵdefineDirective, ɵɵreference, ɵɵresolveBody, ɵɵresolveDocument} from '../../src/render3/index';
|
||||
import {ɵɵelement, ɵɵelementEnd, ɵɵelementStart, ɵɵgetCurrentView, ɵɵlistener, ɵɵtext} from '../../src/render3/instructions/all';
|
||||
import {RenderFlags} from '../../src/render3/interfaces/definition';
|
||||
import {GlobalTargetResolver} from '../../src/render3/interfaces/renderer';
|
||||
import {ɵɵresetView, ɵɵrestoreView} from '../../src/render3/state';
|
||||
|
||||
import {getRendererFactory2} from './imported_renderer2';
|
||||
import {ComponentFixture, containerEl, createComponent, getDirectiveOnNode, renderToHtml, TemplateFixture} from './render_util';
|
||||
|
||||
|
||||
describe('event listeners', () => {
|
||||
let comps: any[] = [];
|
||||
let events: any[] = [];
|
||||
|
||||
class MyComp {
|
||||
showing = true;
|
||||
counter = 0;
|
||||
|
||||
onClick() {
|
||||
this.counter++;
|
||||
}
|
||||
|
||||
static ɵfac =
|
||||
() => {
|
||||
let comp = new MyComp();
|
||||
comps.push(comp);
|
||||
return comp;
|
||||
}
|
||||
|
||||
static ɵcmp = ɵɵdefineComponent({
|
||||
type: MyComp,
|
||||
selectors: [['comp']],
|
||||
decls: 2,
|
||||
vars: 0,
|
||||
/** <button (click)="onClick()"> Click me </button> */
|
||||
template:
|
||||
function CompTemplate(rf: RenderFlags, ctx: any) {
|
||||
if (rf & RenderFlags.Create) {
|
||||
ɵɵelementStart(0, 'button');
|
||||
{
|
||||
ɵɵlistener('click', function() {
|
||||
return ctx.onClick();
|
||||
});
|
||||
ɵɵtext(1, 'Click me');
|
||||
}
|
||||
ɵɵelementEnd();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
class MyCompWithGlobalListeners {
|
||||
/* @HostListener('document:custom') */
|
||||
onDocumentCustomEvent() {
|
||||
events.push('component - document:custom');
|
||||
}
|
||||
|
||||
/* @HostListener('body:click') */
|
||||
onBodyClick() {
|
||||
events.push('component - body:click');
|
||||
}
|
||||
|
||||
static ɵfac =
|
||||
() => {
|
||||
let comp = new MyCompWithGlobalListeners();
|
||||
comps.push(comp);
|
||||
return comp;
|
||||
}
|
||||
|
||||
static ɵcmp = ɵɵdefineComponent({
|
||||
type: MyCompWithGlobalListeners,
|
||||
selectors: [['comp']],
|
||||
decls: 1,
|
||||
vars: 0,
|
||||
template:
|
||||
function CompTemplate(rf: RenderFlags, ctx: any) {
|
||||
if (rf & RenderFlags.Create) {
|
||||
ɵɵtext(0, 'Some text');
|
||||
}
|
||||
},
|
||||
hostBindings:
|
||||
function HostListenerDir_HostBindings(rf: RenderFlags, ctx: any) {
|
||||
if (rf & RenderFlags.Create) {
|
||||
ɵɵlistener('custom', function() {
|
||||
return ctx.onDocumentCustomEvent();
|
||||
}, false, ɵɵresolveDocument as GlobalTargetResolver);
|
||||
ɵɵlistener('click', function() {
|
||||
return ctx.onBodyClick();
|
||||
}, false, ɵɵresolveBody as GlobalTargetResolver);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
class GlobalHostListenerDir {
|
||||
/* @HostListener('document:custom') */
|
||||
onDocumentCustomEvent() {
|
||||
events.push('directive - document:custom');
|
||||
}
|
||||
|
||||
/* @HostListener('body:click') */
|
||||
onBodyClick() {
|
||||
events.push('directive - body:click');
|
||||
}
|
||||
|
||||
static ɵfac = function HostListenerDir_Factory() {
|
||||
return new GlobalHostListenerDir();
|
||||
};
|
||||
static ɵdir = ɵɵdefineDirective({
|
||||
type: GlobalHostListenerDir,
|
||||
selectors: [['', 'hostListenerDir', '']],
|
||||
hostBindings:
|
||||
function HostListenerDir_HostBindings(rf: RenderFlags, ctx: any) {
|
||||
if (rf & RenderFlags.Create) {
|
||||
ɵɵlistener('custom', function() {
|
||||
return ctx.onDocumentCustomEvent();
|
||||
}, false, ɵɵresolveDocument as GlobalTargetResolver)('click', function() {
|
||||
return ctx.onBodyClick();
|
||||
}, false, ɵɵresolveBody as GlobalTargetResolver);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
class PreventDefaultComp {
|
||||
handlerReturnValue: any = true;
|
||||
// TODO(issue/24571): remove '!'.
|
||||
event!: Event;
|
||||
|
||||
onClick(e: any) {
|
||||
this.event = e;
|
||||
|
||||
// stub preventDefault() to check whether it's called
|
||||
Object.defineProperty(
|
||||
this.event, 'preventDefault',
|
||||
{value: jasmine.createSpy('preventDefault'), writable: true});
|
||||
|
||||
return this.handlerReturnValue;
|
||||
}
|
||||
|
||||
static ɵfac = () => new PreventDefaultComp();
|
||||
static ɵcmp = ɵɵdefineComponent({
|
||||
type: PreventDefaultComp,
|
||||
selectors: [['prevent-default-comp']],
|
||||
decls: 2,
|
||||
vars: 0,
|
||||
/** <button (click)="onClick($event)">Click</button> */
|
||||
template:
|
||||
(rf: RenderFlags, ctx: PreventDefaultComp) => {
|
||||
if (rf & RenderFlags.Create) {
|
||||
ɵɵelementStart(0, 'button');
|
||||
{
|
||||
ɵɵlistener('click', function($event: any) {
|
||||
return ctx.onClick($event);
|
||||
});
|
||||
ɵɵtext(1, 'Click');
|
||||
}
|
||||
ɵɵelementEnd();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
comps = [];
|
||||
events = [];
|
||||
});
|
||||
|
||||
it('should call function on event emit', () => {
|
||||
const fixture = new ComponentFixture(MyComp);
|
||||
const comp = fixture.component;
|
||||
const button = fixture.hostElement.querySelector('button')!;
|
||||
|
||||
button.click();
|
||||
expect(comp.counter).toEqual(1);
|
||||
|
||||
button.click();
|
||||
expect(comp.counter).toEqual(2);
|
||||
});
|
||||
|
||||
it('should retain event handler return values using document', () => {
|
||||
const fixture = new ComponentFixture(PreventDefaultComp);
|
||||
const preventDefaultComp = fixture.component;
|
||||
const button = fixture.hostElement.querySelector('button')!;
|
||||
|
||||
button.click();
|
||||
expect(preventDefaultComp.event!.preventDefault).not.toHaveBeenCalled();
|
||||
|
||||
preventDefaultComp.handlerReturnValue = undefined;
|
||||
button.click();
|
||||
expect(preventDefaultComp.event!.preventDefault).not.toHaveBeenCalled();
|
||||
|
||||
preventDefaultComp.handlerReturnValue = false;
|
||||
button.click();
|
||||
expect(preventDefaultComp.event!.preventDefault).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should retain event handler return values with renderer2', () => {
|
||||
const fixture =
|
||||
new ComponentFixture(PreventDefaultComp, {rendererFactory: getRendererFactory2(document)});
|
||||
const preventDefaultComp = fixture.component;
|
||||
const button = fixture.hostElement.querySelector('button')!;
|
||||
|
||||
button.click();
|
||||
expect(preventDefaultComp.event!.preventDefault).not.toHaveBeenCalled();
|
||||
|
||||
preventDefaultComp.handlerReturnValue = undefined;
|
||||
button.click();
|
||||
expect(preventDefaultComp.event!.preventDefault).not.toHaveBeenCalled();
|
||||
|
||||
preventDefaultComp.handlerReturnValue = false;
|
||||
button.click();
|
||||
expect(preventDefaultComp.event!.preventDefault).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should call function chain on event emit', () => {
|
||||
/** <button (click)="onClick(); onClick2(); "> Click me </button> */
|
||||
function Template(rf: RenderFlags, ctx: any) {
|
||||
if (rf & RenderFlags.Create) {
|
||||
ɵɵelementStart(0, 'button');
|
||||
{
|
||||
ɵɵlistener('click', function() {
|
||||
ctx.onClick();
|
||||
return ctx.onClick2();
|
||||
});
|
||||
ɵɵtext(1, 'Click me');
|
||||
}
|
||||
ɵɵelementEnd();
|
||||
}
|
||||
}
|
||||
|
||||
const ctx = {
|
||||
counter: 0,
|
||||
counter2: 0,
|
||||
onClick: function() {
|
||||
this.counter++;
|
||||
},
|
||||
onClick2: function() {
|
||||
this.counter2++;
|
||||
}
|
||||
};
|
||||
renderToHtml(Template, ctx, 2);
|
||||
const button = containerEl.querySelector('button')!;
|
||||
|
||||
button.click();
|
||||
expect(ctx.counter).toBe(1);
|
||||
expect(ctx.counter2).toBe(1);
|
||||
|
||||
button.click();
|
||||
expect(ctx.counter).toBe(2);
|
||||
expect(ctx.counter2).toBe(2);
|
||||
});
|
||||
|
||||
it('should evaluate expression on event emit', () => {
|
||||
/** <button (click)="showing=!showing"> Click me </button> */
|
||||
function Template(rf: RenderFlags, ctx: any) {
|
||||
if (rf & RenderFlags.Create) {
|
||||
ɵɵelementStart(0, 'button');
|
||||
{
|
||||
ɵɵlistener('click', function() {
|
||||
return ctx.showing = !ctx.showing;
|
||||
});
|
||||
ɵɵtext(1, 'Click me');
|
||||
}
|
||||
ɵɵelementEnd();
|
||||
}
|
||||
}
|
||||
|
||||
const ctx = {showing: false};
|
||||
renderToHtml(Template, ctx, 2);
|
||||
const button = containerEl.querySelector('button')!;
|
||||
|
||||
button.click();
|
||||
expect(ctx.showing).toBe(true);
|
||||
|
||||
button.click();
|
||||
expect(ctx.showing).toBe(false);
|
||||
});
|
||||
|
||||
it('should support host listeners on components', () => {
|
||||
let events: string[] = [];
|
||||
class MyComp {
|
||||
/* @HostListener('click') */
|
||||
onClick() {
|
||||
events.push('click!');
|
||||
}
|
||||
|
||||
static ɵfac =
|
||||
() => {
|
||||
return new MyComp();
|
||||
}
|
||||
|
||||
static ɵcmp = ɵɵdefineComponent({
|
||||
type: MyComp,
|
||||
selectors: [['comp']],
|
||||
decls: 1,
|
||||
vars: 0,
|
||||
template:
|
||||
function CompTemplate(rf: RenderFlags, ctx: any) {
|
||||
if (rf & RenderFlags.Create) {
|
||||
ɵɵtext(0, 'Some text');
|
||||
}
|
||||
},
|
||||
hostBindings:
|
||||
function HostListenerDir_HostBindings(rf: RenderFlags, ctx: any) {
|
||||
if (rf & RenderFlags.Create) {
|
||||
ɵɵlistener('click', function() {
|
||||
return ctx.onClick();
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const fixture = new ComponentFixture(MyComp);
|
||||
const host = fixture.hostElement;
|
||||
|
||||
host.click();
|
||||
expect(events).toEqual(['click!']);
|
||||
|
||||
host.click();
|
||||
expect(events).toEqual(['click!', 'click!']);
|
||||
});
|
||||
|
||||
it('should support global host listeners on components', () => {
|
||||
const fixture = new ComponentFixture(MyCompWithGlobalListeners);
|
||||
const doc = fixture.hostElement.ownerDocument!;
|
||||
|
||||
dispatchEvent(doc, 'custom');
|
||||
expect(events).toEqual(['component - document:custom']);
|
||||
|
||||
dispatchEvent(doc.body, 'click');
|
||||
expect(events).toEqual(['component - document:custom', 'component - body:click']);
|
||||
|
||||
// invoke destroy for this fixture to cleanup all listeners setup for global objects
|
||||
fixture.destroy();
|
||||
});
|
||||
|
||||
it('should support host listeners on directives', () => {
|
||||
let events: string[] = [];
|
||||
|
||||
class HostListenerDir {
|
||||
/* @HostListener('click') */
|
||||
onClick() {
|
||||
events.push('click!');
|
||||
}
|
||||
|
||||
static ɵfac = function HostListenerDir_Factory() {
|
||||
return new HostListenerDir();
|
||||
};
|
||||
static ɵdir = ɵɵdefineDirective({
|
||||
type: HostListenerDir,
|
||||
selectors: [['', 'hostListenerDir', '']],
|
||||
hostBindings:
|
||||
function HostListenerDir_HostBindings(rf: RenderFlags, ctx: any) {
|
||||
if (rf & RenderFlags.Create) {
|
||||
ɵɵlistener('click', function() {
|
||||
return ctx.onClick();
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const fixture = new TemplateFixture({
|
||||
create: () => {
|
||||
ɵɵelementStart(0, 'button', 0);
|
||||
ɵɵtext(1, 'Click');
|
||||
ɵɵelementEnd();
|
||||
},
|
||||
decls: 2,
|
||||
directives: [HostListenerDir],
|
||||
consts: [['hostListenerDir', '']]
|
||||
});
|
||||
|
||||
const button = fixture.hostElement.querySelector('button')!;
|
||||
|
||||
button.click();
|
||||
expect(events).toEqual(['click!']);
|
||||
|
||||
button.click();
|
||||
expect(events).toEqual(['click!', 'click!']);
|
||||
});
|
||||
|
||||
it('should support global host listeners on directives', () => {
|
||||
const fixture = new TemplateFixture({
|
||||
create: () => {
|
||||
ɵɵelement(0, 'div', 0);
|
||||
},
|
||||
decls: 1,
|
||||
directives: [GlobalHostListenerDir],
|
||||
consts: [['hostListenerDir', '']]
|
||||
});
|
||||
|
||||
const doc = fixture.hostElement.ownerDocument!;
|
||||
|
||||
dispatchEvent(doc, 'custom');
|
||||
expect(events).toEqual(['directive - document:custom']);
|
||||
|
||||
dispatchEvent(doc.body, 'click');
|
||||
expect(events).toEqual(['directive - document:custom', 'directive - body:click']);
|
||||
|
||||
// invoke destroy for this fixture to cleanup all listeners setup for global objects
|
||||
fixture.destroy();
|
||||
});
|
||||
|
||||
it('should support listeners with specified set of args', () => {
|
||||
class MyComp {
|
||||
counter = 0;
|
||||
data = {a: 1, b: 2};
|
||||
|
||||
onClick(a: any, b: any) {
|
||||
this.counter += a + b;
|
||||
}
|
||||
|
||||
static ɵfac = () => new MyComp();
|
||||
static ɵcmp = ɵɵdefineComponent({
|
||||
type: MyComp,
|
||||
selectors: [['comp']],
|
||||
decls: 2,
|
||||
vars: 0,
|
||||
/** <button (click)="onClick(data.a, data.b)"> Click me </button> */
|
||||
template:
|
||||
function CompTemplate(rf: RenderFlags, ctx: any) {
|
||||
if (rf & RenderFlags.Create) {
|
||||
ɵɵelementStart(0, 'button');
|
||||
{
|
||||
ɵɵlistener('click', function() {
|
||||
return ctx.onClick(ctx.data.a, ctx.data.b);
|
||||
});
|
||||
ɵɵtext(1, 'Click me');
|
||||
}
|
||||
ɵɵelementEnd();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const fixture = new ComponentFixture(MyComp);
|
||||
const comp = fixture.component;
|
||||
const button = fixture.hostElement.querySelector('button')!;
|
||||
|
||||
button.click();
|
||||
expect(comp.counter).toEqual(3);
|
||||
|
||||
button.click();
|
||||
expect(comp.counter).toEqual(6);
|
||||
});
|
||||
|
||||
it('should support local refs in listeners', () => {
|
||||
let compInstance: any;
|
||||
|
||||
const Comp = createComponent('comp', (rf: RenderFlags, ctx: any) => {});
|
||||
|
||||
/**
|
||||
* <comp #comp></comp>
|
||||
* <button (click)="onClick(comp)"></button>
|
||||
*/
|
||||
class App {
|
||||
comp: any = null;
|
||||
|
||||
onClick(comp: any) {
|
||||
this.comp = comp;
|
||||
}
|
||||
|
||||
static ɵfac = () => new App();
|
||||
static ɵcmp = ɵɵdefineComponent({
|
||||
type: App,
|
||||
selectors: [['app']],
|
||||
decls: 3,
|
||||
vars: 0,
|
||||
consts: [['comp', '']],
|
||||
template:
|
||||
(rf: RenderFlags, ctx: App) => {
|
||||
if (rf & RenderFlags.Create) {
|
||||
const state = ɵɵgetCurrentView();
|
||||
ɵɵelement(0, 'comp', null, 0);
|
||||
ɵɵelementStart(2, 'button');
|
||||
{
|
||||
ɵɵlistener('click', function() {
|
||||
ɵɵrestoreView(state);
|
||||
const comp = ɵɵreference(1);
|
||||
return ɵɵresetView(ctx.onClick(comp));
|
||||
});
|
||||
}
|
||||
ɵɵelementEnd();
|
||||
}
|
||||
|
||||
// testing only
|
||||
compInstance = getDirectiveOnNode(HEADER_OFFSET);
|
||||
},
|
||||
dependencies: [Comp]
|
||||
});
|
||||
}
|
||||
|
||||
const fixture = new ComponentFixture(App);
|
||||
expect(fixture.component.comp).toEqual(null);
|
||||
|
||||
const button = fixture.hostElement.querySelector('button') as HTMLButtonElement;
|
||||
button.click();
|
||||
expect(fixture.component.comp).toEqual(compInstance);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user