Testing a form in jasmine, Karma - angularjs

I'd like to test a form in Jasmine, using Karma. When I enter wrong credentials and click the button, a notification appears with the appropriate message. Unfortunately, in the iframe in karma doesn't show this div, so the next expect fails because the selector does not match any element.
it('Testing a form', function () {
browser().navigateTo('/index.html');
input('firstName').enter('Wrong');
input('lastName').enter('Wrong');
element(':button.btn').click();
expect(element('.msg h1').text()).toMatch('Wrong Credentials');
}
The error I'm getting is
Selector .msg h1 did not match any elements.
When I use sleep(10) or pause() in order to see the form after the click event, the message is not appeared, that's why the selector doesn't match any element. Any idea please? Thank you very much!

1.You can create same form element inside test script using $compile service and test it by setting values of text boxes and hit $('button class').click();
And set spy on method which is showing error or success msg.So that you can understand if msg is being displayed or not.
2.You must be creating JSON out of form data and validating it or assigning that form data to any $scope.variable_name.Before invoking validation function explicitly set that variable with wrong input.Then call the function on button click or $scope.$emit('click'); and set spy on method used for showing error message.

You could try this;
Change expect(element('.msg h1').text()).toMatch('Wrong Credentials');
to
expect(element('[ng-view] .msg h1').text()).toMatch('Wrong Credentials');

Related

$uibModal TypeError: Cannot read property 'close' of undefined

I am working in ServiceNow and have a button that pulls up a modal window that renders an embedded form. When a user submits, I have the embedded form $broadcast 'closeModal', and the button receives it to close. My client script looks like this for the embedded form:
$rootScope.$broadcast('closeModal');
and on my button that brings up the modal, my client script looks like this:
$rootScope.$on('closeModal', function() {
c.modalInstance.close();
});
This actually does close the modal window, but my console is showing "TypeError: Cannot read property 'close' of undefined"
Any idea why this is showing up?
Additionally, in my screenshot above, that typeerror actually shows up twice, for two different widgets. I am broadcasting and retrieving the same event for both widgets. I'm not sure if that's against best practice, but I've tried changing one of them to 'closeModal2' for example and the same typeError still shows.
Any suggestions or advice is greatly appreciated!
-- ADDED --
This is a screenshot of my console after logging c:
Simple hack is :
$rootScope.$on('closeModal', function() {
c.modalInstance && c.modalInstance.close();
});
Another suggestion is use $rootScope.$emit and listen at specific scope level $scope.$on

can not click on none visible element

I'm trying to test my angularjs app with protractorjs. I have set up selenium and got the server and runner working. My issue is that when I run my test I get the ElementNotVisibleError. I know that the element I am trying to select is hidden until certain fields have been filled in and this is how I would like this to be kept.
My question is, are there any workarounds to the issue via a call to wait or sleep. I have tried many variations of wait and sleep but with no luck.
My test code is
it('navigates the user to the login page', function(){
ptor = protractor.getInstance();
ptor.get('http://localhost:2222/#/page');
ptor.findElement(protractor.By.input('input.type1')).sendKeys('one');
ptor.findElement(protractor.By.input('input.type2')).sendKeys('two');
ptor.findElement(protractor.By.input('input.type3')).sendKeys('three');
ptor.findElement(protractor.By.input('input.type4')).sendKeys('four');
ptor.findElement(protractor.By.input('input.type5')).sendKeys('five');
ptor.findElement(protractor.By.input('input.type6')).sendKeys('six');
ptor.sleep(5000);
ptor.findElement(protractor.By.id('clickableBtn')).click();//not visible until above fields populated
}, 1000000);
Message from protractor is
Message:
ElementNotVisibleError: element not visible
If the element is not visible until you have input in all of the fields, it is because of Javascript. You may have to kick off that Javascript by typing Tab or Enter after typing that last field:
ptor.findElement(protractor.By.input('input.type6')).sendKeys(Keys.Tab);
Using javascript I was able to click
var linkToClick = ptor.driver.findElement(protractor.By.id('clickableBtn'));
ptor.executeScript("arguments[0].click();", linkToClick );
yes, WebDriver allows you to execute javascript on elements directly so simply do a javascript .click. You would need to convert to your own language but here is how I did it using C#
IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
js.ExecuteScript("arguments[0].click()", element);
Browser.WaitForPageLoad(driver);
I actually created an extender method so that I simply type element.InvisibleClick(driver) and it clicks on it for me. More on that can be found documented HERE.
You can always give it opacity:0
-moz-opacity: 0.00; opacity:.00; filter: alpha(opacity=00);
This should work for all browsers.

angular e2e tests: How can I check if an element got the focus?

I have an angular.js application that should set the focus to a specific element when doing something (ie, set the focus to an invalid form field to let the user correct the error).
I'm trying to test this behavior within an angular-e2e test:
it('should set the focus to the invalid field', function() {
input('email').enter('foo'); // this is not a valid email address
element(/* submit button */).click(); // try to submit the form
// How do I do this?
expect(element(/* email input element */)).toHaveTheFocus();
});
How can I expect a certain element to (not) have the focus? I already tried the ':focus' selector
expect(element('input[id="..."]:focus').count()).toBe(1);
but no success (inspired by Testing whether certain elements are visible or not).
To set the focus, I use the idea of How to set focus on input field?
I was also writing unit tests for this and ended up using a spy on the DOM focus() function (which is, as far as I know, not possible/desireable for e2e tests).
I see two options here. The first, which I really recommend, specially on E2E tests, is to use Jasmine-jQuery which provides the toBeFocused matcher which deals with this.
If you don't want to include Jasmine-jQuery because it's too big or because you don't like it, then you have two options:
Compare the button with the document's active element, can access it with: document.activeElement
Compare the button with the document's active element by getting it from the element itself (this is the way jasmine-jquery does it) with: DOMELEMENT.ownerDocument.activeElement

How to intercept AngularJS $http logging for display in page

I want to intercept console log message from AngularJS and display them in a div on the page. I need this in order to debug ajax traffic in a PhoneGap app.
This is an example of the kind of errors I want to capture:
I tried this Showing console errors and alerts in a div inside the page but that does not intercept Angular error messages.
I also tried the solution gameover suggested in the answers. No luck with that either. Apparently $http is handling error logging differently.
I guess the answer you tried has the right idea but you're overriding the wrong methods. Reading here I can see angularJs uses $log instead of console.log, so to intercept you can try to override those.
Something like this:
$scope.$log = {
error: function(msg){document.getElementById("logger").innerHTML(msg)},
info: function(msg){document.getElementById("logger").innerHTML(msg)},
log: function(msg){document.getElementById("logger").innerHTML(msg)},
warn: function(msg){document.getElementById("logger").innerHTML(msg)}
}
Make sure to run that after importing angular.js.
EDIT
Second guess, override the consoleLog method on the LogProvider inner class on angular.js file:
function consoleLog(type) {
var output ="";
//arguments array, you'll need to change this accordingly if you want to
//log arrays, objects etc
forEach(arguments, function(arg) {
output+= arg +" ";
});
document.getElementById("logger").innerHTML(output);
}
I've used log4javascript for this purpose. I create the log object via
var log = log4javascript.getLogger('myApp')
log.addAppender(new log4javascript.InPageAppender());
I then use this in a value dependency, and hook into it where needed (e.g. http interceptor).
A more lightweight approach might be to use $rootScope.emit and then have a component on your main page which prepends these log messages to a visible div, but this will require you to change all your calls to console.log (or redefine the function in your js).
I think that this message is not even displayed from AngularJS. It looks like an exception which has not been caught in any JavaScript (angular.js just appears on top of your stack because that's the actual location where the HTTP request is being sent).
Take a look at ng.$exceptionHandler. That should be the code you seem to be interested in. If not, take a quick web search for „JavaScript onerror“ which should tell you how to watch for these kinds of errors.
I would rather user an $http interceptor.
Inside the responseError function, you can set a property on a service that will be exposed to the div's scope.

AngularJS - AlertFactory open dialog behavior

i'm creating an AlertFactory because ui.bootstrap.dialog doesn't works in my app.
So i type follow code: http://jsfiddle.net/Premier/BHqKB/17/
enter code here
It works very well if you click on the "Open dialog" button: on screen appear a dialog with my messages.
I also register a listener on keydown: listener fires a broadcast event on which is registered a scope related function. This function calls openDialog to show the dialog. In this way angular doesn't interpolates arguments and alert is shown with {{title}} placeholder.
What is wrong in my code?
Thank you.
You need an $apply to invoke a digest cycle.
ng.element(document).on('keydown', function(e){
//alert('keydown');
//openDialog();
$rootScope.$broadcast('openDialog');
$rootScope.$apply();
});

Resources