I'm very new to Angular and I'm trying to figure much of this out still. I'm writing some tests using Angular 1.5.8 which I generated from the Yeoman Generator.
Specifically, I'm trying to figure out how to manipulate $httpBackend results (I'm not sure if that's important or not)...
In my app.js file I have the following code:
.run(['$rootScope', '$location', 'breadcrumbService', function ($rootScope, $location, breadcrumbService) {
$rootScope.$on('$viewContentLoaded', function () {
jQuery('html, body').animate({scrollTop: 0}, 200);
});
$rootScope.isEditMode = false;
$rootScope.$on('$stateChangeSuccess', function () {
// ------------ this next line is failing -----------
$rootScope.isEditMode = $location.path().toLowerCase().endsWith('/edit') || $location.path().toLowerCase().endsWith('/new');
});
$rootScope.parseJson = function (value) {
return angular.fromJson(value);
};
$rootScope.bc = breadcrumbService;
$rootScope.title = "";
}])
The line about halfway down (where I added the comment) is failing. Specifically, the endsWith function is failing (toLower is fine), with this error:
PhantomJS 2.1.1 (Windows 8 0.0.0) Service: breadcrumbService should return breadcrumb label in json format FAILED
TypeError: undefined is not a constructor (evaluating '$location.path().toLowerCase().endsWith('/edit')') in app/scripts/app.js (line 44)
app/scripts/app.js:44:72
$broadcast#bower_components/angular/angular.js:18005:33
bower_components/angular-ui-router/release/angular-ui-router.js:3353:32
processQueue#bower_components/angular/angular.js:16383:30
bower_components/angular/angular.js:16399:39
$eval#bower_components/angular/angular.js:17682:28
$digest#bower_components/angular/angular.js:17495:36
$apply#bower_components/angular/angular.js:17790:31
done#bower_components/angular/angular.js:11831:53
handleResponse#bower_components/angular-mocks/angular-mocks.js:1368:17
flush#bower_components/angular-mocks/angular-mocks.js:1808:26
test/spec/services/breadcrumbservice.js:33:27
invoke#bower_components/angular/angular.js:4718:24
workFn#bower_components/angular-mocks/angular-mocks.js:3085:26
Here is my test code (some junk modified from different examples - just trying to get it to work):
'use strict';
describe('Service: breadcrumbService', function () {
// load the service's module
beforeEach(module('myModule'));
var $httpBackend, $rootScope, createController, authRequestHandler;
beforeEach(inject(function($injector) {
$httpBackend = $injector.get('$httpBackend');
console.log('Is null? '+ ($httpBackend == null));
$httpBackend.whenGET(/views\/.*/).respond(200, [{}, {}, {}]);
authRequestHandler = $httpBackend.when('GET', '/api/v1/SiteStagings')
.respond({userId: 'userX'}, {'A-Token': 'xxx'});
// Get hold of a scope (i.e. the root scope)
$rootScope = $injector.get('$rootScope');
$httpBackend.flush();
}));
// instantiate service
var breadcrumbService;
beforeEach(inject(function (_breadcrumbService_) {
breadcrumbService = _breadcrumbService_;
}));
it('svc should exist', function () {
expect(!!breadcrumbService).toBe(true);
});
it('should return breadcrumb label in json format', function () {
var result = breadcrumbService.getFromCache('site', 'SiteGroupStagings', 46, 'SiteGroupDesc');
console.log(result);
expect(!!result).toBe(true);
});
});
I don't doubt that I'm doing something wrong here, I just can't quite understand what it is. What does this error really mean and why does it not like my call to endsWith?
Thanks
undefined is not a constructor
is an error message PhantomJS displays when you tried to call a function that is not defined. It depends on the version of ECMAScript which your PhantomJS supports. So as you said it works fine in Chrome, because this browser supports the function you are using in test.
In order to fix your problem and still be able to use PhantomJS you can replace the "unknown to PhantomJS" function with some alternative function.
I was getting TypeError: undefined is not a constructor error using the includes() method. The includes() and endsWith() methods are new in ECMAScript 2015, and are not supported in Internet Explorer, and evidently not by PhantomJS.
There is a chance your end user may be using Internet Explorer. In which case, you may want to use the fully supported indexOf() method instead of includes() or endsWith()
For example, in my case, everything worked great in chrome, but my tests were failing on the line:
if (item.name.includes('contents'))
I changed to using the indexOf() method instead:
if (item.name.indexOf('contents') !== -1)
And then I was no longer getting the error
TypeError: undefined is not a constructor
I debated whether or not to post this as an answer or just an edit to my question, but I guess it's my answer (for now):
It seems the problem is related to PhantomJS. As soon as I changed the engine to Chrome in the karma.conf.js file, those tests passed.
I still don't know what that error message is supposed to mean and why it wasn't working with PhantomJS, but at least I'm now able to continue.
Here are the modifications to my karma.conf.js (in case anyone is curious):
browsers: [
//'PhantomJS',
'Chrome'
],
// Which plugins to enable
plugins: [
'karma-chrome-launcher',
//'karma-phantomjs-launcher',
'karma-jasmine'
],
Btw - I did notice that endsWith is new to ECMAScript6 (I was thinking it was older), but WebStorm shows that it's referencing a helper function in angular-ui-grid. I spent quite a while messing with the files array in the karma.conf.js file in an attempt to see if the ui-grid dependency was loading too late or something. In every test, it worked fine in Chrome but not PhantomJS. I still have no idea why.
In My Case: Cyclic Dependencies Causing:
PhantomJS 2.1.1 (Windows 8 0.0.0) ERROR TypeError: undefined is not a constructor (evaluating '(0, _actions.prefix)('SET_USER_INPUT_PHONE_NUMBER')') at undefined:12
I got the same error after I added imports in my javascript production code (ES6 syntax compiled with babel/webpack).
The changes were fine when a production build of the application was loaded in chrome but running the tests with phantomJS produced the error.
In my case the added imports created cyclic dependencies.
I'm dropping this here for future reference (I stumbled upon the same problem a few weeks ago and don't want to scratch my head again in another couple of weeks) and for others that google the same error.
I faced similar error with PhantomJS:
For me the error was the way in which I was creating a spy object for my service.
Error on line in code file new Service.getData(param1, param2)
Fix in test file: jasmine.createSpyObj('Service',['getData'])
What is was missing was adding ['getData] while creating spyObj
I was using following code
element(by.xpath("//tf-navpane-item[contains(#class,'tf-state-selected')]//tf-navpane-item-text//*[contains(#class,'ng-binding')]")).then(function(ele){
ele.getText().then(function(txt){
console.log("txt: "+txt);
});
});
This code used to work fine when I was using Protractor 1.0. After upgrading Protractor to 3.2.1 ,I started to get following error.
TypeError: element(...).then is not a function
I maybe missing something but not sure what.
Yeah, this is something you should expect since the element() cannot be directly resolved with then() anymore (breaking change in Protractor 2.0). Instead, do:
var elm = element(by.xpath("//tf-navpane-item[contains(#class,'tf-state-selected')]//tf-navpane-item-text//*[contains(#class,'ng-binding')]"));
elm.getText().then(function(txt) {
console.log("txt: " + txt);
});
Note that, if you would need to assert the text, you can pass the getText() into expect() - it understands what a promise is and would resolve it before making an expectation:
expect(elm.getText()).toEqual("Expected text");
I need help figuring out why I am getting this error.
My method is defined in app/server/methods.js
Meteor.methods({
myMethod: function(user) {
Accounts.addEmail(user._id, "thisemail#email.com", true); // set verified to true
}
});
My template has an event that is calling this method from the client.
Template.myTemplate.events({
'click #this-button': function(e) {
Meteor.call("myMethod", userObject, function(error, result) {
if (error) {
console.log(error);
} else {
// do something here
}
});
}
});
I keep getting an Internal Server Error [500] error back to the console.
When I check my server output it says:
Exception while invoking method 'myMethod' TypeError: Object #<Object> has no method 'addEmail'.
Can anyone help me figure out why it can't be found/used?
These are the list of packages I am using, and I thought this came packaged with the accounts-password package according to the Meteor Documentation here.
meteor-platform
iron:core
iron:router
less
zimme:iron-router-active
tomi:upload-server
tomi:upload-jquery
houston:admin
coffeescript
alanning:roles
edgee:slingshot
joshowens:accounts-entry
mystor:device-detection
underscore
email
accounts-password
If I'm reading the commit history correctly, it looks like addEmail was added here as part of meteor 1.2.
The docs always reference the latest version, but your app is using version 1.1, which explains the missing function.
The solution may be as simple as running meteor update, however accounts-entry is ancient and it may be incompatible with meteor 1.2, as noted in this issue.
If you can't or don't want to update, just leave a comment and I can suggest an alternative implementation.
Update: I figured out what the issue was, see my comment below.
Is there a way to guarantee state before each Jasmine test?
For example:
describe('some thing', function () {
beforeEach(function () {
doSetup();
// this expect does not evaluate :(
expect(something).toBe(inSomeState);
});
it('has some behavior', function () {
// test code
});
});
The expect inside of the setup make no difference at all. Even throwing an error in the beforeEach does nothing. I would like to have some assurance that the setup has completed correctly before running the next test.. is there a way to do this?
Okay I see what the issue is. Hoping this will help other people out there having this same issue. grunt-contrib-jasmine does not display errors or failed expects inside of beforeEach or afterEach with the display option set to short. Setting this option to full will once again display Errors and failed expects.
I recently updated my project to dojo version 1.6.2 from 1.6.1 now I keep getting strange errors without any code changed.
Chrome error console:
Error parsing in _ContentSetter#Setter_DIV_0
/etermin/js/dojo-release-1.6.2/dojo/../dijit/layout/ContentPane.js:203
Error undefined running custom onLoad code: This deferred has already been resolved
/etermin/js/dojo-release-1.6.2/dojo/../dijit/layout/ContentPane.js:142
Firefox error console:
dojo.js (vrstica 324)
Error parsing in _ContentSetter#Setter_DIV_0
Error: Could not load class 'dijit.form.FileringSelect
dojo.js (vrstica 372)
Error undefined running custom onLoad code: This deferred has already been resolved
There is a problem in the dojo.js file: If I change it back to 1.6.1 it makes things work. But I want to use 1.6.2 version
Plaease help and advise
UPDATE:
Something strange that I've found:
var p = new dijit.MenuItem({
label: "cut",
})
p.onClick = function() {
dojo.xhrGet({
//some ajax call
});
}
Doesn't work. But if I put just one simple alert before the ajax it works.
p.onClick = function() {
alert("123");
dojo.xhrGet({
//some ajax call
});
}
Why don't you update your Version to 1.9? Sooner or later the legacy dojo won't work anymore and in the Google Hosted librarys i found no Version 1.6.2
Have a look:
https://developers.google.com/speed/libraries/devguide
Is it still available? Where do you get the dojo.js from?
To prevent the timing Issue of the Menu, you can define the onClick when you
define your MenuItem.
Have a look :
var p = new dijit.MenuItem({
label: "Menu Item With an icon",
iconClass: "dijitEditorIcon dijitEditorIconCut",
onClick: function(){alert('i was clicked')}
}));
Regards, Miriam
This is reported as a bug.
Look here for the bug report..
You have to patch your dojo version or Upgrade it to 1.8 or later to fix it.
If you know what you are playing with you can fix it manually.
The patch is on here.
You can manually apply this to your current dojo build to fix it.