Cypress: access custom defined css property - reactjs

I am building an APP using React + chakra-ui and I am in the process of adding Cypress tests to it, but I am facing a blocker and I was wondering if anyone had faced a similar problem and that could help!
Problem:
The test I am trying to pass is to verify that my element contains a CSS property, however, the CSS was generated by Charkaui with their unique syntax (e.g --chakra-scale-x)
My test case is as follow
cy.get('MY_ELEMENT')
.should('be.visible')
.should('have.css', '--chakra-scale-y', 1);
This test gave me the error
expected '<div.css-o64oke>' to have CSS property '--chakra-scale-x'
even though I can see from inspect element that it does have the following property.
Does anyone know a solution or a workaround for this? Thanks in advance!
Edit:

--chakra-scale-y is a css variable, which will be applied (probably as a transform) by the browser css engine.
Take a look in the devtools Computed tab (unselect Show all to see just those applied). If a transform shows up, this is what you need to test for.
In the test use getComputedStyle to check the value identified above.
cy.get('MY_ELEMENT')
.then($el => {
const win = cy.state('window')
const styles = win.getComputedStyle($el[0])
const transform = styles.getPropertyValue('transform')
console.log(transform)
expect(transform).to.eq(...)
})
It looks like you need to check scaleY, this is from the chakra library
const transformTemplate = [
"rotate(var(--chakra-rotate, 0))",
"scaleX(var(--chakra-scale-x, 1))",
"scaleY(var(--chakra-scale-y, 1))",
"skewX(var(--chakra-skew-x, 0))",
"skewY(var(--chakra-skew-y, 0))",
]

Related

Can't find item in cypress even though it's in DOM

No matter what selectors I use, I keep getting the response "Expected to find element: ... but never found it. The curious thing is that in the DOM I am able to find this element and the selector for it (I used this to find the element
Code I have tried
cy.get("#main-content [title='Main']").click({force:true})
But after running the test, Cypress can't find the item no matter what selector it uses. It's also strange that in the preview of the test I'm not able to select the item but it selects a much larger area of the whole page editor.
Anyone know any other way to approach the problem? I will be very grateful for any help
I tried various types of selectors and tools, including in Selenium Webdriver but the same problem occurred
I highly recommend cypress-iframe package to access your elements within the iframe.
Follow the instructions to install it, then use it in your test like so:
cy.iframe('#mgl-pageeditor')
.find('#main-content [title=Main]')
.click()
It looks like you're trying to reach an element that is inside of an iframe element. With most automation frameworks, you need to handle switching into the iframe. Cypress is no different.
Cypress is able to access elements inside iframes, but you have to be explicit when you do.
I normally grab the iframe element, cy.wrap() it's contents, then use the .within() function to execute commands inside the context of it.
// Basic example
cy.get('iframe').then(iframe => {
cy.wrap(iframe.contents()).within(() => {
cy.get("#main-content [title='Main']").click({force:true});
})
})
You can make it easier by turning it into a custom command that handles the cy.wrap() and .within() for you.
// Typescript example of custom .switchToIframe()
Cypress.Commands.add('switchToIframe', { prevSubject: true }, (prevSubject: JQuery<HTMLIFrameElement>, callback: () => void): void => {
cy.wrap(prevSubject.contents(), { log: false }).within(callback);
});
// Test file
it('iframe test', () => {
cy.get('iframe').switchToIframe(() => {
cy.get("#main-content [title='Main']").click({force:true});
})
})
Working with iframes in Cypress: https://www.cypress.io/blog/2020/02/12/working-with-iframes-in-cypress/

How to horizontally scroll in a React Application (ag grid) with UI automation (WebdriverIO /JavaScript)?

We have a grid application exactly similar to this demo application:
https://www.ag-grid.com/example.php
I want to horizontally/vertically scroll to any element in this demo site.
I have tried below methods:
browser.moveTo() : is not working and throwing below error :
stale element reference: element is not attached to the page document
browser.scroll(1665, 147.12345) : Is not doing anything. Pass the step.
browser or element.scrollIntoView() :shows not an existing method. Following error appears:
Property 'scrollIntoView' does not exist on type 'Client> & RawResult'.t
and
Property 'scrollIntoView' does not exist on type 'Client> & RawResult'.t
I am using webdriverio and typescript for UI automation.
wdio version:
"webdriverio": "^4.14.4"
Though none of the existing methods worked, but I solved it by using the "Tab" key. I followed below steps:
I click/select the last visible element in the current screen.
I press "Tab" key (Single or multiple as needed)
This scrolled the page horizontally(which solved my purpose for now).
Try to use scroll with javascript:
browser.execute(function() {
document.querySelector('yourElementLocator').scrollIntoView()
})
Keep in mind that code inside browser.execute does not have access to the outer context. So if you want to pass your element inside you will have to specify this argument after executable code:
browser.execute(function(){}, selector)
https://webdriver.io/docs/api/browser/execute.html
browser.waitUntil(
async () => {
browser.keys(["\ue00F"]);
return await countryEle.isDisplayedInViewport();
},
15000,
undefined,
500
);

