Kumar
Kumar

Reputation: 256

Test case to emit an event on change of a checkbox

Html:

<checkbox (change)="onChange()" [(ngModel)]="ngModel"> Checkbox </checkbox>

ts:

ngModel: boolean;

@Output() checkboxEvent = new EventEmitter<any>();

onChange() {
this.checkboxEvent.emit(this.ngModel);
}

test case:

it('TC 3: should emit an event on change of checkbox', async(() => {
    spyOn(component.checkboxEvent, 'emit');
    component.onChange();
    const edlCheckbox = fixture.debugElement.query(By.css('checkbox ')).nativeElement;
    edlCheckbox.dispatchEvent(new Event('change'));
    fixture.detectChanges();
    expect(component.checkboxEvent ).toHaveBeenCalled();
    expect(component.checkboxEvent .emit).toHaveBeenCalledWith(true);
  }));

Error:

Failed: <toHaveBeenCalled> : Expected a spy, but got EventEmitter(
{ _isScalar: false, observers: [  ], closed: false, 
isStopped: false, hasError: false, thrownError: null,
 __isAsync: false, emit: spy on emit }).
Usage: expect(<spyObj>).toHaveBeenCalled()

Upvotes: 1

Views: 2756

Answers (3)

B.Ramburn
B.Ramburn

Reputation: 306

Ok I got this one working using the following with reactiveforms and faker in my test. You don't have to use Faker.

<div [formGroup]="todoItemFormGroup">
<input type="checkbox" (click)="checkedInput()" formControlName="isComplete" />
....

</div>

I'm using reactiveForm group

    todoItemFormGroup = new FormGroup(
        {
            name: new FormControl('', [Validators.required]),
            isComplete: new FormControl(false)
        }
    )

    checkedInput() {
        this.updateItemtoParent.emit({
            ...this.todoItem.getValue(), //this is my BehaviorSubject<TodoItemDto>
            ...this.todoItemFormGroup.getRawValue() as TodoItemDto, //this is from the formgroup
        } as TodoItemDto);
    }

and finally my spec looks like this:

it("Should emit the checklist item when the checkbox is checked", () => {
        spyOn(component.updateItemtoParent, 'emit');
        const fakeTodoItem: TodoItemDto = {
            id: faker.datatype.uuid(),
            name: faker.name.firstName(),
            checklistId: faker.datatype.uuid(),
            isComplete: false
        };
        component.todoItem.next(fakeTodoItem);
        fixture.detectChanges();
        const compiled = fixture.debugElement.query(By.css('input[type=checkbox]'));

        compiled.nativeElement.click();
        fixture.detectChanges();

        expect((component.todoItemFormGroup.getRawValue() as TodoItemDto).isComplete).toEqual(true);

        expect(component.updateItemtoParent.emit).toHaveBeenCalledWith(fakeTodoItem);
    });

Upvotes: 0

Arnaud Denoyelle
Arnaud Denoyelle

Reputation: 31245

You can do it easier with a callback function :

                                                     // vvvv
it('TC 3: should emit an event on change of checkbox', (done) => {
                                         // vvvv
    component.checkboxEvent.subscribe(() => done());
    fixture.debugElement.query(By.css('checkbox ')).nativeElement.click()
}

By using a done function, the test will fail if the done function is not called within 5s (customizable).

Note : this test does not need any expect() but Karma will complain if you do a test without expect() call. The test will succeed but will provoke a warning.

Upvotes: 0

nircraft
nircraft

Reputation: 8478

You should try this:

it('TC 3: should emit an event on change of checkbox', async(() => {
    spyOn(component.checkboxEvent, 'emit');
    spyOn(component, 'onChange');
    const edlCheckbox = fixture.debugElement.query(By.css('checkbox ')).nativeElement;
    edlCheckbox.click();
    fixture.detectChanges();

    expect(component.onChange).toHaveBeenCalled(); 
    expect(component.checkboxEvent.emit).toHaveBeenCalledWith(true);

  }));

Upvotes: 1

Related Questions