I am trying to get an async intern test working using a separate module to do the request call. I am having an issue returning true once the test is done because I always get a timeout error, even though the request is successful, and the test runs to completion. After the test runs it just sits on the last page and times out. login_test.js is the test file, companyCreate is the request calling file that exists in an external module. I'm not quite sure what is happening to my test return call if I pass it into deferred.callback().
// login_test.js
define([
'intern!object',
'pages/loginpage',
'runtime/testConfig',
'intern/dojo/node!nconf',
'helpers/companyCreate',
'locators/loginpage',
'locators/companyselectionpage'
], function(registerSuite, LoginPage, conf, nconf, Company) {
var tests = {
name: 'Login test',
'Test': function() {
/* make a call to create a company
* param1: test function to run after we get response with login details
* param2: intern object so we can make it async
*/
Company.createCompany(function(response, testObj) {
testObj.timeout = 120000; //The default timeout is 30 seconds. Not enough
var region = nconf.get("region"); //Getting command line region value
var regionData = conf.get(region); //Fetching config data based on region
var loginId = regionData.LOGIN;
var password = regionData.PASSWORD;
var loginPage = new LoginPage(testObj.remote, regionData.DEFAULT_TIMEOUT);
var companySelectionPage = loginPage
.load(regionData.BASE_URL)
.loginIn(loginId, password);
var homePage = companySelectionPage
.doesCurrentURLContain('/companysel')
.isTitlePresent()
.selectCompany(CompanySelectionLocators.data);
return homePage
.doesCurrentURLContain('/homepage')
.getAccumulatedState();
}, this);
}
};
registerSuite(tests);
});
>
// companyCreate.js
define(function(require) {
var request = require('intern/dojo/request');
var Company = {
createCompany: function(callbackArg, testObj) {
// tell intern this is async
var deferred = testObj.async(120000);
// make post
request.post('https://internal.com/createcompany', {
query: {
version: ".0.1",
special: "true"
},
data: JSON.stringify({
userName: "Test",
password: "pass",
userEmail: "email#hi.com"
}),
headers: {
'Content-Type': "application/json"
}
}).then(function(response) {
// success, tell intern async is done, return test function to run and pass it the response
console.log(response);
return deferred.callback(callbackArg(response, testObj));
}, function(err) {
console.log(err);
}, function(evt) {
//console.log(evt);
});
}
};
return Company;
});
deferred.callback is intended to be used to wrap another callback that is executed at another time. It doesn’t resolve the underlying Promise, it returns a new function that, when invoked, resolves the Promise if the passed in callback function doesn’t throw an error. For example:
'Test': function () {
var dfd = this.async();
// this use of `dfd.callback`…
fs.readFile('foo.txt', dfd.callback(function (error, data) {
if (error) {
throw error;
}
assert.strictEqual(data, 'hello, world');
}));
// …is equivalent to this without it:
fs.readFile('foo.txt', function (error, data) {
if (error) {
dfd.reject(error);
return;
}
try {
assert.strictEqual(data, 'hello, world');
}
catch (error) {
dfd.reject(error);
return;
}
dfd.resolve();
}));
}
You should be using deferred.resolve, which resolves the promise to the value passed as the first argument. See the async tests documentation for more detailed information on each of these functions.
Working solution is below. I had no need for this.async. comapnyCreate.js returns the response and promise from the request. login_test.js runs the test after the promise is fulfilled. (still needs some error handling logic)
// login_test.js
define([
'intern!object',
'pages/loginpage',
'runtime/testConfig',
'intern/dojo/node!nconf',
'helpers/companyCreate',
'locators/loginpage',
'locators/companyselectionpage'
], function(registerSuite, LoginPage, conf, nconf, Company) {
var tests = {
name: 'Login test',
'Test': function() {
this.timeout = 60000;
var remote = this.remote;
return Company.createCompany().then(function(response) {
var region = nconf.get("region"); //Getting command line region value
var regionData = conf.get(region); //Fetching config data based on region
var loginId = regionData.LOGIN;
var password = regionData.PASSWORD;
var loginPage = new LoginPage(remote, regionData.DEFAULT_TIMEOUT);
var companySelectionPage = loginPage
.load(regionData.BASE_URL)
.loginIn(loginId, password);
var homePage = companySelectionPage
.doesCurrentURLContain('/companysel')
.isTitlePresent()
.selectCompany(CompanySelectionLocators.data);
return homePage
.doesCurrentURLContain('/homepage')
.getAccumulatedState();
});
}
};
registerSuite(tests);
});
// companyCreate.js
define(function(require) {
var request = require('intern/dojo/request');
var Company = {
createCompany: function() {
// make post
return request.post('https://internal.com/createcompany', {
query: {
version: ".0.1",
special: "true"
},
data: JSON.stringify({
userName: "Test",
password: "pass",
userEmail: "email#hi.com"
}),
headers: {
'Content-Type': "application/json"
}
});
}
};
return Company;
});
Related
Meteor newbie here, I want to do a meteor call to a meteor method which does a get request to an 3rd party API and forwards the returned JSON response to my initial meteor call.
I want to use the returned JSON response to render my html code
here is my js file with meteor method
Meteor.methods({
'jira.get'(projectName, maxResult) {
if (!this.userId) {
throw new Meteor.Error('Not authorized.');
}
check(projectName, String);
check(maxResult, String);
const base64Auth = Meteor.users.findOne({ _id: this.userId }).Authorization;
const options = {
method: 'GET',
url: `https://myCompany.com/.../search?jql=project=${projectName}&maxResults=${maxResult}`,
headers: {
Authorization: base64Auth,
},
};
const future = new Future();
request(options, function(error, response) {
if (error) throw new Error(error);
const jiraResponse = JSON.parse(response.body);
future.return(jiraResponse);
});
return future.wait();
},
});
and my JSX file that calls above Meteor method is as below
export const App = () => {
Meteor.call('jira.get', project='test', maxResult = '10', (error, jiraResponse) => {
console.log("this is working fine: "jiraResponse)
});
console.log('this is undefined', jiraResponse)
}
If i use useState as below, initially the last console log console.log(jiraResp) prints {} as expected but it goes into infinite loop with the correct data after that
const [ jiraResp, setjiraResp ] = useState({})
Meteor.call('jira.get', project='test', maxResult = '10', (error, jiraResponse) => {
if (jiraResponse){
console.log("got the resp ")
setjiraResp(jiraResponse);
}
else{
console.log("not recieved")
}
});
console.log(jiraResp)
How do i get the response of meteor call and update my jiraResponse just once ?
Setting jiraResp in the method callback will trigger a re-render and since you are making the method call in the render method itself, it will repeat the call, hence the loop.
You need to use useEffect:
const [ jiraResp, setjiraResp ] = useState({});
useEffect(() =>
Meteor.call('jira.get', project = 'test', maxResult = '10', (error, jiraResponse) => {
if (jiraResponse) {
console.log("got the resp ");
setjiraResp(jiraResponse);
} else {
console.log("not recieved");
}
}), []);
console.log(jiraResp);
I am calling 2 API request 1 after another so I decided to use the waterfall model but I am facing the issue in it
I have tried so much but not able to solve the issue.
Below is my code:
var unirest = require("unirest");
var async = require("async")
exports.user = (req, res, next) => {
const qry = req.params.id
async.waterfall([
(nextCall) => {
var req = unirest("GET", API_URL1);
req.query({
// some query
});
req.headers({
// some headers
});
req.end(function(subCount) {
// if (resp.error) throw new Error(resp.error);
var channelSubCount = subCount.body
nextCall(null, data)
});
},
(data, nextCall => {
console.log(channelSubCount, 'data')
var reqs = unirest("GET", API_URL2);
reqs.query({
// some query
});
reqs.headers({
// some headers
});
reqs.end(function(res) {
// if (res.error) throw new Error(res.error);
console.log(res.body);
return nextCall(null, {
name: 'abc',
photo: 'src',
count: data
})
});
})
], function(finalData) {
// if (error) { alert('Something is wrong!'); }
console.log('final')
res.status(200).json(
finalData
);
});
};
ERROR:
Reference Error: data is not defined
I don't understand why this is happening.
Also some please show me the right way to implement the above things with optimizations.
Any help appreciated...
Looks like you forgot to close parentheses here in your second arrow function definition:
(data, nextCall => {
It's still a valid JavaScript, but the interpreter now treats data not as a function incoming parameter (as you need), but as a variable. But it's not defined anywhere, therefore you have that error.
Make it like this and it will work:
(data, nextCall) => {
I'm trying to update a Parse Server user from my client web app using the Javascript SDK.
I understand that this isn't possible using Parse.User but is possible using Parse.Object. I'm following the guidance to update Object but can't seem to get bast the 3rd line of the function.
function () {
var updateTheUser = Parse.Object.extend("_User");
var query = new Parse.User.current();
query.get(Parse.User.current().id, {
success: function (update) {
// The object was retrieved successfully.
update.set("phone", "01234 567890");
update.set("Barred", false);
update.save(null, {
success: function (update) {
console.log("Updated!");
}
});
},
error: function (object, error) {
// The object was not retrieved successfully.
// error is a Parse.Error with an error code and message.
}
});
};
};
Nested callbacks are a magnet for errors, as you can see in your code. The callback you think handles the object not retreived actually handles a failed save.
Try the following and see what that shows in your console (note: may not work in IE without babel):
const asPromise = (fn,context,args) => {
return new Promise(
(resolve,reject) => {
args.concat(
{
success:resolve,
error:(o,e) => reject([o,e])
}
);
fn.apply(context,args);
}
);
};
var updateTheUser = Parse.Object.extend("_User");
var query = new Parse.User.current();
//maybe query should be:
// var query = new Parse.Query(User);
// from documentation: http://docs.parseplatform.org/js/guide/#retrieving-objects
asPromise(query.get,query,[Parse.User.current().id])
.then(
update => {
update.set("phone", "01234 567890");
update.set("Barred", false);
return asPromise(
update.save,
update,
[null]
)
}
)
.then(
user => console.log("updated user:",user)
,error => console.warn("Something went wrong:",error)
);
The only way that I've been able to solve this is by doing an AJAX request using the REST API
updateUser = function () {
var userId = Parse.User.current().id;
var data = JSON.stringify({
"username": username,
"firstname": firstname,
"lastname": lastname,
"email": email,
"phone": phone
});
$.ajax({
url: 'myServerURL' + userId,
type: 'PUT',
headers: {
'X-Parse-Application-Id': "my_api",
'X-Parse-Master-Key': "my_masterkey",
'Content-Type': "application/json"
},
"data": data,
success: function (result) {
// Do something with the result
alert("you have successfully updated your account. We're now going to need you to log back in with your new details?");
Parse.User.logOut();
window.location.href = "/#/login";
},
error: function (Response) {
alert(Response.error);
}
});
};
WARNING: As this contains the Master Key, it should be located in Cloud Code on your Parse Server, not in your web app
Only this should work:
var user = Parse.User.current();
user.set("phone", "01234 567890");
user.set("Barred", false);
user.save(null, {
success: function (update) {
console.log("Updated!");
},
error: function (error) {
console.log(error);
}
});
I'm making an user management with the Amazon Web Service names Cognito.
It runs smoothly on local but it is not when I use it on a Wamp server.
I can not figure out why... maybe cause to asynchronous execution ?
I'm using $q and .then(function() { ... }); to wait for it's execution.
This is how I do in my controller :
$scope.validateForm = function() {
if (AuthService.getActifUser() == false) {
//clear local storage
$storage.remove('userData');
}
//getting the form attributes
var datafirstName = {
Name: 'custom:first_name',
Value: $scope.firstName
};
var dataLastName = {
Name: 'custom:last_name',
Value: $scope.lastName
};
var dataEmail = {
Name: 'email',
Value: $scope.email
};
var attributeFirstName = AuthService.setAttributes(datafirstName);
var attributeLastName = AuthService.setAttributes(dataLastName);
var attributeEmail = AuthService.setAttributes(dataEmail);
var attributeList = [];
attributeList.push(attributeFirstName);
attributeList.push(attributeLastName);
attributeList.push(attributeEmail);
// signing try
AuthService.signin($scope.username, $scope.password, attributeList)
.then(function(res) {
// save username in local storage
$storage.set('userData', $scope.username);
// go to the verification page
routeService.goToView('/users-confirmation');
}, function(res) {
console.log(res);
);
}
And in the AuthService Factory :
AuthService.signin = function(username, password, attributeList) {
var deferred = $q.defer();
userPool.signUp(username, password, attributeList, null, function(err, result) {
if (err) {
alert(err);
deferred.reject('registering failled.');
}
console.log('successfully registered.');
deferred.resolve('successfully registered.');
});
return deferred.promise;
};
Unfortunatelly the routeService.goToView() method is never called.
Hope someone know why ?
Could you please add a handler for the promise rejection to ensure that the promise is not being rejected?
It could be that your promise is being rejected and the error hidden. Also, where is invalidPassword being defined?
I need to request some json files that contain data I use for testing. I would like to make the request in the setup method, but there is no async method attached to it. When I run the code below, the log inside the test login function gets sent to the console before my logs from the setup method get sent. Is there a way I can tell setup to wait till my calls get completed before running the tests?
define([
'intern!object',
'pages/LoginPage',
'data-objects/DataFetcher'
], function(registerSuite, LoginPage, DataFetcher) {
registerSuite(function() {
var loginId = admin;
var password = test;
var regionData = US;
var loginPage = null;
return {
name: 'Login test',
setup: function() {
// Initialize page objects
loginPage = new LoginPage(this.remote, this.timeout);
// get test data
DataFetcher.getData(Pages.LoginPage).then(function(response) {
logger.info(DataFetcher.generateData(response));
});
DataFetcher.getData(Pages.TablePage).then(function(response) {
logger.info(DataFetcher.generateData(response));
});
DataFetcher.getData(Pages.PersonPage).then(function(response) {
logger.info(DataFetcher.generateData(response));
});
DataFetcher.getData(Pages.BasicInfoPage).then(function(response) {
logger.info(DataFetcher.generateData(response));
});
DataFetcher.getData(Pages.CompanyInfoPage).then(function(response) {
logger.info(DataFetcher.generateData(response));
});
},
login: function() {
logger.log('info', 'Login is ' + loginId + ' Password ' +
password);
return loginPage.load(regionData.BASE_URL)
.login(loginId, password)
.getAccumulatedState();
}
};
});
});
If you return a Promise from the setup function, Intern will wait for it to resolve before starting tests. You can return a Promise.all(...) of all your requests.