0

This is my day 3 in Angular unit testing with Jasmine and Karma. I'm following Pluralsight lectures. First thing first, dls-option is a component which I'm using form a library. I'll explain. I'm using a library of angular components provided by our company. In the below code <dls-dropdown> and <dls-option> are nothing but <select> and <option> tag of HTML. They've created color and font styling wrapper around it. Here's my code:

timeselector.component.html

<div>
  <h1>Choose one from the list</h1>
  <dls-dropdown>
    <dls-option *ngFor="let mode of modes" [value]="mode">
      <p>{{ mode }}</p>
    </dls-option>
  </dls-dropdown>
 </div>

timeselector.component.ts

import { Component, OnInit, ... } from '@angular/core';
...

@Component({
    selector: 'app-timeselector',
    templateUrl: './timeselector.component.html'
})
export class TimeselectorComponent implements OnInit {
    modes = ["Novice", "Intermediate", "Expert", "Beast"];
    ...
}

and here's my test file: timeselector.component.spec.ts

import { TestBed, ComponentFixture } from "@angular/core/testing"
import { TimeselectorComponent } from './timeselector.component'
import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';

fdescribe('TimeselectorComponent', () => {
    let fixture: ComponentFixture<TimeselectorComponent>;
    @Component({
        selector: 'dls-label',
        template: '<div></div>'
    })
    class DlsLabelComponent {}

    @Component({
        selector: 'dls-dropdown',
        template: '<div></div>'
    })
    class DlsDropdownComponent {}


    @Component({
        selector: 'dls-option',
        template: '<div></div>'
    })
    class DlsDropdownOption {}

    beforeEach(()=>{
        TestBed.configureTestingModule({
            imports: [
                FormsModule
            ],
            declarations: [
                TimeselectorComponent,
                DlsLabelComponent,
                DlsDropdownComponent,
                DlsDropdownOption
            ]
        });
        fixture = TestBed.createComponent(TimeselectorComponent);
    })
    it('should create', ()=> {
        //expect(fixture.componentInstance).toBeTruthy();
    })
})

But my test case is failing. Here's the screenshot: enter image description here

Please help me with this and also feel free to suggest other mistakes as well. This will help me in my career.

PS: I just want to do a shallow testing. I want to mock child components.

Tanzeel
  • 4,174
  • 13
  • 57
  • 110

1 Answers1

1

I think the error message is quite precise here - the dls-options mock component is missing @Input() value.

The timeselector.component.html is rendering dls-option and passing mode into its value input:

<dls-option *ngFor="let mode of modes" [value]="mode">

So you'll need to create that input in your mock:

@Component({
    selector: 'dls-option',
    template: '<div></div>'
})
class DlsDropdownOption {
    @Input() value;
}
watofundefined
  • 334
  • 4
  • 6
  • This solved my problem. Can you please explain a little bit more. Why and how it is working now. – Tanzeel May 09 '20 at 15:15
  • 1
    Glad it did. The `timeselector.component.html` is saying that for each "mode" you want to render `dls-option` and pass that mode through its `[value]` input - hence Angular is expecting that the `dls-option` component has an input with the name "value". If Angular doesn't find such property on the `dls-option` class then it means there's a problem inside your code and Angular throws an error. – watofundefined May 09 '20 at 15:40