Dojo Tooltip Attach to Multiple Nodes: Element Selector Works, but not Class Selector

I'm trying to use dojo Tooltips on a series of SVG elements that are tool buttons in my header. I'm using the method in the docs of attaching tooltips to multiple nodes like this:
new Tooltip({
connectId: query('.header'),
selector: 'svg',
position: ['below'],
getContent: function (e) {
return e.getAttribute('data-tooltiptext');
}
});
And that works, but if I use a selector of '.tool' (every SVG has a class of tool on it) my getContent function never gets called. 'svg.tool' doesn't work as a selector either. The docs an several examples around the net claim class selectors will work, but I've only been able to get element selectors to work.
I'm requiring 'dojo/query' and I've tried using 'dojo/query!css3' but that doesn't seem to make a difference. I don't know if it makes a difference, but I'm using dojo included with ESRI's ArcGIS JS API library, which reports a dojo version of 1.14.2.
I've experienced the same issue when using the selector attribute while creating a Menu. Within an SVG element, element selectors (even comma-concatenated ones) work, but class selectors do not. Outside of the SVG element, they worked just fine. You can play around with this by using dojo.query in your browser's console to see which elements get selected.
I was able to solve the issue by changing the selectorEngine in my dojo config. Using any of css3, css2.1, and css2 worked, so I think the issue may be in the acme engine. If you don't already have a dojo config, you can add it via a script tag:
<script>
var dojoConfig = {
selectorEngine: 'css3',
};
</script>

Placeholder for broken image fails in IE11, using holder.js and AngularJS

I try to setup a placeholder for broken image, using holder.js in an AngularJS framework.
Everything works perfectly on all browsers, except with IE11 (what a surprise!), which gives me a strange "invalid property value" error... I did not even test with older versions of IE.
So, it works when :
I use "holder.js/100%x100%" directly in the src attribute (with no additionnal directive)
I use "holder.js/100x100" as a placeholder for broken image
But it fails when :
I use "holder.js/100%x100%" directly in a data-ng-src instead of src ( => invalid argument)
I use "holder.js/100%x100%" as a placeholder for broken image ( => invalid property value)
After few other tests (with jQuery or pure javascript), I figured out the error does not come from holder.js. I rather think there is an issue with IE11 when using % character in src/ngSrc attributes programmatically ... but I don't know why if I'm right.
Here is the fiddle with the four use cases :
http://jsfiddle.net/msieurtoph/184fseew/
If anybody has an idea about the reason or the way to get it working.
Thx for your help...
EDIT :
Thx to #imsky, here a working fiddle, using data-src instead of src : http://jsfiddle.net/msieurtoph/184fseew/23/
This is a known bug with IE11, where using % in img.src throws an error: https://connect.microsoft.com/IE/feedback/details/997939/ie11-imageelement-setattribute-fails-with-invalid-argument-when-key-is-src-and-value-has-a-percent
There are two solutions here, depending on whether or not you need the src attribute to be set. The first one is to use data-src instead of src:
$timeout(function() {
_this.setAttribute('data-src', holderSrc)
Holder.run({
images: _this,
nocss: true
});
});
This is the cleaner solution and one I recommend.
The other solution would be to replace the element with a clone that has the proper src attribute value. This approach is not as clean and introduces overhead if you need to maintain references to the original image element. I only recommend this if the src attribute needs to be properly set.

Using Moovweb only some of the inline styles are being removed

So I am working in a very old site that is table heavy - everything has been converted to divs, and inside of main.ts I have tried removing the inline styles because the function remove_all_styles() is not working.
#func XMLNode.remove_all_styles() {
remove(".//link[#rel='stylesheet'][not(#data-mw-keep)]|.//style")
}
I also tried adding remove(".//#style") and still failing to remove the div style="" on half of the page. I am not having much luck finding a solution so any help would be appreciated.
edit - as a temporary solution I used this custom JavaScript I found on CSS tricks -
http://css-tricks.com/snippets/javascript/remove-inline-styles/
but I know there is a more appropriate Moovweb solution out there somewhere.
Thanks,
My guess is if you view the source, the inline styles won't be there, which means the styles are added later with JS. Otherwise remove(".//#style") would have worked if you've scoped into the right div.
The only tritium implementation that I can think of is a bit hacky but worked for me on several occasions. You need to reverse engineer the desktop js that adds those inline styles and figure out the selector it uses. Then you can find a workaround by changing the attribute or renaming the node
For example, if the desktop js is something like this
$(".price-table th").css("color", "red");
or like this $(".my-table th").attr("style", "");
You can override the class name in tritium to break the jquery selectors above.
$(".//table[#class='price-table']") {
attributes(class: "new-price-table)
}

Resources