How to use testing-library in Angular 15
Tags: angular, testing, typescript, javascript
Published: 2023-03-22 17:19:19

The included karma/jasmine tests do not follow modern testing-principles like role selectors.

Therefore I recommend removing these tests and replace them with the more useful testing-library approach.

Steps to setup testing-library in an Angular 15 project

# Remove the karma/jasmine tests

- remove all karma & jasmine dependencies from the package.json

```sh
npm remove -D @types/jasmine jasmine-core karma karma-chrome-launcher karma-coverage karma-jasmine karma-jasmine-html-reporter
```

# Install testing-library

```sh
npm i -D @testing-library/dom @testing-library/angular
```

# Install jest test runner

We use jest-preset-angular build on top of ts-jest.

```sh
 npm i -D jest @types/jest jest-preset-angular
```
Create jest configuration file in root: jest.config.js

```js
module.exports = {
  preset: "jest-preset-angular",
  setupFilesAfterEnv: ["<rootDir>/setup-jest.ts"]
};

```

create setup-jest.ts, also includes the most important mocks...

```ts
import 'jest-preset-angular/setup-jest';
Object.defineProperty(window, 'CSS', { value: null });
Object.defineProperty(document, 'doctype', {
  value: '<!DOCTYPE html>',
});
Object.defineProperty(window, 'getComputedStyle', {
  value: () => {
    return {
      display: 'none',
      appearance: ['-webkit-appearance'],
    };
  },
});
/**
 * ISSUE: https://github.com/angular/material2/issues/7101
 * Workaround for JSDOM missing transform property
 */
Object.defineProperty(document.body.style, 'transform', {
  value: () => {
    return {
      enumerable: true,
      configurable: true,
    };
  },
});


```

# change test script

Inside the package.json just replace the test script

from
```json
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "watch": "ng build --watch --configuration development",
    "test": "ng test"
  },
```

to
```json
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "watch": "ng build --watch --configuration development",
    "test": "jest --watch"
  },
```
and remove the test settings from angular.json

```json
...
      "test": {
          "builder": "@angular-devkit/build-angular:karma",
          "options": {
...
```

# create a single angular module definition

I always have a single angular module definition I can pass to testing-library/angular render method. I just reuse it all the time

```ts

export const testModule = {
  declarations: [
    // ...all the declarations from the app.module.ts
  ],
  imports: [
    // ...all the imports from the app.module.ts
    BrowserModule,
    AppRoutingModule,
    CommonModule,
    FormsModule,
    HttpClientModule,
    ReactiveFormsModule,
  ],
  providers: [],
  bootstrap: [AppComponent],
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
};

```

# enjoy

npm run test

should just run the tests inside jest. The existing tests in spec file should be replace by testing-library style tests.

example test:

```ts
import { screen, render } from '@testing-library/angular';
import { testModule } from '../../test.module';

import { CreateAppointmentPageComponent } from './create-appointment-page.component';

describe('CreateAppointmentPageComponent', () => {
  it('should create', async () => {
    await render(CreateAppointmentPageComponent, testModule);
    screen.logTestingPlaygroundURL();
  });
});


```

# known issues

import from src folder does not work, it just does not find something under e.g.

```ts
import { TestService } from 'src/app/services/testService.ts'
```

instead I try always to use relative imports, I never had trouble using them...

```ts
import { TestService } from '../../services/testService.ts'
```