Angular2 Quickstart Tutorial Breaking Karma Tests - "Can't bind to 'ngModel' since it isn't a known property of 'input'."
When configuring the test using the TestBed
, it's like configuring an @NgModule
from scratch for the testing environment. So when adding AppComponent
to the declarations
, and the AppComponent
needs forms directives, you need to import the FormsModule
into to the testbed configuration, just you do in the AppModule
TestBed.configureTestingModule({
declarations: [ AppComponent ],
imports: [ FormsModule ]
})
Related videos on Youtube
Kirsty Purcell
Updated on August 20, 2022Comments
-
Kirsty Purcell almost 2 years
I am following the official Angular "Hero" Quickstart Tutorial whilst trying to TDD it.
https://angular.io/docs/ts/latest/tutorial/toh-pt1.html
As soon as I get to the step to replace:
<input value="{{hero.name}}" placeholder="name">
with
<input [(ngModel)]="hero.name" placeholder="name">
my Karma test runner throws the following error:
Error: Template parse errors: Can't bind to 'ngModel' since it isn't a known property of 'input'. (" name: ][(ngModel)]="hero.name" placeholder="name"> "): AppComponent@6:23 Expected undefined to be defined.
However, the application works as expected and I see no errors in the console. (And I'm fairly confident I followed the tutorial correctly, can't see any typos etc)
My app.components.ts looks like:
import { Component } from '@angular/core'; export class Hero { id: number; name: string; } @Component({ selector: 'my-app', template: ` <h1>{{title}}</h1> <h2>{{hero.name}} details!</h2> <div><label>id: </label>{{hero.id}}</div> <div> <label>name: </label> <input [(ngModel)]="hero.name" placeholder="name"> </div> ` }) export class AppComponent { title = 'Tour of Heroes'; hero: Hero = { id: 1, name: 'Windstorm' }; }
My app.module looks like:
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { AppComponent } from './app.component'; import { FormsModule } from '@angular/forms'; @NgModule({ imports: [ BrowserModule, FormsModule], declarations: [ AppComponent], bootstrap: [ AppComponent ] }) export class AppModule { }
Karma works fine as soon as I remove ngModel from the template, and as I said before the actual app is behaving as expected. I can't seem to find any information relating to my problem after extensive googling :(
My karma.config is the standard quickstart one:
// #docregion module.exports = function(config) { var appBase = 'app/'; // transpiled app JS and map files var appSrcBase = 'app/'; // app source TS files var appAssets = 'base/app/'; // component assets fetched by Angular's compiler var testBase = 'testing/'; // transpiled test JS and map files var testSrcBase = 'testing/'; // test source TS files config.set({ basePath: '', frameworks: ['jasmine'], plugins: [ require('karma-jasmine'), require('karma-chrome-launcher'), require('karma-jasmine-html-reporter'), // click "Debug" in browser to see it require('karma-htmlfile-reporter') // crashing w/ strange socket error ], 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', // transpiled application & spec code paths loaded via module imports { pattern: appBase + '**/*.js', included: false, watched: true }, { pattern: testBase + '**/*.js', included: false, watched: true }, // Asset (HTML & CSS) paths loaded via Angular's component compiler // (these paths need to be rewritten, see proxies section) { pattern: appBase + '**/*.html', included: false, 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: testSrcBase + '**/*.ts', included: false, watched: false }, { pattern: testBase + '**/*.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: {}, // disabled HtmlReporter; suddenly crashing w/ strange socket error reporters: ['progress', 'kjhtml'],//'html'], // HtmlReporter configuration htmlReporter: { // Open this file to see results in browser outputFile: '_test-output/tests.html', // Optional pageTitle: 'Unit Tests', subPageTitle: __dirname }, port: 9876, colors: true, logLevel: config.LOG_INFO, autoWatch: true, browsers: ['Chrome'], singleRun: false }) }
Can anyone help me?