Template parse error in Jasmine test but not actual app

谁都会走 提交于 2019-12-06 17:10:56

问题


I've developed a Jasmine spec to test an angular 2 component MiddleRowComponent. When I run the jasmine test, it gives this error:

zone.js:388 Unhandled Promise rejection: Template parse errors:
'circles' is not a known element:
1. If 'circles' is an Angular component, then verify that it is part of this module.
2. If 'circles' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '@NgModule.schemas' of this component to suppress this message. ("</div>
      <div class="col-md-10 col-sm-12 offset-md-1 flex-xs-middle" id="circles-div">
         [ERROR ->]<circles (onWordChanged)="onWordChanged($event)"></circles>
      </div>
      <div class="col-md-10 "): MiddleRowComponent@9:9
'custom-button' is not a known element:

However if i just run my web app in the browser like normal, the error does not occur. circles is indeed a part of the module. And custom-button is part of a shared module that is imported. Here is the module.ts:

    import { NgModule }           from '@angular/core';
import { CommonModule }       from '@angular/common';
import { SharedModule } from '../shared/shared.module';
import * as LandingPage from './index';

@NgModule({
   imports: [ CommonModule, SharedModule ],
   declarations: [
      LandingPage.MiddleRowComponent,
      LandingPage.LandingPageComponent,
      LandingPage.CirclesComponent
   ],
   exports: [ LandingPage.LandingPageComponent ],
})
export class LandingPageModule { }

Everything is imported and declared as it should be and works when running the app without testing it. I use a done to make the beforeEach work given it's async nature of getting the component template from a seperate template file. I ru the test with a jasmine spec runner html file. How come my components that MiddleRowComponent uses are not known elements in the jasmine test but are when running the app normally?

Here is the jasmine spec:

import 'zone.js/dist/long-stack-trace-zone.js';
import 'zone.js/dist/async-test.js';
import 'zone.js/dist/fake-async-test.js';
import 'zone.js/dist/sync-test.js';
import 'zone.js/dist/proxy.js';
import 'zone.js/dist/jasmine-patch.js';

import { ComponentFixture, TestBed } from '@angular/core/testing';
import {
    BrowserDynamicTestingModule,
    platformBrowserDynamicTesting
} from '@angular/platform-browser-dynamic/testing';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';

import { MiddleRowComponent } from './middle-row.component';

let comp: MiddleRowComponent;
let fixture: ComponentFixture<MiddleRowComponent>;
let de: DebugElement;
let el: HTMLElement;

describe('MiddleRowComponent', () => {
   var fixture: any;
   var comp: any;
    beforeAll(() => {
        TestBed.resetTestEnvironment();
        TestBed.initTestEnvironment(BrowserDynamicTestingModule,
            platformBrowserDynamicTesting());
    });

    beforeEach((done) => {
        TestBed.configureTestingModule({
            declarations: [MiddleRowComponent], // declare the test component
        }).compileComponents().then(() => {
            fixture = TestBed.createComponent(MiddleRowComponent);
            comp = fixture.componentInstance; // MiddleRowComponent test instance
            // query for the title <h1> by CSS element selector
            de = fixture.debugElement.query(By.css('h1'));
            el = de.nativeElement;
            done();
        });
    });

    it('should display original title', () => {
        fixture.detectChanges();
        expect(el.textContent).toContain(comp.word);
    });

    it('should display a different test title', () => {
        comp.word = 'Test Title';
        fixture.detectChanges();
        expect(el.textContent).toContain('Test Title');
    });
});

full error:

zone.js:388 Unhandled Promise rejection: Template parse errors:
'circles' is not a known element:
1. If 'circles' is an Angular component, then verify that it is part of this module.
2. If 'circles' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '@NgModule.schemas' of this component to suppress this message. ("</div>
      <div class="col-md-10 col-sm-12 offset-md-1 flex-xs-middle" id="circles-div">
         [ERROR ->]<circles (onWordChanged)="onWordChanged($event)"></circles>
      </div>
      <div class="col-md-10 "): MiddleRowComponent@9:9
