在 Angular 7 指令上测试 @HostListening('error') [英] Testing @HostListening('error') on Angular 7 directive

查看:36
本文介绍了在 Angular 7 指令上测试 @HostListening('error')的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有一个可以通过 ID 查找的徽标存储库,但在某些情况下它们会丢失,我们需要改为显示默认"徽标.我制定了一个角度指令,使这个过程更容易一些.它是这样使用的:

<img [appLogoFromId]="item.id"/>

这是功能指令

import { Directive, Input, ElementRef, HostListener } from '@angular/core';@指示({选择器:'[appLogoFromId]'})导出类 LogoFromIdDirective {私有静态只读 baseUrl: string = 'https://our-website.com/sitelogos/';私有静态只读 fallbackImgUrl: string = LogoFromIdDirective.baseUrl + 'default.svg';@Input() 设置 appLogoFromId(value: string | number) {this.nativeEl.src = LogoFromIdDirective.baseUrl + value + '.jpg';}私有只读 nativeEl: HTMLImageElement;私人 errCount: number = 0;构造函数(私有元素:ElementRef){this.nativeEl = this.elem.nativeElement;//该指令仅适用于<img>元素,否则抛出错误const elTag = this.nativeEl.tagName.toLowerCase();if (elTag !== 'img') {throw Error(`appLogoFromId"指令只能用于<img>"元素,但这是一个<${elTag}>"元素!`);}}@HostListener('error') onError(): void {//图像路径上的 404 错误,因此我们改为加载此后备图像//但是如果后备图像消失了,我们不想在这里循环,//所以我们需要跟踪我们遇到了多少错误如果(this.errCount <2){this.nativeEl.src = LogoFromIdDirective.fallbackImgUrl;}this.errCount++;}}

我的问题是:如何测试该指令的 @HostListener('error') 部分?

我有这个测试,但它失败了.我需要做些什么不同的事情?

it('应该为无效图像更新 img 元素的 src 属性', () => {component.bankId = 'foo';夹具.detectChanges();期望(nativeEl.src).toBe('https://our-website.com/sitelogos/default.svg');});

错误信息:

预期https://our-website.com/sitelogos/foo.jpg"为https://our-website.com/sitelogos/default.svg".

<小时>

为了完整起见,这是我针对该指令的整个规范文件

import { LogoFromIdDirective } from './logo-from-id.directive';从@angular/core/testing"导入 {ComponentFixture, TestBed };从@angular/core"导入 { Component, DebugElement, NO_ERRORS_SCHEMA };从'@angular/platform-b​​rowser' 导入 { By };@成分({模板:`<img [appLogoFromId]="theId"/>`})类 TestLogoFromIdOnImgComponent {theId: 号码 |字符串 = 5;}@成分({模板:`<div [appLogoFromId]="theId"/>`})类 TestLogoFromIdOnNonImgComponent {theId: 号码 |字符串 = 5;}描述('指令:[appLogoFromId]',()=> {describe('在`` 元素上', () => {让组件:TestLogoFromIdOnImgComponent;让夹具:ComponentFixture;让 inputEl: DebugElement;让 nativeEl: HTMLInputElement;beforeEach(() => {TestBed.configureTestingModule({声明:[TestLogoFromIdOnImgComponent, LogoFromIdDirective],架构:[ NO_ERRORS_SCHEMA ]});夹具 = TestBed.createComponent(TestLogoFromIdOnImgComponent);组件 = 夹具.componentInstance;inputEl = fixture.debugElement.query(By.css('img'));nativeEl = inputEl.nativeElement;});it('应该为有效图像设置 img 元素的 src 属性', () => {夹具.detectChanges();期望(nativeEl.src).toBe('https://our-website.com/sitelogos/5.jpg');});it('当使用数字时,应该更新有效图像的 img 元素 src 属性', () => {组件.theId = 2852;夹具.detectChanges();期望(nativeEl.src).toBe('https://our-website.com/sitelogos/2852.jpg');});it('当使用字符串时,应该更新有效图像的 img 元素 src 属性', () => {component.theId = '3278';夹具.detectChanges();期望(nativeEl.src).toBe('https://our-website.com/sitelogos/3278.jpg');});it('应该为无效图像更新 img 元素的 src 属性', () => {component.theId = 'foo';夹具.detectChanges();期望(nativeEl.src).toBe('https://our-website.com/sitelogos/default.svg');});});describe('在`

` 元素上', () => {it('应该抛出一个错误', () => {TestBed.configureTestingModule({声明: [TestLogoFromIdOnNonImgComponent, LogoFromIdDirective],架构:[ NO_ERRORS_SCHEMA ]});expect(() => TestBed.createComponent(TestLogoFromIdOnNonImgComponent)).toThrow();});});});

解决方案

我终于找到了一个有效的解决方案!

it('应该为无效图像更新 img 元素的 src 属性', () => {const spyError = spyOn(nativeEl, 'onerror' ).and.callThrough();component.bankId = 'foo';夹具.detectChanges();nativeEl.dispatchEvent(new Event('error'));期望(spyError).toHaveBeenCalled();期望(nativeEl.src).toBe('https://our-website.com/sitelogos/default_bank.svg');});

We have a repository of logos that we can look up by ID, but there are a few instances where they are missing and we need to show a "default" logo instead. I've made an angular directive to make this process a bit easier. It's used like this:

<img [appLogoFromId]="item.id"/>

And here's the functioning directive

import { Directive, Input, ElementRef, HostListener } from '@angular/core';

@Directive({
    selector: '[appLogoFromId]'
})
export class LogoFromIdDirective {
    private static readonly baseUrl: string = 'https://our-website.com/sitelogos/';
    private static readonly fallbackImgUrl: string = LogoFromIdDirective.baseUrl + 'default.svg';

    @Input() set appLogoFromId(value: string | number) {
        this.nativeEl.src = LogoFromIdDirective.baseUrl + value + '.jpg';
    }

    private readonly nativeEl: HTMLImageElement;
    private errCount: number = 0;

    constructor(private elem: ElementRef) {
        this.nativeEl = this.elem.nativeElement;

        //This directive only works on <img> elements, so throw an error otherwise
        const elTag = this.nativeEl.tagName.toLowerCase();
        if (elTag !== 'img') {
            throw Error(`The "appLogoFromId" directive may only be used on "<img>" elements, but this is a "<${elTag}>" element!`);
        }
    }

    @HostListener('error') onError(): void {
        //404 error on image path, so we instead load this fallback image
        //but if that fallback image ever goes away we don't want to be in a loop here,
        //so we ned to keep track of how many errors we've encountered
        if (this.errCount < 2) {
            this.nativeEl.src = LogoFromIdDirective.fallbackImgUrl;
        }
        this.errCount++;
    }
}

My question is: How do I test the @HostListener('error') portion of this directive?

I have this test, but it's failing. what do I need to be doing differently?

it('should update the img element src attribute for an invalid image', () => {
    component.bankId = 'foo';
    fixture.detectChanges();
    expect(nativeEl.src).toBe('https://our-website.com/sitelogos/default.svg');
});

error message:

Expected 'https://our-website.com/sitelogos/foo.jpg' to be 'https://our-website.com/sitelogos/default.svg'.


For completeness, here's my entire spec file for this directive

import { LogoFromIdDirective } from './logo-from-id.directive';

import {ComponentFixture, TestBed } from '@angular/core/testing';
import { Component, DebugElement, NO_ERRORS_SCHEMA } from '@angular/core';
import { By } from '@angular/platform-browser';


@Component({
    template: `<img [appLogoFromId]="theId" />`
})
class TestLogoFromIdOnImgComponent {
    theId: number | string = 5;
}

@Component({
    template: `<div [appLogoFromId]="theId" />`
})
class TestLogoFromIdOnNonImgComponent {
    theId: number | string = 5;
}

describe('Directive: [appLogoFromId]', () => {
    describe('On an `<img>` element', () => {
        let component: TestLogoFromIdOnImgComponent;
        let fixture: ComponentFixture<TestLogoFromIdOnImgComponent>;
        let inputEl: DebugElement;
        let nativeEl: HTMLInputElement;

        beforeEach(() => {
            TestBed.configureTestingModule({
            declarations: [TestLogoFromIdOnImgComponent, LogoFromIdDirective],
            schemas:      [ NO_ERRORS_SCHEMA ]
            });
            fixture = TestBed.createComponent(TestLogoFromIdOnImgComponent);
            component = fixture.componentInstance;
            inputEl = fixture.debugElement.query(By.css('img'));
            nativeEl = inputEl.nativeElement;
        });

        it('should set the img element src attribute for a valid image', () => {
            fixture.detectChanges();
            expect(nativeEl.src).toBe('https://our-website.com/sitelogos/5.jpg');
        });

        it('should update the img element src attribute for a valid image when using a number', () => {
            component.theId = 2852;
            fixture.detectChanges();
            expect(nativeEl.src).toBe('https://our-website.com/sitelogos/2852.jpg');
        });

        it('should update the img element src attribute for a valid image when using a string', () => {
            component.theId = '3278';
            fixture.detectChanges();
            expect(nativeEl.src).toBe('https://our-website.com/sitelogos/3278.jpg');
        });

        it('should update the img element src attribute for an invalid image', () => {
            component.theId = 'foo';
            fixture.detectChanges();
            expect(nativeEl.src).toBe('https://our-website.com/sitelogos/default.svg');
        });
    });

    describe('On a `<div>` element', () => {
        it('should throw an error', () => {
            TestBed.configureTestingModule({
                declarations: [TestLogoFromIdOnNonImgComponent, LogoFromIdDirective],
                schemas:      [ NO_ERRORS_SCHEMA ]
            });
            expect(() => TestBed.createComponent(TestLogoFromIdOnNonImgComponent)).toThrow();
        });
    });
});

解决方案

I've finally found a solution that works!

it('should update the img element src attribute for an invalid image', () => {
    const spyError = spyOn(nativeEl, 'onerror' ).and.callThrough();
    component.bankId = 'foo';
    fixture.detectChanges();
    nativeEl.dispatchEvent(new Event('error'));
    expect(spyError).toHaveBeenCalled();
    expect(nativeEl.src).toBe('https://our-website.com/sitelogos/default_bank.svg');
});

这篇关于在 Angular 7 指令上测试 @HostListening('error')的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