首页 > 解决方案 > 如何使用 Jasmine 测试自定义角度 HTML 输入

问题描述

我在单元测试角度组件时遇到问题。通常角度组件像这样放置在页面上:<custom-input/>并且您有一个 HTML 模板:template: '<input/>'但出于我的目的,我将选择器放在括号中:selector:'[custom-input]'并在页面上使用组件,如下所示:<input custom-input/>。我遇到的问题是在 Jasmine 中测试时呈现的组件是 a<div>而不是<input/>. 有没有办法让 Jasmine 将组件编译为 HTML 输入而不是 div?

更新:

组件.ts

@Component({
  selector: '[prps-text]',
  template:`
  `,
})
export class PrpsTextComponent implements OnInit {

  @Input() size: string = '';
  @Input() maxlength: string = '';
  @Input() property: string = '';
  @Input() readonly: string = '';
  @Input() styleClass: string = '';

  @HostBinding('attr.type') inputType: string = 'text'
  @HostBinding('attr.name') inputName: string = ''
  @HostBinding('attr.maxlength') inputMaxLength: string = ''
  @HostBinding('attr.size') inputSize: string = ''
  @HostBinding('attr.value') inputValue: string = ''
  @HostBinding('attr.readonly') isReadOnly: string | null = null;
  @HostBinding('attr.class') class: string = '';
  
  
  constructor() { }

  ngOnInit(): void {
    if(this.property != ''){
      this.inputName = this.property
    }
    if(this.maxlength != ''){
      this.inputMaxLength = this.maxlength
    }
    if(this.size != ''){
      this.inputSize = this.size
    }
    if (this.readonly === 'true') {
      this.isReadOnly = ''
    }
    if(this.styleClass != ''){
      this.class = this.styleClass
    }
  }

}

应用组件.html

<input prps-text type="text"/>

规格

import { ComponentFixture, TestBed } from '@angular/core/testing';

import { PrpsTextComponent } from './prps-text.component';

describe('PrpsTextComponent', () => {
  let component: PrpsTextComponent;
  let fixture: ComponentFixture<PrpsTextComponent>;
  let compiled: HTMLElement;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      declarations: [ PrpsTextComponent ]
    })
    .compileComponents();
  });

  beforeEach(() => {
    fixture = TestBed.createComponent(PrpsTextComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
    compiled = fixture.debugElement.nativeElement;
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });

  it('should create with type attribute text', () => {
    expect(compiled.getAttribute('type')).toEqual('text')
  })

  it('should set name attribute when property has value', () => {
    component.property = "organization"

    component.ngOnInit()
    fixture.detectChanges()

    expect(component.property).toBe('organization')
    expect(component.inputName).toBe('organization')
    expect(compiled.getAttribute('name')).toEqual('organization');
  })

  it('should set maxlength attribute', () => {
    component.maxlength = '3'
    
    component.ngOnInit()
    fixture.detectChanges()

    expect(component.maxlength).toBe('3')
    expect(component.inputMaxLength).toBe('3');
    expect(compiled.getAttribute('maxlength')).toBe('3')
  })

  it('should set size attribute', () => {
    component.size = '3'

    component.ngOnInit()
    fixture.detectChanges()

    expect(component.size).toBe('3')
    expect(component.inputSize).toBe('3')
    expect(compiled.getAttribute('size')).toBe('3')
  })

  it('should set to readonly', () => {
    component.readonly = 'true'

    component.ngOnInit()
    fixture.detectChanges()

    expect(component.readonly).toBe('true')
    expect(component.isReadOnly).toBeTrue
    expect(compiled.getAttribute('readonly')).toBeTrue
  })

  it('should set styleClass', () => {
    component.styleClass = 'input_disabled'

    component.ngOnInit()
    fixture.detectChanges()

    expect(component.styleClass).toBe('input_disabled')
    expect(component.class).toBe('input_disabled')
    expect(compiled.getAttribute('class')).toBe('input_disabled')
  })
});

我的组件没有模板,因为该组件在技术上不是一个组件,而是一个具有自定义行为属性的元素,因此当组件由测试编译时,它呈现如下:<div id="root66" ng-version="11.0.9"></div>而不是这样:<input id="root66" ng-version="11.0.9"/>。我无法像输入一样测试 div,这就是我要解决的问题。问题是:有没有办法将组件模拟为输入而不是 div,以便我可以正确测试功能?

标签: angularunit-testingjasmine

解决方案


如果要使用属性选择器或指令测试组件,则必须将其封装在另一个组件中。这是一个例子:

@Component({
  selector: 'prps-text-test',
  template:`<div [prps-text]></div>
  `,
})
export class PrpsTextTestComponent {}

describe('PrpsTextComponent', () => {
  let component: PrpsTextTestComponent;
  let fixture: ComponentFixture<PrpsTextTestComponent>;
  let compiled: HTMLElement;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      declarations: [ PrpsTextComponent, PrpsTextTestComponent ]
    })
    .compileComponents();
  });

 [...]
});

推荐阅读