spectator: Can't get instance of tested component when using custom host

Hello, thanks for great lib! I have DownloadComponent inside DropzoneComponent that itself used inside ParentComponent:

Parent
    |
    ---> Dropzone (child)
               |
               ---> Download (grandchild)

Now I want to test DropzoneComponent ability to redirect data from it’s child DownloadComponent to it’s parent ParentComponent.

...
export class DownloadComponent {
    @Output() selectedFile = new EventEmitter<string>();

    onDownloadClick(fileType: ExportFileFormat): void {
        this.selectedFile.emit('someValue');`
    }
}
...
export class DropzoneComponent {
    @Input() allowCSV = false;
    @Input() sampleTemplateFilename = null;

    @Output() file = new EventEmitter<string>();
    @Output() template = new EventEmitter<string>();

    onTemplateSelectedForDownload(file: string): void {`
        this.template.emit(file);`
    }
}

Template of DropzoneComponent:

...
<p *ngIf="sampleTemplateFilename">
    <app-download
        fileName="sampleTemplateFilename"
        (selectedFile)="onTemplateSelectedForDownload($event)"
    ></app-download>
</p>
...

What I’m doing:

@Component({
   selector: 'host',
   template: '',
   changeDetection: ChangeDetectionStrategy.OnPush,
})
class HostComponent {
   allowCSV = false;
   sampleTemplateFilename = '';
   onTemplate = (template: string): void => {}; // I want to test this method have been called
   onFile = (file: string): void => {};
}

fdescribe('DropzoneComponent', () => {
  const templateName = 'test.csv';
  const createHost = createHostFactory({
    component: DropzoneComponent,
    host: HostComponent,
  });

let host: SpectatorHost<DropzoneComponent, HostComponent>;

beforeEach(() => {
   host = createHost("
      <app-dropzone
         [allowCSV]="allowCSV"
         [sampleTemplateFormats]=""
         (template)="onTemplate()"
         (file)="onFile()">
      </app-dropzone>
   " );
});

it('Should redirect sample template file name to parent component', () =>
   const downloadComponent = host.get<DownloadComponent>(DownloadComponent);
   const dropzoneComponent = host.get<DropzoneComponent>(DropzoneComponent);
   const templateEmitSpy = spyOn(dropzoneComponentt.template, 'emit');
   downloadComponent['selectedFile'] = new EventEmitter<string>() as any;
   downloadComponentt.selectedFile.emit(templateName);
   expect(templateEmitSpy).toHaveBeenCalledWith(templateName);
});
}

Now I have two problems in IT function:

  1. I got downloadComponent instance on line 1, but when trying to get dropzoneComponent instance on line 2 I getting “NullInjectorError: No provider for DropzoneComponent!”. How is that possible that I can get grandchild, but can’t get child?
  2. My expectation newer resolving because DownloadComponent ‘selectedFile’ output not connecting to DropzoneComponent. Is it a way to test this case somehow?

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 20 (8 by maintainers)

Most upvoted comments

Your code was within ngIf, and you didn’t use the sampleTemplateFilename input correctly. It should be used in the host. Here’s the working example: https://ng-run.com/edit/hzVfmutVQ8dj5NGpPlTa.

I spent a lot of time helping you. Try to test your code thoroughly before you say it doesn’t work. I’m sorry, this is not a StackOverflow. I hope you understand.

If things are missing from the documentation, we would love to hear.

@antonpegov Please can you at least post your full test source code (+ components under test) without compile errors? Also, I get the following error when trying to reproduce your test:

const templateEmitSpy = spyOn(downloadComponent.template, 'emit');

Property 'template' does not exist on type 'SpyObject<DownloadComponent>'.