Search code examples
angularjestjstestbed

When exactly is compileComponents needed?


I am migrating my component unit tests with only jest to UI tests using Testbed and jest (Before I had just unit test with component = new MyCompontent()).

I am using Angular 11.

There is one thing I do not understand about compileComponents. In the docs it says "You can ignore this section if you only run tests with the CLI ng test command because the CLI compiles the application before running the tests."

I am not calling ng test but jest --watch but my tests work both with and without compileComponents ( by work I mean they assert correctly my view).

Also there is a "You must call this method if any of the testing module components have a templateUrl or styleUrls because fetching component template and style files is necessarily asynchronous"

My component is using both templateUrl and styleUrls

@Component({
  selector: 'app-my-example',
  templateUrl: './my-example.component.html',
  styleUrls: ['./my-example.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class MyExampleComponent {}

So what I am missing? I want to be sure that my test will not break if I eventually set a CI or similar.

or should I always call compileComponents ? I am under the impression it will be not so efficent to do this if not needed.

So, when exactly does compileComponents is needed ?

Edit:

This is my jest config

module.exports = {
  preset: 'jest-preset-angular',
  setupFilesAfterEnv: ['<rootDir>/src/setupJest.ts'],
  transformIgnorePatterns: ['<rootDir>/node_modules/(?!@ionic|@saninn|@ngrx|@capacitor-community|@capacitor)'],
  watchPathIgnorePatterns: ['/node_modules/', ...ignoredFiles],
  coverageReporters: process.env.CI ? ['text'] : ['lcov'],
  // coverageReporters: ['lcov'],
  // coverageReporters: ['text'],
  testPathIgnorePatterns: ['/node_modules/', ...ignoredFiles],
  modulePathIgnorePatterns: [...ignoredFiles],
  collectCoverage: false,
  notify: true,
  // notifyMode: 'failure',
  coverageDirectory: './coverage',
  collectCoverageFrom: ['<rootDir>/src/**/*.ts', '!**/*.module.ts', '!**/*.enum.ts'],
  coveragePathIgnorePatterns: ['/node_modules/', 'package.json', ...ignoredFiles],
  globals: {
    'ts-jest': {
      tsconfig: '<rootDir>/src/tsconfig.spec.json',
      diagnostics: {
        ignoreCodes: [
          6138, // declared but never read
          6133, // declared but never used,
          2322 // object should just have known keys
        ]
      }
    }
  }
};

Solution

  • I suspect you don't see any difference between running ng test and jest command because your jest configuration uses jest-preset-angular that involves its own Angular replace resource transformer https://github.com/thymikee/jest-preset-angular/blob/master/src/transformers/replace-resources.ts

     * Given the input
     * @Component({
     *   selector: 'foo',
     *   templateUrl: './foo.component.html`,
     *   styleUrls: ['./foo.component.scss'],
     *   styles: [`h1 { font-size: 16px }`],
     * })
     *
     * Produced the output for `CommonJS`
     * @Component({
     *   selector: 'foo',
     *   templateUrl: require('./foo.component.html'),
     *   styles: [],
     * })
    

    That is similar that Angular CLI does https://github.com/angular/angular-cli/blob/master/packages/ngtools/webpack/src/transformers/replace_resources.ts

    See also: