Is there a way to return true or false if an element is clickable. I want to check if one of 3 imprint links is clickable - automated-tests

I want to find out if imprint links are working. Sometimes there are cookie consistent banners and you can not click the link on the page.
But is there a way to find out if there is a second imprint link is clickable on the modal?
export const ttValidateImprintClickable = () => {
cy.log("validateImprintClickable - NCA TESTIFY");
cy.get("a")
.contains("Impressum")
.each((item) => {
let isClick = item.;
debugger;
});
};
Example page https://www.qi-digital.de
Plugin to publish solution open source https://github.com/ncatestify/cypress-base-plugin/blob/main/src/commands/tt-validate-imprint-clickable.ts

The problem is not that you need to find one of the options that is clickable. All the links are all non-clickable because the cookie dialog is covering them.
This is how you can dismiss the cookie dialog and the gray mask which covers the main page
cy.visit('https://www.qi-digital.de');
// in case the cookie is already set and the mask does not appear
// use a conditional check first
cy.get('body').then($body => {
if ($body.find('#SgCookieOptin').length) {
cy.get('.sg-cookie-optin-box-close-button').click()
}
})
// now just click the link
cy.contains('a', 'Impressum').click()
// and confirm the new page appears
cy.contains('h1', 'Impressum', {timeout:10_000}).should('be.visible')
It seems to me that in the test runner, the cookie dialog always appears, in which case you can simplify the test
cy.visit('https://www.qi-digital.de');
// remove the cookie dialog
cy.get('.sg-cookie-optin-box-close-button').click()
// now just click the link
cy.contains('a', 'Impressum').click()
// and confirm the new page appears
cy.contains('h1', 'Impressum', {timeout:10_000}).should('be.visible')
Clicking the "Impressum" link on the cookie modal
This code will click the "Impressum" link that is on the footer of the cookie modal.
I added some code to clear application data to force the modal, but it's not consistently showing the cookie modal.
cy.clearCookies()
cy.clearLocalStorage()
cy.get('#SgCookieOptin') // cookie modal
.find('a:contains(Impressum)') // find the link in the modal footer
.then($a => $a.removeAttr('target')) // stop new browser tab opening
.click()

Take a look at this page Is focusable
Is focusable
Returns a boolean indicating whether an element can receive focus.
Cypress internally uses this method everywhere to figure out whether an element is hidden,
mostly for actionability.
So try mapping the elements to the true/false result of this method
cy.contains('a', 'Impressum')
.each($el => {
const isActionable = Cypress.dom.isFocusable($el)
... // continue test
})
Looking at your gist, this may be what you need
cy.contains('a', 'Impressum')
.filter((index, el) => Cypress.dom.isFocusable(Cypress.$(el)) )
.eq(0)
.click()
Where the filter command takes a function and passes only those that return true.
Since Cypress.dom.isFocusable() needs a jQuery object (same as passed to .each()) we first need to wrap the "raw" element given to .filter().
Next, take the first only in case multiple items are clickable.
Or click multiple items at once like this (but probably you only want one item).
cy.contains('a', 'Impressum')
.filter((index, el) => Cypress.dom.isFocusable(cy.wrap($el)) )
.click({multiple:true})

Related

Cypress click() failed because this element is detached from the DOM in iteration

