How to chain selectors in order to get element inside with webdriverio - webdriver-io

I have a page with list of products on it.
This is how HTML DOM looks like for one product item:
<div class="module card listing-search-card js-product-card " id="product-entry-123" data-product-id="123" data-toggle-status="open" data-out-of-stock="" data-toggle-isbundle="false" data-load-prices-async="false">
<div class="product-entry__wrapper">
<div class="card__header">
<div class="promotion">
<div class="product-entry__right promotion-card__body on-promotion--banner-offer">
</div>
<a href="/Products/p/123" tabindex="-1">
<picture>
<img class="card__image mobile-img lazyload" src="/medias/image-mobile">
<img class="card__image desktop-img lazyloaded" src="/medias/image-desktop">
</picture>
</a>
</div>
</div>
<div class="product-entry__body-actions-wrapper">
<div class="product-entry__body card__body">
<h3 class="card__title">
Schweppes
</h3>
<div class="product-entry__summary card__description-wrapper">
<div class="product-entry__summary__list">
<div class="card__detail-wrapper">
<div class="product-entry__summary__item card__description-product-detail">
33 x 24</div>
<div class="product-entry__summary__item card__description-product-code">
<span class="product-entry__code">
123</span>
</div>
</div>
<div class="container-type">
box</div>
</div>
</div>
</div>
<div class="cta-container">
<div class="card__amount-wrapper ">
<div class="card__amount">
61,83 € <span class="base-unit">HT/CHACUN</span>
<p class="sales-unit-price is-price">
<span>soit</span> 10,00 €
</span></span></p>
</div>
</div>
<div class="add-to-cart__footer add-to-cart__action">
<div class="success-overlay">Add to cart</div>
<div class="add-to-cart__action--active">
<div class="form-quantity__wrapper quantity-action quantity-action__wrapper"
data-form-quantity-id="123">
<div class="form-quantity ">
<button class="form-quantity__decrease quantity-action__decr icon-Minus disabled" type="button"
tabindex="-1" aria-label="decrement" data-form-quantity-decrement="">
</button>
<input id="product-123" class="form-quantity__input form-control quantity-action__value js-
quantity-input-typing" name="product-123" type="text" value="1" maxlength="4" data-price-
single="10.00" data-price-currency="€" data-parsley-range="[1,9999]" data-form-quantity-times="1"
data-parsley-multiplerange="1" data-parsley-type="integer" data-parsley-validation-threshold="1"
required="">
<button class="form-quantity__increase quantity-action__incr icon-Add-to-list" type="button"
tabindex="-1" aria-label="increment" data-form-quantity-increment="">
</button>
</div>
<span class="form-quantity__update" data-form-quantity-success=""></span>
</div>
<div class="add-to-cart__total">
<button class="button button--primary js-addToCart" role="button" title="Add
to cart" data-product-id-ref="123" data-modal-trigger="" data-modal-target="#add-to-cart-modal" data-
modal-before-trigger="addToCart" data-component-id="product list" tabindex="-1">
<div class="button__text">
<span class="button__text-add js-added-price">Add</span>
<span class="button__text-to-cart js-added-price">to cart</span>
</div>
<span class="button__text js-added-price mobile-only">Add</span>
</button>
</div>
</div>
</div>
<div class="add-to-template">
<button class="add-to-template--button button js-addToNewTemplate" type="button" data-modal-
trigger="" data-modal-target="#add-to-template-modal" data-modal-before-
trigger="openAddToTemplateModal" data-product-code="123">
<span>Add to list</span>
</button>
</div>
</div>
</div>
</div>
I am calling this function:
isSortedAlphabeticallyAscending($$('div.js-product-card'));
And the function implementation is:
isSortedAlphabeticallyAscending(list) {
for (let i = 0; i < (list.length - 1); i++) {
let outOfStockCurrent = list[i].getAttribute('data-out-of-stock');
let outOfStockNext = list[i + 1].getAttribute('data-out-of-stock');
let idCurrent = list[i].getAttribute('id');
let idNext = list[i + 1].getAttribute('id');
console.log("outOfStockCurrent " + outOfStockCurrent + " " + idCurrent);
console.log("outOfStockNext " + outOfStockNext + " " + idNext);
let productIdCurrent = idCurrent.split('-').pop();
let productIdNext = idNext.split('-').pop();
let currentText = list[i].$('a[href*="' + productIdCurrent + '"]').getText();
let nextText = list[i+1].$('a[href*="'+ productIdNext + '"]').getText();
console.log("currentText " + currentText);
console.log("nextText " + nextText);
if(outOfStockCurrent === "true" || outOfStockNext === "true") continue;
if (currentText > nextText) return false;
}
return true;
}
I ignore out of stock products since they are always at the bottom of the page.
But the list[i].$('a[href*="' + productIdCurrent + '"]').getText() is always returning empty text.
I would like it to get "Schweppes" text, i.e. product name.
Is there a way to chain somehow differently part with .$a[href ...] to get the text from the <a> tag inside the <div> element of the list of products using webdriverio 5?
Thanks!

