Constants not available for jest tests in Actions - javascript

When I run navAction-test.js below I get following error: TypeError: Cannot read property 'DATA_LOADED' of undefined
As I understand it the constant.DATA_LOADED is undefined, I'm guessing jest is mocking it and for this reason constant is undefined, I've tried everything I could find on the next but it remains undefined.
Is there anyone out there who can help. I would really appreciate it.
navAction.js:
var dispatcher = require('../dispatcher/AppDispatcher');
var constants = require('../constants/constants');
module.exports = {
load: function() {
def = $.ajax({
url: 'http://api.facebook.com/',
data: {},
success: function (data, textStatus, jqXHR) {
dispatcher.dispatch({type: constants.DATA_LOADED, data: data});
}
});
}
}
navAction-test.js:
jest.dontMock('../navAction.js');
describe('Tests NavigationCollectionActionCreators', function() {
var $;
var dispatcher;
var navAction;
beforeEach(function() {
$ = require('jquery');
dispatcher = require('../../dispatcher/AppDispatcher');
navAction = require('../navAction.js');
});
it('tests calls $.ajax & dispatcher ', function () {
navAction.load();
$.ajax.mock.calls[0][0].success({body: {header: {items: [{name: 'The name', link: 'http://www.facebook.com'}]}}});
expect(dispatcher.dispatch).toBeCalledWith({type: 'DATA_LOADED', data: [{name: 'The name', link: 'http://www.timeout.com'}]});
});
});
//constants.js
var keyMirror = require('keymirror');
module.exports = keyMirror({
DATA_LOADED: null,
});
UPDATE:
I got this to work by adding the following to navAction-test.js:
var constants = {
DATA_LOADED: 'DATA_LOADED',
DATA_NOT_LOADED: 'DATA_NOT_LOADED'
};
jest.setMock('../../constants/constants', constants);
Is this the correct way of doing it?

Add to test:
jest.dontMock('../constants/constants');
If you do not want to use automocking at all, you can remove all of the jest.dontMock and put instead:
jest.autoMockOff();
Your method to solve the problem (in the update at the bottom) is not appropriate in my opinion because it violates DRY (do not repeat yourself). What happens when you added another action constant? Now you have to remember to add it in the test too. That is problematic.

Related

EXTJS 4 build , singleton not called?

i am trying to make put my app in production mode , i face problem that my js code keep complain about missing javascript object and not run ,
in my app.js i have this
requires: [
"FleetM.utility.SharedData"
],
and this shared data is used in all controllers and view as singleton with name SharedData , but after build , the minified js keep say that SharedData is missing , but if i put it in console it print all values, even if i use uncompressed js the same result , here is my SharedData class
Ext.define('FleetM.utility.SharedData', {
alternateClassName: 'SharedData',
singleton: true,
'PreventALLUpdateDelete': 0,
'vehicles_creation': 0,
//..... alot of varibles here
'appSettings': 0,
'user': 0,
'i18n': 0,
success_load: false,
'comWizard': 0,
constructor: function () {
Ext.Ajax.request({
url: "USERS/GetAccessLevelData",
method: 'GET',
scope: this,
success: function (response, opts) {
var data = Ext.decode(response.responseText, true);
try {
SharedData.user = data;
SharedData.user.Connected=1;
} catch (err) {
}
try {
SharedData.PreventALLUpdateDelete = data.PreventALLUpdateDelete;
SharedData.vehicles_creation = data.vehicles_creation;
var language = SharedData.user.language;
} catch (err) {
}
switch (language) {
case '0':
language = "En";
break;
case '1':
language = "Ar";
break;
default:
language = "En";
break;
}
this.LoadI18n(language);
success_load: true;
},
failure: function (err) {
//Ext.MessageBox.alert(SharedData.i18n.Reports.ErrorMsg, SharedData.i18n.Reports.tryAgain);
}
});
},
LoadI18n: function (language) {
var me = this;
Ext.Ajax.request({
url: "data/i18n" + language + ".json",
method: 'GET',
scope: this,
success: function (response, opts) {
var data = Ext.decode(response.responseText, true);
try {
SharedData.i18n = data;
} catch (err) {
}
me.success_load = true;
},
failure: function (err) {
//Ext.MessageBox.alert(SharedData.i18n.Reports.ErrorMsg, SharedData.i18n.Reports.tryAgain);
}
});
}
});
----UPDATE----
I have done add requires for all controllers , and views , it still
complain
look at the images bellow ,
You have to add it to the requires array of each class, to have it available for all of it.
It is not enough to have it just in your app.js.
In development mode the missing class can be loaded dynamically, but in the production app.js all requires are appended in the order they need to be.
For Example: requires["C1", "FleetM.utility.SharedData", "C2"]
Would result in an app.js like
All the code with the requires for C1
All the code and requires for SharedData
All the code and requires for C2
When C1 needs SharedData for it's functionality it has to require it as well or SharedData is not available at that time for C1.
Update
You can not access the singleton FleetM.utility.SharedData during the configuration of the class, because it is not initialized during that point.
You should be able to access it in the constructor method of the store.
constructor: function() {
this.data = [
id: 0,
name: SharedData.i18n.configuration.Type_Vehicles
];
this.callParent(arguments);
}

