I'm trying to implement a hover command in Cypress, so I'm doing this:
Cypress.Commands.add("hover", { prevSubject: "element" }, (subject) => {
return subject.trigger("mouseenter");
});
And using it like this:
cy.get(`[test-id="my-test-id"]`).hover();
But it's not working: the hover call doesn't seem to have any effect on the execution of the test.
If I remove the custom command and just put the contents of that function inline, it works:
cy.get(`[test-id="my-test-id"]`).trigger("mouseenter");
What am I doing wrong with the custom command?
Have you tried wrapping the subject first?
cy.wrap(subject).trigger("mouseenter");
Related
I am working with Cypress v9.6.1 and custom elements with shadow dom. We have several custom elements which are deeply nested - I am able to query for an input that is deeply nested with several web components successfully with something like this:
// WORKS!
cy.get(‘custom-element-1’)
.shadow()
.find('custom-element-2’)
.shadow()
.find('custom-element-3’)
.shadow()
.find(`custom-element-4[id=“ce”4]`)
.shadow()
.find('input');
What I'd like to do is determine the presence of that input before moving forward in the test.
Pseudo code -
if (cy.('.deeply-nested-element').exists() ){
do.not.click(button-a)
} else {
click(button-a)
}
Following the cypress docs for conditional testing -> element presence I attempted to express the above in a conditional and use on the length attribute to determine presence
//DOES NOT WORK
cy.get(‘custom-element-1').then(($ce) => {
if($ce.shadow()
.find('custom-element-2’)
.shadow()
.find('custom-element-3’)
.shadow()
.find(`custom-element-4[id=“ce”4]`)
.shadow()
.find('input')) // then do something
}
This gave me an error. Property 'shadow' does not exist on type 'JQuery<HTMLElement>'. Did you mean 'show'?ts(2551)
Ignoring the ts error resulted in cypress test failing with:
$ce.find(...).shadow is not a function
I switched it up a little by chaining off of shadow() with the same result
//ALSO DOES NOT WORK
cy.get(‘custom-element-1').shadow().then(($ceshadow) => {
$ce
.find('custom-element-2’)
.shadow()
.find('custom-element-3’)
.shadow()
.find(`custom-element-4[id=“ce”4]`)
.shadow()
.find('input');
}
And for this one:
$ce.find(...).shadow is not a function
It looks to me like the promise off of the get method does not pass to the callback an element with a shadow dom (JQuery). The small problem I'm trying to figure out is a workaround to that. The larger problem is how to set up a conditional that is determined by the presence of an element that is deeply nested within custom element shadow doms. Any advice would be much appreciated.
The .shadow() command is a Cypress command, but $ce is a jQuery object that can't call Cypress commands directly.
$ce.find(...).shadow is not a function occurs because both jQuery and Cypress have .find(), but only Cypress has .shadow().
By making includeShadowDom:true global either in config or the test options, Cypress commands can be used without needing to chain .shadow() at every step.
If it's custom-element-1 that is conditional, this should work
it('tests deeply-nested shadow elements', {includeShadowDom:true}, () => {
cy.get('body').then($body => {
const ce1 = $body.find('custom-element-1');
if (ce1.length) {
cy.wrap(ce1) // wrap jQuery element into Cypress result
// so that includeShadowDom:true is effective
.find('custom-element-2')
.find('custom-element-3')
.find('custom-element-4[id="ce4"]')
.find('input'))
}
})
})
I am trying to click an element inside frame. When i use cy.wrap i get Error
" Timed out retrying: Expected to find element: '[name="border_top"].contents() body #acceptInvitation', but never found it.
Code
it('Automate C# Corner Page', function() {
cy.get('[name="border_top"]').then(function ($iframe) {
const doc = $iframe.contents().find('body')
// doc.find('#acceptInvitation').click({force:true})
cy.wrap(doc.find('#acceptInvitation')).click({force:true})
})
After you add a helper function to your cypress/support/commands.js as I describe in my answer here (Cypress - run test in iframe), you can evaluate whether the button exists with:
cy.get('#iframe-id')
.iframe('body #yourButtonId')
.should('exist')
I think clicking the element in the iframe could be done like this.
cy.get('#iframe-id')
.iframe('body #yourButtonId')
.click({force:true})
install cypress-iframe()
import cypress-iframe in the file
cy.iframe().find('selector');
you can declare one method into base js file like shown below:
getIframeBody() {
return cy
.get('object')
.its('0.contentDocument').
its('body')
.then(cy.wrap)
};
Then use this method as:
getIframeBody().find("cssLocater).click(); OR getIframeBody().xpath("xpath).click();
This will work for sure.
I'm using CKEDITOR in inline mode with multiple editors per page. To create them, I use <textarea> tags in the HTML and then run a script that executes CKEDITOR.inline() against each of them as soon as the webpage is loaded.
That works fine as long as I define my final configuration in "config.js", but I need to update one of the configuration options dynamically.
Here's my script, using JQuery to loop thru the <textarea> elements after the page is loaded. As a diagnostic, I have the CKEDITOR.replace() sandwiched between alert statements. This code replaces the first <textarea> with an editor and displays the first alert statement. However, it quits during the CKEDITOR.replace() statement and never displays the second alert.
$(function () {
$("textarea").each(function () {
editor = CKEDITOR.inline($(this)[0]);
alert("Before replace, editor=" + editor);
CKEDITOR.replace(editor, {
filebrowserImageUploadUrl: "/new/url/to/be/executed"
});
alert("After replace");
})
});
Not only does the second alert not execute, but the configuration option I'm trying to update remains as it appears in "config.js".
I think I need to specify something other than "editor" as the first parameter for the CKEDITOR.replace() statement, but I don't know what.
After more research, I discovered that I can set configuration options within the CKEDITOR.inline method call. Here's a working version of the script:
$(function () {
$("textarea").each(function () {
CKEDITOR.inline($(this)[0], {
filebrowserImageUploadUrl: "/new/url/to/be/executed"
});
});
});
I am trying to test a flow
1.Ajax Request > Loader is visible
2.Response Received > a.Loader is hidden
b.Redirect to another page(where a interstitial is visible)
White testing them with casperJS I use the waitFor method, something like this.
casper.waitFor(function check() {
return this.evaluate(function() {
return $("#loader").is(":hidden");
});
}, function then() {
this.test.pass("Ajax request");
this.waitDone();
}, function timeout() { // step to execute if check has failed
this.echo("Timeout: page did not load in time...").exit();
},4000);
The thing is even if the condition is passed in check, then is not executed until the page is not redirected(read the flow, I am trying to test) and the test suite won't move to the next step.
Is there something I am missing here ?
Make sure your reference 'this' is located within a casper block:
casper.then(function() {
this.waitFor(function check() {
Possible quick fix without knowing more detail. Pass jQuery variable to evaluate.
this.evaluate(function($) {
You could also try:
casper.waitWhileVisible('#loader', function() {
// executes when #loader is hidden
});
docs located at: CasperJS waitWhileVisible
I wrote a jQuery plugin to filter select list options. It works great on one list, but not on more elements: http://jsfiddle.net/vgXPh/4/
$("select.filter").listFilter(); // doesn't work
$("select.filter:first").listFilter(); // works
I don't see any global variables that could be messing it up. Am I calling my bind events correctly? JSLint doesn't complain. What am I doing wrong?
You should probably surround your code with this.each(), like this:
$.fn.listFilter = function() {
this.each(function() {
(...)
});
return this;
};