SzybkiSasza
SzybkiSasza

Reputation: 1599

Cannot properly test files that are not part of the project directory in Angular + Karma

I have a following files structure:

Both projects (App and Lib) were built using Angular CLI (angular.json is unchanged so far, apart from codeCoverage option). I'm not able to run the tests that are part of shared directory:

I think the problem for the App is that the coverage reporter does not see the shared directory, despite the fact that the tests (and even final report) include these (it only shows src from the project)

As for the library, I suppose it's something about how does the Karma resolve the paths so Typescript can see them.

My test.ts file (only additional paths were added):

// This file is required by karma.conf.js and loads recursively all the .spec and framework files

import 'zone.js/dist/zone-testing-bundle';

import { getTestBed } from '@angular/core/testing'; // tslint:disable-line
import {
  BrowserDynamicTestingModule,
  platformBrowserDynamicTesting
} from '@angular/platform-browser-dynamic/testing';

declare const require: any;

// First, initialize the Angular testing environment.
getTestBed().initTestEnvironment(
  BrowserDynamicTestingModule,
  platformBrowserDynamicTesting()
);

// Then we find all the tests.
const projectContext = require.context('./', true);
const sharedContext = require.context('../../../shared', true);

// And load the modules.
sharedContext.keys().map(sharedContext);
projectContext.keys().map(projectContext);

My 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: '../../shared',
    frameworks: ['jasmine', '@angular-devkit/build-angular'],
    plugins: [
      require('karma-jasmine'),
      require('karma-chrome-launcher'),
      require('karma-mocha-reporter'),
      require('karma-jasmine-html-reporter'),
      require('karma-coverage-istanbul-reporter'),
      require('@angular-devkit/build-angular/plugins/karma')
    ],
    client: {
      clearContext: false // leave Jasmine Spec Runner output visible in browser
    },
    coverageIstanbulReporter: {
      dir: require('path').join(__dirname, '../coverage'),
      reports: ['html', 'lcovonly', 'text-summary'],
      fixWebpackSourcePaths: true
    },
    reporters: ['mocha'],
    mochaReporter: {
      ignoreSkipped: true
    },
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    browsers: ['ChromeHeadless'],
    singleRun: false,
  });
};

My tsconfig.spec.json (I tried to modify paths, but it didn't help):

{
  "extends": "../../tsconfig.json",
  "compilerOptions": {
    "baseUrl": "../../",
    "rootDir": "../../",
    "outDir": "../../out-tsc/spec",
    "types": [
      "jasmine",
      "node"
    ],
    "module": "esnext",
    "inlineSources": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "resolveJsonModule": true,
    "esModuleInterop": true,
    "importHelpers": true,
    "preserveSymlinks": true
  },
  "include": [
    "./src/**/*.ts",
    "./src/**/*.spec.ts",
    "../../shared/**/*.ts",
    "../../shared/**/*.spec.ts"
  ],
  "exclude": []
}

Any ideas?

Upvotes: 1

Views: 1797

Answers (1)

SzybkiSasza
SzybkiSasza

Reputation: 1599

The problem boiled down to including shared files two times in compilation. It's enough to have projectContext.keys() in test.ts as follows:

// This file is required by karma.conf.js and loads recursively all the .spec and framework files

import 'zone.js/dist/zone-testing-bundle';

import { getTestBed } from '@angular/core/testing'; // tslint:disable-line
import {
  BrowserDynamicTestingModule,
  platformBrowserDynamicTesting
} from '@angular/platform-browser-dynamic/testing';

declare const require: any;

// First, initialize the Angular testing environment.
getTestBed().initTestEnvironment(
  BrowserDynamicTestingModule,
  platformBrowserDynamicTesting()
);

// Then we find all the tests.
const projectContext = require.context('./', true);

// And load the modules.
projectContext.keys().map(projectContext);

This works because shared is symlinked inside lib directory. Symlink, thanks to Git implementation, is even portable between Unix / Windows. That solved it!

So to sum up:

  • Add symlink to shared directory inside projects instead of using real directory
  • Remove duplicated require.context
  • Use files from symlinked directory instead of going two paths outside of the project

Upvotes: 1

Related Questions