Cypress - how to get child of a specific parent element - get

I am stuck by finding a specific button within my list of items... The button exists 3 times with exact same data-testid, but the parent is different. And I end with
error: cy.click() can only be called on a single element. Your subject contained 3 elements. Pass { multiple: true } if you want to serially click each element.
HTML:
<div data-testid="list-item">
<div>
<div>
<span data-testid="status1">
<button data-testid="details_button">click</button>
</div>
</div>
</div>
<div data-testid="list-item">
<div>
<div>
<span data-testid="status2">
<button data-testid="details_button">click</button>
</div>
</div>
</div>
How can I select the details_button of either status1 or status2?
My attempt was:
cy.get('[data-testid=status1]')
.get('[data-testid="details_button"]').click()
cy.get('[data-testid=status1]')
.parent().parent()
.get('[data-testid="details_button"]').click()

Your first attempt is almost correct, but use .find() for the second step
cy.get('[data-testid=status1]')
.find('[data-testid="details_button"]') // find works here (same as .within())
.click()
Works for this HTML
<div data-testid="list-item">
<div>
<div>
<span data-testid="status1">
<button data-testid="details_button">click</button>
<!-- span closing tag is missing -->
</div>
</div>
</div>
The reason that works is because the HTML posted is slightly invalid - the <span> has no closing tag.
Cypress thinks that the button is inside the span, so using .find() works.
However if that's a typo, you should change to your 2nd command using .parent() and also change .get() to .find()
cy.get('[data-testid=status1]')
.parent()
.find('[data-testid="details_button"]')
.click()
Works for this HTML
<div data-testid="list-item">
<div>
<div>
<span data-testid="status1"></span>
<!-- span is closed, button is outside span so use .parent() command -->
<button data-testid="details_button">click</button>
</div>
</div>
</div>

You can use the siblings() method is cypress.
cy.get('[data-testid=status1]').siblings('[data-testid="details_button]').click()
cy.get('[data-testid=status2]').siblings('[data-testid="details_button]').click()
You can also use a combination of parent() and within(), something like:
cy.get('span[data-testid=status1]')
.parent('div')
.within(() => {
cy.get('button[data-testid="details_button]').click()
})
cy.get('span[data-testid=status2]')
.parent('div')
.within(() => {
cy.get('button[data-testid="details_button]').click()
})

Related

Semantic UI: get current dropdown search input text

I'm trying to filter some results I will get from an api using Semantic UI's dropdown search component.
The issue is that I don't know how to get the text I'm typing in the input field
The dropdown search I have:
<div class="ui fluid search selection dropdown" id="user-dropdown">
<input id="user-dropdown-input" name="country" type="hidden">
<i class="dropdown icon"></i>
<div class="default text">Search...</div>
<div class="menu" id="user-dropdown-menu">
<div class="item" data-value="af">
<span class="description">123</span>
<span class="text">User123</span>
</div>
<div class="item" data-value="af">
<span class="description">123</span>
<span class="text">User123</span>
</div>
<div class="item" data-value="af">
<span class="description">123</span>
<span class="text">User123</span>
</div>
</div>
</div>
How dropdown is initialized:
$(document).ready(function () {
$('.ui.dropdown').dropdown({
clearable: true,
fullTextSearch: true
});
});
What I tried:
$('#user-dropdown').on('keyup', function () {
let input = $('#user-dropdown');
console.log('Val: ' + input.dropdown().val());
// also tried: $('#user-dropdown-input').val()
// $('#user-dropdown-input').html()
// $('#user-dropdown-input').text()
});
Basically what I want is if I type "abc" to print the value "abc" into the console, but I don't know how to get that value.
what worked for me was searching the input used for search that looks like:
<input class="search" autocomplete="off" tabindex="0">
and I added a type to this input
document.getElementsByClassName('search').type = 'text';
and then got the value by class on keyup
$('.search').keyup(function() {
console.log($(this).val());
});

Get text from span using cheerio and node.js

Hi I'm trying to the text inside the span, the one with "Text to get"
I'm getting the div with class="membership-limit-section capture-area" using cheerio and node.js, but I can't get the text from the span.
I have this function to get the div and I can see that it does have more elements inside, but I can«t get the text
url = "URLdata";
rp(url)
.then(function (html) {
var getHtml = $("div[class='membership-limit-section capture-area']", html);
console.log(getHtml);
})
.catch(function (err) {
console.log(err);
});
<body data-n-head>
<div id="_nuxt">
<div id="__layout">
<div class="app-wrapper purge-css-ignore">
<div class="main-container">
<section class="el-container">
<main
class="el-main auto-height-on-print capture-area"
id="components-root"
>
<div data-v-5cc60f9e>
<div data-v-5cc60f9e class="responsive-section">
<div
data-v-7ce2662e
data-v-5cc60f9e
class="membership-limit-section capture-area"
>
<div data-v-5cc60f9e class="dividends">
<div>
<div
data-v-593f497d
class="el-card capture-area is-always-shadow"
>
<h1 data-v-593f497d>Test</h1>
<div
role="alert"
class="el-alert el-alert--warning is-light"
data-v-593f497d
>
<div class="el-alert__content">
<span class="el-alert__title">Text to get</span>
<i
class="el-alert__closebtn el-icon-close"
style="display: none;"
></i>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
</section>
</div>
</div>
</div>
</div>
</body>
Can someone help on how to get the text from the span?
Thanks
The following selector will do for that specific response: .membership-limit-section.capture-area .el-alert__title
Then you can use .text() to obtain the text of the span.
var getHtml = $(
".membership-limit-section.capture-area .el-alert__title",
html
);
console.log(getHtml.text())
Update:
gurufocus.com/stock/KO/dividend I want the "Continuous dividend
increase since 1963" but I cannot get it. I'm able to parse info from
yahoo using cheerio, but not from this website
The content you want to scrape, is loaded on the client side using XHR. So you won't be able to parse it directly using request & cheerio since that part is not being returned, either you hit the endpoint returning that data directly, or you use puppeteer on the main site.
When scraping with requests and cheerio, always log the content and see if what you want to parse is present.
The following selector will do for that specific response: const a=$('div.membership-limit-section capture-area').innerText Then just use a variable it has text of span tag.

