title: Angular2 component testing. Karma not loading templateUrl
body: <p>I am currently trying to write some tests for my Angular2 application and am having some issues whereas if I use the templateUrl property of the Angular2 component (linking to an HTML file) instead of template the test does not run. The async call back within the test will timeout as the .html file is not loaded. When I place the template code within the component file itself it works correctly. I can also see the request for the .html timing out in my browser so this leads me to the problem that the .html file is not being found.</p>
  
  <p>I have looked at my karma.conf file and everything seems to be in order. I have also set this line to 'true' to include .html files when Karma is running in the karma.conf file:</p>
  
  <pre><code>{ pattern: appBase + '**/*.html', included: true, watched: true },
  </code></pre>
  
  <p>Here is my whole karma.conf file:</p>
  
  <pre><code>module.exports = function(config) {
  
      var appBase    = 'app/';      // transpiled app JS and map files
      var appSrcBase = 'app/';      // app source TS files
      var appAssets  = 'app/'; // component assets fetched by Angular's compiler
  
      // Testing helpers (optional) are conventionally in a folder called `testing`
      var testingBase    = 'testing/'; // transpiled test JS and map files
      var testingSrcBase = 'testing/'; // test source TS files
  
      config.set({
          basePath: '',
          frameworks: ['jasmine'],
  
          plugins: [
              require('karma-jasmine'),
              require('karma-chrome-launcher'),
              require('karma-jasmine-html-reporter')
          ],
  
          client: {
              builtPaths: [appSrcBase, testingBase], // add more spec base paths as needed
              clearContext: false // leave Jasmine Spec Runner output visible in browser
          },
  
          customLaunchers: {
              // From the CLI. Not used here but interesting
              // chrome setup for travis CI using chromium
              Chrome_travis_ci: {
                  base: 'Chrome',
                  flags: ['--no-sandbox']
              }
          },
  
          files: [
              // System.js for module loading
              'node_modules/systemjs/dist/system.src.js',
  
              // Polyfills
              'node_modules/core-js/client/shim.js',
              'node_modules/reflect-metadata/Reflect.js',
  
              // zone.js
              'node_modules/zone.js/dist/zone.js',
              'node_modules/zone.js/dist/long-stack-trace-zone.js',
              'node_modules/zone.js/dist/proxy.js',
              'node_modules/zone.js/dist/sync-test.js',
              'node_modules/zone.js/dist/jasmine-patch.js',
              'node_modules/zone.js/dist/async-test.js',
              'node_modules/zone.js/dist/fake-async-test.js',
  
              // RxJs
              { pattern: 'node_modules/rxjs/**/*.js', included: false, watched: false },
              { pattern: 'node_modules/rxjs/**/*.js.map', included: false, watched: false },
  
              // Paths loaded via module imports:
              // Angular itself
              { pattern: 'node_modules/@angular/**/*.js', included: false, watched: false },
              { pattern: 'node_modules/@angular/**/*.js.map', included: false, watched: false },
  
              { pattern: 'systemjs.config.js', included: false, watched: false },
              { pattern: 'systemjs.config.extras.js', included: false, watched: false },
              'karma-test-shim.js', // optionally extend SystemJS mapping e.g., with barrels
  
              // transpiled application &amp; spec code paths loaded via module imports
              { pattern: appBase + '**/*.js', included: false, watched: true },
              { pattern: testingBase + '**/*.js', included: false, watched: true },
  
  
              // Asset (HTML &amp; CSS) paths loaded via Angular's component compiler
              // (these paths need to be rewritten, see proxies section)
              { pattern: appBase + '**/*.html', included: true, watched: true },
              { pattern: appBase + '**/*.css', included: false, watched: true },
  
              // Paths for debugging with source maps in dev tools
              { pattern: appSrcBase + '**/*.ts', included: false, watched: false },
              { pattern: appBase + '**/*.js.map', included: false, watched: false },
              { pattern: testingSrcBase + '**/*.ts', included: false, watched: false },
              { pattern: testingBase + '**/*.js.map', included: false, watched: false}
          ],
  
          // Proxied base paths for loading assets
          proxies: {
              // required for component assets fetched by Angular's compiler
              "/app/": appAssets
          },
  
          exclude: [],
          preprocessors: {},
          reporters: ['progress', 'kjhtml'],
  
          port: 9879,
          colors: true,
          logLevel: config.LOG_INFO,
          autoWatch: true,
          browsers: ['Chrome'],
          singleRun: false
      })
  }
  </code></pre>
  
  <p>I am not sure why these .html files are not being loaded so can anyone see why this is happening? I don't want to include the template code in each component as some of them are very large and my file structure has already compensated for separate view-file functionality.</p>
  
  <p>The component (with the code that works commented out):</p>
  
  <pre><code>import { Component } from "@angular/core";
  
  @Component({
      selector: 'categories-component',
      templateUrl: '/app/views/catalog/categories/categories-dashboard.html',
      //template: '&lt;h1&gt;{{ title }}&lt;/h1&gt;',
      moduleId: module.id
  })
  
  export class CategoriesComponent {
      public title:String = 'Categories';
  }
  </code></pre>
  
  <p>the testing module:</p>
  
  <pre><code>import {TestBed, ComponentFixture, ComponentFixtureAutoDetect, async} from "@angular/core/testing";
  import { By} from "@angular/platform-browser";
  import { CategoriesComponent } from "../../../../components/catalog/categories/CategoriesComponent";
  import { DebugElement } from "@angular/core";
  
  let comp:    CategoriesComponent;
  let fixture: ComponentFixture&lt;CategoriesComponent&gt;;
  let de:      DebugElement;
  let el:      HTMLElement;
  
  describe('Component: CategoriesComponent', () =&gt; {
  
      beforeEach(() =&gt; {
          TestBed.configureTestingModule({
              declarations: [ CategoriesComponent ],
              providers: [
                  { provide: ComponentFixtureAutoDetect, useValue: true }
              ]
          });
      });
  
      it('should display original title', (done) =&gt; {
          TestBed.compileComponents()
              .then(() =&gt; {
                  done();
                  fixture = TestBed.createComponent(CategoriesComponent);
  
                  comp = fixture.componentInstance; // CategoriesComponent test instance
  
                  // query for the title &lt;h1&gt; by CSS element selector
                  de = fixture.debugElement.query(By.css('h1'));
                  el = de.nativeElement;
  
                  expect(el.textContent).toContain(comp.title);
                  done();
              });
      });
  });
  </code></pre>
  
  <p>I also get this error in the Karma Runner when starting Karma:</p>
  
  <pre><code>07 12 2016 14:17:15.658:WARN [proxy]: failed to proxy app/views/catalog/categories/categories-dashboard.html (socket hang up)
  </code></pre>
  
  <p>I am adding these URLs to add extra clarity to my answer. When I access the application the successful XHR request for the template is:</p>
  
  <pre><code>http://product-admin.dev/app/views/catalog/categories/categories-dashboard.html
  </code></pre>
  
  <p>And the URL that is being called to get the template from the test runner (and failing) is:</p>
  
  <pre><code>http://localhost:9879/app/views/catalog/categories/categories-dashboard.html
  </code></pre>
  
  <p>the karma-test-shim file:</p>
  
  <pre><code>// /*global jasmine, __karma__, window*/
  Error.stackTraceLimit = 0; // "No stacktrace"" is usually best for app testing.
  
  // Uncomment to get full stacktrace output. Sometimes helpful, usually not.
  // Error.stackTraceLimit = Infinity; //
  
  jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000;
  
  // builtPaths: root paths for output ("built") files
  // get from karma.config.js, then prefix with '/base/' (default is 'app/')
  var builtPaths = (__karma__.config.builtPaths || ['app/'])
      .map(function(p) { return '/base/'+p;});
  
  __karma__.loaded = function () { };
  
  function isJsFile(path) {
      return path.slice(-3) == '.js';
  }
  
  function isSpecFile(path) {
      return /\.spec\.(.*\.)?js$/.test(path);
  }
  
  // Is a "built" file if is JavaScript file in one of the "built" folders
  function isBuiltFile(path) {
      return isJsFile(path) &amp;&amp;
          builtPaths.reduce(function(keep, bp) {
              return keep || (path.substr(0, bp.length) === bp);
          }, false);
  }
  
  var allSpecFiles = Object.keys(window.__karma__.files)
      .filter(isSpecFile)
      .filter(isBuiltFile);
  
  System.config({
      baseURL: 'base',
      // Extend usual application package list with test folder
      packages: { 'testing': { main: 'index.js', defaultExtension: 'js' } },
  
      // Assume npm: is set in `paths` in systemjs.config
      // Map the angular testing umd bundles
      map: {
          '@angular/core/testing': 'npm:@angular/core/bundles/core-testing.umd.js',
          '@angular/common/testing': 'npm:@angular/common/bundles/common-testing.umd.js',
          '@angular/compiler/testing': 'npm:@angular/compiler/bundles/compiler-testing.umd.js',
          '@angular/platform-browser/testing': 'npm:@angular/platform-browser/bundles/platform-browser-testing.umd.js',
          '@angular/platform-browser-dynamic/testing': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic-testing.umd.js',
          '@angular/http/testing': 'npm:@angular/http/bundles/http-testing.umd.js',
          '@angular/router/testing': 'npm:@angular/router/bundles/router-testing.umd.js',
          '@angular/forms/testing': 'npm:@angular/forms/bundles/forms-testing.umd.js',
      },
  });
  
  System.import('systemjs.config.js')
      .then(importSystemJsExtras)
      .then(initTestBed)
      .then(initTesting);
  
  /** Optional SystemJS configuration extras. Keep going w/o it */
  function importSystemJsExtras(){
      return System.import('systemjs.config.extras.js')
          .catch(function(reason) {
              console.log(
                  'Warning: System.import could not load the optional "systemjs.config.extras.js". Did you omit it by accident? Continuing without it.'
              );
              console.log(reason);
          });
  }
  
  function initTestBed(){
      return Promise.all([
          System.import('@angular/core/testing'),
          System.import('@angular/platform-browser-dynamic/testing')
      ])
  
          .then(function (providers) {
              var coreTesting    = providers[0];
              var browserTesting = providers[1];
  
              coreTesting.TestBed.initTestEnvironment(
                  browserTesting.BrowserDynamicTestingModule,
                  browserTesting.platformBrowserDynamicTesting());
          })
  }
  
  // Import all spec files and start karma
  function initTesting () {
      return Promise.all(
          allSpecFiles.map(function (moduleName) {
              return System.import(moduleName);
          })
      )
          .then(__karma__.start, __karma__.error);
  }
  </code></pre>