I am setting up a web form using angular whereby users will complete the form, get a response from the server, and then get redirected to another page.
angular.module('discountController', ['discServices'])
.controller('discCtrl', function(Discount, $timeout, $location){
var app = this;
app.reqDiscount = function(discountData) {
Discount.reqDiscount(app.discountData).then(function(data) {
if (data.data.success) {
app.successMsg = data.data.message ; // Create Success Message
$timeout(function(){
console.log('timeout fired');
$location.path('/discountoutcome');
} , 3000);
} else {
app.errorMsg = data.data.message; // Create an error message
}
});
};
});
In the above code I call the app.reqDiscount function and I successfully get a response from the server which populates the app.successMsg variable. But the $timeout function does not then work. However, if I place the $timeout function outside of the if-else statement it does work. This is not what I want, because if there is an error I want to stay on the page.
In other areas of my code I have placed a $timeout function in a nested position like this and it works, so I don't understand why it would not work here.
Any help you can give me would be great. Even if you can not answer this question if you can give me some tips on debugging that would be helpful as console.log() is my only method of debugging currently. I am using Visual Studio Code.
Chrome console:
Chrome console screen shot
Visual Studio Console:
VSC console
I got it. I had coded the API incorrectly. data.data.success was returning false instead of true. Thanks for your help.
Related
I'm using Protractor with Cucumber to write some tests but I'm stuck at some point. In step after login, I'm rerouting to another page using browser.get(url) function provided by protractor. But it always returns before the page is completely loaded. I have tried many solutions so far but no luck. I have tried with browser.wait, browser.get(url).then(function(){ // code when it loads}) but Im getting 0 positive results.
Here's my code:
// Steps will be implemented here
this.Given(/^I am logged in as user \'([^\']*)\'$/, function (user, callback) {
console.log('USER: ' + user);
browser.driver.get('https://cit-was70-l06/ipa')
browser.driver.findElement(by.xpath('my_xpath')).sendKeys(user);
browser.driver.findElement(by.xpath('my_xpath')).sendKeys(user);
browser.driver.findElement(by.xpath('my_xpath')).click().then(callback);
});
this.Then(/^The screen is shown, with title \'([^\']*)\'$/, function (title, callback) {
console.log('Title from feature file: ' + title);
var url = 'some/url/in/application/';
browser.get(url).then(function(){
// This portion executes before page is completely loaded.
// So if I try to get any element, it throws me an error.
// [15:32:13] E/launcher - "process.on('uncaughtException'" error, see
// launcher
// [15:32:13] E/launcher - Process exited with error code 199
// It works if I add static delay to wait for page load completely
// but that will not be a good solution if I have too much pages to test
callback();
});
console.log('After page laoad');
});
Any suggested work around will be much appreciated.
[15:32:13] E/launcher - "process.on('uncaughtException'" error, see launcher
[15:32:13] E/launcher - Process exited with error code 199
The above error can be caused due to various reasons mostly related to promises. But it should throw the correct message. There is already a work around provided here https://github.com/angular/protractor/issues/3384 to catch the exact error message.
You could change the launcher.ts file in your protractor dependency as mentioned in above forum to catch the error inorder to debug your issue.
And I would suggest you to return your promises instead of callbacks when writing step definitions in protractor-cucumber, in this way cucumber would know when to complete its async actions.
Try the below code.check whether it helps.
browser.get(url);
browser.waitForAngular();
then try to call your function.
Use protractor.ExpectedConditions to check visibility of any elements on page which will be displayed after successful login. Write a customized method as shown below.
If element displayed, then navigate other page using browser.get();
Code Snippet
EC = protractor.ExpectedConditions;
//targetElement=element(locator);
this.isElementVisible = function (targetElement, timeOut) {
'use strict';
timeOut = timeOut !== undefined ? timeOut : 8000;
browser.wait(EC.visibilityOf(targetElement),
timeOut).thenCatch(function()
{
assert.fail(' element is not visible');
});
};
So I have 2 promise functions. When there is an error for the first function I want it to display an error message. When either complete or fail I would like them to execute a finally catch all function but for some reason it isn't working.
my code looks like this:
// If our garment has a logo
shared.logoExists(garment, model).then(function () {
// Save our panel
return shared.save(model);
// If there was an error
}, function () {
// Display an error message
toastr.warning(localization.resource.logoPlacementError.message);
// Always close the library
}).finally(function () {
// Reset our attachments
self.resetAttachment();
// Hide our library
self.closeLibrary();
});
So basically what I am trying to achieve is if the first function fails, it will display and error.
When the second function fails, it won't do anything.
But if either succeed or fail, it will always close the library.
Does anyone know how I can achieve this?
You have to use .catch after closing the then function:
// If our garment has a logo
shared.logoExists(garment, model).then(function () {
// Save our panel
return shared.save(model);
// If there was an error
}).catch(function () {
// Display an error message
toastr.warning(localization.resource.logoPlacementError.message);
// Always close the library
}).finally(function () {
// Reset our attachments
self.resetAttachment();
// Hide our library
self.closeLibrary();
});
Depending on which version of Angular you're using, you may have to use "always" instead of "finally". Try "always" and see if it works.
How to always run some code when a promise is fulfilled in Angular.js
It turns out that my way works fine. The logoExists function was not resolving / rejecting a promise in all places that it should be. When I fixed that, my code above worked.
i'm newbie in angular js, have created a project in angular js and want to maintain log on server for all the issues occuring at the client side.
Gone through various blogs and found few suggestions for applying stack js but couldn't understand the implementation for same.
Please suggest if it is possible to log all the errors in project from one single point of client side, at the server through factory or service method using angular js.
This is possibly by overriding angulars built in $exceptionHandler. Below is the snippet of code from my own app that logs any failures to the backend, but also prints them into the console, in case the backend logging fails. As my javascript is minified, I use StackTrace to turn this back into an un-minified stack trace, and send that to my backend.
function exceptionLoggingService($injector) {
function error(exception, cause) {
// preserve the default behaviour which will log the error
// to the console, and allow the application to continue running.
var $log = $injector.get('$log');
var $window = $injector.get('$window');
$log.error.apply($log, arguments);
var errorMessage = exception.toString();
StackTrace.fromError(exception).then(function (arrayStack) {
var exceptionData = angular.toJson({
errorUrl: $window.location.href,
errorMessage: errorMessage,
stackTrace: arrayStack,
cause: ( cause || "" )
});
// now post this exceptionData to your backend
}).catch(function (backendLoggingError) {
$log.warn("Error logging failure.");
$log.log(backendLoggingError);
});
}
return(error);
}
angular.module('dashboard-ui').factory('$exceptionHandler', ['$injector', exceptionLoggingService])
I have the following service that runs when I navigate to a products page:
app.factory('ProductService',['$http','$location',function($http,$location){
var factory = {};
factory.getAll = function(){
$http.get('/products').success(function(response){
console.log('success callback hit');
if(response.status === 401){
console.log(response);
$location.path('login');
}
}).error(function(){
console.log('error');
});
};
return factory;
}]);
In my express router, I check if req.isAuthenticated() and if not (which is the case I'm testing), I call:
return res.status(401).send("Not Authorized");
That's the only place in my server where I send a 401 response, so I know the $http.get(/products) is going to the right place, and I see the get request returning 401 in my console, but why aren't any of my callbacks being hit? (Nothing is logged to the console and I don't get redirected on the client.) I read something about needing to reject the promise if I'm using global interceptors, but I don't think I am using any interceptors? EDIT: This is why I don't think it's a duplicate of the question suggested since I'm not using custom interceptors.
UPDATE: My error handler was getting called, just nothing was logged in my node.js command window (duh, because it's on the client). Thanks for the help everyone!
My error handler was getting called, just nothing was logged in my node.js command window (duh, because it's on the client). Thanks for the help everyone!
So, I'm trying to script a login form for automation through protractor, but running into some problems when I'm trying to verify the cookies after the page redirect.
Here's my sample code:
describe('login', function () {
var app;
var LoginPage = require('./login.page.e2e.js');
// Before each test, refresh page
beforeEach(function () {
LoginPage.get();
app = element(by.css('body'));
});
// Check route, make sure it hasn't been redirected somewhere strange
it('should be at path: /login', function () {
expect(browser.getCurrentUrl()).toContain('/login');
});
/**
* Login as a provider (phoenix.e2e.login.test#leadingreach.com)
*/
it('should be able to login', function () {
// Fill out fields
LoginPage.populate_provider_form();
// Login as provider
// Clicking this button fires off an AJAX request that logs in the user, and populates a few browser cookies
element(by.css('#provider-login-form-container #login_btn')).click();
// These two statements work fine. They seem to wait for the redirect and end up passing.
expect(browser.getCurrentUrl()).toContain('/dashboard');
expect(app.evaluate('currentUser.username')).toEqual('phoenixe2elogin');
// The following statements are executed before the page redirects, and therefore fail
expect(!!browser.manage().getCookies().lrrt).toBe(true);
expect(!!browser.manage().getCookies().lrco).toBe(true);
expect(browser.manage().getCookies().lrrm).toBe('false');
});
});
It's been about 3 or 4 months since I created my first Protractor tests, so I'm re-learning all the new syntax, etc. I'm currently under the impression that using waitsFor and methods like that aren't really encouraged (or supported) anymore, so I'm wondering how someone could go about scripting something like this.
In order to get protractor to wait for the element to appear, you have to use the following syntax:
ptor.findElement(by.id('my-elt')).then(function (elt) {
expect(elt.evaluate('my.binding')).toBe('someValue');
});
Took me a while to figure this out, hope it ends up helping someone :D