I've written up an application that uses Ember Data. It's passing all it's tests and running as expected, however, something is causing a repeated deprecation warning to be thrown into console.
I'd like to know how to disable these warnings in Ember.
You can just do Ember.deprecate = function(){} in your application.js file and that should disable ember deprecation warnings.
It's always good to consider deprecations, but if you want to just turn them off entirely add the following 2 lines to your main app.js file.
Ember.deprecate = function(){};
Ember.warn = function(i){};
My suggestion here, so you won't completely miss the deprecation warnings - they're there for a reason, right?
These are simplified versions of what deprecate would do, but logging to DEBUG (so you can filter them out easily) and without the stacktrace (for simplicity). They'll also not show repeated messages:
CoffeeScript:
Ember.deprecate = (->
already_shown = []
(msg, test, opt)->
return false if test
if already_shown.indexOf(msg) == -1
warning = "DEPRECATION: #{msg}"
warning += " See: #{opt.url}" if opt.url
console.debug warning
already_shown.push msg
)()
JS:
Ember.deprecate = (function() {
var already_shown = [];
return function (msg, test, opt) {
if (test) return false;
if (already_shown.indexOf(msg) === -1) {
var warning = 'DEPRECATION: ' + msg;
if (opt.url) {
warning += ' See: ' + opt.url;
}
console.debug(warning);
}
already_shown.push(msg);
};
})();
Modifed for Ember 2.3 version (thank's to igorsantos07)
const alreadyShownFactory = () => {
let alreadyShown = [];
return (msg, test, opt) => {
if (test)
return false;
if( alreadyShown.indexOf(msg) === -1 ) {
let warning = 'DEPRECATION: ' + msg;
if(opt && opt.url) {
warning += ' See: ' + opt.url;
}
console.warn(warning);
alreadyShown.push(msg);
}
};
};
Ember.deprecate = alreadyShownFactory();
Ember.warn = alreadyShownFactory();
//see https://guides.emberjs.com/v2.3.0/configuring-ember/handling-deprecations/
Ember.Debug.registerDeprecationHandler((() => {
let alreadyShown = [];
return (message, options, next) => {
if(alreadyShown.indexOf(message) === -1) {
next(message, options);
alreadyShown.push(message);
}
};
})());
For Ember 3.8 below code in app/initializers/deprecation.js worked for me. This disables the deprecations while running tests. You can modify according to your needs.
import { registerDeprecationHandler } from '#ember/debug';
export function initialize() {
registerDeprecationHandler((message, options, next) => {
if (options && options.until && options.until !== '2.0.0') {
return;
} else {
next(message, options);
}
});
}
export default { initialize };
Took this from the docs
If you're looking for this in Ember >=2.0.0, you have to change this in:
Ember.Logger.warn = () => {}
Ember.Logger.deprecate = () => {}
Related
I want to know how to write test code using mocha for the meteor function
export const physicalToLogical = (physicalStatus, planningStartDate, planningEndDate) => {
if(physicalStatus === STATUS_PHYSICAL_CREATING) {
return STATUS_LOGICAL_CREATING;
} else if (physicalStatus === STATUS_PHYSICAL_OPEN) {
const now = new Date();
if(planningStartDate.getTime() <= now && planningEndDate.getTime() > now) {
return STATUS_LOGICAL_OPEN_FOR_PLAN;
} else if(planningStartDate.getTime() > now) {
return STATUS_LOGICAL_PROSPECT;
}
return STATUS_LOGICAL_REVIEW;
} else if (physicalStatus === STATUS_PHYSICAL_CLOSED) {
return STATUS_LOGICAL_CLOSED;
} else if (physicalStatus === STATUS_PHYSICAL_ARCHIVED) {
return STATUS_LOGICAL_ARCHIVED;
}
throw new Error("Not implemented yet");
};
First, this function has nothing to do with Meteor.
Writing tests for such a function would involve sending different statuses to the method and expecting the different results.
Here's an example (using chai as the assertions library) :
describe('physicalToLogical', () => {
it('should return the given status', () => {
expect(physicalToLogical(STATUS_PHYSICAL_CREATING, null, null)).
toEqual(STATUS_LOGICAL_CREATING);
});
it('should...', () => {
...
});
...
});
This is one of the many simple cases you have to write for that code.
Several other tests need to be written for the cases involving dates, but the format is more or less the same.
I'm using expectSaga ('redux-saga-test-plan') to test one of my sagas and I'm wondering how to test multiple calls made within the same saga.
Sagas.js
export function* fetchSomething(arg){
const response = yield call(executeFetch, arg);
if(response.status === 200){
// trigger success action
} else if (response.status >= 400){
const errResp = yield response.json();
const errorCode = yield call(sharedUtilToExtractErrors, errResp);
yield put(
{ type: 'FETCH_FAILED', errorMessage: UI_ERR_MSG, errorCode }
);
}
}
Unit test
import { expectSaga } from 'redux-saga-test-plan';
describe('fetchSomething', () => {
// positive paths
// ..
// negative paths
it('fetches something and with status code 400 triggers FETCH_FAILED with error message and extracted error code', () => {
const serverError = { message: 'BANG BANG BABY!' };
const koResponse = new Response(
JSON.stringify(serverError),
{ status: 400, headers: { 'Content-type': 'application/json' } }
);
return expectSaga(fetchSomething)
.provide(
{
call: () => koResponse,
call: () => serverError.message,
}
)
.put({
type: 'FETCH_FAILED', errorMessage: UI_ERR_MSG, serverError.message
})
.run();
})
})
Clearly having the "call" attribute twice in the same object passed in to provide() doesn't work but also calling provide() twice doesn't do the trick. Any suggestions?
Thanks
This is how you can provide multiple calls according to the documentation:
.provide([ // this external array is actually optional
[call(executeFetch, arg), koResponse],
[call(sharedUtilToExtractErrors, serverError), serverError.message],
])
or if you're lazy and don't want to specify the arguments:
import * as matchers from 'redux-saga-test-plan/matchers';
.provide(
[matchers.call.fn(executeFetch), koResponse],
[matchers.call.fn(sharedUtilToExtractErrrors), serverError.message],
)
Neither of these two worked for me though as for some reason it was not mocking out the dependencies and still calling them caused errors.
I solved using a dynamic provider:
.provide({
// select(effect, next) { return 'something-for-a-selector' },
call(effect) {
switch(effect.fn.constructor.name) {
case executeFetch.constructor.name: return koResponse;
case sharedUtilToExtractErrors.constructor.name: return serverError.message;
default: throw new Error('Unknown function called in test');
}
}
})
I have component with a couple of properties, using a promise in the willRender hook to try and create a (pagination) object:
export default Ember.Component.extend({
pagination:null,
testing:null, // to check if this.set is ok within the promise!
willRender() {
let page = {};
let model = this.get('data');
model.get('products').then(relatedItems => {
let maxRecords = relatedItems.get('length');
relatedItems.forEach(function(item,index) {
if (item.get('slug') === itemModel.get('id')) {
if (index === 0) {
page.Prev = null;
page.Next = relatedItems.objectAt(index+1).get('slug');
}
else if (index+1 === maxRecords) {
page.Prev = relatedItems.objectAt(index-1).get('slug');
page.Next = null;
}
else {
page.Prev = relatedItems.objectAt(index-1).get('slug');
page.Next = relatedItems.objectAt(index+1).get('slug');
}
}
});
this.set('testing','hello world');
console.log(this.get('testing')); // hello world
this.set('pagination',page);
console.log(this.get('pagination')); // Object {Prev: "product-1", Next: "product-2"}
},reject => {
console.log('error '+reject);
});
}
})
In my template
{{testing}} // prints hello world
However, if I try and access {{pagination}} eg {{log pagination}}, the browser crashes with a loop printing out the object to the console.
I don't know where I'm going wrong here - any help much appreciated!
It's likely you are triggering the template to rerender causing willRender to fire over and over which causes an infinite loop in your code.
willRender is a non-standard place to do this code, init would be more standard since it only fires on initialization of the component. Even better would be to use
myInit: Ember.on('init', function(){
....
})`
instead of overriding willRender on the object.
try to check whether Object is present at specific position. i think its going undefined during iteration of for loop. try to ensure that ObjectAt is not returning undefined or null value during running of for loop.
relatedItems.forEach(function(item,index) {
if (item.get('slug') === itemModel.get('id')) {
if (index === 0) {
page.Prev = null;
if(relatedItems.objectAt(index+1) ! = undefined) {
page.Next = relatedItems.objectAt(index+1).get('slug');
}else{
page.Next == null;
}
}
else if (index+1 === maxRecords) {
if(relatedItems.objectAt(index-1) ! = undefined) {
page.Prev = relatedItems.objectAt(index-1).get('slug');
}else{
page.Prev = null;
}
page.Next = null;
}
else {
if(relatedItems.objectAt(index-1) ! = undefined) {
page.Prev = relatedItems.objectAt(index-1).get('slug');
}else{
page.Prev = null;
}
if(relatedItems.objectAt(index+1) ! = undefined) {
page.Next = relatedItems.objectAt(index+1).get('slug');
}else{
page.Next = null;
}
}
}
Please ensure that Object at is returning object.
There seems to be a few problems here, would be interested to know what your console errors are.
You don't seem to have defined itemModel so don't know how you're referencing that.
Also you can't access this from within a .then. You need to do something like this to set a component variable.
var _this = this;
promise().then(function(results) {
_this.set('testing', 'hello world');
});
you are not using , after testing:null
there should be , after testing property like that
pagination:null,
testing:null, // i use ',' after testing: null property
try to use your pagination code under init hook rather than willrender hook
init() {
//you code
},
I can't seem to fetch new data in Internet Explorer 9. For the purpose of an example I test the store this way:
App.__container__.lookup('store:main').find('style')
The only error I receive is the following:
SCRIPT5022: Error: Assertion Failed: [object Object]
Does Ember-data works out of the box (without polyfills, ...) in Internet Explorer 9?
versions:
Ember: 1.9.1
Ember-data: 1.0.0-beta.12
Problem solved. When doing an AJAX request with jQuery, this normally happens through the XMLHttpRequest object.
On IE8-9, this object is not present, instead it uses XDomainRequest. The simplest fix for this is adding: https://github.com/MoonScript/jQuery-ajaxTransport-XDomainRequest.
ember-data works out of the box with IE8+. According to this issue:
We've been supporting IE8 with our platform (built on Ember) for a
while now. Things I know:
shim/sham is not needed, it's polyfilled by Ember and Ember-Data.
You will need it if you want additional things like .bind() on a function, then you must prepend it to the vendor file (using Brocfile)
and we only include the shim for that purpose, not the sham
Solution Synthesis
Reason :
On IE8-9, this object is not present, instead it uses XDomainRequest.
Solution :
The issue is solved. When using an AJAX request with jQuery. Normally this is done through the XMLHttpRequest object. A simple fix would be using the Open-Source jQuery-ajaxTransport-XDomainRequest
Code : Adding :
jQuery-ajaxTransport-XDomainRequest.js
/*!
* jQuery-ajaxTransport-XDomainRequest - v1.0.4 - 2015-03-05
* https://github.com/MoonScript/jQuery-ajaxTransport-XDomainRequest
* Copyright (c) 2015 Jason Moon (#JSONMOON)
* Licensed MIT (/blob/master/LICENSE.txt)
*/
(function(factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as anonymous module.
define(['jquery'], factory);
} else if (typeof exports === 'object') {
// CommonJS
module.exports = factory(require('jquery'));
} else {
// Browser globals.
factory(jQuery);
}
}(function($) {
// Only continue if we're on IE8/IE9 with jQuery 1.5+ (contains the ajaxTransport function)
if ($.support.cors || !$.ajaxTransport || !window.XDomainRequest) {
return $;
}
var httpRegEx = /^(https?:)?\/\//i;
var getOrPostRegEx = /^get|post$/i;
var sameSchemeRegEx = new RegExp('^(\/\/|' + location.protocol + ')', 'i');
// ajaxTransport exists in jQuery 1.5+
$.ajaxTransport('* text html xml json', function(options, userOptions, jqXHR) {
// Only continue if the request is: asynchronous, uses GET or POST method, has HTTP or HTTPS protocol, and has the same scheme as the calling page
if (!options.crossDomain || !options.async || !getOrPostRegEx.test(options.type) || !httpRegEx.test(options.url) || !sameSchemeRegEx.test(options.url)) {
return;
}
var xdr = null;
return {
send: function(headers, complete) {
var postData = '';
var userType = (userOptions.dataType || '').toLowerCase();
xdr = new XDomainRequest();
if (/^\d+$/.test(userOptions.timeout)) {
xdr.timeout = userOptions.timeout;
}
xdr.ontimeout = function() {
complete(500, 'timeout');
};
xdr.onload = function() {
var allResponseHeaders = 'Content-Length: ' + xdr.responseText.length + '\r\nContent-Type: ' + xdr.contentType;
var status = {
code: 200,
message: 'success'
};
var responses = {
text: xdr.responseText
};
try {
if (userType === 'html' || /text\/html/i.test(xdr.contentType)) {
responses.html = xdr.responseText;
} else if (userType === 'json' || (userType !== 'text' && /\/json/i.test(xdr.contentType))) {
try {
responses.json = $.parseJSON(xdr.responseText);
} catch(e) {
status.code = 500;
status.message = 'parseerror';
//throw 'Invalid JSON: ' + xdr.responseText;
}
} else if (userType === 'xml' || (userType !== 'text' && /\/xml/i.test(xdr.contentType))) {
var doc = new ActiveXObject('Microsoft.XMLDOM');
doc.async = false;
try {
doc.loadXML(xdr.responseText);
} catch(e) {
doc = undefined;
}
if (!doc || !doc.documentElement || doc.getElementsByTagName('parsererror').length) {
status.code = 500;
status.message = 'parseerror';
throw 'Invalid XML: ' + xdr.responseText;
}
responses.xml = doc;
}
} catch(parseMessage) {
throw parseMessage;
} finally {
complete(status.code, status.message, responses, allResponseHeaders);
}
};
// set an empty handler for 'onprogress' so requests don't get aborted
xdr.onprogress = function(){};
xdr.onerror = function() {
complete(500, 'error', {
text: xdr.responseText
});
};
if (userOptions.data) {
postData = ($.type(userOptions.data) === 'string') ? userOptions.data : $.param(userOptions.data);
}
xdr.open(options.type, options.url);
xdr.send(postData);
},
abort: function() {
if (xdr) {
xdr.abort();
}
}
};
});
return $;
}));
I am working on an app that makes heavy use of JavaScript. I need to unit test this code. In an effort to do that, I'm relying on Jasmine.
Some of my JavaScript code throws JavaScript Error objects. Those objects assign values to the message and name property of the Error object. I assign a type of exception to the name property. For instance, sometimes the name is set to OutOfRangeException, sometimes its ArgumentException, etc.
How do I use the toThrowError function in the Jasmine framework to test if a thrown error has a specific name? Currently, my JavaScript looks like the following:
function getRandomNumber(max) {
if ((!isNaN(parseFloat(max)) && isFinite(max)) === false) {
var error = new Error('You must provide a number');
error.name = 'ArgumentException';
throw error;
}
if ((max === null) || (max < 1) || (max > 100)) {
var error = new Error('The maximum value must be greater than 0 and less than 100.');
error.name = 'ArgumentOutOfRangeException';
throw error;
}
return Math.floor(Math.random() * max) + 1;
}
function ArgumentException(message) {
this.name = 'ArgumentException';
this.message = message || '';
}
ArgumentException.prototype = new Error();
ArgumentException.prototype.constructor = ArgumentException;
How can I write a Jasmine test that checks for an ArgumentException error or an ArgumentOutOfRangeException error?
Thank you!
Checking exception for a function with parameter is not supported in jasmine. But you can use below workaround to overcome this limitation and test your functions.
describe('toThrowError test case', function() {
it('test getRandomNumber function for undefined', function() {
expect(function() {
getRandomNumber(undefined);
}).toThrowError("You must provide a number");
});
it('test getRandomNumber function for 0', function() {
expect(function() {
getRandomNumber(0);
}).toThrowError("The maximum value must be greater than 0 and less than 100.");
});
});
toThrowError matcher takes 1 or 2 parameters
1 Parameter - Either exception message or exception type
2 Parameters - Exception type and Exception message
Example to check based on exception type:
function getRandomNumber(max) {
throw new SyntaxError();
}
describe('toThrowError test case', function() {
it('test getRandomNumber function for undefined', function() {
expect(function() {
getRandomNumber(undefined);
}).toThrowError(SyntaxError);
});
});
Refer link for different types of exceptions.
Custom Error Message
Below mentioned snippet gives a sample for using the custom error messages.
function getRandomNumber(max) {
throw new ArgumentException();
}
function ArgumentException(message) {
this.name = 'ArgumentException';
this.message = message || '';
}
ArgumentException.prototype = new Error();
ArgumentException.prototype.constructor = ArgumentException;
describe('toThrowError test case', function() {
it('test getRandomNumber function for undefined', function() {
expect(function() {
getRandomNumber(undefined);
}).toThrowError(ArgumentException);
});
});