I try to test my Single Page Application with cypress.
The first page has multiple buttons as anchor tags which direct you to the second site(Angular routing).
On the second site i have a "back" button.
So i want my test to click on a button, wait for the second site to appear, click on the back and repeat this for all remaining buttons.
This is my cypress test:
describe('Select products', function () {
before(() => {
cy.visit('http://localhost:4200/')
})
it('Clicking through products', function () {
// getting each anchor to click
cy.get('a[data-cy=submit]').each(
($el) => {
// click to get on next site
cy.wrap($el).click()
// click to go back
cy.contains('go back').click()
}
)
})
})
It works fine for the first run(get all buttons => click the first => go back) but after getting back on the start site before clicking the next button cypress throws an error:
Can someone help me with this?
Thanks for any help!
cy.get('a[data-cy=submit]') must get a list of the buttons and store them to iterate via .each(), but the code within .each() navigates away from the first page - I guess that Angular destroys the original elements that .each() is trying to iterate over.
This is similar to iterating over a list and altering the list within the iteration, the loop fouls up because the list changes.
If you know how many buttons there are, this would be a better way
const buttonCount = 4;
for (let i = 0; i < buttonCount; i++) {
cy.get('a[data-cy=submit]').eq(i).click();
cy.contains('go back').click();
}
If the buttons are dynamic (you don't know the count), use
cy.get('a[data-cy=submit]').then($buttons => {
const buttonCount = $buttons.length;
for (let i = 0; i < buttonCount; i++) {
cy.get('a[data-cy=submit]').eq(i).click();
cy.contains('go back').click();
}
}

how to use page scroll to id plugin on page template in wordpress?

I have homepage which is created by using multiple small template pages in wordpress. I have set menus on it . now i want to go on particular section/ template using menu. like if i press contact menu button then it should go smoothly downwards of homepage where the contact template has been called. I am using "Page scroll to id" plugin of wordpress but its not working. I have also seen that this plugin work when the page is created by dashoard page. Please help me , how can i navigate to my template page/section using this plugin. If any other plugin is there , please tell me about it . i will try to use that too.
Thanks
To create smooth scroll on link click follow the below steps :
Step 1: Add section ids in menu href including #section1 from admin section Appearance >> Menu .
Step 2: Create section or div with id name section1.
<div id="section1"></div>
Step 3: Paste the below code under your custom js file.
$(document).ready(function(){
// Add smooth scrolling to all links
$("a").on('click', function(event) {
// Make sure this.hash has a value before overriding default behavior
if (this.hash !== "") {
// Prevent default anchor click behavior
event.preventDefault();
// Store hash
var hash = this.hash;
// Using jQuery's animate() method to add smooth page scroll
// The optional number (800) specifies the number of milliseconds it takes to scroll to the specified area
$('html, body').animate({
scrollTop: $(hash).offset().top
}, 800, function(){
// Add hash (#) to URL when done scrolling (default click behavior)
window.location.hash = hash;
});
} // End if
});
});
I hope it will helps you.

How to customize(Change design like color, font, images) of Google Chrome custom navigation

Hi I was displaying a confirm navigation when user closed my website like
I used below code to display custom navigation in my website
$(document).ready(function () {
var popit = true;
window.onbeforeunload = function () {
if (popit == true) {
popit = false;
return "Are you sure you want to leave?";
}
}
});
Can anyone suggest me how to customize confirm navigation.
No, it is not possible to style these as they are Browser generated UI. If you want to be able to style a confirmation box or an alert then you will need to use the <dialog> element or some other method - note you will not be able to stop the browser from unloading like you can with and alert or confirm

Framework7 starter page "pageInit" NOT WORKING

anyone using framework7 to create mobile website? I found it was great and tried to learn it by myself, now I meet this problem, after I create my App, I want to do something on the starter page initialization, here, my starter page is index.html, and I set data-page="index", now I write this below:
$$(document).on('pageInit', function (e) {
var page = e.detail.page;
// in my browser console, no "index page" logged
if (page.name === 'index') {
console.log("index page");
});
// but I changed to any other page other than index, it works
// my browser logged "another page"
if(page.name === 'login') {
console.log('another page');
}
});
Anyone can help? Thank you so much.
I have also encountered with the same problem before.
PageInit event doesn't work for initial page, only for pages that you navigate to, it will only work for index page if you navigate to some other page and then go back to index page.
So I see two options here:
Just not use pageInit event for index page - make its initialization just once (just make sure you put this javascript after all its html is ready, or e.g. use jquery's on document ready event)
Leave index page empty initially and load it dynamically via Framework7's mainView.loadContent method, then pageInit event would work for it (that was a good option for me as I had different index page each time, and I already loaded all other pages dynamically from underscore templates)
I am facing same issue and tried all solutions in various forums.. nothing actually worked. But after lot of RnD i stumbled upon following solution ...
var $$ = Dom7;
$$(document).on('page:init', function (e) {
if(e.detail.page.name === "index"){
//do whatever.. remember "page" is now e.detail.page..
$$(e.detail.page.container).find('#latest').html("my html here..");
}
});
var me = new Framework7({material: true});
var mainview = me.addView('.view-main', {});
.... and whatever else JS here..
this works perfectly..
surprisingly you can use "me" before initializing it..
for using for first page u better use document ready event. and for reloading page event you better use Reinit event.
if jquery has used.
$(document).on('ready', function (e) {
// ... mainView.activePage.name = "index"
});
$(document).on('pageReinit', function (e) {
//... this event occur on reloading anypage.
});

Can I enable users on Plone4 to show/hide the Portlet column on-the-fly

The Portlets in Plone are quite handy but I'd like to be able to provide some method to users to be able to temporarily hide/show the portlets column. That is, by clicking a button, the portlets column should collapse and you see the content page in full width. Then clicking again and the portlets panel on the left expands and the main content page width shrinks to accommodate.
I've observed the HTML ID of the portlets column is "portal-column-one" and I tried adding a button to the page that runs javascript to set the visibility property of that element to "hidden" but this seemed to have no effect. I was able to go into Firebug and add style="visibility:hidden;" to the "portal-column-one" element and it had the effect of making the region invisible w/o resizing the page.
I am using Plone 4.1. I have the site configured with navigation portlet on all pages except the main page which has Navigation, Review List and Recent Changes.
So it seems it must be possible to embed some javascript in the page (I was thinking of adding this to the plone.logo page which I've already customized). But I guess its more complicated than the few stabs I've made at it.
Thanks in advance for any advice.
Solution (Thanks to input from Ulrich Schwarz and hvelarde):
The solution I arrived at uses JavaScript to set CSS attributes to show/hide the Portlets Column (Left side) and expand the content column to fill the space the porlets column filled.
I started by customizing the Plone header template to add a link for the user to toggle the view of the Porlets column. I also put the necessary javascript functions in this header.
To customize the header, go to the following page (need to be logged in as Admin of your Plone site):
http://SERVER/SITE/portal_view_customizations/zope.interface.interface-plone.logo
Where:
SERVER is the address and port of your site (e.g. localhost:8080)
SITE is the short name of your Plone Site
To create this page:
Go to Site Setup (as Admin)
Go to Zope Management Interface
Click on "portal_view_customizations"
Click on "plone.logo" (or at least this is where I choose to put the button so it would be located just above the navigation Portlet)
Add the following to the page:
<script>
function getById(id) {
return document.getElementById(id);
}
function TogglePortletsPanel() {
var dispVal = getById('portal-column-one').style.display
if( dispVal == "none") { // Normal display
SetPortletsPanelState("inline");
} else { // Full Screen Content
SetPortletsPanelState("none");
}
}
function SetPortletsPanelState(dispVal) {
var nav = getById('portal-column-one');
var content = getById('portal-column-content');
if( dispVal == "none") { // Normal display
nav.style.display='none';
content.className='cell width-full position-0';
// Set cookie to updated value
setCookie("portletDisplayState","none",365);
} else { // Full Screen Content
nav.style.display='inline';
content.className='cell width-3:4 position-1:4';
// Set cookie to updated value
setCookie("portletDisplayState","inline",365);
}
}
function InitializePortletsPanelState() {
var portletDisplayState=getCookie("portletDisplayState");
//alert("portletDisplayState="+portletDisplayState)
if (portletDisplayState!=null) SetPortletsPanelState(portletDisplayState);
}
function setCookie(c_name,value,exdays) {
//alert(c_name+"="+value);
// cookie format: document.cookie = 'name=value; expires=Thu, 2 Aug 2001 20:47:11 UTC; path=/'
var exdate=new Date();
exdate.setDate(exdate.getDate() + exdays);
var exp= ((exdays==null) ? "" : "; expires="+exdate.toUTCString());
document.cookie=c_name + "=" + escape(value) + exp + "; path=/";
}
function getCookie(c_name) {
var i,x,y,ARRcookies=document.cookie.split(";");
for (i=0;i<ARRcookies.length;i++) {
x=ARRcookies[i].substr(0,ARRcookies[i].indexOf("="));
y=ARRcookies[i].substr(ARRcookies[i].indexOf("=")+1);
x=x.replace(/^\s+|\s+$/g,"");
if (x==c_name) return unescape(y);
}
}
function addLoadEvent(func) {
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = func;
} else {
window.onload = function() {
if (oldonload) {oldonload(); }
func();
}
}
}
addLoadEvent(InitializePortletsPanelState);
</script>
<a style="font-size:50%;" href="javascript:TogglePortletsPanel();">Toggle Portlets Panel</a>
6. Save the page
Notes:
I got the names of the plone div elements using Firebug.
I also used Firebug to experiment with different settings to speed up prototyping. For example, editing the HTML inline to verify settings do as expected.
There is a slight but of delay until the Left Portlet panel is hidden. This is only obvious on Safari for me (which is probably due to how fast it is) but not on Firefox or IE.
Maybe it's just a matter of setting the right property: you want display:none, not visibility:hidden.
But even then, the content area will probably not reflow automatically, you'll need to (dynamically) change the class on it as well.
Specifically, you'll need to put classes width-full and position-0 on portal-column-content, instead of width-1:2 and position-1:4.
This must be achieved client side by javascript (jquery).
You must first read documentation about the css grid framework used by plone: deco.gs. The website is down so, git clone this repo: https://github.com/limi/deco.gs and open pages in a webbrowser
Note: you just have to change css classes on the containers.
Try adi.fullscreen, it respects Plone's css-structure as Ulrich Schwarz thoughtfully mentioned.

Resources