We are setting up a unit test framework for our Ionic2 project
while running npm test , we are faced with the following error.
I give below the src/.ts and src/.spec.ts alongwith the cmd window error
Please help resolve
Chrome 55.0.2883 (Windows 8.1 0.0.0) ERROR: Error{rejection: 'Failed
to load app.html', promise : ZoneAwarePromise{__zone_symbol__state: 0,
__zone_symbol__value: 'Failed to load app.html'}, z one: Zone{_properties: Object{}, _parent: null, _name: '',
_zoneDelegate: ZoneDelegate{_t askCounts: ..., zone: ..., _parentDelegate: ..., _forkZS: ..., _forkDlgt: ..., _interceptZS: .. ., _interceptDlgt: ..., _invokeZS: ..., _invokeDlgt: ...,
_handleErrorZS: ..., _handleErrorDlgt : ..., _scheduleTaskZS: ..., _scheduleTaskDlgt: ..., _invokeTaskZS: ..., _invokeTaskDlgt: ...,
_cancelTaskZS: ..., _cancelTaskDlgt: ..., _hasTaskZS: ..., _hasTaskDlgt: ...}}, task: ZoneTask{ runCount: 1, type: 'microTask', zone: Zone{_properties: ..., _parent: ..., _name: ..., _zoneDel egate:
...}, source: 'Promise.then', data: undefined, scheduleFn: undefined,
cancelFn: null, ca llback: function () { ... }, invoke: function () {
... }}}
Chrome 55.0.2883 (Windows 8.1 0.0.0) DashboardService should return a
non empty array FAILED TypeError: Cannot read property 'assertPresent'
of undefined at resetFakeAsyncZone
(C:/Users/user/AppData/Local/Temp/karma-typescript-bundle
-66485eOt1ZMUGTWZ.js:143884:22) at Object. (C:/Users/user/AppData/Local/Temp/karma-typescript-bundle
-66485eOt1ZMUGTWZ.js:144536:13) Error: ProxyZoneSpec is needed for the async() test helper but could not be found. Plea se make sure that
your environment includes zone.js/dist/proxy.js at runInTestZone
(C:/Users/user/AppData/Local/Temp/karma-typescript-bundle-6648
5eOt1ZMUGTWZ.js:143659:19) at Object.
(C:/Users/user/AppData/Local/Temp/karma-typescript-bundle
-66485eOt1ZMUGTWZ.js:143633:17) TypeError: Cannot read property 'getData' of null at Object.
(src/pages/dashboard/dashboard.spec.ts:47:35 <- src/pages/das
hboard/dashboard.spec.js:40:31) Chrome 55.0.2883 (Windows 8.1 0.0.0):
Executed 1 of 1 (1 FAILED) ERROR (0.019 secs / 0.003 secs
import { async, ComponentFixture, TestBed } from '#angular/core/testing';
import { FormsModule, ReactiveFormsModule } from '#angular/forms';
import { App, Config, Form, IonicModule, Keyboard, DomController, MenuController, NavController, Platform ,NavParams} from 'ionic-angular';
import { DashboardPage } from './dashboard';
import { ConfigMock } from '../../mock';
import { AzureDatasync } from '../../app/providers/azure-datasync';
let dashboard = null;
let navCtrl: NavController;
let navParams: NavParams;
let datasync: AzureDatasync;
let fixture: ComponentFixture<DashboardPage> = null;
let instance: any = null;
describe('DashboardService', () => {
// beforeEach(() => {
// dashboard = new DashboardPage(navCtrl,navParams,datasync);
// console.log(dashboard);
// });
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [DashboardPage],
providers: [
App, DomController, Form, Keyboard, MenuController, NavController, Platform,
{provide: Config, useClass: ConfigMock},
],
imports: [
FormsModule,
IonicModule,
ReactiveFormsModule,
],
})
.compileComponents().then(() => {
fixture = TestBed.createComponent(DashboardPage);
console.log(fixture);
instance = fixture;
console.log(instance);
fixture.detectChanges();
});
}));
it('should return a non empty array', () => {
let result = dashboard.getData();
console.log(result);
expect(Array.isArray(result)).toBeTruthy;
expect(result.length).toBeGreaterThan(0);
}
);
});
import { Component, OnInit } from '#angular/core';
import { NavController, NavParams } from 'ionic-angular';
import { AzureDatasync } from '../../app/providers/azure-datasync';
import 'zone.js/dist/async-test';
/*
Generated class for the Dashboard page.
See http://ionicframework.com/docs/v2/components/#navigation for more info on
Ionic pages and navigation.
*/
#Component({
selector: 'page-dashboard',
templateUrl: 'dashboard.html'
})
export class DashboardPage implements OnInit {
todays: any ;
ticklers: any;
cases: any;
constructor(public navCtrl: NavController, public navParams: NavParams, public datasync: AzureDatasync) {}
ngOnInit(){
this.getData();
}
getData() {
this.todays = [
{type: "abc", name: "test", duration: "9.30 AM - 10.00 AM"},
{type: "def", name: "test2", duration: "12.45 AM - 3.10 PM"}
];
this.ticklers = [
{name: "abc", description: "A Court "},
{name: "def", description: "dd"}
];
this.cases = [
{name: "Msh", duedate: "Due on 7th Dec", priority: "PsI", timeduration: "24hrs", imgurl:"_blank.png"},
{name: "ss Smith", duedate: "Due on 11th Dec", priority: "Pris", timeduration: "30 mins ", imgurl:"./person_blank.png"}
];
}
}
I was having the same issue with Jasmine and Karma.
In my karma.conf I loaded some additional files into the browser:
// list of files / patterns to load in the browser
files: [
'../node_modules/zone.js/dist/zone.js', // 'Uncaught ReferenceError: Zone is not defined'
'../node_modules/zone.js/dist/proxy.js', // 'TypeError: Cannot read property 'assertPresent' of undefined'
'../node_modules/zone.js/dist/sync-test.js', // 'TypeError: Cannot read property 'assertPresent' of undefined'
'../node_modules/zone.js/dist/jasmine-patch.js', // 'TypeError: Cannot read property 'assertPresent' of undefined'
// ANY OTHER FILES TO LOAD FOR YOUR TESTS
],
Related
I am trying add markers dynamically/programatically after map is renderer but nothing is happening. Please see my code below
Service Code:
import { Injectable } from '#angular/core';
import { MapboxMarker, MapboxView, Mapbox } from "#nativescript-community/ui-mapbox";
import { registerElement } from '#nativescript/angular';
import { isIOS } from "#nativescript/core/platform";
#Injectable({
providedIn: 'root'
})
export class MapService {
mapboxView: MapboxView;
mapbox: Mapbox;
/**
* Creates an instance of Mapbox.
* #param config
* #memberof Mapbox
*/
constructor() {
registerElement("Mapbox", () => require("#nativescript-community/ui-mapbox").MapboxView);
}
generateMap(view: any) {
const settings = {
container: view,
accessToken: 'pk.eyJ1IjoiaGV5aXR6c3llZCIsImEiOiJjbDA5aTZlb3gwMGxsM2puejdyeTQyZnNjIn0.aJUDueGHXwKea-kN8lxn2g',
style: 'traffic_day',
margins: {
left: 18,
right: 18,
top: isIOS ? 390 : 454,
bottom: isIOS ? 50 : 8
},
center: {
lat: 52.3702160,
lng: 4.8951680
},
zoomLevel: 18, // 0 (most of the world) to 20, default 0
showUserLocation: false, // default false
hideAttribution: false, // default false
hideLogo: false, // default false
hideCompass: false, // default false
disableRotation: false, // default false
disableScroll: false, // default false
disableZoom: false, // default false
disableTilt: false, // default false
markers: [
{
id: 1,
lat: 52.3732160,
lng: 4.8941680,
title: 'Nice location',
subtitle: 'Really really nice location',
selected: true,
iconPath: '~/assets/Img/map.png',
onTap: () => console.log("'Nice location' marker tapped"),
onCalloutTap: () => console.log("'Nice location' marker callout tapped")
}
]
};
const mapView = new MapboxView();
mapView.setConfig(settings);
view.content = mapView;
}
}
Component.ts code:
import { Component, OnInit } from '#angular/core';
import { MapService } from 'map/map.service';
import { Page } from "#nativescript/core/ui/page";
import { ContentView } from "#nativescript/core/ui/content-view";
#Component({
selector: 'app-map-service-demo',
templateUrl: './map-service-demo.component.html',
styleUrls: ['./map-service-demo.component.css']
})
export class MapServiceDemoComponent implements OnInit {
constructor(public map: MapService, public page: Page) { }
ngOnInit(): void {
const contentView : ContentView = <ContentView>this.page.getViewById( 'mapContainer' );
this.map.generateMap(contentView);
}
}
Component.html code:
<StackLayout>
<ContentView height="100%" width="100%" id="mapContainer">
</ContentView>
</StackLayout>
The above implementation is not displaying markers by default even there is markers: [{}] property available in the settings.
Moreover, In the below code, I dont get what mapbox refers to
mapbox.addMarkers([
firstMarker,
{
// more markers..
}
])
Please guide me on adding markers programatically.
I'm new to RxJS, and I'm trying to figure out how to observe the data when it become available. I'm using Nuxt SSR and I'm fetching data from Firebase. The initial post value is set to null, and once the data object become available, it should run the head() function only once. I get this type error.
Cannot read property 'pipe' of null
If I initiate post: {}, as empty object, I get this type error.
post$.pipe is not a function
Appreciate if I can get some help or guidance.
// page\:post.vue
<script>
import { mapState, mapActions } from 'vuex'
import { take } from 'rxjs/operators'
export default {
fetch() {
this.fetchPost()
},
computed: {
...mapState('posts', ['post']),
},
methods: {
...mapActions('posts', ['fetchPost']),
},
head() {
const post$ = this.post
post$.pipe(take(1)).subscribe((post) => {
return {
title: this.post.title,
link: [{ rel: 'canonical', href: this.post.canonical }],
meta: [
{ hid: 'name', itemprop: 'name', content: this.post.title },
{
hid: 'description',
itemprop: 'description',
content: this.post.content,
},
],
}
})
},
}
</script>
// store\posts.js
export const state = () => ({
post: null,
})
export const mutations = {
setPost(state, payload) {
state.post = payload
},
}
export const actions = {
async fetchPost({ commit }, key) {
const doc = await postsCollection.doc(key).get()
if (doc.exists) commit('setPost', doc.dat())
},
}
Edit
Using Subject. However, there is still issue where the meta tags are generated before the post data is set.
// page\:post.vue
<script>
import { mapState, mapActions } from 'vuex'
import { take } from 'rxjs/operators'
export default {
fetch() {
this.fetchPost()
},
computed: {
...mapState('posts', ['post']),
},
methods: {
...mapActions('posts', ['fetchPost']),
},
head() {
const postSubject = new Subject()
const post = postSubject.asObservable()
postSubject.next(this.post)
post.subscribe((post) => {
return {
title: post.title,
link: [{ rel: 'canonical', href: post.canonical }],
meta: [
{ hid: 'name', itemprop: 'name', content: post.title },
{
hid: 'description',
itemprop: 'description',
content: post.content,
},
],
}
})
},
}
</script>
// store\posts.js
export const state = () => ({
post: null,
})
export const mutations = {
setPost(state, payload) {
state.post = payload
},
}
export const actions = {
async fetchPost({ commit }, key) {
const doc = await postsCollection.doc(key).get()
if (doc.exists) commit('setPost', doc.dat())
},
}
You need to subscribe to an Observable. As I understood, in your case this.post is not type of an Observable.
As this.post is populated at some point of time, you need to subscribe to an observable which should emit data when you say this.post is now populated with data. For that you can use a Subject.
See this example: link
I have an iOS app that needs to pass data to a vue front-end:
const customerStore = new Vuex.Store({
state: {
data: [
{ id:1, title: 'Foo' },
{ id:2, title: 'Bar' }
]
},
mutations: {
list (state, data) {
state.data = data
}
}
})
const ListCustomersPage = {
key: 'ListCustomersPage',
template: '#ListCustomersPage',
components: { toolbar, cellcustomer },
data() {
return {
title: 'Select Customer',
items: customerStore.state.data
}
},
methods: {
push() {
}
}
};
However, I need to mutate the store from an injection on the webview:
web.InjectJavascriptAsync("customerStore.commit('list', [])").Start()
But the list is not changed. No error is shown when calling the injection.
I'm trying to mock the ActivatedRoute object is a test to simulate the passing of a parameter.
However every time the jasmine tests runs I get the following error:
Error: Can't resolve all parameters for ActivatedRoute: (?, ?, ?, ?, ?, ?, ?, ?).
at syntaxError (http://localhost:9876/_karma_webpack_/webpack:/node_modules/#angular/compiler/esm5/compiler.js:485:22)
at CompileMetadataResolver.webpackJsonp../node_modules/#angular/compiler/esm5/compiler.js.CompileMetadataResolver._getDependenciesMetadata (http://localhost:9876/_karma_webpack_/webpack:/node_modules/#angular/compiler/esm5/compiler.js:15700:1)
at CompileMetadataResolver.webpackJsonp../node_modules/#angular/compiler/esm5/compiler.js.CompileMetadataResolver._getTypeMetadata (http://localhost:9876/_karma_webpack_/webpack:/node_modules/#angular/compiler/esm5/compiler.js:15535:1)
at CompileMetadataResolver.webpackJsonp../node_modules/#angular/compiler/esm5/compiler.js.CompileMetadataResolver._getInjectableMetadata (http://localhost:9876/_karma_webpack_/webpack:/node_modules/#angular/compiler/esm5/compiler.js:15515:1)
at CompileMetadataResolver.webpackJsonp../node_modules/#angular/compiler/esm5/compiler.js.CompileMetadataResolver.getProviderMetadata (http://localhost:9876/_karma_webpack_/webpack:/node_modules/#angular/compiler/esm5/compiler.js:15875:1)
at http://localhost:9876/_karma_webpack_/webpack:/node_modules/#angular/compiler/esm5/compiler.js:15786:1
at Array.forEach (<anonymous>)
at CompileMetadataResolver.webpackJsonp../node_modules/#angular/compiler/esm5/compiler.js.CompileMetadataResolver._getProvidersMetadata (http://localhost:9876/_karma_webpack_/webpack:/node_modules/#angular/compiler/esm5/compiler.js:15746:1)
at CompileMetadataResolver.webpackJsonp../node_modules/#angular/compiler/esm5/compiler.js.CompileMetadataResolver.getNonNormalizedDirectiveMetadata (http://localhost:9876/_karma_webpack_/webpack:/node_modules/#angular/compiler/esm5/compiler.js:15007:1)
at CompileMetadataResolver.webpackJsonp../node_modules/#angular/compiler/esm5/compiler.js.CompileMetadataResolver._getEntryComponentMetadata (http://localhost:9876/_karma_webpack_/webpack:/node_modules/#angular/compiler/esm5/compiler.js:15848:26)
The Test looks like as follows:
import { TestBed } from '#angular/core/testing';
import { ReviewComponent } from './review.component';
import { ActivatedRoute, Router, Params } from '#angular/router';
import {AppModule} from "../app.module";
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';
class MockRouter {
navigate = jasmine.createSpy('navigate');
}
class MockActivatedRoute extends ActivatedRoute {
params: Observable<Params>;
constructor(parameters?: { [key: string]: any; }) {
super();
this.params = Observable.of(parameters);
}
}
describe('ReviewComponent', () => {
let mockActivatedRoute: MockActivatedRoute;
let mockRouter: MockRouter;
beforeEach(() => {
mockActivatedRoute = new MockActivatedRoute({'id': 1});
mockRouter = new MockRouter();
TestBed.configureTestingModule({
declarations: [ReviewComponent],
providers: [
{provide: ActivatedRoute, useValue: mockActivatedRoute},
{provide: Router, useValue: mockRouter}
],
imports: [AppModule]
}).compileComponents();
});
// beforeEach(async(() => {
//
// TestBed.configureTestingModule({
// declarations: [ ReviewComponent ],
// providers: [{provide: ActivatedRoute, useValue: activeRoute},
// {provide: Router, useValue: mockRouter}]
// })
// .compileComponents();
// }));
it('should create', () => {
const fixture = TestBed.createComponent(ReviewComponent);
fixture.detectChanges();
const editComponent = fixture.debugElement.componentInstance;
expect(editComponent).toBeTruthy();
});
// it('should have a review rating', () => {
// const compiled = fixture.debugElement;
// const title = compiled.query(By.css('.reviewRating'));
// expect(title).not.toBeNull();
// });
//
// it('should have a review product name', () => {
// const compiled = fixture.debugElement;
// const productName = compiled.query(By.css('.review-title'));
// expect(productName).not.toBeNull()
// });
//
// it('should have a header image', () => {
// const compiled = fixture.debugElement;
// const title = compiled.query(By.css('.reviewImageMain'));
// expect(title).not.toBeNull();
// });
});
I've tried a number of things to mock the object however as you can see from the log, for some reason the TestBed is not using the mock and is instead using import.
Can anyone help? I've lost so many hours today to this problem.
I almost forgot, the component looks like this:
import { Component, OnInit } from '#angular/core';
import {ActivatedRoute, Router} from "#angular/router";
import {OnDestroy} from "#angular/core/src/metadata/lifecycle_hooks";
#Component({
selector: 'app-review',
templateUrl: './review.component.html',
providers: [ActivatedRoute],
styleUrls: ['./review.component.css']
})
export class ReviewComponent implements OnInit, OnDestroy {
id: string;
private sub: any;
constructor(private route: ActivatedRoute, private router: Router){
}
cancel() {
this.router.navigate(['/search']);
}
ngOnInit() {
this.sub = this.route.params.subscribe(params => {
this.id = params['id'];
});
}
ngOnDestroy() {
this.sub.unsubscribe();
}
}
Got it :)
Wow, that was inconspicuous.
in review ReviewComponent in the providers I had included
providers: [ActivatedRoute]
This caused the the exception to happen, once I removed this line the test began to pass.
6 hours lost but bug found :)
import { Component, OnInit } from '#angular/core';
import {ActivatedRoute, Router} from "#angular/router";
import {OnDestroy} from "#angular/core/src/metadata/lifecycle_hooks";
#Component({
selector: 'app-review',
templateUrl: './review.component.html',
providers: [],
styleUrls: ['./review.component.css']
})
export class ReviewComponent implements OnInit, OnDestroy {
id: string;
private sub: any;
constructor(private route: ActivatedRoute, private router: Router){
}
cancel() {
this.router.navigate(['/search']);
}
ngOnInit() {
this.sub = this.route.params.subscribe(params => {
this.id = params['id'];
});
}
ngOnDestroy() {
this.sub.unsubscribe();
}
}
In the following test, the router.navigation property has a length of zero. How do we access our routes NavModel?
import { Container } from "aurelia-framework";
import { RouterConfiguration, Router } from "aurelia-router";
describe("the RouterConfiguration", function () {
let container: Container = new Container();
let routerConfiguration: RouterConfiguration = container.get(RouterConfiguration);
let router: Router = container.get(Router);
it("adds a route with a NavModel", function (done) {
routerConfiguration.mapRoute({
moduleId: "test",
name: "test",
navigationStrategy: (instruction) => {
instruction.config.moduleId = "something";
},
route: "test",
});
let configureRouter: Promise<void> = router.configure(routerConfiguration);
configureRouter.then(function () {
router.baseUrl = "foobar";
router.refreshNavigation();
expect(router.isConfigured).toBe(true);
expect(router.routes.length).toBe(1);
expect(router.navigation.length).toBe(1); // fails
expect(router.hasRoute("test")).toBe(true);
done();
});
});
});
Writing the router to the console displays this:
Router
{
parent: null,
options: Object{},
container: undefined,
history: undefined,
viewPorts: Object{},
routes: [
Object
{
moduleId: ...,
name: ...,
navigationStrategy: ...,
route: ...,
settings: ...,
navModel: ...
}
],
baseUrl: '',
isConfigured: true,
isNavigating: false,
navigation: [],
currentInstruction: null,
_fallbackOrder: 100,
_recognizer: RouteRecognizer
{
rootState: State {charSpec: ..., nextStates: ...},
names: Object{test: ...}
},
_childRecognizer: RouteRecognizer
{
rootState: State{charSpec: ..., nextStates: ...},
names: Object{test: ...}
},
_resolveConfiguredPromise: function (value) { ... },
_configuredPromise: Promise
{
_bitField: 33554432,
_fulfillmentHandler0: undefined,
_rejectionHandler0: undefined,
_promise0: undefined,
_receiver0: undefined,
_trace: CapturedTrace
{
_parent: ...,
_promisesCreated: ...,
_length: ...,
_promiseCreated: ...
}
}
}
I think you just need to add the nav: true property to the route you are mapping in mapRoute.
routerConfiguration.mapRoute({
moduleId: "test",
name: "test",
navigationStrategy: (instruction) => {
instruction.config.moduleId = "something";
},
route: "test",
nav: true // I want the route to be included in the nav model...
});