I was trying acceptance test for login page, using cli mirage as mock server. Routes defined in a mirage works fine, when accessing it from application. But when trying it in ember test it returns
Mirage: Your Ember app tried to POST 'http://localhost:4200/tests?module=Acceptance | login', but there was no route defined to handle this request. Define a route that matches this path in your mirage/config.js file. Did you forget to add your namespace?
Acceptance Test
test('visiting /login', function(assert) {
server.create('login', { username: 'xxx#test.com', password: 'password' });
visit('/login');
fillIn('input[placeholder="Email"]', 'xxx#test.com');
fillIn('input[placeholder="Password"]', 'password');
click('button.btn-primary');
andThen(function() {
assert.equal(currentURL(), '/route');
});
});
Mirage/config
import Mirage from 'ember-cli-mirage';
export default function() {
this.post('/token', function(db, request) {
var params = formEncodedToJson(request.requestBody);
if(params.username === "xxx#test.com && params.password === "password") {
return {
"auth":"Pass$Word",
"token_type":"bearer"
};
} else{
var body = { errors: 'Email or password is invalid' };
return new Mirage.Response(401, {}, body);
}
});
How to rectify this issue? someone help me please.
Issue is in environment configuration. After defined configurations for test worked fine.
for me, I have explicitly add host etc because without it, it resolves to a different port from my mirage config.js
Related
I'm trying to write an acceptance test to see if a certain property in the model for the route I visit equals what I am asserting.
I am not outputting information to the page with this route, instead I will be saving some portion of it to localstorage using an ember addon. So normally I realize I could use a find() to find an element on the page and check it's content to determine if the model is being resolved but that won't work for this case.
In the acceptance test I have this setup (using mirage btw)
test('Returns a user', function(assert) {
// Generate a user
var user = server.create('user',{first_name: 'Jordan'});
// Visit the index page with the users short_url
visit('/' + user.short_url);
var route = this.application.__container__.lookup('route:index');
// Assert that the model the user we created by checking the first name we passed in
assert.equal(route.model.first_name,'Jordan','Model returns user with first name Jordan');
});
But when I run the test it shows the result as being undefined
UPDATE:
After trying Daniel Kmak's answer I still cannot get it to pass. This is the route code I am working with
import Ember from 'ember';
import LocalUser from 'bidr/models/user-local';
export default Ember.Route.extend({
localUser: LocalUser.create(),
navigationService: Ember.inject.service('navigation'),
activate() {
this.get('navigationService').set('navigationMenuItems', []);
},
beforeModel() {
this.localUser.clear();
},
model(params) {
var self = this;
return this.store.queryRecord('user',{short_url: params.short_url}).then(function(result){
if(result){
self.set('localUser.user', {
"id": result.get('id'),
"first_name": result.get('first_name'),
"active_auction": result.get('active_auction'),
"phone": result.get('phone')
});
// transition to event page
self.transitionTo('items');
} else {
self.transitionTo('home');
}
});
}
});
And the test looks like this
import Ember from 'ember';
import { module, test } from 'qunit';
import startApp from 'bidr/tests/helpers/start-app';
module('Acceptance | index route', {
beforeEach: function() {
this.application = startApp();
},
afterEach: function() {
Ember.run(this.application, 'destroy');
}
});
test('Returns a user', function(assert) {
var user = server.create('user',{first_name: 'Jordan'});
visit('/' + user.short_url);
var route = this.application.__container__.lookup('route:index');
andThen(function() {
assert.equal(route.get('currentModel.first_name'),'Jordan','Model returns user with first name Jordan');
});
});
All the code works as it should in development.
Ok, so I've experimented with testing in Ember and it seems you should be good with getting model in andThen hook:
test('returns a user', function(assert) {
visit('/'); // visit your route
var route = this.application.__container__.lookup('route:index'); // find your route where you have model function defined
andThen(function() {
console.log(route.get('currentModel')); // your model value is correct here
assert.equal(currentURL(), '/'); // make sure you've transitioned to correct route
});
});
Taking your code it should run just fine:
test('Returns a user', function(assert) {
var user = server.create('user',{first_name: 'Jordan'});
visit('/' + user.short_url);
var route = this.application.__container__.lookup('route:index');
andThen(function() {
assert.equal(route.get('currentModel.first_name'),'Jordan','Model returns user with first name Jordan');
});
});
Another thing to note is that you can access model via route.currentModel property.
For my model:
export default Ember.Route.extend({
model() {
return Ember.RSVP.hash({
simple: 'simpleValue',
promise: Ember.RSVP.resolve(5)
});
}
});
In andThen with console.log(route.get('currentModel')); I got:
Object {simple: "simpleValue", promise: 5}
Logged.
Setup:
Ember : 2.0.2
Ember Data : 2.0.1
jQuery : 1.11.3
Ember Simple Auth : 1.0.0 (jjAbrams Branch)
Ember CLI : 1.13.8
I'm using pretender to mock a server.
Usecase:
Using a custom authenticator to interface with the server.
Have 2 routes: login, protected (and by default index,application)
When I login with the right credentials, the authenticate method of the authenticator gets called and successfully logs the response object which is passed to resolve().
Observations:
After logging in and being directed to the protected page, Refreshing the protected route (Which has AuthenticatedRouteMixin) leads back to login page.
Localstorage has no values bound to it even after successful login.
Before login: ember_simple_auth:session -> {"authenticated":{}}
restore() method of authenticator never called.
Going to another route from the protected route after auth and coming back goest to login page again.
//authenticators/custom.js
import Ember from 'ember';
import Base from 'ember-simple-auth/authenticators/base';
export default Base.extend({
restore: function (data) {
return new Ember.RSVP.Promise(function (resolve, reject) {
console.log("RESOLVE",data);
if (!Ember.isEmpty(data.token)) {
//TODO Remove log
resolve(data);
} else {
console.log("REJECTING",data);
reject();
}
});
},
authenticate(credentials) {
return new Ember.RSVP.Promise((resolve, reject) =>
Ember.$.ajax({
url: '/token',
type: 'POST',
data: JSON.stringify({
email: credentials.identification,
password: credentials.password
}),
contentType: 'application/json;charset=utf-8',
dataType: 'json'
}).then(function (response) {
Ember.run(function () {
//This logs the expected information
console.log("Response", response, response.token, response.user);
resolve(response);
});
}, function (xhr, status, error) {
console.log("error", error, xhr.responseText);
var response = xhr.responseText;
Ember.run(function () {
reject(response);
});
}));
},
invalidate(token) {
return API.logout(token);
}
});
//environment.js
ENV['ember-simple-auth'] = {
store: 'session-store:local-storage',
routeAfterAuthentication: '/protected'
};
TLDR;
How do I make the session persist?
I got it all working together finally. Ember 2.0 and ESA 1.0
Here are the steps I took:
Create a new ember cli project
Update Ember and ember data values to ^2.0.0 in bower.json Source
Add ESA jjAbrams dep to package.json Source
run npm install && bower install
Gotchas: (This was the original problem which caused the problems described in the question)
If you're upgrading from older versions of ESA, all references to 'simple-auth/..' should be updated to refer 'ember-simple-auth/..' instead..
.. This include imports for authenticators, authorizers, stores, mixins and the Config key in the config/environment.js file.
All this shouldn't be an issue once ESA 1.0 and Ember Cli for Ember 2.0 comes out :)
I'm trying to test my registration and login processes, the integration tests were passing perfectly prior to creating an initializer to extend the Ember-Simple-Auth Session object with the currentUser property.
It all works correctly in the browser, its just the tests now fail all in the sessionAuthenticationSucceeded action in the application route on the following line:
this.get('session.currentUser').then(function(user) {
with : TypeError: Cannot read property 'then' of undefined
/routes/application.js
import Ember from 'ember';
import ApplicationRouteMixin from 'simple-auth/mixins/application-route-mixin';
export default Ember.Route.extend(ApplicationRouteMixin, {
actions: {
sessionAuthenticationSucceeded: function () {
var self = this;
this.get('session.currentUser').then(function(user) {
if (user.get('account') && user.get('status') === 'complete'){
self.transtionTo('home');
} else {
console.log('Need to complete Registration');
self.transitionTo('me');
}
});
}
}
}
/initializers/custom-session.js
import Ember from 'ember';
import Session from 'simple-auth/session';
export default {
name: 'custom-session',
before: 'simple-auth',
initialize: function(container) {
// application.deferReadiness();
Session.reopen({
currentUser: function() {
var id = this.get('user_id');
if (!Ember.isEmpty(id)) {
console.log('getting the current user');
return container.lookup('store:main').find('user', id);
}
}.property('user_id')
});
// application.advanceReadiness();
}
};
/tests/integration/visitor-signs-up-test.js
test('As a user with valid email and password', function(){
var email = faker.internet.email();
signUpUser(email, 'correctpassword', 'correctpassword');
andThen(function(){
equal(find('#logged-in-user').text(), email, 'User registered successfully as ' + email);
equal(sessionIsAuthenticated(App), true, 'The session is Authenticated');
});
});
test/helpers/registration-login.js
export function signUpUser(email, password, passwordConfirmation) {
visit('/register').then(function(){
fillIn('input.email', email);
fillIn('input.password', password);
fillIn('input.password-confirmation', passwordConfirmation);
click('button.submit');
});
}
I have tried using
application.deferReadiness()
as you can see commented out in the initializer (also pass in application in that instance) to ensure the async request has completed and user is available but that hasn't worked either.
I am using Pretender to intercept the api requests, but the call to api/v1/users/:id isn't being made at all during the tests.
The strange part is it works perfectly in the browser.
I'm trying to understand why this won't this work? Any guidance would be appreciated!
NB: I have also tried solution listed here and here with same outcome as above.
I have figured out the problem, turns out I wasn't returning a user_id from the api/v1/users/sign_in request Pretender was intercepting hence when sessionAuthenticationSucceeded fired, there was no user_id available and thus currentUser was never being updated/triggered.
I'll leave all the code up there in case it helps somebody else. Comments or improvements to it are still very welcome!
I'm simply trying to write some tests to make sure logging in and out works, including everything that goes with it. Here's what I'm doing so far:
tests/integration/sessions-test.js
import Ember from "ember";
import { test } from 'ember-qunit';
import startApp from '../helpers/start-app';
var App;
module('Integrations: Sessions', {
setup: function() {
App = startApp();
},
teardown: function() {
Ember.run(App, App.destroy);
}
});
test('Unsuccessful Sign In', function() {
expect(3);
visit('/sign-in');
andThen(function() {
fillIn('input#email', 'test#user.com');
fillIn('input#password', 'bad_password');
click('input#submit');
andThen(function() {
equal(currentRouteName(), 'sign-in', 'Unsuccessfull sign in stays on the sign in page.');
ok($('input#email, input#password').hasClass('error'), 'Inputs have a class of "error."');
equal($('input#submit').prop('disabled'), false, 'Submit button is not disabled.');
});
});
});
test('Successful Sign In', function() {
expect(2);
visit('/sign-in');
andThen(function() {
fillIn('input#email', 'test#user.com');
fillIn('input#password', 'password');
click('input#submit');
andThen(function() {
equal(currentRouteName(), 'welcome', 'Successfull sign in redirects to welcome route.');
ok(find('.message').length, "Page contains a list of messages.");
});
});
});
And, here's a trimmed down version of the sign in logic behind the scenes:
app/controllers/sign-in.js
import Ember from 'ember';
export default Ember.Controller.extend({
needs: ['application'],
actions: {
signIn: function() {
var self = this;
var data = this.getProperties('email', 'password');
// Attempt to sign in and handle the response.
var promise = Ember.$.post('/v3/sessions', data);
promise.done(function(response) {
Ember.run(function() {
self.get('controllers.application').set('token', response.access_token);
self.transitionToRoute('welcome');
});
});
...
}
}
});
The "Unsuccessful Sign In" test works just fine. The "Successful Sign In" starts to work, then quits halfway through. It signs in, then redirects correctly. On the welcome page, when it makes a call to get the messages, the node server is responding with Error: Not enough or too many segments and a 500 status. What in the world does that mean and how can I fix it, assuming I don't have any control over the API?
Also, the API is written primarily using Koa and Passport, as far as I know.
Figured it out. Apparently, it was an authentication error, not that you'd ever be able to guess that by the error message.
In the sign in controller, there's a line where I was setting the token property of the application controller. The application controller had an observer to watch that property for changes, then setup the AJAX headers when it changed. Problem is, observes use Ember's run loop, which is disabled while testing.
To fix the issue, I set the AJAX headers there in the sign in controller, just before transitioning to the welcome route.
I am following a Dockyard Tutorial on using ember-cli with rails. This particular section is on basic integration testing. Unfortunately, it doesn't seem to be registering properly (at least I don't think so). The test should fail and say something along the lines of "Expected: 'Welcome to Boston Ember'"; rather, it says "should pass jshint" which it is and is therefore passing. Any idea what I am doing wrong?
tests/integration/landing-page-test.js
import Ember from 'ember';
import startApp from 'bostonember/tests/helpers/start-app';
var App;
module('Integration - Landing Page', {
setup: function() {
App = startApp();
},
teardown: function() {
Ember.run(App, 'destroy');
}
});
test('Should welcome me to Boston Ember', function() {
visit('/').then(function() {
equal(find('h2#title').text(), 'Welcome bloopde bloopasa to Boston Ember');
});
});
tests/helpers/start-app.js
/* global require */
var Application = require('bostonember/app')['default'];
var Router = require('bostonember/router')['default'];
import Ember from 'ember';
export default function startApp(attrs) {
var App;
var attributes = Ember.merge({
// useful Test defaults
rootElement: '#ember-testing',
LOG_ACTIVE_GENERATION:false,
LOG_VIEW_LOOKUPS: false
}, attrs); // but you can override;
Router.reopen({
location: 'none'
});
Ember.run(function(){
App = Application.create(attributes);
App.setupForTesting();
App.injectTestHelpers();
});
App.reset(); // this shouldn't be needed, i want to be able to "start an app at a specific URL"
return App;
}
Will provide additional info upon request. Thank you!
Must have just been a hiccup?
Solution was to recreate the file, same code, but works now.