9
votes

I'm setting up a NativeScript-Angular project, and would like to implement unit tests using Jasmine-Karma in order to test my components using css selectors. How can I setup a simple unit test (beyond the sample test provided on the official repository) for a simple component?

This is for a new project using NativeScript CLI 6.0 with Android API level 28.

I have tried using the regular Angular TestBed which is claimed to be supported on this blog post: https://www.nativescript.org/blog/announcing-the-nativescript-4.1-release

I have also tried following their working tests on the official nativescript-angular repository: https://github.com/NativeScript/nativescript-angular/tree/master/tests

Either way I seem to be doing something wrong when I try to do my own implementation because I get the following errors:
Uncaught Error: Zone already loaded
TypeError: Cannot read property 'injector' of null
TypeError: Cannot read property 'getComponentFromError' of null
TypeError: Cannot read property 'currentPage' of undefined

Has anyone managed to get TestBed unit tests working in NativeScript with Jasmine-Karma?

test-main.ts

import "nativescript-angular/zone-js/testing.jasmine";
import { nsTestBedInit } from "nativescript-angular/testing";
nsTestBedInit();

example.ts

import { ItemsComponent } from '~/app/item/items.component';
import { By } from '@angular/platform-browser';
import { nsTestBedBeforeEach, nsTestBedAfterEach, nsTestBedRender } from 'nativescript-angular/testing';

describe('item-detail-component', () => {
  beforeEach(nsTestBedBeforeEach(
    [ItemsComponent]
  ));
  afterEach(nsTestBedAfterEach());

  it(`should contain items`, () => {
    return nsTestBedRender(ItemsComponent).then((fixture) => {
      fixture.detectChanges();
      const list = fixture.debugElement.query(By.css('.list-group'));

      expect(list).toBeDefined();
    });
  })
});

I am expecting to be able to run the test without getting any errors.

I have included two repos for each test implementation.
Steps to reproduce:
1. Download repo
2. yarn install
3. tns test android

https://github.com/gsavchenko/nativescript-ns-testbed

update

for anyone else wondering how to further test their front-end using end to end tests it seems like appium is the go to https://docs.nativescript.org/plugins/ui-tests

3
I think your question is so huge for others to see and try to answer , Please try to make it a bit short and specific about your issue , If you have multiple question try to make one for each - Abdulrahman Falyoun
Yeah I agree I am working on making minimal reproduction steps and repos at the moment. - George S
I've edited my question to be more bare-bones and my question to be clearer. If any readers would like me to make further simplifications please let me know. - George S
This is the exact issue I'm having as well. IMO, after adding testing to project with tns test init, performing an action like ng generate service Foo should result in foo.service.spec.ts being included in the tests. However, even after manual intervention as you have here, I can't for the life of me get it to work. - Miles

3 Answers

3
votes

To use TestBed you have to alter your karma.conf.js to:

    // list of files / patterns to load in the browser
    files: [
      'src/tests/setup.ts',
      'src/tests/**/*.spec.ts'
    ],

The file src/tests/setup.ts should look like this for jasmine:

import "nativescript-angular/zone-js/testing.jasmine";
import {nsTestBedInit} from "nativescript-angular/testing";
nsTestBedInit();

or if using mocha:

import "nativescript-angular/zone-js/testing.mocha";
import {nsTestBedInit} from "nativescript-angular/testing";
nsTestBedInit();

You'll find a sample here: https://github.com/hypery2k/tns_testbed_sample

0
votes

I was facing the same issue like you. I finally found a way to make Unit Test in Nativescript-Angular works.

To fix my issue I add beforeAll(() => nsTestBedInit()); and afterAll(() => { }); Also change from TestBed to nsTestBed... I just follow the idea on https://github.com/NativeScript/nativescript-angular/blob/master/tests/app/tests/detached-loader-tests.ts

Also add into tsconfig.tns.json file this line: "include": ["src/tests/*.spec.ts"],

My issue now is split all test into multiple file. Like appComponent in a test file and homeCompenent in a second test file. When the app grow the unit test also grow, we need organize our code.

Here my code (file name: src/tests/test.spec.ts):

    import "reflect-metadata";
    import { AppComponent } from "../app/app.component";
    import { nsTestBedBeforeEach, nsTestBedAfterEach, nsTestBedRender, nsTestBedInit }     from "nativescript-angular/testing";
    import { HomeComponent } from "@src/app/home/home.component";
    describe("AppComponent", () => {
        beforeAll(() => nsTestBedInit());
        afterAll(() => { });
        beforeEach(nsTestBedBeforeEach([AppComponent, HomeComponent]));
        afterEach(nsTestBedAfterEach());
        it("should be: app works!", () => {
            return nsTestBedRender(AppComponent).then((fixture) => {
                fixture.detectChanges();
                const app = fixture.componentInstance;
                expect(app.title).toBe("app works!");
            });
        });
        describe("HomeComponent", () => { 
            it("should contain: Home works!", () => {
              return nsTestBedRender(HomeComponent).then((fixture) => {
                  fixture.detectChanges();
                  const app = fixture.componentInstance;
                  expect(app.title).toBe("Home works!");
              });
            });
        });
    });

And here the result:

JS: NSUTR: downloading http://192.168.10.169:9876/context.json
JS: NSUTR: eval script /base/node_modules/jasmine-core/lib/jasmine-core/jasmine.js?be3ff9a5e2d6d748de5b900ac3c6d9603e2942a7
JS: NSUTR: eval script /base/node_modules/karma-jasmine/lib/boot.js?945a38bf4e45ad2770eb94868231905a04a0bd3e
JS: NSUTR: eval script /base/node_modules/karma-jasmine/lib/adapter.js?3098011cfe00faa2a869a8cffce13f3befc1a035
JS: NSUTR: eval script /base/src/tests/test.spec.bundle.js?6e0098824123f3edc2bb093fa874b3fdf268841e
JS: NSUTR: beginning test run
NativeScript / 28 (9; Android SDK built for x86): Executed 1 of 2 SUCCESS (0 secs / 0.545 secs)
NativeScript / 28 (9; Android SDK built for x86): Executed 2 of 2 SUCCESS (0.829 secs / 0.735 secs)
TOTAL: 2 SUCCESS
JS: NSUTR: completeAck
NativeScript / 28 (9; Android SDK built for x86) ERROR
  DisconnectedClient disconnected from CONNECTED state (transport error)
NativeScript / 28 (9; Android SDK built for x86): Executed 2 of 2 SUCCESS (0.829 secs / 0.735 secs)
-1
votes

Your issue is happening because of these lines.

beforeAll(() => nsTestBedInit()); afterAll(() => { });

Each test file tries to initialize test bed. Make sure that you initialize it in your entry component.

Please refer entry file test-main.ts specified in karma.config.js