The above selector list[i].$('a[href*="' + productIdCurrent + '"]').getText() targeted 2 elements.
What I needed to go one div further and find it there:
list[i].$('div.product-entry__body-actions-wrapper').$('a[href*="' + productIdCurrent + '"]').getText()
And voila, text appeared :)
Hope it will help someone with the similar issue :D

Related

How to unshift/push image to list in vue

I have list of comments and I could append username of user, content and date to the list put when I tried to append the user image it shows null and I tried to append image from internet and also it shows null
<ul v-for="comment in comments" :key="comment">
<li class="comment-object">
<div class="image-container">
<img class="profile-pic" :src="'http://192.168.63.200:8000' + comment.author_image" v-on:change="currentUserImage" alt="profile picture"/>
</div>
<div class="comment-text">
<h2 class="username" style="color: #C2C3C4">{{comment.author}} <span class="muted">· {{comment.publish}}</span></h2>
<p class="comment">{{comment.content}} </p>
</div>
</li>
</ul>
await axios.post('/video/api/video/comments/create/', commentData)
.then(response => {
this.comments.unshift({ content: this.commentContent, author: this.$store.state.user.username, author_image: 'https://image.shutterstock.com/image-photo/surreal-image-african-elephant-wearing-260nw-1365289022.jpg', likes:0, publish:'now'})
})
The problem was in <img class="profile-pic" :src="'http://192.168.63.200:8000' + comment.author_image" v-on:change="currentUserImage" alt="profile picture"/>
I just removed the url http://192.168.63.200:8000 and it worked

VUE's focus() method return a console error? How to use it correctly?

