I would like to inject a custom http service in my embedded task form application.
Herewith is the code snippet:
<script cam-script type="text/form-script">
inject([ '$scope', '$http', function($scope, $http) {
camForm.on('form-loaded', function() {
// Custom service call
$http.get('http://localhost:8888/books/1').then(function(response){
alert(JSON.stringify(response.data));
});
});
}]);
When the form loads the http://localhost:8888/books/1 isn't invoked and I don't know why.
For anybody else running into the same issue here is the code snippet that made debugging a bit easier:
<script cam-script type="text/form-script">
debugger;
inject([ '$scope', '$http', function($scope, $http) {
camForm.on('form-loaded', function() {
$http({
method: 'GET',
url: 'http://localhost:8888/books/1'
}).then(
function successCallback(response)
{
alert('SUCCESS :-) ' + angular.toJson(response.data));
$scope.data = response.data
},
function errorCallback(response) {
alert('FAILED :-( ' + response.status);
});
});
}]);
</script>
As for the solution, I had to enable CORS on the server that was receiving the request. See https://spring.io/guides/gs/rest-service-cors/
Related
Problem
I have a /login route that uses ember-simple-auth to implement authentication. During testing ember-cli-mirage is used to mock the backend. The user logs in by providing their email address and password.
In total I have 4 acceptance tests for this route, similar to the test below:
test('should show error message for invalid email', function(assert) {
visit('/login');
fillIn('input#email', 'invalid-email');
fillIn('input#password', 'invalid-password');
click('button.button');
andThen(function() {
assert.equal(find('div.notification').text(), "Invalid email/password");
});
});
When I run the tests using ember t only the first test in the file fails. If I comment this test out, the next one fails, and so on. If I run the tests in server mode with ember t -s the same test fails; however, when I press enter to re-run the tests, all the tests pass.
The failure message is always the same, shown below:
not ok 7 PhantomJS 2.1 - Acceptance | login: should show error message for invalid email
---
actual: >
expected: >
Invalid email/password
stack: >
http://localhost:7357/assets/tests.js:22:19
andThen#http://localhost:7357/assets/vendor.js:48231:41
http://localhost:7357/assets/vendor.js:48174:24
isolate#http://localhost:7357/assets/vendor.js:49302:30
http://localhost:7357/assets/vendor.js:49258:23
tryCatch#http://localhost:7357/assets/vendor.js:68726:20
invokeCallback#http://localhost:7357/assets/vendor.js:68738:21
publish#http://localhost:7357/assets/vendor.js:68709:21
http://localhost:7357/assets/vendor.js:48192:24
invoke#http://localhost:7357/assets/vendor.js:10892:18
flush#http://localhost:7357/assets/vendor.js:10960:15
flush#http://localhost:7357/assets/vendor.js:11084:20
end#http://localhost:7357/assets/vendor.js:11154:28
run#http://localhost:7357/assets/vendor.js:11277:19
run#http://localhost:7357/assets/vendor.js:32073:32
http://localhost:7357/assets/vendor.js:48783:24
Log: |
After all the tests have run, test emits an exception:
# tests 60
# pass 59
# skip 0
# fail 1
Not all tests passed.
Error: Not all tests passed.
at EventEmitter.getExitCode (/home/jon/projects/jonblack/wishlist-web/node_modules/testem/lib/app.js:434:15)
at EventEmitter.exit (/home/jon/projects/jonblack/wishlist-web/node_modules/testem/lib/app.js:189:23)
at /home/jon/projects/jonblack/wishlist-web/node_modules/testem/lib/app.js:103:14
at tryCatcher (/home/jon/projects/jonblack/wishlist-web/node_modules/testem/node_modules/bluebird/js/release/util.js:16:23)
at Promise._settlePromiseFromHandler (/home/jon/projects/jonblack/wishlist-web/node_modules/testem/node_modules/bluebird/js/release/promise.js:510:31)
at Promise._settlePromise (/home/jon/projects/jonblack/wishlist-web/node_modules/testem/node_modules/bluebird/js/release/promise.js:567:18)
at Promise._settlePromise0 (/home/jon/projects/jonblack/wishlist-web/node_modules/testem/node_modules/bluebird/js/release/promise.js:612:10)
at Promise._settlePromises (/home/jon/projects/jonblack/wishlist-web/node_modules/testem/node_modules/bluebird/js/release/promise.js:691:18)
at Async._drainQueue (/home/jon/projects/jonblack/wishlist-web/node_modules/testem/node_modules/bluebird/js/release/async.js:138:16)
at Async._drainQueues (/home/jon/projects/jonblack/wishlist-web/node_modules/testem/node_modules/bluebird/js/release/async.js:148:10)
at Immediate.Async.drainQueues (/home/jon/projects/jonblack/wishlist-web/node_modules/testem/node_modules/bluebird/js/release/async.js:17:14)
at runCallback (timers.js:637:20)
at tryOnImmediate (timers.js:610:5)
at processImmediate [as _immediateCallback] (timers.js:582:5)
It seems odd that this is emitted for tests failing rather than just reporting the test failure, so perhaps it's related.
Running the tests in Firefox and Chromium work, as does running the application in development mode and logging in manually. The problem is limited to phantomjs.
I have other acceptance tests for another route and these all pass. It seems limited to the /login route, suggesting that it is possibly related to authentication.
Debugging
I've tried debugging by adding pauseTest() to the test and "phantomjs_debug_port": 9000 to testem.js but both Firefox and Chromium do nothing when I use the debug console. This might be my lack of experience debugging phantomjs, but I would at least expect it to give me an error - it literally does nothing.
It feels as though there is a timing issue between phantomjs and something, possible ember-simple-auth, in my Ember app.
I'm not that experienced debugging phantomjs problems nor Ember acceptance test failures, so any help is appreciated.
Versions
ember-cli 2.10.0
ember-simple-auth 1.1.0
ember-cli-mirage 0.2.4
Update 1
The button is inside a login-form component:
<form {{action 'login' on='submit'}}>
<p class="control has-icon">
{{input value=email id='email' placeholder='email' class='input'}}
<i class="fa fa-envelope"></i>
</p>
<p class="control has-icon">
{{input value=password id='password' placeholder='password'
type='password' class='input'}}
<i class="fa fa-lock"></i>
</p>
<p class="control">
<button class="button is-success" disabled={{isDisabled}}>Log In</button>
</p>
</form>
The component's login action just calls the passed in login handler:
import Ember from 'ember';
export default Ember.Component.extend({
email: "",
password: "",
isDisabled: Ember.computed('email', 'password', function() {
return this.get('email') === "" || this.get('password') === "";
}),
actions: {
login() {
var email = this.get('email');
var password = this.get('password');
this.attrs.login(email, password);
}
}
});
Which is the authenticate method in the login controller:
import Ember from 'ember';
export default Ember.Controller.extend({
session: Ember.inject.service(),
actions: {
authenticate(email, password) {
this.get('session').authenticate('authenticator:oauth2', email, password).catch((data) => {
this.set('errors', data['errors']);
});
}
}
});
Update 2
As suggested by Daniel I added a delay to the test:
test('should show error message for invalid email', function(assert) {
visit('/login');
fillIn('input#email', 'invalid-email');
fillIn('input#password', 'invalid-password');
click('button.button');
andThen(function() {
Ember.run.later(this, function() {
assert.equal(find('div.notification').text(), "Invalid email/password");
}, 0);
});
});
Using only Ember.run.later the test still failed, but putting that inside the andThen causes it to pass. Have you noticed the bizarre part? The delay is 0 milliseconds.
I still want to find an explanation for this because I don't trust that this will run the same on whatever machine the tests run on.
Update 3
Today I had a surprise: suddenly the tests were working again!
I added a new route with acceptance tests. The route itself is an authenticated route, so the tests use the authenticateSession test helper from ember-simple-auth to authenticate.
when I remove the tests that use this helper, the error returns!.
I'm not sure what this means. It feels like the issue is with ember-simple-auth, but it might also be a giant coincidence that the helper resolves another timing issue.
Down the rabbit hole we go...
Update 4
Below is the configuration for the auth endpoints in ember-cli-mirage:
this.post('/token', function({db}, request) {
var data = parsePostData(request.requestBody);
if (data.grant_type === 'password') {
// Lookup user in the mirage db
var users = db.users.where({ email: data.username });
if (users.length !== 1) {
return new Mirage.Response(400, {'Content-Type': 'application/json'}, {
errors: [{
id: 'invalid_login',
status: '400',
title: 'Invalid email/password',
}]
});
}
var user = users[0];
// Check password
if (data.password === user.password) {
if (!user.active) {
return new Mirage.Response(400, {'Content-Type': 'application/json'}, {
errors: [{
id: 'inactive_user',
status: '400',
title: 'Inactive user',
}]
});
} else {
return new Mirage.Response(200, {
'Content-Type': 'application/json'
}, {
access_token: 'secret token!',
user_id: user.id
});
}
} else {
return new Mirage.Response(400, {'Content-Type': 'application/json'}, {
errors: [{
id: 'invalid_login',
status: '400',
title: 'Invalid email/password',
}]
});
}
} else {
return new Mirage.Response(400, {'Content-Type': 'application/json'}, {
errors: [{
id: 'invalid_grant_type',
status: '400',
title: 'Invalid grant type',
}]
});
}
});
this.post('/revoke', function(db, request) {
var data = parsePostData(request.requestBody);
if (data.token_type_hint === 'access_token' ||
data.token_type_hint === 'refresh_token') {
return new Mirage.Response(200, {'Content-Type': 'application/json'});
} else {
return new Mirage.Response(400, {'Content-Type': 'application/json'},
{error: 'unsupported_token_type'});
}
});
Update 5
Here's my config/environment.js file:
/* jshint node: true */
module.exports = function(environment) {
var ENV = {
modulePrefix: 'wishlist-web',
environment: environment,
rootURL: '/',
locationType: 'auto',
EmberENV: {
FEATURES: {
},
EXTEND_PROTOTYPES: {
// Prevent Ember Data from overriding Date.parse.
Date: false
}
},
APP: {
}
};
if (environment === 'development') {
}
if (environment === 'test') {
// Testem prefers this...
ENV.locationType = 'none';
// keep test console output quieter
ENV.APP.LOG_ACTIVE_GENERATION = false;
ENV.APP.LOG_VIEW_LOOKUPS = false;
ENV.APP.rootElement = '#ember-testing';
}
if (environment === 'production') {
ENV.ServerTokenEndpoint = 'http://localhost:9292/token';
ENV.ServerTokenRevocationEndpoint = 'http://localhost:9292/revoke';
ENV.ApiHost = 'http://localhost:9292';
}
return ENV;
};
You have few things to try here to debug this issue.
You could remove {{isDisabled}} from button to make sure it's not disabled when you try to click it.
Use setTimeout instead of andThen and see if it's timing issue.
Replace authenticate action code with nothing, to make sure it isn't causing your test to fail.
You could also rewrite test to put your assert.ok after some event in JavaScript. For example you could mock authenticate action or observer errors property. You can do this by using lookups or registers in acceptance environment - tests from one of my Ember CLI addons could help you - ember-link-action/tests/acceptance/link-action-test.js.
Edit
Having seen what worked for you experience tells me that you should try 2 things.
For this code:
andThen(function() {
Ember.run.later(this, function() {
assert.equal(find('div.notification').text(), "Invalid email/password");
}, 0);
});
You could try Ember.run.scheduleOnce('afterRender', this, () => { ... assert here } instead of using Ember.run.later. Or you could try using just Ember.run instead of Ember.run.later.
Conclusion: The key to fixing this issue could be putting your assertion in Ember Run Loop.
I would assume that the error you're seeing (Invalid email/password) is the (mock) server response and indicates something is wrong with either the mock or the credentials you're using in the test.
I'd also not use mirage for mocking the authentication request. mirage (just like Jason API) is resource based and not something that's well suited for authentication.
First, a facebook user is logged client-side with using Facebook JS SDK.
FB.init() is called with the following parameters:
{
version : 'v2.0',
appId: '...',
status : true,
cookie : true,
xfbml : false
}
Then, in PHP, a session is created:
$session = (new FacebookJavaScriptLoginHelper())->getSession();
Once FB API calls have been made from PHP, I still can continue calling FB API from withing js.
But as soon as my page sends a new command to the server instructing it to make an FB API call, it doesn't work the second time, and the FB API says:
An access token is required to request this resource.
Obviously, this is called one more time and after that it stops working:
$session = (new FacebookJavaScriptLoginHelper())->getSession();
If the user updates the page in his browser, the next call from the server will work again. What I want instead is to keep querying FB API from both the server and the browser simultaneously without reloading the page.
It is out of date, but maybe will help someone
<?php
//some code here - requires and uses
FacebookSession::setDefaultApplication($SETTINGS['fbappid'], $SETTINGS['fbsecret']);
$helper = new FacebookJavaScriptLoginHelper();
$session;
try {
$session = $helper->getSession();
} catch(FacebookRequestException $ex) {
//
} catch(\Exception $ex) {
//
}
?>
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<script>
window.fbAsyncInit = function() {
FB.init({
appId : '<?php echo $SETTINGS['fbappid'] ?>',
xfbml : true,
version : 'v2.0',
status : true,
cookie : true
});
FB.getLoginStatus(function(response) {
if (response.status === 'connected') {
var uid = response.authResponse.userID;
var accessToken = response.authResponse.accessToken;
FB.login(function () {
FB.api('/me', {
fields: 'id'
}, function (response) {
console.log(response);
});
}, {
scope: 'publish_actions'
});
} else if (response.status === 'not_authorized') {
} else {
}
});
};
(function(d, s, id){
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {return;}
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/en_US/sdk.js";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
</script>
<div id="fb-root"></div>
<?php
//here url to go to my app
echo "<a href='...'>Sign in to Facebook application</a>";
if ($session) {
echo "<br/>logged in";
}
?>
</body>
</html>
Note that login comes after second access to page if cookies were not set. So ajax request is needed to check properly.
I m using twitter anywhere api for allowing user to sign in with twitter and get their twitter data to store it my table.Since twitter anywhere api is going to expire soon how can i migrate this functionality to oauth.
my javascript:
<script src="https://platform.twitter.com/anywhere.js?id={{twitterappid}}&v=1"></script>
<script type="text/javascript">
var twt_connected = 0;
var Uuid = '2334443224';
$(function(){
if ($('#twtlogin').length) {
// do something
twttr.anywhere(function(twitter) {
if(twitter.isConnected()){
//alert('Welcome, you are connected');
currentUser = twitter.currentUser;
screenName = currentUser.data('screen_name');
jQuery.ajax({url:"/twitter/Uuid="+Uuid+"/" ,
type: "POST",
data: {user: JSON.stringify(currentUser) },
dataType: "json",
success: function(result) {
}});
document.getElementById("twtlogin").innerHTML = '<img src="/images/icon_tconnected.gif" width="153" height="37" alt="Connected" />';
}
});
}
});
$("#login").click(function(e){
e.preventDefault();
if (twt_connected == 0){
$.post("/twt-click-time/Uuid="+Uuid+"/","clicked",function(data){})
twttr.anywhere(function (T) {
T.bind("authComplete", function (e, user) {
document.getElementById("twtlogin").innerHTML = '<img src="/images/icon_tconnected.gif" width="153" height="37" alt="Connected" />';
twt_connected = 1;
currentUser = T.currentUser;
screenName = currentUser.data('screen_name');
jQuery.ajax({url:"/twitter/Uuid="+Uuid+"/" ,
type: "POST",
data: {user: JSON.stringify(currentUser) },
dataType: "json",
success: function(result) {
}});
});
T.signIn();
});
}
});
</script>
I m using django at my backend.
I'm doing this right now for flask. The easiest option is just to plug-in some server side oauth calls.
It's a reasonably large amount of code so I won't copy and paste the whole thing here, but the github page for simplegeo's oauth2 actually has a "logging into django with twitter" walkthrough that should help out.
After having gone through a few options, I think I like twython best. It's just this to do the first step of the oauth:
from twython import Twython
t = Twython(app_key='key',
app_secret='secret',
callback_url='http://google.com/')
auth_props = t.get_authentication_tokens()
print auth_props
SO I am trying to have my web site publish info to a user's facebook page. Where I am now is that I placed the following code (as instructed by another stackoverflow contributor), which is getting executed however the alert with "error occurred" comes up. Do I need to request the publish_stream permission as well? If so, I cannot figure out how to add that to my code. Sorry, I'm not much of a scripter and I have very limited knowledge on doing any integration into facebook. My ultimate goal is to be able to post information to a users facebook page on their behalf (this won't be done without their permission). Any help would be much appreciated:
<div id="fb-root"></div>
<script>
window.fbAsyncInit = function() {
FB.init({
appId : 'XXXXXXXXXXXXXXXXXXXX', // App ID
channelUrl : '//www.XXXXXXXXXXXXXX.com/channel.html', // Channel File
status : true, // check login status
cookie : true, // enable cookies to allow the server to access the session
xfbml : true, // parse XFBML
oauth : true
});
});
// Additional initialization code here
};
// Load the SDK Asynchronously
(function(d){
var js, id = 'facebook-jssdk', ref = d.getElementsByTagName('script')[0];
if (d.getElementById(id)) {return;}
js = d.createElement('script'); js.id = id; js.async = true;
js.src = "//connect.facebook.net/en_US/all.js";
ref.parentNode.insertBefore(js, ref);
}(document));
</script>
<SCRIPT language="JavaScript">
FB.login(function(response) {
if (response.authResponse) {
console.log('Welcome! Fetching your information.... ');
FB.api('/me', function(response) {
console.log('Good to see you, ' + response.name + '.');
});
} else {
console.log('User cancelled login or did not fully authorize.');
}
});
</SCRIPT>
<SCRIPT language="JavaScript">
var body = 'Reading JS SDK documentation';
FB.api('/me/feed', 'post', { message: body }, function(response) {
if (!response || response.error) {
alert('Error occured');
} else {
alert('Post ID: ' + response.id);
}
})
</SCRIPT>
Why don't you expand the error handling a little bit?
alert("Error occured: " + response.error.message);
And did you check the console log for errors? Maybe authentication didn't work.
I have a facebook application in which the user is authenticated with PHP and grants permissions to the app, including publish_stream.
During the application, the user is going through several screens.
On the last screen, the is user chooses if they want to share a post on their wall.
If they do, an automated and formatted post should be posted on their wall.
I've tried to do it with Javascript but it didn't work. Can you see what's wrong?
Thanks!
Here's my code:
<div id="fb-root"></div>
<script>
window.fbAsyncInit = function() {
FB.init({
appId : 'MY APP ID',
status : true,
cookie : true,
xfbml : true
});
};
(function() {
var e = document.createElement('script');
e.src = 'http://connect.facebook.net/en_US/all.js';
e.async = true;
document.getElementById('fb-root').appendChild(e);
}());
</script>
<script>
function postToFacebook() {
var body = '';
var params = {};
params['message'] = 'MESSAGE';
params['name'] = 'NAME';
params['description'] = '';
params['link'] = '';
params['picture'] = 'https://www.URL.com/pic.jpg';
params['caption'] = 'CAPTION';
FB.api('/me/feed', 'post', params, function(response) {
if (!response || response.error) {
// alert('Error occured');
} else {
// alert('Post ID: ' + response);
}
});
}
</script>
From reading your question and the various comments it seems to me that the users session information is not persisting into the JavaScript SDK - this assumes that there is a valid user session being maintained serverside.
First of all you should check that you are using the most up to date PHP SDK. To double check download and install the latest version from GitHub.
I think this should solve your problem as the cookies containing the authorised users session data should be passed between the PHP and JavaScript SDKs.
If that doesn't work I have a suspicion that the user is not being authenticated correctly serverside. In which case you could try the following.
Before you postToFacebook() you should check the users the users logged in status and log them in if necessary. For example:
FB.getLoginStatus(function(response) {
if (response.authResponse) {
// logged in and connected user, someone you know
postToFacebook();
} else {
// no user session available, someone you dont know
FB.login(function(response) {
if (response.authResponse) {
// logged in and connected user
postToFacebook();
} else {
// User cancelled login or did not fully authorize
}
}, {scope: 'YOUR,REQUIRED,PERMISSIONS'});
}
});
You are not calling the function postToFacebook()!
window.fbAsyncInit = function() {
FB.init({
appId : 'MY APP ID',
status : true,
cookie : true,
xfbml : true
});
postToFacebook();
};
When you attempt to do this:
FB.api('/me/feed', 'post', params, function(response) { .. });
You need to pass the access token along with the call. I assume you have it on the php/server side, so then:
FB.api('/me/feed/access_token='[INSERT_ACCESS_TOKEN], 'post', params, function(response) { .. });