In my component set
data(){
categories: this.$parent.categories => which I set in main.js
}
Code file main.js
import categories from '../config/categories';
new Vue({
router,
data: {
categories: categories
}
});
I created 1 function unit test
it(‘check component is a button’,() => {
const wrapper = shallow(FormSearch);
expect(wrapper.contains(‘button’)).toBe(true);
});
I run test then show error: Error in data(): "TypeError: Cannot read property ‘categories’ of undefined"
How to fix it. Help me.
Why not import you categories config file directly into your component?
import Categories from '../config/categories'
then your data method can directly access it:
data () { return { categories: Categories }}
You'll find that much easier to test
yes, thanks you. I changed. I run test then it happens error other
Cannot find module '../../config/categories' from 'mycomponet.vue'.
Although. I run project on browser just working well.
How to fix it. Thanks you very much
For Testing , you can set mock data to escape undefined error while testing . But it is not standard solution .....
it(‘check component is a button’,() => {
const wrapper = shallow(FormSearch);
let mockCategories = { // mock category data }
wrapper.$parent = {
categories: mockCategories
}
expect(wrapper.contains(‘button’)).toBe(true);
});
Try this approach:
const Parent = {
data: () => ({
val: true
}),
template: '<div />'
}
const wrapper = shallowMount(TestComponent, {
parent: Parent
})
I would like to display an error message when the server responses with record not found.
The model in the route handler:
model: function(userLoginToken) {
var userLoginToken= this.store.createRecord('userLoginToken');
return userLoginToken;
},
The action:
actions: {
sendOTP: function(userLoginToken) {
var thisObject = this;
var model=this.currentModel;
this.store.findRecord('user-login-token', userLoginToken.get('mobileNumber')).then(function(response) {
//thisObject.get('controller').set('model', response);
},
function(error) {
//thisObject.get('controller').set('model', error);
//alert("model======== "+model.get('errors'));
});
},
The template is not displaying any error message.
The template:
{{#each model.errors.messages as |message|}}
<div class="errors">
{{message}}
</div>
{{/each}}
Unfortunately, the error message doesn't appear.
Ember depends on an DS.error object, in order to get errors from your models the response has to fulfill the requirements. In order to get Ember to recognize an valid error, in Ember 2.x the error code MUST be 422 and has to follow jsonapi http://jsonapi.org/format/#errors-processing
If you want to catch the errors from the backend response you have to use the catch method:
this.store.findRecord('user-login-token', userLoginToken.get('mobileNumber'))
.then(success => {
// Do whatever you need when the response success
})
.catch(failure => {
// Do whatever you need when the response fails
})
},
For catching the errors automatically as you are doing in your template, your backend needs to response in the right way. I would suggest you to read the answer for this SO question.
I have uses angular translate from here (http://pascalprecht.github.io/angular-translate/) and it's just work fine, but it break my controller's unit test whith Error:
Unexpected request: GET scripts/i18n/locale-en.json
I don't understant why?
I use yeoman and test with karma.
app.js:
'use strict';
(function() {
angular.module('wbApp', ['authService', 'authUserService', 'checkUserDirective', 'ui.bootstrap', 'pascalprecht.translate'])
.config(function($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'views/login.html',
controller: 'LoginCtrl',
access: {
isFree: true
}
})
.when('/main', {
templateUrl: 'views/main.html',
controller: 'MainCtrl',
access: {
isFree: false
}
})
.otherwise({
redirectTo: '/'
});
});
})();
configTranslate.js:
'use strict';
(function() {
angular.module('wbApp')
.config(['$translateProvider',
function($translateProvider) {
$translateProvider.useStaticFilesLoader({
prefix: 'scripts/i18n/locale-',
suffix: '.json'
});
$translateProvider.preferredLanguage('en');
}]);
})();
karma.conf.js:
files = [
...
'app/bower_components/angular-translate/angular-translate.js',
'app/bower_components/angular-translate-loader-static-files/angular-translate-loader-static-files.js',
...
];
controller test:
'use strict';
describe('Controller: LoginCtrl', function() {
// load the controller's module
beforeEach(module('wbApp'));
var LoginCtrl, scope, location, httpMock, authUser;
// Initialize the controller and a mock scope
beforeEach(inject(function($controller, $rootScope, $location, $httpBackend, AuthUser) {
authUser = AuthUser;
location = $location;
httpMock = $httpBackend;
scope = $rootScope.$new();
LoginCtrl = $controller('LoginCtrl', {
$scope: scope
});
httpMock.when('GET', 'scripts/i18n/locale-en.json').passThrough();
}));
it(...);
...
});
if i add this in test controller, product same error:
httpMock.when('GET', 'scripts/i18n/locale-en.json').respond(200);
httpMock.flush();
or
httpMock.when('GET', 'scripts/i18n/locale-en.json').passThrough();
httpMock.flush();
i find this post How do I test controllers with Angular Translate initialized in App Config? but not helped me :/
I extensively use $httpBackend in my tests and it works fine, but in this case it is ineffective. If I comment the line:
$translateProvider.preferredLanguage('en');
obviously an error, if I add on the runtime (in my controllers)
$translate.uses(local);
I end up with the same error?
So I turn to the translation configuration (configTranslate.js) or at runtime is the same result:
Unexpected request: GET scripts/i18n/locale-en.json
Here is the syntax that I tested, either in a "beforeEach(inject(function(...});"
or in a test "it('...', function() {...});"
httpMock.expectGET('scripts/i18n/locale-en.json');
httpMock.when('GET', 'scripts/i18n/locale-en.json').passThrough();
httpMock.when('GET', 'scripts/i18n/locale-en.json').respond(data);
with at end
httpMock.flush();
I also tried a $ apply
httpMock.expectGET('scripts/i18n/locale-fr.json');
scope.$apply(function(){
$translate.uses('fr');
});
httpMock.flush();
nothing happens, Still this error is driving me crazy ..
If you have any suggestion
it's a known issue, please follow the documentation here: unit testing angular
The solution
Unfortunately, this issue is caused by the design of
angular-translate. To get around these errors, all we can do is to
overwrite our module configuration in our test suite, that it doesn't
use asynchronous loader at all. When there's no asynchronous loader,
there's no XHR and therefore no error.
So how do we overwrite our module configuration at runtime for our
test suite? When instantiating an angular module, we can always apply
a inline function which is executed as configuration function. This
configuration function can be used to overwrite the modules
configuration since we have access to all providers.
Using the $provide provider, we can build a custom loader factory,
which should then be used instead of the static files loader.
beforeEach(module('myApp', function ($provide, $translateProvider) {
$provide.factory('customLoader', function () {
// loader logic goes here
});
$translateProvider.useLoader('customLoader');
}));
Please read more in the above link provided.
We took the approach of ignoring the translation loader in unit tests, rather than being forced to modify each of the spec files.
One way to do it could be by separating the loader configuration to a separate file and then exclude it in karma.
So for example you can create a file app-i18n-loader.js (all other module configurations takes place in a different file):
angular
.module('myApp')
.config(loaderConfig);
loaderConfig.$inject = ['$translateProvider', '$translatePartialLoaderProvider'];
function loaderConfig($translateProvider, $translatePartialLoaderProvider) {
$translateProvider.useLoader('$translatePartialLoader', {
urlTemplate: 'assets/i18n/{part}/{lang}.json'
});
$translatePartialLoaderProvider.addPart('myApp');
}
And in your karma.conf.js exclude the file:
files: [
'bower_components/angular/angular.js',
'bower_components/angular-mocks/angular-mocks.js',
//...
'bower_components/angular-translate/angular-translate.js',
'bower_components/angular-translate-loader-partial/angular-translate-loader-partial.js',
'app/**/*.mdl.js',
'app/**/*.js'
],
exclude: [
'app/app-i18n-loader.js'
],
(Note: Answer edited to a solution that does not require grunt/gulp).
I wanted a solution,
which was not too hacky
which didn't require me to change my actual application code,
which wouldn't interfere with the ability to load additional modules
and most importantly which wouldn't require me to change every
single test.
This is what I ended up with:
// you need to load the 3rd party module first
beforeEach(module('pascalprecht.translate'));
// overwrite useStaticFilesLoader to get rid of request to translation file
beforeEach(module(function ($translateProvider) {
$translateProvider.useStaticFilesLoader = function () {
};
}));
Assuming you don't need the actual translations for your unit tests, this works great. Just put the beforeEach on a global level, preferably in it's own file inside the test folder. It will be executed before every other test then.
I encountered this problem with protractor tests. My solution was to mock translations like this:
angular.module('app')
.config(function ($translateProvider) {
$translateProvider.translations('en', {});
$translateProvider.preferredLanguage('en');
})
Now no language files are downloaded, no strings get translated and I just test against the string keys in specifications:
expect(element(by.css('#title')).getText()).toEqual('TITLE_TEXT');
Try putting to test method:
it('should ...', function() {
httpMock.when('GET', 'scripts/i18n/locale-en.json').respond({});
httpMock.expectGET('scripts/i18n/locale-en.json');
scope.resetForm(); // Action which fires a http request
httpMock.flush(); // Flush must be called after the http request
}
See examples from Angular docs
Please have a look at https://github.com/PascalPrecht/angular-translate/blob/master/test/unit/service/loader-static-files.spec.js as a reference.
In general, I would recommend using a standard translation loader for unit tests (without the hassle of http loadings) which means you can provide the labels with $translateProvider.translations(). Why? Because you do not have to test the remote loading functionality which is part of angular-translate project.
None of the solutions worked for me but I came with these solutions:
1) If you need to use scope.$apply(), or should deal with states in your test (after the $apply() the 2nd approach won't work), override your app's translations with the $translateProvider.translations() method, using a plugin to load JSON files
beforeEach(module(function ($translateProvider) {
$translateProvider.translations('en', readJSON('scripts/i18n/locale-en.json'));
}));
2) If your tested controller depends on the $translate service you can use a plugin to load JSON files and combine it with $httpBackend to load your locale file when angular-translate requests it.
beforeEach(inject(function (_$httpBackend_) {
$httpBackend = _$httpBackend_;
$httpBackend.whenGET('scripts/i18n/locale-en.json').respond(readJSON('scripts/i18n/locale-en.json'));
$httpBackend.flush();
})));
Note this should be below your beforeEach(module('myApp')); or you will get an $injector error.
I made a simple mock service for $translate
$translate=function (translation) {
return {
then: function (callback) {
var translated={};
translation.map(function (transl) {
translated[transl]=transl;
});
return callback(translated);
}
}
};
Usage example here : https://gist.github.com/dam1/5858bdcabb89effca457
I use this pattern.
ApplicationModule set regular angular-translate config.
test code load 'testModule' instead of 'applicationModule'
// application module .js
(function() {
'use strict';
angular
.module('applicationModule', [
'ngAnimate',
'ngResource',
'ui.router',
'pascalprecht.translate'
])
.config(['$stateProvider', '$urlRouterProvider', '$translateProvider', '$translatePartialLoaderProvider', config]);
function config($stateProvider, $urlRouterProvider, $translateProvider, $translatePartialLoaderProvider) {
// set routing ...
$translateProvider.useStaticFilesLoader({
prefix: 'i18n/locale-',
suffix: '.json'
});
$translateProvider.useMessageFormatInterpolation();
$translateProvider.fallbackLanguage(['en']);
$translateProvider
.registerAvailableLanguageKeys(['en', 'ko'], {
'en_US': 'en',
'ko_KR': 'ko'
})
.determinePreferredLanguage(navigator.browserLanguage);
$translateProvider.addInterpolation('$translateMessageFormatInterpolation');
$translateProvider.useSanitizeValueStrategy('escaped');
}
})();
// test.module.js
(function() {
'use strict';
angular
.module('testModule', ['applicationModule'])
.config(['$translateProvider', '$translatePartialLoaderProvider', config])
.run(['$httpBackend', run]);
function config($translateProvider, $translatePartialLoaderProvider) {
$translateProvider.useLoader('$translatePartialLoader', {
urlTemplate: 'i18n/locale-en.json'
});
$translatePartialLoaderProvider.addPart('applicationModule');
}
function run($httpBackend) {
$httpBackend.when('GET', 'i18n/locale-en.json').respond(200);
}
})();
// someDirective.spec.js
describe("a3Dashboard", function() {
beforeEach(module("testModule"))
var element, $scope;
beforeEach(inject(function($compile, $rootScope) {
$scope = $rootScope;
element = angular.element("<div>{{2 + 2}}</div>");
$compile(element)($rootScope)
}))
it('should equal 4', function() {
$scope.$digest();
expect(element.html()).toBe("4");
})
})
Late to the table with this, but I got round this by specifying that Karma simply serve the files as per this entry in karma.conf.js:
files: [
...
{pattern: 'scripts/i18n/*.json', included: false, served: true},
...
]
The 2016 answer for this is to preprocess your json into your tests and properly test translations work on your directives.
I use karma-ng-json2js-preprocessor. Follow all the steps to setup your karma.conf then in your test file, prepend the relevant file as a module, then set that information in $translateProvider.
beforeEach(module('myApp', '/l10n/english-translation.json'));
// Mock translations for this template
beforeEach(module(function($translateProvider, englishTranslation) {
$translateProvider.translations('en_us', englishTranslation);
$translateProvider.useSanitizeValueStrategy(null);
$translateProvider.preferredLanguage('en_us');
}));
Note according to the plugin, it uses your filename to generate a camelcased module name. You can play with the function inside the module's /lib but basically it remove all dashes but KEEPS underscores in a camelCase. So en_us becomes En_us.
You'll also need to tell your test that it is expecting that file as a GEt.
$httpBackend.expect('GET', '/l10n/english-translation.json').respond(200);
I'm playing around with this demo app https://github.com/kagemusha/ember-rails-devise-demo that uses Ember to create a JavaScript implemenation of Devise registration for Rails. The app uses CoffeeScript. I converted it to JavaScript using the compiler on the coffeescript.org website, but now I'm getting these unexpected token and string errors.I'm very inexperienced with Ember and don't know how to make heads or tails of this error messages.
For example, at the top of the settings file, the code does this memoization check (syntax same for both the coffeescript and JavaScript version)
App.urls ||= {}
Which triggers this error when I load the app.
Uncaught SyntaxError: Unexpected token = :3000/assets/settings.js?body=1:1
Same thing happens with the same type of code in the authentications_helper file
App.Authentication ||= {}
Which triggers this error
Uncaught SyntaxError: Unexpected token = authentication_helper.js:1
However, it also obviously affects the rest of the code in the authentication_helper file. When I try to register, I click a link in a template
{{view App.MenuItem href="#/registration" label="Register"}}
which calls the register function in the App.RegistrationRoute
App.RegistrationRoute = Ember.Route.extend({
model: function() {
Ember.Object.create();
},
actions: {
register: function() {
log.info("Registering...");
App.Authentication.register(this);
},
which tries to trigger this register function in the authentication_helper file (the file with the App.Authentication ||= {} at the top), but I'm getting an
Uncaught TypeError: Cannot call method 'register' of undefined
I'm guessing this App.Authentication isn't defined because of the error relating to the unexpecting = in the caching function.
Have I given you enough code to help me make some progress on these errors?
App.Authentication.register = function(route) {
$.ajax({
url: App.urls.register,
type: "POST",
data: {
"user[name]": route.currentModel.name,
"user[email]": route.currentModel.email,
"user[password]": route.currentModel.password,
"user[password_confirmation]": route.currentModel.password_confirmation
},
success: function(data) {
App.currentUser = data.user;
App.LoginStateManager.transitionTo("authenticated");
route.transitionTo('home');
},
error: function(jqXHR, textStatus, errorThrown) {
route.controllerFor('registration').set("errorMsg", "That email/password combo didn't work. Please try again");
}
});
};
App.urls ||= {} is not valid JS, so I suspect that your coffee script has not been translated to JS correctly. You're right that App.Authentication is not defined and is causing your other problems. The JS translation of App.urls ||= {} would be App.urls = App.urls || {}.
I am converting from Ember data 0.13 to 1.0.0 Beta 1. In 0.13, I was using the becameError and becameInvalid states to know whether there was a problem when saving a record.
In 1.0.0 there is no longer a transaction and you need to use the save promise to handle errors. See below:
save: function() {
this.get('model').save().then(function () {
alert("Record saved");
}, function () {
alert("Problem");
});
},
In the above, I want to make a distinction between validation errors and all the rest (just as it was before in 0.13 with becameError and becameInvalid).
Is there a way to access the error object and how to read the validation errors included in the json response ? Before this was via this.get('content.errors') ...
Hoep somebody can help
Marc
Three steps:
Return errors in a proper format. If it Rails application, then:
\# Rails controller, update function
format.json { render json: {errors: #post.errors.messages}, status: :unprocessable_entity }
Set errors in promise
// app.js
save: function() {
self = this;
this.get('model').save().then(function () {
alert("Record saved");
}, function (response) {
self.set('errors', response.responseJSON.errors);
});
}
Display errors in a handlebar template
<\!-- index.html -->
{{input type="text" value=title}}<span class="alert-error">{{errors.title}}</span>
Not sure if this helps you substitute the bacameInvalid and becameError since states are now being removed, but you could try this as a catchall workaround:
Ember.RSVP.configure('onerror', function(error) {
console.log(error.message);
console.log(error.stack);
});
Hope it helps.