Cypress Click if item exist - cypress

I need a way to easily trigger a click() event only if an element exist on page.
the fact that the element (confirm modal dialog) itself exist is not an issue for my test, but this can stop next steps. so I want to click OK only if the dialog is shown.
I tried something like this, but it didn't work:
cy.get('body').find("button[data-cy=sometag]").then(items => {
if(items.length) {
cy.get('button[data-cy=sometag]').click();
}
});

If you want to test that the modal exists but don't want to fail the test if it doesn't, use a jQuery selector.
const found = Cypress.$('button[data-cy=sometag]').length
Modals are likely to animate on opening, so you you will need to repeat the check a few times, which you can do in a function
function clearModal(selector, timeout = 1000, attempts = 0)
if (attempts > (timeout / 100)) {
return; // modal never opened
}
if (!Cypress.$(selector).length) { // not there yet, try again
cy.wait(100)
clearModal(selector, timeout, ++attempts)
else {
Cypress.$(selector).click() // modal is up, now close it
}
}
clearModal('button[data-cy=sometag]')

If you use the find like this cy.get('body').find("button[data-cy=sometag]") this will fail always whenever the element is not present. Instead you can use the find command inside the If condition and check its length.
cy.get('body').then($body => {
if ($body.find("button[data-cy=sometag]").length > 0) {
cy.get('button[data-cy=sometag]').click();
} else {
//Do something
}
})
Instead of body, you can also use the parent element of the element in question, which you know for sure is visible and present on the page every time.

Related

How to write condition for locator is present in the page using Cypress

I am looking for the condition in cypress to verify and click locator is present or not.
If element is present go to condition and click on the element else leave and continue with the execution. Below code i have tried,
cy.get(".paginationPanel.ng-star-inserted").then(($test)=> {
if($test.text().includes('Show:')){
//do something
}else{
}
})
Unfortunately, I am unable to success. Can anyone please help me.
That code works, what is wrong?
What do you want to click? The "Show" dropdown would be
cy.get(".paginationPanel").then(($panel) => {
if($panel.text().includes('Show:')) {
cy.contains('label', 'Show').prev().click() // click the Show dropdown
} else {
}
})

How can I check with Google Apps Script whether the sidebar opened by "SpreadsheetApp.getUi().showSidebar(html);" is open or not open?

Background: The sidebar cannot be opened with onOpen().
"PropertiesService.getScriptProperties();" should not be used because it is only suitable for one user (possible overlaps). If the sidebar is open, nothing should happen to prevent it from being reloaded, otherwise it should be opened. A global variable could not be overwritten within a function for the next execution.
function sidebar() {
if (? == 'off') {
var html = HtmlService.createHtmlOutputFromFile('sidebar')
.setTitle('Title');
SpreadsheetApp.getUi()
.showSidebar(html);
}
}
With getUserProperties() it works per user per script. A sidebar can be opened with onOpen() by adding a trigger to the respective script for onOpen() at https://script.google.com/home/.
var status = PropertiesService.getUserProperties(); // global variable
function onOpen() {
status.setProperty('sidebar', 'off');
sidebar();
}
function sidebar() {
if (status.getProperty('sidebar') == 'off') {
var html = HtmlService.createHtmlOutputFromFile('sidebar')
.setTitle('Title');
SpreadsheetApp.getUi()
.showSidebar(html);
status.setProperty('sidebar', 'on');
}
}
This is what I found to work in this particular situation. It's not perfect, but it is functional and pretty simple:
.html
window.setInterval(function(){
google.script.run.collectPing();
}, 10000);
.gs
function collectPing() {
CacheService.getDocumentCache().put('sidebar', 'on', 15);
}
While the sidebar is open, it calls the server-side every 10 seconds and sets a property in the cache which lasts for 15 seconds. You can then write a function on the server-side that looks at the cache and does something based on the cache property. I just came up with this, so it is relatively untested, though my first try seems to indicate that it works.

Test only if element still present

