zaitsman
zaitsman

Reputation: 9509

Ng5 Karma Jasmine test renders component instead of result page

Let's say i have a very simple 'create' unit test, kind that ng cli generates for you:

describe('MyComponent', () => {
  let component: MyComponent;
  let fixture: ComponentFixture<MyComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [MyComponent],
      imports: [
        HttpClientTestingModule,
        FormsModule,
        RouterTestingModule.withRoutes([{ path: 'home', redirectTo: '/' }])
      ],
      providers: [SomeService1, SomeService2, { provide: SomeService3, useValue: {} }],
      schemas: [NO_ERRORS_SCHEMA]
    })
      .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(MyComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });
});

Now when i run this test like so ng test --browser=Chrome instead of looking at Karma results page, i am looking at my component.

My CLI version is 1.6.3, Karma 1.7.1, Angular 5.2.0, OS macOS.

Update My browser is captured, karma loads, tests run but instead of karma results i see my full-screen component because it's css overlays their results. If i find the div and delete it in the DOM, i can see Karma results.

I was just expecting Angular to remove that node.

Upvotes: 10

Views: 5473

Answers (2)

Ruluk
Ruluk

Reputation: 375

I am not really sure why the DOM compilation of the component stays after the test ends, but I noticed it happens only for the last test that ran. If you can add another component test that also compiles a component but doesn't add a full-screen component, the previous one is correctly removed. So, simply adding more tests could be the easiest solution.

But if that's not enough, here goes two possible solutions:

1. Don't compile it

If your tests don't involve verifying the resulting DOM, you can simplify the arrangement of your test by using the component directly.

describe('MyComponent', () => {
  TestBed.configureTestingModule({
    // declarations: [MyComponent],
    imports: [
      HttpClientTestingModule,
      FormsModule,
      RouterTestingModule.withRoutes([{ path: 'home', redirectTo: '/' }]),
    ],
    // 1. Add the component as a provider.
    providers: [MyComponent, SomeService1, SomeService2, { provide: SomeService3, useValue: {} }],
    schemas: [NO_ERRORS_SCHEMA],
  });

  it('should do thing #1', () => {
    // 2. Test it like you would test a service.
    const comp = TestBed.get(MyComponent);
    expect(comp.value).toBe(false, 'off at first');
    comp.doThing1();
    expect(comp.value).toBe(true, 'on after click');
    comp.doThing1();
    expect(comp.value).toBe(false, 'off after second click');
  });

  it('should do thing #2', () => {
    const comp = TestBed.get(MyComponent);
    expect(comp.value2).toMatch(/is off/i, 'off at first');
    comp.doThing2();
    expect(comp.value2).toMatch(/is on/i, 'on after clicked');
  });
});

More info here.

2. Remove it from DOM

If you do need to test the DOM, the only workaround I have found is to explicitly remove the HTML element after finishing the tests.

  afterEach(() => {
    if (fixture.nativeElement && 'remove' in fixture.nativeElement) {
      (fixture.nativeElement as HTMLElement).remove();
    }
  });

Upvotes: 14

John Vandivier
John Vandivier

Reputation: 2426

Instead of running ng test try running ng test --sourcemaps=false

This solved the same issue for me.

It's not a valid state as the comments indicate; Karma reports the following for me which indicates a bad state (you could include info like this in your question next time for clarity):

10% building modules...
No captured browser...
Chrome 63.0.3239 (Windows 10 0.0.0): Executed 0 of 14 DISCONNECTED (10.003 secs / 0 secs)...
Disconnected, because no message in 10000 ms.`

I was actually unable to see the issue myself - I kept thinking I wrote the test incorrectly. A coworker correctly identified the issue by opening Dev Tools on the Karma browser instance (with the unexpected rendered component). There the console reported the following, which we searched and it led us to the answer:

Failed to load ng:///DynamicTestModule/AboutDsloCardComponent.ngfactory.js: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https.
(anonymous) @ zone.js:2956
zone.js:192 Uncaught DOMException: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'ng:///DynamicTestModule/AboutDsloCardComponent.ngfactory.js'.
    at http://localhost:9876/_karma_webpack_/webpack:/C:/Users/john.vandivier/workspace/halfaker/usa4-ui/ella-framework/node_modules/zone.js/dist/zone.js:2956:1

Upvotes: 0

Related Questions