I'm currently writing some Protractor tests for an app. But in the app i'm using controller as syntax as the pieces I want to work on are components. The problem is that when i use the selector of "" $ctrl.functionName"" it's giving me an illegal selector statement.
Anyone have any ideas about this?
let btn = $$("button[ng-click^=$ctrl.initRequest].secondary.bf-btn");
expect(btn.isDisplayed()).toBe(true);
The error message is
Failed: invalid selector: An invalid or illegal selector was specified
If you cannot assign a meaningful id or other attribute to the element, you need to fix your current selector. At the very least, there should be quotes around the ng-click value:
button[ng-click^='$ctrl.initRequest'].secondary.bf-btn
Note that a slightly better version, that would also not require quotes, would be to use a partial match:
button[ng-click*=initRequest].secondary.bf-btn
And, see if you can drop the questionable classes and have just:
button[ng-click*=initRequest]
Related
I simplified the code i need to test to this:
<html ng-app="home" ng-strict-di=""><head>....
And i am running some protractor tests, i want to access the value of ng-app so i can compare and see which app is running in each page.
I have tried
var appName = element(by.xpath('/html/#ng-app'))
but it is not returning a usable promise or text i can compare with
appName.getText().then(function(name) {
expect(name).toBe('home')
});
But protractor complains:
InvalidSelectorError: invalid selector: The result of the xpath expression "/html/#ng-app" is: [object Attr]. It should be an element.
So i'm a bit baffled as how can i access my angular app name from protractor to test for app running independently of localization of labels.
Any insight into this enigma?
And it seems like magically, when you order your thoughts to formulate the question, the answer comes to you.
the trick is to get the html as element
var appNameHtml = element(by.xpath('/html'))
and then, in the test, get the ng-app attribute and use it:
appNameHtml.getAttribute('ng-app').then(function(value) {
expect(value).toBe('home');
});
And bingo, you can extract the app name.
Maybe this is a very basic question, but it was driving me insane :)
your answer will suffice I guess in this case. But just wanted to highlight a more generic approach in case ng-app may reside not only on html element.
var elementWithNgApp = element(by.css('*[ng-app]'))
And then wanted to add one more thing. You need not resolve the promise of getAttribute to do an expect on its value. Jasmine resolves the promise for you. You can have something like this
expect(elementWithNgApp.getAttribute('ng-app')).toBe('home');
I am migrating an application from Angular1 to Angular2, in which I used the svg.js library to draw an SVG. Some elements of the SVG contained "ng-click" directives, that I made the SVG library print to the final SVG.
That worked alright in Angular1, however, now the directive is called "(click)" and everything breaks. I traced the SVG sources and found that the following call
this.node.setAttribute(attr, value.toString())
results in the following error message:
VM22161:1 Uncaught DOMException: Failed to execute 'setAttribute' on 'Element': '(click)' is not a valid attribute name.(…)
Any ideas to solve that problem? Patching the SVG source would be ok for me, if there's no other way.
A valid and quick workaround is to use the binding syntax of Angular2, that allows to use "on-click" instead of "(click)".
I have a custom Angular service which creates a custom DOM node using angular.element(). Meanwhile, since I also want the element to have a set of predefined attributes, I pass a JS object as a second parameter to the function:
var element = angular.element('<node-name />', {
class: "some css class",
onclick: "someClickHandler()"
});
Although this works OK as far as the attribute is not specific to Angular.
The problem is that I'm not able to produce Angular-like dashed-case (don't know what their actual name is) attributes (e.g. ng-click).
For now, if I do:
var element = angular.element('<node-name />', {ngClick: 'someClickHandler'}); // ng-click here is definitely not possible as it leads to a syntax error
it will always result in the DOM node as:
<node-name ngclick="someClickHandler"></node-name>
which doesn't work the Angular way.
So, is there any way that a camel-case attribute be converted to its equivalent dashed-case in the DOM?
Any help would be appreciated.
You don't really need any additional code to convert from camelCase to snake-case (although you could). It's better to use snake-case in the first place if you really want to, just make sure you put property name in quotes, otherwise the name is not valid identifier:
var element = angular.element('<node-name />', {
'ng-click': 'someClickHandler'
});
Trying to check the value of this element on an angular plunker:
it('should display valid',function(){
browser.get('http://embed.plnkr.co/3nt01z/preview');
var errortext =element(By.xpath('body>div>h2>span:nth-child2)')).getText);
expect(errortext).toBe('Not:(');
})
Getting an error though:
Stacktrace:
InvalidSelectorError: invalid selector: Unable to locate an element with the xpath expression body>div>h2>span:nth-child(2) because of the following error:
SyntaxError: Failed to execute 'evaluate' on 'Document': The string 'body>div>h2>span:nth-child(2)' is not a valid XPath expression.
Is there a better way to find this span element or what is the right xpath expression?
I think you meant By.cssSelector(...).
By.xpath expects an XPath expression, which would be something like /body/div/h2/span[2], although I'm not sure about the exact syntax.
By the way, your code would be easier to test if you added an ID or CSS class to the element, so you don't need to depend on the exact DOM structure.
Try to use element(by.css('some css selector'))
Also, you have a typo in code - getText; instead of getText();
Or try this:
var errortext = element(By.xpath('/body/div/h2/span[2]')).getText();
I try to setup a placeholder for broken image, using holder.js in an AngularJS framework.
Everything works perfectly on all browsers, except with IE11 (what a surprise!), which gives me a strange "invalid property value" error... I did not even test with older versions of IE.
So, it works when :
I use "holder.js/100%x100%" directly in the src attribute (with no additionnal directive)
I use "holder.js/100x100" as a placeholder for broken image
But it fails when :
I use "holder.js/100%x100%" directly in a data-ng-src instead of src ( => invalid argument)
I use "holder.js/100%x100%" as a placeholder for broken image ( => invalid property value)
After few other tests (with jQuery or pure javascript), I figured out the error does not come from holder.js. I rather think there is an issue with IE11 when using % character in src/ngSrc attributes programmatically ... but I don't know why if I'm right.
Here is the fiddle with the four use cases :
http://jsfiddle.net/msieurtoph/184fseew/
If anybody has an idea about the reason or the way to get it working.
Thx for your help...
EDIT :
Thx to #imsky, here a working fiddle, using data-src instead of src : http://jsfiddle.net/msieurtoph/184fseew/23/
This is a known bug with IE11, where using % in img.src throws an error: https://connect.microsoft.com/IE/feedback/details/997939/ie11-imageelement-setattribute-fails-with-invalid-argument-when-key-is-src-and-value-has-a-percent
There are two solutions here, depending on whether or not you need the src attribute to be set. The first one is to use data-src instead of src:
$timeout(function() {
_this.setAttribute('data-src', holderSrc)
Holder.run({
images: _this,
nocss: true
});
});
This is the cleaner solution and one I recommend.
The other solution would be to replace the element with a clone that has the proper src attribute value. This approach is not as clean and introduces overhead if you need to maintain references to the original image element. I only recommend this if the src attribute needs to be properly set.