I'm trying to focus on several elements of my form but the first one, despite being applied, returns an error by console.
This is my template:
<div class="container">
<div class="col-xs-12">
<div class="row">
<h1 class="animal-title">Your selection is : </h1>
</div>
<div class="wrapper">
<form class="first-form" #submit.prevent="onSubmit">
<div class="image-wrapper">
<div class="sel-image">
<div v-on:click="imageSelected = true" v-for="item in items" v-bind:key="item.id">
<label>
<input
type="radio"
name="selectedItem"
ref="item"
:value="item.id"
v-model="itemFormInfo.selectedItem"
#change="onChangeItem($event)"
/>
<img v-if="item.id === 1" src="../../assets/1.png" />
<img v-if="item.id === 2" src="../../assets/2.png" />
<img v-if="item.id === 3" src="../../assets/3.png" />
</label>
<p class="cie-animal-subtitle">{{item.name}}</p>
</div>
</div>
</div>
<div class="form-select">
<div v-show="filteredStock && (imageSelected || itemFormInfo.selectedItem) > 0">
<h1 v-if="this.itemName === 'Phone' || this.itemName === 'Tablet'" for="selectedItem" ref="itemVisible">
Select the brand of your <span>{{this.itemName}}</span> :
</h1>
<h1 v-if="this.itemName === 'PC'" for="selectedBreed" ref="itemVisible">
Select the type of your <span>{{this.itemName}}</span> :
</h1>
<select
ref="brand"
class="form-control"
id="selectedBrand"
v-model="itemFormInfo.selectedBrand"
#change="onChangeBrand($event)">
<option v-for="brand in filteredBrand" v-bind:key="brand.name">{{ brand.name }}</option>
</select>
<div v-show="this.isBrandSelected">
<h1>What are you going to use your
<span>{{itemName}}</span> for ?
</h1>
<input
type="text"
id="componentName"
ref="componentName"
class="form-control fields"
style="text-transform: capitalize"
v-model="itemFormInfo.component"
#keypress="formChange($event)"
/>
<div class="loader-spinner" v-if="loading">
<app-loader/>
</div>
</div>
</div>
</div>
<div class="service-options" v-show="isComponentCompleted">
<div class="from-group">
<h1>
Here are the options for your <span>{{this.itemFormInfo.component}}</span> :
</h1>
<div class="services">
<div class="column-service" v-for="option in options" v-bind:key="option.name">
<div class="service-name">{{option.name}}</div>
<div class="service-price">{{option.price.toString().replace(".", ",")}} </div>
</div>
</div>
and here my first method
onChangeItem(event) {
let item = event.target._value;
this.itemName = this.getItemName(item);
if (this.isItemSelected = true) {
this.isItemSelected = false;
this.isComponentCompleted = false;
this.isLoaderFinished = false;
this.itemFormInfo.name = ""
}
this.$refs.item.focus();
},
in this function that I control my first input, the focus is working but it returns me by console the following error:
"this.$refs.item.focus is not a function at VueComponent.onChangeItem"
I have seen some references to similar cases where they involved the reference in a setTimeout or used the this.$nextTick(() => method but it didn't work in my case.
What am I doing wrong?
How can I focus on the next select with ref brand, once I have chosen the value of the first input?
Thank you all for your time and help in advance
How can I focus on the next select with ref brand, once I have chosen the value of the first input?
You want to put focus on brand but your onChangeItem handler is calling this.$refs.item.focus() (trying to focus item). Seems strange to me...
Reason for the error is you are using ref inside v-for.
Docs: When used on elements/components with v-for, the registered reference will be an Array containing DOM nodes or component instances
So the correct way for accessing item ref will be this.$refs.item[index].focus().
Just be aware that right now v-for refs do not guarantee the same order as your source Array - you can find some workarounds in the issue discussion...

Vue.js how to use radio buttons inside v-for loop

I'm trying to use radio buttons, so that users can choose one of the photos as their profile photo:
<ul v-for="p in myPhotos">
<li>
<div>
<div>
<div>
photo id: {{p.imgId}}
</div>
<input type="radio" v-model="profileImg" value="p.imgId"> Choose as profile image
</div>
<div><img v-bind:src="BASE_URL +'/uploads/' + userId + '/'+ p.imgId" /> </div>
</div>
</li>
</ul>
The values are otained like this:
created () {
axios.get(this.BASE_URL + '/profile/g/myphotos/', this.jwt)
.then( res => {
this.myPhotos = res.data.photos;
this.showUploadedPhoto = true;
this.profileImg = res.data.profileImg
})
.catch( error => {
console.log(error);
})
},
When an photo is chosen, the profileImg variable should be set to that photo's imgId.
The problem is how to let users to choose only one photo as profile image inside this v-for loop?
Update: a photo my myPhotos object that I'm iterate over:
By providing name you can treat it as one element
var app = new Vue({
el:"#app",
data:{
images:[{imgId:1},{imgId:2},{imgId:3}],
profileImg:2
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div>
<div v-for="image in images">
<input type="radio" v-model="profileImg" name="profileImg" :value="image.imgId"> Choose as profile image
</div>
You have selected : {{profileImg}}
</div>
</div>
How about setting name attribute for the input field
<ul v-for="p in myPhotos">
<li>
<div>
<div>
<div>
photo id: {{p.imgId}}
</div>
<input type="radio" name="user_profile_photo" v-model="profileImg" :value="p.imgId"> Choose as profile image
</div>
<div><img v-bind:src="BASE_URL +'/uploads/' + userId + '/'+ p.imgId" /> </div>
</div>
</li>
</ul>

Slow DOM Change with v-show

I've been troubleshooting an issue where, inside of a nested v-for loop, a simple v-show directive is taking up toward 4 seconds to actually apply the display: none; attribute in the DOM.
The basic layout is this. I've changed the actual naming to be all about cars; because why not!
I do apologize for the wall of code, but I felt it was relevant to include a basic jist of the component structure.
<div class="vehicle-history" v-if="fetchComplete && !fetchError">
<h3 class="header-bold">History</h3>
<div class="history-container" v-for="car in vehicles.cars" :key="car.id">
<div class="vehicle-header">
<div class="toyota" v-if="car.model == 'toyota'">
<span class="model-id">#{{ car.type }}_#{{ car.id }}</span> - #{{ car.title }}
</div>
<div class="audi" v-if="car.model == 'audi'">
<span class="model-id">#{{ car.type }}_#{{ car.id }}</span> - #{{ car.title }}
</div>
<div class="benz" v-if="car.model == 'benz'">
<span class="model-id">#{{ car.type }}_#{{ car.id }}</span> - #{{ car.title }}
</div>
<div class="rolls" v-if="car.model == 'rolls'">
<span class="model-id">#{{ car.type }}_#{{ car.id }}</span> - #{{ car.title }}
</div><br />
<small v-for="color in car.colors">#{{ color.name }} </small>
</div>
<div class="vehicle-body">
<div class="description">#{{ car.description }}</div>
<div class="review-container" v-if="car.reviews.length > 5">
<div class="review" v-for="n in (0, 4)" :key="car.reviews[n].id">
<strong>#{{ car.reviews[n].rating }}</strong> - #{{ car.reviews[n].content }}<br />
<small>#{{ car.reviews[n].created_at.date }} #{{ car.reviews[n].created_at.timezone }}</small>
<span v-show="n == 4 && !car.displayFull"><br />
<button type="button"
class="btn btn-link"
data-toggle="collapse"
v-on:click="car.displayFull = true"
v-bind:data-target="'#expanded-reviews-' + car.id">More details
</button>
</span>
</div>
<div class="collapse" v-bind:id="'expanded-reviews-' + car.id">
<div class="review" v-for="n in (4, car.reviews.length-1)" :key="car.reviews[n].id">
<strong>#{{ car.reviews[n].rating }}</strong> - #{{ car.reviews[n].content }}<br />
<small>#{{ car.reviews[n].created_at.date }} #{{ car.reviews[n].created_at.timezone }}</small>
<span v-if="n == car.reviews.length-1"><br />
<button type="button"
class="btn btn-link"
data-toggle="collapse"
v-on:click="car.displayFull = false"
v-bind:data-target="'#expanded-reviews-' + car.id">Less details
</button>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
What I've tried
Adding the :key to the relevant loops
Moving the v-show attribute from the button (where it was originally at) to the parent span.
Wrapping it in <keep-alive> (which didn't work at all, it broke visibility as a whole)
Swapping v-show for v-if and vice-versa
The expected output
What I'm trying to accomplish is to make sure the button for "More details" hides away when the accordion gets expanded (that is, when the "More details" button is initially clicked) and re-appears if the "Less details" button is clicked.
The actual output
Whilst it does the above, there's a delay of between 2-5 seconds from clicking the button, to it getting the display: none; attribute applied in the DOM. The change to the Vue variable however appears instant.
Do you have any clue why this may be, and if there's a good workaround for this? Thank you, as always!
UPDATE
Revised code example below based on a number of suggestions. This is a flat out copy of existing code, so no changes to naming this time around.
<div class="incident-history text-center col-xs-12 padding-bottom" v-if="fetchComplete && !fetchError">
<h3 class="heading3 black-text">Incident History</h3>
<div class="incident-container" v-for="incident in responseData.incident.resolved" :key="incident.id">
<div class="incident-header">
<div :class="'title-' + incident.classification">
<span class="incident-id">#{{ incident.type }}_#{{ incident.id }}</span> - #{{ incident.title }}
</div><br />
<small v-for="monitor in incident.monitors">#{{ monitor.name }} </small>
</div>
<div class="incident-body">
<div class="description">#{{ incident.content }}</div>
<div class="update" v-for="(comment, index) in incident.comments.slice(0,5)">
<strong>#{{ comment.type }}</strong> - #{{ comment.content }}<br />
<small>#{{ comment.created_at.date }} #{{ comment.created_at.timezone }}</small>
</div>
<div class="collapse"
v-bind:id="'expanded-update-' + incident.id"
v-if="incident.comments.length > 4">
<div class="update" v-for="(comment, index) in incident.comments.slice(5)">
<strong>#{{ comment.type }}</strong> - #{{ comment.content }}<br />
<small>#{{ comment.created_at.date }} #{{ comment.created_at.timezone }}</small>
</div>
</div>
<button type="button"
class="btn btn-link"
data-toggle="collapse"
v-show="incident.comments.length > 4 && !incident.displayFull"
v-on:click="incident.displayFull = !incident.displayFull"
v-bind:data-target="'#expanded-update-' + incident.id">Show more
</button>
<button type="button"
class="btn btn-link"
data-toggle="collapse"
v-show="incident.comments.length > 4 && incident.displayFull"
v-on:click="incident.displayFull = !incident.displayFull"
v-bind:data-target="'#expanded-update-' + incident.id">Show less
</button>
</div>
</div>
</div>
I will note that the above code block is run inside of yet another for-loop. The basic topology is this (lengths may vary)
responseData: Object
incident: Object
active: Array[4]
0: Object
1: Object
Property: SomeValue
Property: SomeValue
Property: SomeValue
Property: SomeValue
Property: SomeValue
Comments: Array[3]
0: Object
1: Object
Property: SomeValue
Property: SomeValue
2: Object
2: Object
3: Object
Alternative Solution
I've come up with a working, and likely better alternative for the changing of "Read more" to "Read less" and vice versa.
button.full-details[aria-expanded="true"]:after {
content: 'Show less';
}
button.full-details[aria-expanded="false"]:after {
content: 'Show more';
}
This works fine, and just needs adding a few lines of CSS as well as a class to the button (or targeting the Bootstrap button class, but that's not great for many reasons).
That said, I'm going to leave this one open for a little bit to hopefully gain an understanding into why the issue arose with Vue in the first place.
It is surprising to hear 2-5 secs lag in display, but then there's quite a bit going on in that template. Hard to tell if suggested changes will impact the page visuals, without a test system.
The button(s) seems most problematic, creates one per review but only needs one per car, has to evaluate v-show or v-if for all of them.
Have one button outside the reviews loop,
<button class="btn btn-link" type="button"
data-toggle="collapse" :data-target="'#expanded-reviews-' + car.id"
#click="car.displayFull = !car.displayFull">
{{ buttonPrompt(car.displayFull) }}
</button>
I'd also consider creating a car child component, even a review grandchild component, as reasoning about the layout becomes difficult when it's that busy.
The final thing is so obvious, I'm thinking it must be an artifact of the domain renaming.
This
<div class="toyota" v-if="car.model == 'toyota'">
<span class="model-id">#{{ car.type }}_#{{ car.id }}</span> - #{{ car.title }}
</div>
<div class="audi" v-if="car.model == 'audi'">
<span class="model-id">#{{ car.type }}_#{{ car.id }}</span> - #{{ car.title }}
</div>
<div class="benz" v-if="car.model == 'benz'">
<span class="model-id">#{{ car.type }}_#{{ car.id }}</span> - #{{ car.title }}
</div>
<div class="rolls" v-if="car.model == 'rolls'">
<span class="model-id">#{{ car.type }}_#{{ car.id }}</span> - #{{ car.title }}
</div>
could become this
<div :class="car.model">
<span class="model-id">{{ car.type }}_{{ car.id }}</span> - {{ car.title }}
</div>
Also, what is this? #{{?
Edit after comment - on the question of how many buttons are created
It sounds like you are expecting only one or two buttons to be rendered? Here's a test.
From a spec for Cars.vue created with your template,
Test data has 6 reviews,
<script>
export default {
data () {
return {
fetchComplete: true,
fetchError: false,
cars: [
{
model: 'toyota',
type: 'hatch',
id: 1,
title: 'corolla',
description: 'grey corolla',
colors: [{name: 'grey'}, {name: 'grey'}, {name: 'grey'}],
reviews: [
{rating: 2, content: 'its grey', created_at: {date: ''}},
{rating: 2, content: 'its grey', created_at: {date: ''}},
{rating: 2, content: 'its grey', created_at: {date: ''}},
{rating: 2, content: 'its grey', created_at: {date: ''}},
{rating: 2, content: 'its grey', created_at: {date: ''}},
{rating: 2, content: 'its grey', created_at: {date: ''}},
]
}
]
}
},
The test,
it('count the buttons', () => {
const buttons = wrapper.element.querySelectorAll('button');
console.log(buttons)
})
Results,
LOG LOG: Object{
0: <button type="button" data-toggle="collapse" data-target="#expanded-reviews-1" class="btn btn-link">More details</button>,
1: <button type="button" data-toggle="collapse" data-target="#expanded-reviews-1" class="btn btn-link">More details</button>,
2: <button type="button" data-toggle="collapse" data-target="#expanded-reviews-1" class="btn btn-link">More details</button>,
3: <button type="button" data-toggle="collapse" data-target="#expanded-reviews-1" class="btn btn-link">More details</button>,
4: <button type="button" data-toggle="collapse" data-target="#expanded-reviews-1" class="btn btn-link">Less details</button>,
length: 5}
Then, there's the question of whether the change detection cycle is smart enough not to re-evaluate button creation each cycle. I'll see if we can test that too.
Placement of v-if
It just occurred to me, this
<button class="btn btn-link" ... >
<span v-if="n === car.reviews.length-1">Less details</span>
</button>
might be better as this
<button class="btn btn-link" ... v-if="n === car.reviews.length-1">
Less details
</button>
Missing first review
The v-for="n in (0, 4)" loop seems to miss out the first review. If I set the ratings to be sequential numbers, the first is not displayed.
<div class="review" v-for="n in (0, 4)">
<strong>#{{ car.reviews[n].rating }}</strong> - #{{ car.reviews[n].content }}
Try
<div class="review" v-for="(review,n) of car.reviews.slice(0,5)" :key="review.id">
<strong>#{{ review.rating }}</strong> - #{{ review.content }}
...
<div class="review" v-for="(review,n) of car.reviews.slice(5)">
(keeping n for button v-if expression).

find values in code using selenium

I need to print names of friends list of facebook account which are in the code.I am using java, webdriver, eclipse. so how can i do it..?
My code is:
hc_location=friends_tab">
<div class="clearfix _42ef">
<div class="_6a rfloat _ohf">
<div class="uiProfileBlockContent">
<div class="_6a">
<div class="_6a _6b" style="height:100px"/>
<div class="_6a _6b">
<div class="fsl fwb fcb">
<a data-hovercard="/ajax/hovercard/user.php?id=100004354923588&extragetparams=%7B%22hc_location%22%3A%22friends_tab%22%7D" data-gt="{"engagement":{"eng_type":"1","eng_src":"2","eng_tid":"100004354923588","eng_data":[]},"coeff2_registry_key":"0406","coeff2_info":"AatFZB3bSKV1-v1-TR2ok-dPAbN9rzl_3kU0pGsa25fiWaVHx5-bjHLWKDd3viMwgv1yaRLvlMdX3-X03tbhtjEZ","coeff2_action":"1","coeff2_pv_signature":"738277089"}" href="https://www.facebook.com/sivaramakrishna.churukuri?fref=pb&hc_location=friends_tab">Sivaramakrishna Churukuri</a>
</div>
<a class="uiLinkSubtle" data-gt="{"coeff2_registry_key":"0406","coeff2_info":"AauP9VE6r6RJg9RklXss8Ij7rBBpi8gQXqOJbBK3dhvJV9-qk6TEr1oJklIPahLAfMkkWVB_SIlPbQ6vlwDJIe13","coeff2_action":"13","coeff2_pv_signature":"738277089"}" href="https://www.facebook.com/sivaramakrishna.churukuri/friends">103 friends</a>
</div>
</div>
</div>
</div>
</div>
</li>
<li class="_698">
<div class="clearfix _5qo4">
<a class="_5q6s _8o _8t lfloat _ohe" data-hovercard="/ajax/hovercard/user.php?id=100003212947042&extragetparams=%7B%22hc_location%22%3A%22friends_tab%22%7D" aria-hidden="true" tabindex="-1" href="https://www.facebook.com/kamesh.peri.5?fref=pb&hc_location=friends_tab">
<div class="clearfix _42ef">
<div class="_6a rfloat _ohf">
<div class="uiProfileBlockContent">
<div class="_6a">
<div class="_6a _6b" style="height:100px"/>
<div class="_6a _6b">
<div class="fsl fwb fcb">
<a data-hovercard="/ajax/hovercard/user.php?id=100003212947042&extragetparams=%7B%22hc_location%22%3A%22friends_tab%22%7D" data-gt="{"engagement":{"eng_type":"1","eng_src":"2","eng_tid":"100003212947042","eng_data":[]},"coeff2_registry_key":"0406","coeff2_info":"AauBaMRFF-E1ITEW9Rva9NO6xU67IbSuJZEgYIzHEB4CVZ_e6MM2fHCqF75opZvYnSlnHSOqYQ3EaZucFsMq6WMd","coeff2_action":"1","coeff2_pv_signature":"738277089"}" href="https://www.facebook.com/kamesh.peri.5?fref=pb&hc_location=friends_tab">Kamesh Peri</a>
</div>
<a class="uiLinkSubtle" data-gt="{"coeff2_registry_key":"0406","coeff2_info":"Aat-c_R0rmMkazYv1tQfMWB254d055vp_28IHeIbPNodi5AgjkwSKK0gxoikjPCHdstPnIZgBGM4DLQexsa3ctZ5","coeff2_action":"13","coeff2_pv_signature":"738277089"}" href="https://www.facebook.com/kamesh.peri.5/friends">374 friends</a>
</div>
</div>
</div>
</div>
</div>
</li>
<li class="_698">
<div class="clearfix _5qo4">
<a class="_5q6s _8o _8t lfloat _ohe" data-hovercard="/ajax/hovercard/user.php?id=678773097&extragetparams=%7B%22hc_location%22%3A%22friends_tab%22%7D" aria-hidden="true" tabindex="-1" href="https://www.facebook.com/rchalasani?fref=pb&hc_location=friends_tab">
<div class="clearfix _42ef">
<div class="_6a rfloat _ohf">
<div class="uiProfileBlockContent">
<div class="_6a">
<div class="_6a _6b" style="height:100px"/>
<div class="_6a _6b">
<div class="fsl fwb fcb">
<a data-hovercard="/ajax/hovercard/user.php?id=678773097&extragetparams=%7B%22hc_location%22%3A%22friends_tab%22%7D" data-gt="{"engagement":{"eng_type":"1","eng_src":"2","eng_tid":"678773097","eng_data":[]},"coeff2_registry_key":"0406","coeff2_info":"AasX8OsfTavfyAhEpE-iOv9PuaD2vgAhBs9ByrQ72VN1TWGanfz8Cc6UlLt7hsMf-Js","coeff2_action":"1","coeff2_pv_signature":"738277089"}" href="https://www.facebook.com/rchalasani?fref=pb&hc_location=friends_tab">Rama Chalasani</a>
</div>
<a class="uiLinkSubtle" role="button" rel="dialog" href="/browse/mutual_friends/?uid=678773097" ajaxify="/ajax/browser/dialog/mutual_friends/?uid=678773097" data-tooltip-uri="/ajax/mutual_friends/tooltip.php?friend_id=678773097" data-hover="tooltip">24 mutual friends</a>
I need to print Sivaramakrishna Churukuri, Kamesh Peri, Rama Chalasani which are in
<a></a>
tags
Thanks in advance.
I have tried this
driver.findElement(By.id("email")).sendKeys("smallfishhh4#gmail.com");
driver.findElement(By.id("pass")).clear();
driver.findElement(By.id("pass")).sendKeys("password");
// driver.findElement(By.id("u_0_n")).click();
driver.findElement(By.xpath("//label[#id='loginbutton']/input")).click();
driver.findElement(By.className("headerTinymanName")).click();
driver.findElement(By.xpath("//a[#data-medley-id='pagelet_timeline_medley_friends']")).click();
// List<WebElement> ele = driver.findElement(By.className("fsl fwb fcb"));
List<WebElement> allNames = driver.findElements(By.xpath("//div[#class='fsl fwb fcb']/a"));
//List<WebElement> allNames = driver.findElements(By.xpath("//div[#class='uiProfileBlockContent']/a"));
int num = driver.findElements(By.xpath("//ul")).size();
System.out.println(num);
System.out.println(allNames.size());
for(int j=0; j<num; j++){
for(int i=0;i<allNames.size();i++){
System.out.println(allNames.get(i).getText());
names = names+allNames.get(i).getText();
}
}
Get friend list using Selenium is web scraping and you should not do it, its illegal. Instead use the graph api with Java to achieve your goal. Below is one example. Another option you can use is RestFB(http://restfb.com/legacy-rest-api.html)
public void getIds(){
Session session = Session.getActiveSession();
String query = "select uid from user where uid in (select uid2 from friend where uid1 = me())";
Bundle params = new Bundle();
params.putString("q", query);
Request request = new Request(session, "/me/friends", params, HttpMethod.GET, new Request.Callback() {
#Override
public void onCompleted(Response response) {
Log.d("Id's :", "Response = "+response);
}
});
Request.executeBatchAsync(request);
}