AngularJS - e2e testing - Why does this by.css selector work? - angularjs

So I'm starting to break into AngularJS from a JavaScript (& jQuery) background. I've been wading through the tutorial, and an loving the way it's set up. Currently I'm looking at lesson 10 and I can't figure out why a piece of the code works. I have tried googling and poking through the documentation...the protractor docs don't even seem to have anything for by.css and I couldn't figure out how to search for this very concisely :/ ... Apologies if I'm just missing something seriously obvious.
In the e2e test scenario there is this code:
it('should swap main image if a thumbnail image is clicked on', function() {
element(by.css('.phone-thumbs li:nth-child(3) img')).click();
expect(element(by.css('img.phone')).getAttribute('src')).toMatch(/img\/phones\/nexus-s.2.jpg/);
element(by.css('.phone-thumbs li:nth-child(1) img')).click();
expect(element(by.css('img.phone')).getAttribute('src')).toMatch(/img\/phones\/nexus-s.0.jpg/);
});
which acts on this page-html:
<ul class="phone-thumbs ng-scope">
<li ng-repeat="img in phone.images" class="ng-scope">
<img ng-src="img/phones/nexus-s.0.jpg" ng-click="setImage(img)" src="img/phones/nexus-s.0.jpg">
</li>
</ul>
produced by this ng-markup:
<ul class="phone-thumbs">
<li ng-repeat="img in phone.images">
<img ng-src="{{img}}" ng-click="setImage(img)">
</li>
</ul>
I can't figure out why the element(by.css('img.phone'))... is functional. Based on the selector (and coming from jQuery) I would expect to see a 'phone' class on the images...but it's not there. Does the '.phone' reference something else?
I can see that removing the '.phone' portion gives '.....warning: more than one element found for locator By.cssSelector("img") - you may need to be more specific', so how is '.phone' providing that specificity?
Thanks,
Ben

You're just looking in the wrong place:
It is checking if clicking on a thumbnail
//app/partials/phone-detail.html (line 9):
<img ng-src="{{img}}" ng-click="setImage(img)">
makes THIS image:
//app/partials/phone-detail.html (line 1):
<img ng-src="{{mainImageUrl}}" class="phone">
change it's source. img.phone is exactly what you would expect.
The docs for by.css are here: https://github.com/angular/protractor/blob/master/docs/locators.md

Related

Scraping based on "nested property"

After having created a few different spiders I thought I could scrape practically anything, but I've hit a roadblock.
Given the following code snippet:
<div class="col-md-4">
<div class="tab-title">Homepage</div>
<p>
<a target="_blank" rel="nofollow"
href="http://www.bitcoin.org">http://www.bitcoin.org
</a>
</p>
</div>
How would you go about selecting the link that is in within <a ... </a> based on the text within the tab-title div?
The reason that I require that condition is because there are several other links that fit this condition:
response.css('div.col-md-4 a::attr(href)').extract()
My best guess is the following:
response.css('div.col-md-4 div.tab-title:contains("Homepage") a::attr(href)').extract()
Any insights are appreciated! Thank you in advance.
Note: I am using Scrapy.
How about this using XPath:
response.xpath('//div[#class="tab-title" and contains(., "Homepage")]/..//a/#href')
Find a div with class tab-title which contains Homepage inside, then step up to the parent and look for a child on any level.
EDIT:
Using CSS, you should be able to do it like this:
response.css('div.tab-title:contains("Homepage") ~ * a::attr(href)')

show images in disorder by the ng-repeat in angularjs

you can see part of my code:
<ul>
<li ng-repeat="commentItem in comments track by $index">
<div style="float: left; width: 15%;;">
<img width="100%" src="{{commentItem.headImage}}">
</div>
</li>
</ul>
<ion-infinite-scroll ng-if="comment.loadMore" on-infinite="loadMoreComments()">
</ion-infinite-scroll>
when the 'comments' contains less data ,all looks normal.But when there are lots of data in the array(maybe 100 or more),the images will be showed in disorder.For example, the image should be in the third "li" will be showed in the fourth "li".Could anyone tell me why,please!
PS. I use the ionic.bundle.js,but I dont know it will cause something wrong or not. And when the event of ion-infinite-scroll be tiggered,I will push the new data into the "comments" array.
Tracking by $index is not a good idea. Can you track by commentItem.id (or another unique identifier on the commentItem) instead? I'm not sure if that will solve the problem but looking at that code snippet, that's the first thing I would try.

Angular works in strange way

