1

I am writing an Angular application, and it just happens that one of the third-party components happens to be in React. I wrote a wrapper NG component to render the React one, and it works beautifully giving the desired result. However, this setup messes up all the test cases giving the dreaded error:

Cannot read properties of undefined (reading 'ɵcmp')

The test cases are written in jest.

React Component

export const ReactoComponent: FunctionComponent<IProps> = (props: IProps) => {
  return (
    <div className={`reacto-component`}>
      <span>Counter: {props.counter}</span>
    </div>
  );
};

Angular Wrapper

@Component({
  selector: 'wrapper',
  standalone: true,
  templateUrl: './wrapper.component.html',
})
export class WrapperComponent implements AfterViewInit {
  counter = 42;

  @ViewChild('myReactContainer', { static: false }) container!: ElementRef;

  ngAfterViewInit() {
    this.render();
  }

  render() {
    const { counter } = this;
    ReactDOM.render(
      <div className={'wrapper'}>
        <ReactoComponent counter={counter} />
      </div>,
      this.container.nativeElement
    );
  }
}

Wrapper Test

describe('WrapperComponent', () => {
  let component: WrapperComponent;
  let fixture: ComponentFixture<WrapperComponent>;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [WrapperComponent],
    }).compileComponents();

    fixture = TestBed.createComponent(WrapperComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });
});

Error

Expected value   undefined
Received:
  undefined

Message:
  Cannot read properties of undefined (reading 'ɵcmp')

jest.config

module.exports = {
  preset: 'jest-preset-angular',
  setupFilesAfterEnv: ['<rootDir>/setup-jest.ts'],
  globalSetup: 'jest-preset-angular/global-setup',
  testMatch: ['**/*.test.ts'],
};

How do I fix the unit tests?

I was able to replicate the error using a simple Stackblitz: https://stackblitz.com/edit/stackblitz-starters-se1ssj (run npm run test on the Stackblitz console)

2
  • 1
    You need to properly configure jest to transform tsx files stackblitz.com/edit/… Commented Nov 19, 2024 at 13:35
  • @yurzui Thanks! Please add it as an answer (and mention the config change) so that I can accept it Commented Nov 19, 2024 at 14:00

2 Answers 2

2
+50

You probably need to configure jest to properly take .tsx files otherwise it can't find them so that you're getting undefined

jest.config.js

module.exports = {
  preset: 'jest-preset-angular',
  setupFilesAfterEnv: ['<rootDir>/setup-jest.ts'],
  globalSetup: 'jest-preset-angular/global-setup',
  testMatch: ['**/*.test.ts'],
  moduleFileExtensions: ['ts', 'tsx', 'js', 'json'],  // add these
  transform: {                                        // two options
    '^.+\\.(tsx)?$': 'ts-jest',
  },
};
Sign up to request clarification or add additional context in comments.

Comments

1

The error should be likely due to the fact that Angular's standalone components are not yet fully supported in your testing setup. To fix this, you can try the below steps:

  • Ensure Angular and Jest are properly configured: Make sure you have the necessary dependencies and configurations for Jest and Angular.

  • Update the TestBed configuration: Since WrapperComponent is a standalone component, you need to ensure that it is properly imported and declared in the TestBed configuration.

You can update the test file as follow:

import { ComponentFixture, TestBed } from '@angular/core/testing';
import { WrapperComponent } from './wrapper.component';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';

describe('WrapperComponent', () => {
  let component: WrapperComponent;
  let fixture: ComponentFixture<WrapperComponent>;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [WrapperComponent],
      schemas: [CUSTOM_ELEMENTS_SCHEMA], // Add this line
    }).compileComponents();

    fixture = TestBed.createComponent(WrapperComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });
});

Explanation: We have added CUSTOM_ELEMENTS_SCHEMA that allows the use of custom elements (like your standalone component) in the template without throwing errors.

  • Note: Please ensure proper imports. Make sure that WrapperComponent is imported in the TestBed.configureTestingModule properly.

Safety Checks:

  • Check your Jest Configuration: Ensure that your Jest configuration (jest.config.js) is properly setup and you're able to test the application if this test class is excluded.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.