Duplicated reponse with Axios in React component's lifecycle method - django

I'm making a web application and configured a Django backend server to which I make API calls with axios.get. The problem is, the middleware code is being executed twice and I don't understand why, I'm using the API call within a React component's lifecycle method:
componentDidMount() {
console.log('This line prints only once in the console');
axios.get("http://server:port").
.then((response) => {
console.log('This line prints twice in the console!');
})
.catch((err) => console.log(err););
}
I was expecting the second call (in the dummy code snippet) to be executed only once...
Am I doing something wrong? What is going on?

Related

Where do I use Pretender to enable Ember Qunit integration tests with rails-csrf?

We are using rails-csrf in our ember-cli app. The README on rails-csrf says:
Be sure to mock out the call to the csrf server endpoint. Otherwise your tests will fail with
"error while processing route: [route]"
messages in the browser console. For example:
server = new Pretender(function() {
this.get('/csrf', function(request) {
return [200, {"Content-Type": "application/json"},
JSON.stringify({
"authenticity_token": "token"
})
];
});
});
I understand the problem here (our integration tests are indeed showing this error) and I understand how Pretender solves it. I've got Pretender installed via ember-cli-pretender.
What I don't understand is how to make sure this code snippet - configuration for a Pretender mock - is working. I have it installed in the setup block of the integration test module, and it gets called, but the error is still present and the tests still aren't passing.
Here's the current non-working state:
module('Integration test', {
setup: function() {
App = startApp();
var server = new Pretender(function() {
this.get('/our/api/for/csrf', function(request) {
return [200, {"Content-Type": "application/json"},
JSON.stringify({
"authenticity_token": "token"
// I've also tried putting a real token from the server here instead of "token"
})
];
});
});
},
teardown: function() {
Ember.run(App, App.destroy);
}
});
The mock is getting called, but whatever it's returning is apparently not enough for rails-csrf. It looks like the beforeModel call in the application route is returning a promise; it's not clear if that's expected and being resolved.
(This question is superficially similar to this older one, but the available tools for handling this in Ember have changed significantly.)
I updated our app from ember-cli 0.1.12 and ember 1.8.1 to ember-cli 0.2.0 and ember 1.10.0. I also updated Pretender to 0.6.0 (the ember-cli-pretender package installed 0.1.0). This didn't solve anything by itself, but it did lead to a telling change in how the integration test failed. Now, Pretender was intercepting data requests and returning an error because I hadn't defined handlers for them.
Error: Pretender intercepted GET /our/api/data/:id but no handler was defined for this type of request
So the issue was no longer Ember but my configuration of Pretender. Once I mocked data requests to the API, we were off and running.
tl;dr make sure you have the latest version of Pretender.

Ember CLI: How to do Asynchronous Model Unit Testing with RESTAdapter

I want to test my models, and their integration with my REST API, using the Ember testing framework which ships with Ember CLI, but requests, using my RESTAdapter settings are not being made in my tests, within my model tests. As it stands, any call to save() on a model will cause all tests following it to not execute:
Here is a test I made to check interaction with the server (REST API):
test "store can be used to send data to server", ->
store = #store()
Ember.run ->
cpanel = store.createRecord "item"
cpanel.save().then((response) =>
equal(response.status, 200)
)
This completely blocks all tests following this one; furthermore, no requests are made to the server, when monitoring the Network tab in Chrome dev tools:
A friend advised me to use the QUnit Async Helper, but when using that, I find that this.store() is undefined (perhaps the Ember QUnit Adapter decided to leave out support for async testing helpers?):
asyncTest "Async creates account on server", ->
expect(2)
store = #store()
Ember.run =>
account = store.createRecord("account", {
siteName: "sample account"
url: "http://url.com"
})
account.save().then((response) =>
equal(response.status, 200)
ok account
start()
)
How can I write an async test for my individual models, and test their integration with my REST API using the Ember QUnit framework in Ember CLI without having to write integration tests?
I'm not sure where status is coming from, the promise of save returns the record, not the response from server.
In order to use start, you must use stop first.
stop();
someAsyncCall(function(){
start();
});
And the store is only injected into routes and controllers, and isn't in scope of your tests. You'll need to use the container to get the store.
store = App.__container__.lookup('store:main');
It'd look something like this:
test("save a record", function(){
var record,
store = App.__container__.lookup('store:main');
stop();
Em.run(function(){
record = store.createRecord('color', {color:'green'});
record.save().then(function(){
start();
equal(record.get('id'), 1);
});
});
});
Example: http://emberjs.jsbin.com/wipo/49/edit

How to handle invalid routes without slash in Ember.js

