Skip to content

bug(Dialog): MatTestDialogOpener (This constructor is not compatible with Angular Dependency Injection) #27703

Open
@bederuijter

Description

@bederuijter

Is this a regression?

  • Yes, this behavior used to work in the previous version

The previous version in which this bug was not present was

No response

Description

The MatDialog API mentions a MatTestDialogOpener that can be used when writing tests that involve a mat-dialog.

Instead, when using the MatTestDialogOpener when writing my test it throws an error:

NG0202: This constructor is not compatible with Angular Dependency Injection because its dependency at index 0 of the parameter list is invalid.
   This can happen if the dependency type is a primitive like a string or if an ancestor of this class is missing an Angular decorator.

   Please check that 1) the type for the parameter at index 0 is correct and 2) the correct Angular decorators are defined for this class and its ancestors.

Reproduction

I don't know how to provide a StackBlitz reproduction that involve a test. Using the mat dialog opener test I was still able to reproduce the error (In the hopes of eliminating user error 🙂)

import {Component, Inject} from '@angular/core';
import {fakeAsync, TestBed, flush} from '@angular/core/testing';
import {MatTestDialogOpenerModule, MatTestDialogOpener} from '@angular/material/dialog/testing';
import {MAT_DIALOG_DATA, MatDialogRef, MatDialogState} from '@angular/material/dialog';
import {NoopAnimationsModule} from '@angular/platform-browser/animations';

describe('MDC-based MatTestDialogOpener', () => {
  beforeEach(fakeAsync(() => {
    TestBed.configureTestingModule({
      imports: [MatTestDialogOpenerModule, NoopAnimationsModule],
      declarations: [ExampleComponent],
    });

    TestBed.compileComponents();
  }));

  it('should open a dialog when created', fakeAsync(() => {
    const fixture = TestBed.createComponent(MatTestDialogOpener.withComponent(ExampleComponent));
    flush();
    expect(fixture.componentInstance.dialogRef.getState()).toBe(MatDialogState.OPEN);
    expect(document.querySelector('mat-dialog-container')).toBeTruthy();
  }));

  it('should throw an error if no dialog component is provided', () => {
    expect(() => TestBed.createComponent(MatTestDialogOpener)).toThrow(
      Error('MatTestDialogOpener does not have a component provided.'),
    );
  });

  it('should pass data to the component', fakeAsync(() => {
    const config = {data: 'test'};
    TestBed.createComponent(MatTestDialogOpener.withComponent(ExampleComponent, config));
    flush();
    const dialogContainer = document.querySelector('mat-dialog-container');
    expect(dialogContainer!.innerHTML).toContain('Data: test');
  }));

  it('should get closed result data', fakeAsync(() => {
    const config = {data: 'test'};
    const fixture = TestBed.createComponent(
      MatTestDialogOpener.withComponent<ExampleComponent, ExampleDialogResult>(
        ExampleComponent,
        config,
      ),
    );
    flush();
    const closeButton = document.querySelector('#close-btn') as HTMLElement;
    closeButton.click();
    flush();
    expect(fixture.componentInstance.closedResult).toEqual({reason: 'closed'});
  }));
});

interface ExampleDialogResult {
  reason: string;
}

/** Simple component for testing MatTestDialogOpener. */
@Component({
  template: `
    Data: {{data}}
    <button id="close-btn" (click)="close()">Close</button>
  `,
})
class ExampleComponent {
  constructor(
    public dialogRef: MatDialogRef<ExampleComponent, ExampleDialogResult>,
    @Inject(MAT_DIALOG_DATA) public data: any,
  ) {}

  close() {
    this.dialogRef.close({reason: 'closed'});
  }
}

Expected Behavior

To be able to write tests using the MatTestDialogOpener

Actual Behavior

MatTestDialogOpener throwing an error related to the Dependency injection

NG0202: This constructor is not compatible with Angular Dependency Injection because its dependency at index 0 of the parameter list is invalid.
    This can happen if the dependency type is a primitive like a string or if an ancestor of this class is missing an Angular decorator.

    Please check that 1) the type for the parameter at index 0 is correct and 2) the correct Angular decorators are defined for this class and its ancestors.

      at ɵɵinvalidFactoryDep (../../../../node_modules/@angular/core/fesm2022/core.mjs:668:11)
      at NodeInjectorFactory.MatTestDialogOpener2_Factory [as factory] (../../../../ng:/MatTestDialogOpener2/ɵfac.js:5:48)
      at getNodeInjectable (../../../../node_modules/@angular/core/fesm2022/core.mjs:4669:44)
      at createRootComponent (../../../../node_modules/@angular/core/fesm2022/core.mjs:13264:35)
      at ComponentFactory.create (../../../../node_modules/@angular/core/fesm2022/core.mjs:13122:25)
      at initComponent (../../../../node_modules/@angular/core/fesm2022/testing.mjs:26421:51)
      at _ZoneDelegate.Object.<anonymous>._ZoneDelegate.invoke (../../../../node_modules/zone.js/bundles/zone-testing-bundle.umd.js:421:30)
      at FakeAsyncTestZoneSpec.Object.<anonymous>.FakeAsyncTestZoneSpec.onInvoke (../../../../node_modules/zone.js/bundles/zone-testing-bundle.umd.js:4779:37)
      at ProxyZoneSpec.Object.<anonymous>.ProxyZoneSpec.onInvoke (../../../../node_modules/zone.js/bundles/zone-testing-bundle.umd.js:3088:43)
      at _ZoneDelegate.Object.<anonymous>._ZoneDelegate.invoke (../../../../node_modules/zone.js/bundles/zone-testing-bundle.umd.js:420:56)
      at Object.onInvoke (../../../../node_modules/@angular/core/fesm2022/core.mjs:26321:33)
      at _ZoneDelegate.Object.<anonymous>._ZoneDelegate.invoke (../../../../node_modules/zone.js/bundles/zone-testing-bundle.umd.js:420:56)
      at Zone.Object.<anonymous>.Zone.run (../../../../node_modules/zone.js/bundles/zone-testing-bundle.umd.js:175:47)
      at NgZone.run (../../../../node_modules/@angular/core/fesm2022/core.mjs:26175:28)
      at _TestBedImpl.createComponent (../../../../node_modules/@angular/core/fesm2022/testing.mjs:26424:41)
      at Function.createComponent (../../../../node_modules/@angular/core/fesm2022/testing.mjs:26231:37)

Environment

  • Angular: 16.1.7
  • CDK/Material: 16.1.6
  • Browser(s): N/A
  • Operating System (e.g. Windows, macOS, Ubuntu): macOS

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3An issue that is relevant to core functions, but does not impede progress. Important, but not urgentarea: material/dialog

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions