How to Display Rendered Component with Karma Test Runner?

Viewed 458

I have created a new angular app v13 using cli with the defaults. I replaced the app.component.html file to display 4 images. This loads in the browser fine doing npm start. When I run npm test and run the test that checks for the existence of these images (using a class selector) the test passes but I don't see the images in the Karma chrome browser window. Using devtools I see they are loaded.

In general, how do I get the component dom to display on Karma Chrome page?

EDIT: Here's some code

app.component.ts

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'flopbuster_basics';
}

app.component.css

.fit-picture {
    width: 250px;
}

app.component.html

<div class="posters">
  <span class="poster">
    <img class="fit-picture" src="assets/images/posters/cloudy.jpg" alt="Cloudy With a Chance of Meatballs">
  </span>
  <span class="poster">
    <img class="fit-picture" src="assets/images/posters/luca.jpg" alt="Luca">
  </span>
  <span class="poster">
    <img class="fit-picture" src="assets/images/posters/peanuts.jpg" alt="The Peanuts Movie">
  </span>
  <span class="poster">
    <img class="fit-picture" src="assets/images/posters/zootopia.jpg" alt="Zootopia">
  </span>
</div>

app.component.spec.ts

import { TestBed } from '@angular/core/testing';
import { AppComponent } from './app.component';

describe('AppComponent', () => {
  beforeEach(async () => {
    await TestBed.configureTestingModule({
      declarations: [
        AppComponent
      ],
    }).compileComponents();
  });

  it('should create the app', () => {
    const fixture = TestBed.createComponent(AppComponent);
    const app = fixture.componentInstance;
    expect(app).toBeTruthy();
  });

  it(`should have as title 'flopbuster_basics'`, () => {
    const fixture = TestBed.createComponent(AppComponent);
    const app = fixture.componentInstance;
    expect(app.title).toEqual('flopbuster_basics');
  });

  it('should display the movie posters of 4 movie flops', () => {
    const fixture = TestBed.createComponent(AppComponent);
    fixture.detectChanges();
    const compiled = fixture.nativeElement as HTMLElement;
    expect(compiled.querySelectorAll('.poster').length).toBe(4);
  });
});

karma.conf.js

// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html

module.exports = function (config) {
  config.set({
    basePath: '',
    frameworks: ['jasmine', '@angular-devkit/build-angular'],
    plugins: [
      require('karma-jasmine'),
      require('karma-chrome-launcher'),
      require('karma-jasmine-html-reporter'),
      require('karma-coverage'),
      require('@angular-devkit/build-angular/plugins/karma')
    ],
    client: {
      jasmine: {
        // you can add configuration options for Jasmine here
        // the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html
        // for example, you can disable the random execution with `random: false`
        // or set a specific seed with `seed: 4321`
      },
      clearContext: false // leave Jasmine Spec Runner output visible in browser
    },
    jasmineHtmlReporter: {
      suppressAll: true // removes the duplicated traces
    },
    coverageReporter: {
      dir: require('path').join(__dirname, './coverage/flopbuster_basics'),
      subdir: '.',
      reporters: [
        { type: 'html' },
        { type: 'text-summary' }
      ]
    },
    reporters: ['progress', 'kjhtml'],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    browsers: ['Chrome'],
    singleRun: false,
    restartOnFileChange: true,
    files: [
      {pattern: 'src/assets/images/posters/*.jpg', watched: false, included: false, served: true, nocache: false}

    ]
  });
};

package.json

{
  "name": "flopbuster-basics",
  "version": "0.0.0",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "watch": "ng build --watch --configuration development",
    "test": "ng test"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "~13.2.0",
    "@angular/common": "~13.2.0",
    "@angular/compiler": "~13.2.0",
    "@angular/core": "~13.2.0",
    "@angular/forms": "~13.2.0",
    "@angular/platform-browser": "~13.2.0",
    "@angular/platform-browser-dynamic": "~13.2.0",
    "@angular/router": "~13.2.0",
    "rxjs": "~7.5.0",
    "tslib": "^2.3.0",
    "zone.js": "~0.11.4"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "~13.2.5",
    "@angular/cli": "~13.2.5",
    "@angular/compiler-cli": "~13.2.0",
    "@types/jasmine": "~3.10.0",
    "@types/node": "^12.11.1",
    "jasmine-core": "~4.0.0",
    "karma": "~6.3.0",
    "karma-chrome-launcher": "~3.1.0",
    "karma-coverage": "~2.1.0",
    "karma-jasmine": "~4.0.0",
    "karma-jasmine-html-reporter": "~1.7.0",
    "typescript": "~4.5.2"
  }
}

The rendered page Rendered page

But here is the test output in Karma

karma output in chrome

And using DevTools I see the images are getting loaded loaded images

1 Answers

I had the same issue and I resolved it by modifying the project's test.ts file to pass ModuleTeardownOptions to getTestBed().initTestEnvironment() with a value of { teardown: { destroyAfterEach: false }}, like this:

getTestBed().initTestEnvironment(
  BrowserDynamicTestingModule,
  platformBrowserDynamicTesting(),
  // Set destroyAfterEach to false:
  { teardown: { destroyAfterEach: false }}
);

You can either pass the options to TestBed.configureTestingModule() for any specific test case(s), or globally via TestBed.initTestEnvironment() like in the example above.

Related