Search code examples
angulartypescriptjasmine

Why is the primeng dialog empty during Jasmine testing of this Angular TypeScript app?


I am trying to test a component by clicking on the actual elements. However, the elements don't seem to render properly in test.

I have the following component.

import {ChangeDetectionStrategy, Component, EventEmitter, Input, Output} from '@angular/core';

@Component({
    selector: 'app-help',
    changeDetection: ChangeDetectionStrategy.OnPush,
    templateUrl: './help.component.html',
    styleUrls: ['./help.component.scss']
})
export class HelpComponent {
    @Input() showHelp = false;
    @Input() version = '0';
    @Input() versionCheck = false;
    @Output() emitCloseHelpDialog = new EventEmitter<any>();
    @Output() emitSubmitHelpForm = new EventEmitter<any>();

    additionalHelpInformationStr = '';

    closeHelpDialog(evt) {
        this.emitCloseHelpDialog.emit();
    }

    submitHelpForm(evt) {
        const formData = {
            additionalHelpInformationStr:
            this.additionalHelpInformationStr,
        };
        this.emitSubmitHelpForm.emit(formData);
    }

    reloadIdea(evt) {
        location.reload(true);
    }
}

Which has a template which looks like so:

<p-dialog (onHide)="closeHelpDialog($event)"
      [(visible)]="showHelp"
      [closeOnEscape]="false"
      [modal]="false"
      [resizable]="false"
      [responsive]="false"
      appendTo="body"
      styleClass="help-dialog"
      header="Support">
<div *ngIf="versionCheck">
    A new version ofis available. Click to <span
(click)="reload($event)"
class="new-version-notice">reload</span>.
    <br/>
</div>
<span>
    Please add a comment or concern below.<br/>
    <textarea [(ngModel)]="additionalHelpInformationStr"
              #additionalHelpInformation
              cols="75"
              class="help-textarea"
              pInputTextarea
              rows="10"></textarea>
</span>
<div class="style-notice">
    Version: {{ version }}
</div>
<p-footer>
    <p class="align-right">
        <button (click)="closeHelpDialog($event)"
                class="ui-button-secondary"
                icon="fa fa-fw fa-close"
                label="Cancel"
                type="button"
                pButton></button>
        <button (click)="submitHelpForm($event)"
                class="ui-button"
                icon="fa fa-paper-plane"
                label="Send"
                type="button"
                pButton></button>
    </p>
</p-footer>

The problem is when I try to test. The HTML does not fully render.

<div id="root0" _nghost-a-c0="" ng-version="8.2.4">
    <p-dialog _ngcontent-a-c0=""
              appendto="body"
              header="Support"
              styleclass="help-dialog"
              ng-reflect-visible="false"
              ng-reflect-header="Support"
              ng-reflect-resizable="false"
              ng-reflect-modal="false"
              ng-reflect-close-on-escape="false"
              ng-reflect-responsive="false"
              ng-reflect-append-to="body"
              ng-reflect-style-class="help-dialog">
    <!--bindings={"ng-reflect-ng-if": "false"}-->
</p-dialog>
</div>

This is what my test component looks like:

import {ComponentFixture, TestBed} from '@angular/core/testing';
import {HelpComponent} from './help.component';
import {DialogModule} from 'primeng/dialog';
import {InputTextareaModule} from 'primeng/inputtextarea';
import {FormsModule} from '@angular/forms';

describe('help component', () => {

    let app: HelpComponent;
    let fixture: ComponentFixture<HelpComponent>;

    beforeEach(() => {
        TestBed.configureTestingModule({
            declarations: [
                HelpComponent,
            ],
            imports: [
                DialogModule,
                FormsModule,
                InputTextareaModule,
            ],
            }
        );

        fixture = TestBed.createComponent(HelpComponent);
        app = fixture.debugElement.componentInstance;
    });

    it('should create properly', () => {
        expect(app).toBeTruthy();
        fixture.detectChanges();
        fixture.whenStable().then(() => {
        const element = fixture.nativeElement;
        // this console log outputs the HTMLfragment above which is empty
        console.log('element is ', element);
    });
});

    it('should emit close dialog event', () => {
        // this test of course works.
        const component = fixture.componentInstance;
        spyOn(component.emitCloseHelpDialog, 'emit');
        component.closeHelpDialog(new Event('click'));
        fixture.detectChanges();
     expect(component.emitCloseHelpDialog.emit).toHaveBeenCalledWith();
    });
});

What am I missing?


Solution

  • Install ng-mocks from npm or similar and then change your TestBed to the following:

    TestBed.configureTestingModule({
            declarations: [
                HelpComponent,
                MockComponent(Dialog),
            ],
            schemas: [
                CUSTOM_ELEMENTS_SCHEMA
            ],
            imports: [
                FormsModule,
                InputTextareaModule,
            ],
            }
        );