The following is the code of mine. In this I've used ng-click instead of ng-href for some reason.
I've used ng-click like ng-click="navigateUrl('link{{$index+1}}')". In the view, the value is showing correctly like navigateUrl('link2'). But when I receive it in the controller, I am getting 'link{{$index+1}}'.
Here My confusion is that was working code. After somedays, i got the issue like this. So I've reverted the code from ng-click to ng-href. I want to know where I've made mistake and what is the reason for this issue?
<li ng-repeat="item in commonObject.itmes" ng-click="commonObject.sideBarIsCollapsed=!commonObject.sideBarIsCollapsed">
<a class="cursorPointer" ng-href="#/link{{$index+1}}" title="{{item.name}}"
ng-if="item.isSelected && item.reportId!=3">
<i class="glyph-icon icon-linecons-tv"></i>
<span> {{item.name}}</span>
</a>
</li>

SlyRepeat and ngInclude asking for transclusion on

I need to display a potential huge treeview in my webapplication. During testing I found out that using the standard template rendering method of angular with ngRepeat and ngInclude are not performing enough (it takes around 5 seconds to show the info). Removing binding (because there is no use for it) gave no results.
After some googling I found a module called scalyr https://github.com/scalyr/angular This should really optimize the performance of rendering.
My code:
<script type="text/ng-template" id="tree_item_renderer.html">
{{data.name}}
<ul>
<li sly-repeat="data in data.childNodes " ng-include="'tree_item_renderer.html'"></li>
</ul>
</script>
<ul>
<li sly-repeat="data in vm.rows" ng-include="'tree_item_renderer.html'"></li>
</ul>
When running this code I get an exception
Error: [$compile:multidir] Multiple directives [slyRepeat, ngInclude] asking for transclusion on: <li sly-repeat="data in data.childNodes " ng-include="'tree_item_renderer.html'">
Is this fixable? Or is it impossible to run scalyr with ng-Include.
There is a problem with multiple transclusions on the same element, but there's an easy solution:
<li sly-repeat="data in data.childNodes ">
<div ng-include="'tree_item_renderer.html'"></div>
</li>
There is a module that offer multiple transclusions, but I've never played with it, so I'm not sure that it works.
When you figure out your tree, tell me if the sly-repeat is worth it, as I've got a huge tree to build as well.

Conditionally change img src based on model data

I want to represent model data as different images using Angular but having some trouble finding the "right" way to do it. The Angular API docs on expressions say that conditional expressions are not allowed...
Simplifying a lot, the model data is fetched via AJAX and shows you the status of each interface on a router. Something like:
$scope.interfaces = ["UP", "DOWN", "UP", "UP", "UP", "UP", "DOWN"]
So, in Angular, we can display the state of each interface with something like:
<ul>
<li ng-repeat=interface in interfaces>{{interface}}
</ul>
BUT - Instead of the values from the model, I'd like to show a suitable image. Something following this general idea.
<ul>
<li ng-repeat=interface in interfaces>
{{if interface=="UP"}}
<img src='green-checkmark.png'>
{{else}}
<img src='big-black-X.png'>
{{/if}}
</ul>
(I think Ember supports this type of construct)
Of course, I could modify the controller to return image URLs based on the actual model data but that seems to violate the separation of model and view, no?
This SO Posting suggested using a directive to change the bg-img source. But then we are back to putting URLs in the JS not the template...
All suggestions appreciated. Thanks.
please excuse any typos
Instead of src you need ng-src.
AngularJS views support binary operators
condition && true || false
So your img tag would look like this
<img ng-src="{{interface == 'UP' && 'green-checkmark.png' || 'big-black-X.png'}}"/>
Note : the quotes (ie 'green-checkmark.png') are important here. It won't work without quotes.
plunker here (open dev tools to see the produced HTML)
Another alternative (other than binary operators suggested by #jm-) is to use ng-switch:
<span ng-switch on="interface">
<img ng-switch-when="UP" src='green-checkmark.png'>
<img ng-switch-default src='big-black-X.png'>
</span>
ng-switch will likely be better/easier if you have more than two images.
Another way ..
<img ng-src="{{!video.playing ? 'img/icons/play-rounded-button-outline.svg' : 'img/icons/pause-thin-rounded-button.svg'}}" />
<ul>
<li ng-repeat=interface in interfaces>
<img src='green-checkmark.png' ng-show="interface=='UP'" />
<img src='big-black-X.png' ng-show="interface=='DOWN'" />
</li>
</ul>
For angular 4 I have used
<img [src]="data.pic ? data.pic : 'assets/images/no-image.png' " alt="Image" title="Image">
It works for me , I hope it may use to other's also for Angular 4-5. :)

Resources