At the moment, I handle invalid routes in Ember.js like this:
this.route('invalid', { path: '*path' }
This works and applies to routes like:
https://www.appname.com/#/misspelled_name
However, when using Dropbox Datastores API, I am having some problems. After an authentication request, Dropbox redirects me to:
https://www.appname.com/#access_token=...
Is there a way to handle this route? Without the slash before the route name? In this case, the 'invalid' route is not applied and I receive an error 'The route access_token=... was not found'. How should I handle this response in Ember?
UPDATE
I don't think it is possible to handle this. The only working solution for me was to do authentication before Ember was even loaded. After successful authentication, I load my ember app:
window.dropboxClient = new Dropbox.Client({
key: 'some_key'
});
dropboxClient.authenticate({ interactive: true }, function(error) {
if (error) {
return console.log('Error during authentication');
}
});
yepnope([{
test : window.dropboxClient.isAuthenticated(),
yep : ['my-ember-app.js']
}])
I don't have direct experience with EmberJS, but one possibility might be to run client.authenticate({ interactive: false }); before the EmberJS script is even loaded.
Another alternative is to specify a different redirect URI (not the same page as the rest of your app) and not load EmberJS on that page. (That page would then presumably redirect back to the main app when it was done.) You could also forgo redirects altogether and use the pop-up auth driver instead.
Before the #/, you aren't actually inside of the ember app. As a result, none of the ember code will have any impact on this.

How can I mock an http call executed in module.run Angular app?

I am trying to run the following code (where fusseApp is an angularModule) :
fusseApp.run(function(URI, $http){
$http.get('/check/userLogged').then(function(response){
console.log(response);
});
PS : Actually my http call is executed in a factory and here we just have a call to this factory
The angularModule is mocked with :
angular.module('fusseApp.mainMocks', ['fusseApp', 'fusseApp.loginMocks', 'ngMockE2E', 'ngResource'])
.run(function($httpBackend, $http) {
...
$httpBackend.whenGET('/check/userLogged').respond(200,response);
My problem is that fusseApp.run is executed before the mock module is initialized. So I a have an error :
Uncaught Error: Unexpected request: GET /check/userLogged
No more request expected
This problem seems to have been raised in the jasmine unit-test, but I cannot find a solution. Is it possible to run my $http call after an event that tells me when the application is completely initialized?
My need is to check that the user is authenticated before displaying any data on screen.
maybe this can help...
.run() is always executed if you set ng-app="" in you code, its part of the boostrap process, from there on you can't stop the compile & linking process, but there's many ways to go to prevent a view from being rendered if the user is not logged in:
A) Manual angular boostraping (not so fun but feasible) can be done after authentication is ok, either use jQuery $.ajax or another lib because $http service is out the picture outside NG.
B) But in your .run() you have access to $rootScope and all of the NG services, therefore you can listen for $stateChangeStart and inside the listener perform you auth validation.
This is more or less the best practice for NG authentication, this listener keeps checking every time the user changes state, (which is good so that you can catch sessions expirations), In my code (which I use in prod in various projects) I do exactly this:
$rootScope.$on("$stateChangeStart", function(event, toState, toParams, fromState, fromParams) {
if (!AuthService.isAuthenticated()) {
$state.transitionTo("login"); // redirect to login page
event.preventDefault();
}
});
AuthService is just a simple service that returns true or false if the user is authenticated.
In my experience the best solution to hide views to unauthorized users and redirect, is to catch state change process like I show before.
Because you can decorate states these properties are accessible in the toState argument (in ui-router at least) So it's possible to do all kinds of fancy stuff like catching user roles and so on...

How do you handle a asyc request made in `Ember.Application.initializer` when writing QUnit integration test?

I am trying to setup ember.js with QUnit to write integration tests.
Following the directions on http://emberjs.com/guides/testing/integration/ I have:
document.write('<div id="ember-testing-container"><div id="ember-testing"></div></div>');
App.rootElement = '#ember-testing';
App.setupForTesting();
App.injectTestHelpers();
module("Integration Tests", {
setup: function() {
App.reset();
}
});
test("root lists first page of posts", function(){
visit("/").then(function() {
equal(find(".post").length, 5, "The first page should have 5 posts");
// Assuming we know that 5 posts display per page and that there are more than 5 posts
});
});
However when I run QUnit I get the following error:
Assertion failed: You have turned on testing mode, which disabled the
run-loop's autorun. You will need to wrap any code with asynchronous
side-effects in an Ember.run
This assertion error is triggered because I am making a http request in the app initializer to check if there is a current user session. This returns a 401 error if there is no valid user. (If I force the app to always return 200 for this request, this assertion error does not occur and the tests continue as expected).
I believe the app and API is behaving correctly by returning a http error for an invalid user, and I don't want to change to response to a 200 just to get my tests working. What do I need to do to get ember and QUnit to handle a http error and assertion? From what I've read I need to wrap something with Ember.run, but I can't figure out what.
Your unit and integration tests should ideally run in isolation from external resources (like an HTTP API), so mocking HTTP requests is the easiest pattern.
To get truly full-stack smoke testing, you'll want to exercise the app with browser automation tools like PhantomJS.