I'm having issues doing a very simple component test in a NativeScript Angular 2 application. I can't seem to just call "new Component()" and then test it like was shown in this test example. I'm trying an implementation of the Angular 2 TestBed in order to gain access to the component. This doesn't appear to be working either. Has anybody run into a similar problem or have any experience with this?
Component under test:
import { Component } from "#angular/core";
#Component({
selector: "links",
templateUrl: "./components/links/links.component.html"
})
export class LinksComponent {
test = "test";
public constructor() {
}
}
Test:
import "reflect-metadata";
import { LinksComponent } from "../../components/links/links.component";
import { ComponentFixture, TestBed } from '#angular/core/testing';
describe("Links Component", () => {
let comp: LinksComponent;
let fixture: ComponentFixture<LinksComponent>;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [ LinksComponent ],
});
fixture = TestBed.createComponent(LinksComponent);
comp = fixture.componentInstance;
});
it("will pass because this is a silly test", () => {
expect(comp.test).toEqual("test");
})
});
Log output:
NativeScript / 10.3 (10.3; iPhone) ../../tests/components/links.spec.js at line 0 FAILED
ReferenceError: Can't find variable: Zone
NativeScript / 10.3 (10.3; iPhone): Executed 1 of 0 (1 FAILED) (0 secs / 0 seNativeScript / 10.3 (10.3; iPhone): Executed 1 of 0 (1 FAILED) ERROR (0.008 secs / 0 secs)
CONSOLE LOG file:///app/tns_modules/nativescript-unit-test-runner/main-view-model.js:258:24: NSUTR: completeAck
May 11 16:16:43 --- last message repeated 1 time ---
CONSOLE LOG file:///app/tns_modules/nativescript-unit-test-runner/main-view-model.js:90:28: NSUTR-socket.io: io server disconnect
CONSOLE LOG file:///app/tns_modules/nativescript-unit-test-runner/main-view-model.js:151:24: NSUTR: disregarding second execution
Test run failed.
AFAIK TestBed does not work on NativeScript Angular.
To mock components you need to instance them with new, resolving each dependency.
You should study this repository to be able to do some unit testing on NativeScript.
Related
I'm using this component : https://github.com/euvl/vue-notification
Since then, all of my Mocha chai test units are failing .
this.$notify is not a function
This is my login spec :
// Importing The testing library
import { expect } from "chai";
import { mount } from '#vue/test-utils'
// Importing The component I need to test
import Login from "#/components/Login.vue";
// Mounting the component as in real life
const wrapper = mount(Login);
describe("Login test", () => {
it("getAuth() to be a function", () => {
expect(wrapper.vm.getAuth).to.be.a("function");
});
});
I've tried out mount, shallowMount, render with no luck .
Any workaround ?
I'm calling vue-notification in main.js like this :
import Notifications from "vue-notification";
Vue.use(Notifications);
Thank you !
EDIT :
Ive tried to add
const $notify = require('vue-notification')
To my Login.vue component with no luck
EDIT 2 : Tried to call the function like this with no luck :
this.$root.$notify({
group: 'foo',
title: 'Hello ',
text: 'Cool'
});
[Vue warn]: Error in mounted hook: "TypeError: this.$root.$notify is not a function"
*EDIT : ***** Resolved by me ****** *
I was badly importing vue . Please see my working login.spec.js testing file there :
// THE ASSERTION LIBRARY
import { expect } from "chai";
// THE TESTING LIBRARY
import { mount } from "#vue/test-utils";
// THE COMPONENT THAT I WANT TO TEST
import Login from "#/components/Login.vue";
// THE EXTERNAL COMPONENTS LINKED TO MY LOGIN COMPONENT THAT I NEED TO JOIN
import Vue from 'vue';
import Vuelidate from 'vuelidate'
Vue.use(Vuelidate)
import {
required,
minLength,
between
} from "vuelidate/lib/validators";
import Notifications from "vue-notification";
import velocity from 'velocity-animate'
Vue.use(Notifications, { velocity });
// THE WRAPPER CONTAIN MY LOGIN MOUNTED COMPONENT, JUST LIKE IN THE REAL LIFE
const wrapper = mount(Login)
describe("Login test", () => {
it("getAuth() to be a function", () => {
expect(wrapper.vm.getAuth).to.be.a("function");
});
});
When trying to run a Unit Test on a Vuetify 2 app I get the error for SASS Stylesheets not being found, they are there.
The app has had no unit testing before so we need to include it to this project, I have tried to create a new fresh project and the testing works perfectly there, I have used multiple guides such as: https://vuetifyjs.com/en/getting-started/unit-testing But I get the same issues no matter what I use. I have tried mocha, mocha-webpack, chai, vue-test-utils, Jest etc.
https://imgur.com/X3zHFBE
https://imgur.com/kQoiJBB
Does not work
import { expect } from 'chai'
import { shallowMount } from '#vue/test-utils'
import Tabs from '#/components/ui/Tabs.vue'
let wrapper = shallowMount(Tabs);
console.log(wrapper);
describe('Tabs.vue', () => {
it('current tab equals empty', () => {
// wrapper.vm.clearValue();
expect(wrapper.vm.currentTab).to.equal('');
});
});
Works
import { expect } from 'chai'
import { shallowMount } from '#vue/test-utils'
import HelloWorld from '#/components/HelloWorld.vue'
describe('HelloWorld.vue', () => {
it('renders props.msg when passed', () => {
const msg = 'new message'
const wrapper = shallowMount(HelloWorld, {
propsData: { msg }
})
expect(wrapper.text()).to.include(msg)
})
})
Also tried the code examples here: https://vuetifyjs.com/en/getting-started/unit-testing
They do not work also.
I expect the tests to actually run and either return success or failed. I actually get an error for each of the stylesheets using SASS.
In my vue component , in the mounted i am calling a service class which in turn invokes axios call ..like below
import StudentService from '../utils/student.services'
export default {
name: 'student-summary',
mounted () {
console.log('%c FeeMdoule-Data Recieved on Mount as %s', 'color: blue ;font-size : 12px', JSON.stringify(this.filingData))
StudentService.getDetails().then(data => {
this.sList = data
})
},
// ...
}
I have now written JEST test cases of the vue component and i have mocked axios within vue component test cases..
But i think the right approach is to mock the studentServices rather than not mock axios directly from component...
How to mock the studentservices from the vue compoent test and not have any axios in the test case of my vue component?
Jest documents describe class mocks here
StudentService.spec.js
import StudentService from '../utils/student.services'
jest.mock('../utils/student.services');
describe("StudentService", () => {
let mockDetails = [{ studentId: 1 }]
StudentService.getDetails = jest.fn().mockResolvedValue(mockDetails);
afterEach(() => {
// reset mock after each test
StudentService.getDetails.mockReset();
});
it("should get details", () => {
// ... mount your component
expect(StudentService.getDetails).toHaveBeenCalled();
});
});
I am trying to implement unit tests for an Angular 2 app. But I can't get it it to work.
As test runner mocha is used and executed like this:
mocha -r ts-node/register -t 10000 ./**/*.unit.ts
Consider the following test file where I define two test cases which basically should do the same thing, but neither one is working.
shared.service.unit.ts
import { TestBed, async, inject } from '#angular/core/testing';
import { SharedService } from './shared.service';
import * as Chai from 'chai';
import 'mocha';
const expect = Chai.expect;
describe('SharedService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [SharedService],
providers: [SharedService]
});
});
it('should be an object',
inject([SharedService], (service: SharedService) => {
expect(service).to.be.an('object');
})
);
});
describe('SharedService without the TestBed', () => {
let service: SharedService;
beforeEach(() => {
service = new SharedService();
});
it('should be an object', () => {
expect(service).to.be.an('object');
});
});
The first one 'SharedService' uses the Angular Testing Utility. Running it gives:
ReferenceError: Zone is not defined
The second one 'SharedService without TestBed'does not use any Angular code (similar to this example from Angular 2 Testing guide). Running it gives:
TypeError: Reflect.getMetadata is not a function
After adding these lines to the test file:
import 'core-js/es6';
import 'core-js/es7/reflect';
import 'zone.js/dist/zone';
Both test cases give the same error (from zone.js\dist\zone.js):
TypeError: Cannot read property 'prototype' of undefined
What am I doing wrong?
Got it, just needed to import 'core-js/es7/reflect':
import 'core-js/es7/reflect';
import 'mocha';
import * as Chai from 'chai';
let expect = Chai.expect;
import { SharedService } from './shared.service';
describe('SharedService', () => {
let service: SharedService;
beforeEach(() => {
service = new SharedService();
})
it('should be an object', () => {
expect(service).to.be.an('object');
})
});
You need to load all that stuff - angular, ngzone, metadata, es shims, etc. - statically in the mocha's - or systemjs or whatever you use for setting this stuff up - configuration.
I'm trying to understand unit testing in Angular2 v2.0.0. I used angular-cli to generate a project, and am running unit tests by launching 'ng test'. The cli generates a sample component including tests.
I have expanded the sample component test by trying to create a host component in which I might test future custom components. Similar to the method I found here:
unit testing using host components
The problem is that after instantiating the test component, it fails a test to look for a bound value inside the test component. It's the last test in the sequence here.
/* tslint:disable:no-unused-variable */
import { TestBed, async } from '#angular/core/testing';
import { AppComponent } from './app.component';
import { Component, Input, OnInit } from '#angular/core';
// let's create a host component to test subcomponents
#Component({
template: `<span>{{testitemname}}</span>`
})
class TestComponent {
testitemname: 'testitem';
testitemtags: ['tag1', 'tag2', 'tag3'];
}
describe('App: Testhostcomp', () => {
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [
AppComponent,
TestComponent
],
});
});
it('should create the app', async(() => {
let fixture = TestBed.createComponent(AppComponent);
let app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
}));
it(`should have as title 'app works!'`, async(() => {
let fixture = TestBed.createComponent(AppComponent);
let app = fixture.debugElement.componentInstance;
expect(app.title).toEqual('app works!');
}));
it('should render title in a h1 tag', async(() => {
let fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
let compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('h1').textContent).toContain('app works!');
}));
// this test fails
it('should render the property value inside the test component', async(() => {
let fixture = TestBed.createComponent(TestComponent);
fixture.detectChanges();
let compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('span').textContent).toContain('testitem');
}));
});
It fails with the following error:
26 10 2016 10:48:15.456:INFO [Chrome 54.0.2840 (Windows 7 0.0.0)]: Connected on socket /#mcN6GltigqminZ3yAAAA with id 34237141
Chrome 54.0.2840 (Windows 7 0.0.0) App: Testhostcomp should render the property value inside the test component FAILED
Expected '' to contain 'testitem'.
at webpack:///C:/Angular2Projects/testhostcomp/src/app/app.component.spec.ts:49:55 <- src/test.ts:12000:60
at ZoneDelegate.invoke (webpack:///C:/Angular2Projects/testhostcomp/~/zone.js/dist/zone.js:232:0 <- src/test.ts:20985:26)
at AsyncTestZoneSpec.onInvoke (webpack:///C:/Angular2Projects/testhostcomp/~/zone.js/dist/async-test.js:49:0 <- src/test.ts:13735:39)
at ProxyZoneSpec.onInvoke (webpack:///C:/Angular2Projects/testhostcomp/~/zone.js/dist/proxy.js:76:0 <- src/test.ts:14427:39)
Chrome 54.0.2840 (Windows 7 0.0.0): Executed 4 of 4 (1 FAILED) (0 secs / 0.196 secs)
Chrome 54.0.2840 (Windows 7 0.0.0) App: Testhostcomp should render the property value inside the test component FAILED
Expected '' to contain 'testitem'.
at webpack:///C:/Angular2Projects/testhostcomp/src/app/app.component.spec.ts:49:55 <- src/test.ts:12000:60
at ZoneDelegate.invoke (webpack:///C:/Angular2Projects/testhostcomp/~/zone.js/dist/zone.js:232:0 <- src/test.ts:20985:26)
at AsyncTestZoneSpec.onInvoke (webpack:///C:/Angular2Projects/testhostcomp/~/zone.js/dist/async-test.js:49:0 <- src/test.ts:13735:39)
Chrome 54.0.2840 (Windows 7 0.0.0): Executed 4 of 4 (1 FAILED) (0.273 secs / 0.196 secs)
I noticed that when I changed {{testitemname}} to 'testitem', the test passes. So I think it might have something to do with binding? I don't understand why this doesn't work. Thank you in advance for your help.
[1]: https://angular.io/docs/ts/latest/guide/testing.html#!#component-inside-test-host "host components"
It's because you are using 'testitem' as the type not as the value
field: Type; // colon is used for typing
field = value; // equals sign for assignment
your code
testitemname: 'testitem';
testitemtags: ['tag1', 'tag2', 'tag3'];