react pagination for sections

Im using NodeJS with React and I have a problem. I didnt find a npm module or a code that allowed me to create a pagination for a list of results.
I have a variable called "jobs", that contains a list of job ads.
In my render function I call:
{this.state.jobs.map(this.renderClass)}
that map every job with a function.
This function is renderClass, that contains the render of:
<section key={c.id} className="panel panel-featured-left panel-featured-primary">
<Link to={'/job/'+c.id}>
<div className="panel-body">
<div className="widget-summary">
<div className="widget-summary-col widget-summary-col-icon">
<div className="summary-icon">
<img src={image} className="img-responsive" />
</div>
</div>
<div className="widget-summary-col">
<div className="summary">
<h4 className="title">{c.company}</h4>
<div className="info">
<strong className="amount"></strong><br/>
<p><i className="fa fa-map-marker"></i> {c.location}</p>
<p><i className="fa fa-suitcase"></i> {c.position}</p>
</div>
</div>
<div className="summary-footer">
<a className="text-muted text-uppercase"><i className="fa fa-calendar"></i> {day}/{month}/{year}</a>
</div>
</div>
</div>
</div>
</Link>
</section>
In this way I have a huge list of jobs, but I would a paging.
How can I do this?
Thanks
I would save the page in a state,
and do something like that (say each page has 10 jobs ) -
{this.state.jobs.slice(this.state.page * 10, this.state.page * 10 + 10)
.map(this.renderClass)}
I suggest your need to build a component for handling pagination. Some thing like that:
<Pagiantion
listLenght = {111}
selectedPage = {1}
itemPerPage = {10}
....
/>
I found the best component handling it, react-pagination-custom.
It allow you custom everything (number buttons, wrap container, spread,..). Its document is well, demo is also clear.

unable to select react id | watir

Hi Fairly new to watir and came across this problem. How can I select the button in the following snippet of code
<div id="side bar" class="sidebar">
<div class="inner active" data-reactid=".1">
<a class="back side bar" data-reactid=".1.0" href="#overview">
<h2 data-reactid=".1.1">
<div class="price clearfix" data-reactid=".1.2">
<div class="values type-current-value" data-reactid=".1.3">
<div class="values date-current-value" data-reactid=".1.4">
<div class="values duration-current-value" data-reactid=".1.5">
<div class="values passengers-current-value" data-reactid=".1.6">
<div class="values yacht-current-value" data-reactid=".1.7">
<div class="values flight-current-value" data-reactid=".1.8">
<div class="share-quote" data-reactid=".1.9">
<a class="share-quote cta-button cta-button-blue = share-quote-processed" data-reactid=".1.9.0" data-modal-url="/share-quote" href="#">Share this quote</a>
</div>
I am trying the following which produces a no method error
b.links(:xpath => '//div[#class="share-quote"]/a').to_a.click
The code is trying to click an array of links, rather than an individual link. That is why you get an undefined method error.
You need to click a specific link within the collection. For example:
# Click the first link
b.links(:xpath => '//div[#class="share-quote"]/a').first.click
# Click the last link
b.links(:xpath => '//div[#class="share-quote"]/a').first.click
# Click the nth link
b.links(:xpath => '//div[#class="share-quote"]/a')[n].click
Assuming there is only one of these links on the page, it would be more Watir-like to do:
b.div(class: 'share-quote').link.click

nested template rendering in backbone.js

I have a template like
script type: "text/template", id: "list-template", '''
<div class="display">
<div id="list-name"><%= name %></div>
<span class="list-destroy"></span>
</div>
<div>
<ul id="ul-cards">
</ul>
</div>
<div class="edit">
<input class="list-input" type="text" value="<%= name %>" />
<input id="btnEdit" type="button" value="Save" class="primary wide js-add-list" />
<input id="hdnListId" type="hidden" value="<%= listId%>" />
</div>
<form class="add-list-card js-add-list-card clearfix">
<textarea placeholder="Add card" class="new-card"></textarea>
<input type="button" value="Add" class="primary js-add-card">
<a class="app-icon close-icon dark-hover cancel js-cancel-add-card" href="#" id="closeCard"></a>
</form>
'''
in this template i have <ul id="ul-cards"> element in which i want to render another template which display list inside this ul.
this template is :
script type: "text/template", id: "card-template", '''
<div>
<span class="card-name"><%= name %></span>
</div>
'''
is it possible or i have to do it in another way?
please help me if anyone have idea.
thanks in advace.
it is worked but still i have one problem in data display in
<ul id="ul-cards"> there sholud be 2 as per records in my database but it will display only 1 . data fetch properly but display only last data.
There are two ways to do this: the DOM way and the template way.
The DOM way involves adding your views using DOM methods: you have your ListView and your CardView; the ListView invokes individual CardViews that fill in the ListView's element.
The template way requires that you remember this: backbone's views are policy frameworks, not policy templates. Render doesn't have to render into the DOM. You can use render() to return a string, for example. If your event manager is on the ListView object only (possible; I've done this), then you can have ListView invoke "the resulting array of an array of CardView renders" and insert that directly into ListView's template. This is actually faster, as you only require the browser to analyze the entire ListView HTML blob once, when it's inserted into the innerHTML of the parent DOM object.

Resources