'custom-button' is not a known element:
1. If 'custom-button' is an Angular component, then verify that it is part of this module.
2. If 'custom-button' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '@NgModule.schemas' of this component to suppress this message. ("
      </div>
      <div class="col-md-10 offset-md-1 flex-xs-middle" id="try-now-div">
         [ERROR ->]<custom-button buttonName="try now" (click)="tryNowClick()"></custom-button>
      </div>
   </div>
"): MiddleRowComponent@12:9 ; Zone: ProxyZone ; Task: Promise.then ; Value: Error: Template parse errors:(…) Error: Template parse errors:
'circles' is not a known element:
1. If 'circles' is an Angular component, then verify that it is part of this module.
2. If 'circles' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '@NgModule.schemas' of this component to suppress this message. ("</div>
      <div class="col-md-10 col-sm-12 offset-md-1 flex-xs-middle" id="circles-div">
         [ERROR ->]<circles (onWordChanged)="onWordChanged($event)"></circles>
      </div>
      <div class="col-md-10 "): MiddleRowComponent@9:9
'custom-button' is not a known element:
1. If 'custom-button' is an Angular component, then verify that it is part of this module.
2. If 'custom-button' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '@NgModule.schemas' of this component to suppress this message. ("
      </div>
      <div class="col-md-10 offset-md-1 flex-xs-middle" id="try-now-div">
         [ERROR ->]<custom-button buttonName="try now" (click)="tryNowClick()"></custom-button>
      </div>
   </div>
"): MiddleRowComponent@12:9
    at TemplateParser.parse (http://localhost:3002/node_modules/@angular/compiler/bundles/compiler.umd.js:7730:21)
    at RuntimeCompiler._compileTemplate (http://localhost:3002/node_modules/@angular/compiler/bundles/compiler.umd.js:17573:53)
    at eval (http://localhost:3002/node_modules/@angular/compiler/bundles/compiler.umd.js:17493:64)
    at Set.forEach (native)
    at RuntimeCompiler._compileComponents (http://localhost:3002/node_modules/@angular/compiler/bundles/compiler.umd.js:17493:21)
    at createResult (http://localhost:3002/node_modules/@angular/compiler/bundles/compiler.umd.js:17404:21)
    at ZoneDelegate.invoke (http://localhost:3002/node_modules/zone.js/dist/zone.js:232:26)
    at ProxyZoneSpec.onInvoke (http://localhost:3002/node_modules/zone.js/dist/proxy.js:79:39)
    at ZoneDelegate.invoke (http://localhost:3002/node_modules/zone.js/dist/zone.js:231:32)
    at Zone.run (http://localhost:3002/node_modules/zone.js/dist/zone.js:114:43)consoleError @ zone.js:388_loop_1 @ zone.js:417drainMicroTaskQueue @ zone.js:421ZoneTask.invoke @ zone.js:339
zone.js:390 Error: Uncaught (in promise): Error: Template parse errors:(…)

回答1:


Well, the module of your test only has MiddleRowComponent declared. So it doesn't know about CircleComponent:

TestBed.configureTestingModule({
    declarations: [MiddleRowComponent], // declare the test component
})

Add all the necessary components in the declarations of the testing module, or add LandingPageModule to the imports of the testing module.




回答2:


I had a similar problem and found this page, and while JB Nizet's answer led to a solution for me, it didn't work for me as-is. I'm not trying to take away from his solid answer to the original question, just trying to help the next person who comes along.

My problem was exactly like the OP's, except that my custom component (MiddleRowComponent in this example) used a third-party component. The unit test error was given about the third-party tag used in my template, even though it worked just fine in the actual app. The solution for me was to also include an imports for the third-party in my testing module:

TestBed.configureTestingModule({
    declarations: [MiddleRowComponent],
    imports: [TheThirdPartyModule]
})

Then my unit tests ran without the error. Hope that helps!




回答3:


Another option is to add the NO_ERRORS_SCHEMA schema to the test setup. Any unrecognised components will now not cause an error. I use this a lot when working with third party modules like Angular Material Design.

import { NO_ERRORS_SCHEMA } from '@angular/core';
...
  beforeEach(
    async(() => {
      TestBed.configureTestingModule({
        declarations: [MiddleRowComponent],
        schemas: [NO_ERRORS_SCHEMA]
      }).compileComponents();
    })
  );


来源:https://stackoverflow.com/questions/40715688/template-parse-error-in-jasmine-test-but-not-actual-app

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!