I have a notification message which pops up upon saving a file and wish to close it only if it is still present when I need to press the next button which may be covered by this notification.
So far this is how I have tried to conditionally close the notification
Cypress.Commands.add('notificationClose', () => {
if (cy.get('.notification').should('be.visible')) {
console.log('CLOSE ME');
cy.get('.notification-dismiss').click({mulitple: true});
}else{
console.log('ALREADY GONE');
}
});
I have also tried a jQuery solution I found here too.
Cypress.Commands.add('notificationClose', () => {
if (Cypress.$('.notifications-wrapper') == true) {
cy.get('.notification-dismiss').click({mulitple: true});
}
});
I only use this immediately before needing to click the subsequent button, so the notification may close on its own.
The element in question is only temporarily attached to the DOM after saving the file.
How do I ask if this element is attached to the DOM?
I'm not completely sure that I understand your issue. But this is what I assume you mean:
You have a popup that isn't closed sometimes.
If the popup isn't closed you want to close it.
If the popup is closed you want to continue the test.
If that is correct we only need to fix step 1 and 2 since those are special. Continuing the test is just like you normally do.
To get the behaviour you need to get() the element and assert if it is present. You can do that with this code:
cy.get('body').then($body => {
if ($body.find('.notification').length === 1) {
cy.get('.notification-dismiss').click()
}
})
// continu the test

protractor click action relies on ptor.sleep(). How can I resolve correctly?

I'm a newbie trying to not rely so much or at all on using ptor.sleep() calls, especially after the click below. The line below never gets the value (they all return Nan)unless I include the ptor.sleep(1000); call after the click() below.
I've made various attempts to make the array elem to resolve before the results of the list after clicking, wrapping the click in the function, etc, but nothing I've tried works without the sleep calls. Already read up on protractor control flow.
devCountString = parseInt(arr[i]);
Thanks for any insights, maybe something obvious I've missed so that I can remove the ptor.sleep() calls.
my spec:
describe('\n == patch List suite results == \n', function() {
// login already was done in config files, onPrepare function.
var ptor, noFilterCount;
// needed here if we turn ptor.ignoreSynchronization = false;
beforeEach(function() {
ptor = protractor.getInstance();
ptor.ignoreSynchronization = true;
browser.get('https://my.abc.com:3000/fixes');
ptor.sleep(1200);
}); //end beforeEach()
it('11 - verify filter fewer', function() {
var sevStringElm, sevString;
var applicableCount;
ptor.ignoreSynchronization = false;
ptor.sleep(500);
sevStringElm = element(by.css("input.form-control.bf-spinner"));
sevStringElm.clear();
ptor.sleep(500);
sevStringElm.sendKeys( '8' );
ptor.sleep(500);
// click on the "fewer" spinner, wrap the click to wrap the .
var fewerPromise = element(by.css("span.bf-spinner-toggle:nth-child(2)")).click();
ptor.sleep(1000);
// now get the list of clickable elements in each device card. by title
var applicableDevicesElm = element.all(by.css("[title$='Applicable\ Devices']"));
applicableDevicesElm.getText().then(function(arr) {
console.log("arr.length= "+arr.length);
for (var i = 0; i < arr.length; i++) {
devCountString = parseInt(arr[i]);
expect(devCountString).toBeLessThan( 9 );
};
});
});
Everytime an action goes to the webdriver, Protractor will put that into the flow queue as shown in the documentation. As a result, when you get to inspect your elements after the click, the queue should have resolved the dependencies and have your state ready for the finder. In any case, even if you don't want to have the implicit wrapping that Protractor does on its actions (which are always asyc), you can put a .then(function(){}) after the click and put the post click logic in that anonymous calback function.
On a side note, you should have to use ptor anymore. Use browser instead that mixes in the protractor instance capabilities. Example: browser.sleep(1000)

Is it possible to run something before DOMContentLoaded?

I want to inject stylesheets and scripts before DOMContentLoaded.
In Google Chrome it is possible using run_at = document_start.
Is there something similar in Firefox addons? Can I run things before gBrowser.addEventListener("DOMContentLoaded" ? How?
The current workaround I'm using is the following
gBrowser.addEventListener("DOMNodeInserted",
function (e)
{
if (typeof(e.relatedNode.tagName) != "undefined" &&
e.relatedNode.tagName == "DIV")
{
var window = e.relatedNode.ownerDocument.defaultView;
if (window.MyScript) return; // if it was injected
// ignore other events
if (/siteregex/i.test(window.location.href))
{
Initialize(window); // inject scripts
}
}
},
true);
DIV is the first element on body, so it will load right after this node. I won't have to wait for the whole page.

Resources