Why each oo function/module after ajax, then each function/module attribute change to the last execute?

I tried to sync database return html string append to each .buttonContainer , use action.js execute other file loadButton module use parameter point specific element.
the result should be use different .buttonContainer and with their attr id connect db get result append to each .buttonContainer
My question is if I set ajax option async default true, then both return html string will append to the last .buttonContainer.
I can't understand I already set each module/function have their attr el from each execute parameter.
Why and how to solve it?
I tried to change async to false then it work but slowly the page, so I'm trying to find other solution.
<div class="buttonContainer" data-user-id="0"></div>
<div class="buttonContainer" data-user-id="1"></div>
action.js
define(['DomReady!', 'jquery', 'loadButton'],function (DomReady, $, loadButton) {
return {
init: function() {
// loop each element as parameter and execute
$('.buttonContainer').each(function(index, el) {
var config = {};
config.el = $(this);
loadButton.init(config);
});
},
}
});
loadButton.js
define(['DomReady!', 'jquery'],function (DomReady, $) {
return {
init: function(config) {
this.config = {};
this.config.el = config.el; // set each execute have their own private attribute
this.onLoadAction();
},
onLoadAction: function() {
this.onLoadController();
},
onLoadController: function() {
var userId = this.config.el.attr('data-user-id');
var mthis = this;
this.onLoadRequestDB('load/'+userId).done(function(response) {
console.log(mthis.config.el);
var response = JSON.parse(response);
mthis.config.el.append(response.button);
});
},
onLoadRequestDB: function(url) {
return $.ajax({
url: url,
type: 'GET',
processData: false,
contentType: false,
// async: false
});
},
}
});
Edit:
https://stackoverflow.com/a/22121078/1775888 I found some solution here, so I edit loadButton.js like this
..
init: function(config) {
this.config = {};
this.config.el = config.el; // set each execute have their own private attribute
this.onLoadAction(this.config);
},
onLoadAction: function(config) {
this.onLoadController(config);
},
onLoadController: function(config) {
..
pass parameter, then it work.
But I still want to know why I set the loadButton.js init this, in each loop but still can be cover after ajax. makes all response append to element from last execute loadButton.js config parameter

Angular $update resource

EDIT: If it's difficult to troubleshoot without me posting more code, let me know and I can add more to the question.
I have two instances of basically the same code, and one of them is working while the other isn't.
Working fine:
$scope.update = function() {
var question = $scope.question;
question.$update(function() {
$location.path('questions/' + question._id);
});
};
Not working:
$scope.updateAnswer = function() {
var answer = $scope.answerEdited;
answer.$update(function() {
$location.path('questions/' + $routeParams.questionId);
});
$scope.toggleEditAnswer(answer);
};
I get the error: undefined is not a function at my $update function. Here's my resource:
angular.module('intquestApp')
.factory('Answers', function ($resource) {
return $resource('api/answers/:answerId', {
answerId: '#_id'
}, {
update: {
method: 'PUT'
}
});
});
What exactly am I doing wrong? If I understand the flow correctly, the answer.$update uses the resource somehow? Also, if I use console.log to view what answer is being updated, it is the correct one:
Resource {_id: "543d8896039390eb5e000001", created: "2014-10-14T20:33:26.514Z", creator: Object, questionid: "543d8693994fc1685d000001", __v: 0…}
How exactly can I troubleshoot this?
Could you try the following and check if it works?
$scope.updateAnswer = function() {
Answers.update($scope.answerEdited, function(response) {
$location.path('questions/' + $routeParams.questionId);
});
$scope.toggleEditAnswer(answer);
};

Backbone targetModel = undefined

I am running into this issue with backbone where the model seems to be undefined to backbone, though all scripts are loaded.
(I am using require to load backbone and other javascript files).
So whenever I do a collection.fetch I get this error in firebug:
TypeError: targetModel is undefined
When I run the script it holds at this point:
if (attrs instanceof Model) {
id = model = attrs;
} else {
id = attrs[targetModel.prototype.idAttribute];
}
when I hover with my mouse over targetModel it says: undefined
It somehow doesn't seem to work now and the only thing I did was changing my html template, which only get loaded after the collection.fetch.
Can you please help me out here?
Here is my model:
var OF = OF || {};
OF.UsersMdl = Backbone.Model.extend({
default: {
username: '',
mailinglist: '',
email: ''
},
initialize: function() {
//
},
result: {
success: false,
message: ''
},
validate: function(att) {
}
});
Here is the collection:
var OF = OF || {};
OF.UsersCollection = Backbone.Collection.extend({
initialize: function() {
//
},
parse: function(data){
return data["all-users"];
},
model: OF.UsersMdl,
url: 'php/api/users'
});
And last but not least the router with the require part:
goToUsers: function() {
require(['./models/users', './views/users_view', './collections/user_collection'], function(UsersMdl, UsersView, UsersCollection) {
OF.usersMdl = new OF.UsersMdl;
OF.usersCollection = new OF.UsersCollection;
OF.usersView = new OF.UsersView;
//when the collection is fetched
$.when(OF.usersCollection.fetch({
data: {
"admin": OF.login.attributes.admin,
"session": OF.login.attributes.session
},
success: function(){
//console.log(OF.usersCollection.length);
}
//then render the view
})).then(function(){
OF.usersView.render();
}, 300);
});
},
Here is the JSON which will be retreived by the fetch:
{
"all-users":
[
{
"username":"tester",
"mailinglist":"1",
"email":"tester#tester.test"
},
{
"username":"tester2",
"mailinglist":"1",
"email":"tester2#tester.test"
},
{
"username":"tester3",
"mailinglist":"0",
"email":"tester3#tester.test"
}
]
}
Thanks in advance
I had this same error and banged my head against it for quite a while because backbone is new to me and this was compounding a fetch issue. Anyhow, I eventually figured out that order matters. Doh! (Less obvious when using CoffeeScript and "class" statements I thinks.) With one of my models I was setting the Collection before the Model (thanks to bad example code from the Backbone.js on Rails book). I reversed that and this error went away to reveal my true fetch issue.
Similarly, your model: property may be invalid for this reason or another reason, leaving it undefined when attempting to reference later.
Side note: I had a similar error in Backbone 1.0.0. When I upgraded to Backbone 1.1.0 I then got this exact error at the same point in backbone code.

Uncaught TypeError: has no method 'storeKeyFor'

I am new to Sproutcore and am learning the basics. I'm stuck at the following problem:
I have a model:
Myapp.Space = SC.Record.extend({
id: SC.Record.attr(Number),
name: SC.Record.attr(String),
creator: SC.Record.toOne('Myapp.User', {isMaster: YES, inverse: 'space'})
});
Myapp.User = SC.Record.extend({
id: SC.Record.attr(String),
name: SC.Record.attr(String)
});
And a controller:
Myapp.spaces_controller = SC.ArrayController.create(
{
allowsMultipleSelection: NO,
selection: null,
isEditable: YES
});
In my data source I am doing a remote GET call:
fetch: function(store, query) {
var recordType = query.get('recordType');
var url;
if (recordType === Myapp.Space) {
url = "spaces"
}
SC.Request.getUrl(this.baseApiUrl(store) + url).set('isJSON', YES)
.notify(this, this._didFetch, {
store: store,
recordType: recordType
}).send();
},
_didFetch: function (response, params) {
var store = params.store,
recordType = params.recordType;
if (SC.$ok(response)) {
store.loadRecords(recordType, response.get('body'));
}
},
When I call
Myapp.spaces_controller.set('content', Myapp.store.find(Myapp.Space));
(after login of the user) I get the error:
Uncaught TypeError: Object function (props) {
this.__sc_super__ = ret.prototype;
return this._object_init(props);
} has no method 'storeKeyFor' javascript.js?1377681200:11281
SC.Store.SC.Object.extend.loadRecord javascript.js?1377681200:11281
SC.Store.SC.Object.extend.loadRecords javascript.js?1377681200:11337
Myapp.DataSource.SC.DataSource.extend._didFetch data_source.js?1378388369:39
SC.Response.SC.Object.extend._notifyListeners javascript.js?1377681198:392
SC.Response.SC.Object.extend.notify javascript.js?1377681198:413
(anonymous function) javascript.js?1377681198:314
SC.run javascript.js?1377681203:14741
SC.Response.SC.Object.extend.receive javascript.js?1377681198:298
SC.XHRResponse.SC.Response.extend.finishRequest javascript.js?1377681198:628
SC.mixin.handle javascript.js?1377681199:4249
(anonymous function)
I can access the objects in the response body but the store does not get the data.
I could not find any mentioning of this error online. Can anybody help?
The error of Object function(props) ... has no method 'storeKeyFor' looks to me like you are attempting to call a function on a Class rather than on an actual Instance of that class.
My first guess is that your recordType is being set as an actual class rather than a string, and that may be causing some issues. In general, I would recommend using 'MyApp.Space' whenever dealing with record types as that will be evaluated and found at runtime. If it can't find it for some reason, it will throw a slightly nicer message.
Hope this helps!

Categories

Resources