Reputation: 509
friends! Few days ago I started my automation tests studying with Cypress. I have problems with getting element.
As for example I provide this HTML layout:
<div class="class_0">
<div class="class_1"></div>
<div class="class_2">
<div class="label_0">
<div class="label_1">Some text 1</div>
</div>
</div>
<div class="class_3">
<div class="tooltip_0"></div>
<div class="tooltip_1">
<form>
<button>Button</button>
</form>
</div>
<div class="tooltip_2"></div>
</div>
</div>
<div class="class_0">
<div class="class_1"></div>
<div class="class_2">
<div class="label_0">
<div class="label_1">Some text 2</div>
</div>
</div>
<div class="class_3">
<div class="tooltip_0"></div>
<div class="tooltip_1">
<form>
<button>Button</button>
</form>
</div>
<div class="tooltip_2"></div>
</div>
</div>
I want to click on button, but it's possible to find only <div class="label_1">Some text 1</div>
. I using this code:
cy.get('.label_1').contains('Some text 1').parents().find('button').click()
or this:
cy.get('.label_1').contains('Some text 1').parent(). ... .parent().find('button').click()
But I have my own solution, but it's problem to get count of this: <div class="class_0">
block.
Upvotes: 0
Views: 1130
Reputation: 48610
You can iteratively search for a parent with a button child. If a button is eventually found, click it.
Here is a recursive function to locate the parent with a button child.
function findCousin(node, childSelector) {
while (node != null & node.length > 0 && node.find(childSelector).length < 1) {
node = node.parent();
}
return node ? node.find(childSelector) : null;
}
Edit: So, it looks like Cypress uses jQuery behind the scenes. I created a simple shim to emulate your existing functionality wihout altering it.
// *** IGNORE: BEGIN SHIM ***
$.fn.findByContentText = function(text) {
return this.contents().filter((i, c) => $(c).text().trim() == text.trim());
};
class CyElement {
constructor(selector) { this.ref = $(selector); }
contains(text) { return this.ref.findByContentText(text); }
parent() { return new CyElement(this.ref.parent()); }
find(selector) { return new CyElement($(this.ref.find())); }
click() { this.ref.trigger('click'); }
}
const cy = {};
cy.get = (selector) => new CyElement(selector);
// *** IGNORE: END SHIM ***
let target, button;
target = cy.get('.label_1').contains('Some text 1');
button = findCousin(target, 'button');
if (button != null) {
button.click();
}
target = cy.get('.label_1').contains('Some text 2');
button = findCousin(target, 'button');
if (button != null) {
button.click();
}
function findCousin(node, childSelector) {
while (node != null & node.length > 0 && node.find(childSelector).length < 1) {
node = node.parent();
}
return node ? node.find(childSelector) : null;
}
function handleClickEvent(button) {
console.log(`Clicked on ${button.textContent}`);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="class_0">
<div class="class_1"></div>
<div class="class_2">
<div class="label_0">
<div class="label_1">Some text 1</div>
</div>
</div>
<div class="class_3">
<div class="tooltip_0"></div>
<div class="tooltip_1">
<form>
<button onclick="handleClickEvent(this); return false;">Button 1</button>
</form>
</div>
<div class="tooltip_2"></div>
</div>
</div>
<div class="class_0">
<div class="class_1"></div>
<div class="class_2">
<div class="label_0">
<div class="label_1">Some text 2</div>
</div>
</div>
<div class="class_3">
<div class="tooltip_0"></div>
<div class="tooltip_1">
<form>
<button onclick="handleClickEvent(this); return false;">Button 2</button>
</form>
</div>
<div class="tooltip_2"></div>
</div>
</div>
Here is a jQuery-only version
// *** IGNORE: BEGIN SHIM ***
(($) => {
$.fn.findByContent = function(text) {
return this.contents().filter((i, c) => $(c).text().trim() == text.trim());
};
$.fn.cousin = function(childSelector) {
let node = this;
while (node != null & node.length > 0 && node.find(childSelector).length < 1) {
node = node.parent();
}
return node ? node.find(childSelector) : null;
}
})(jQuery);
$('button').on('click', (e) => {
console.log(`Clicked on ${$(e.target).text()}`);
e.preventDefault();
})
let button1 = $('.label_1').findByContent('Some text 1').cousin('button');
if (button1 != null) {
button1.click();
}
let button2 = $('.label_1').findByContent('Some text 2').cousin('button');
if (button2 != null) {
button2.click();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="class_0">
<div class="class_1"></div>
<div class="class_2">
<div class="label_0">
<div class="label_1">Some text 1</div>
</div>
</div>
<div class="class_3">
<div class="tooltip_0"></div>
<div class="tooltip_1">
<form>
<button>Button 1</button>
</form>
</div>
<div class="tooltip_2"></div>
</div>
</div>
<div class="class_0">
<div class="class_1"></div>
<div class="class_2">
<div class="label_0">
<div class="label_1">Some text 2</div>
</div>
</div>
<div class="class_3">
<div class="tooltip_0"></div>
<div class="tooltip_1">
<form>
<button>Button 2</button>
</form>
</div>
<div class="tooltip_2"></div>
</div>
</div>
Upvotes: 1