When my test fails to find an element on a page, Jest prints out the DOM to my screen. I'm using MUI and it makes a mess with classnames, like this:
<div
class="MuiFormControl-root MuiTextField-root css-1akjbnu-MuiFormControl-root-MuiTextField-root"
>
<label
class="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-shrink MuiInputLabel-outlined MuiFormLabel-colorPrimary MuiFormLabel-filled MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-shrink MuiInputLabel-outlined css-rrjzhf-MuiFormLabel-root-MuiInputLabel-root"
data-shrink="true"
for="application-name-yq40gwnkmyh"
id="application-name-yq40gwnkmyh-label"
>
Application name
</label>
It's really hard to read it. I wonder if there's an option to hide class names from this output, and only leave the DOM elements?
Update: seems it's react-testing-library, not jest. But anyway, looks like there's no such option: https://testing-library.com/docs/dom-testing-library/api-debugging/#debugging
Unfortunately, it doesn't seem like there's an option to hide the class names from the output when using react-testing-library. However, you can try using a DOM inspector tool like the Chrome DevTools to inspect the elements on the page and see the structure of the DOM. This can be useful for debugging and understanding the structure of the page, without having to sift through the class names.
You can also consider using a custom formatter for Jest, such as the pretty-quick package, which can format the test output in a more readable manner. This might make it easier to understand the output of the tests, even if the class names are still present.
If you still have trouble reading the output, you can consider using a separate tool for visualizing the DOM, such as a browser extension or a standalone application. These tools can provide a visual representation of the DOM that is easier to understand, which can be helpful when debugging your tests.
Related
I am trying to extract the price from this webpage: https://www.allbirds.com/products/mens-wool-runner-up-mizzles-natural-grey?size=13
I narrowed it down to these divs:
<div class="jsx-3947815802 Container">
<div class="jsx-526902087 Grid">
<div class="jsx-2943457050 Grid__cell Grid__cell--small-12 Grid__cell--medium-7 Grid__cell--large-up-8">...
The jsx-{random_number} for the class names is suspicious to me. They seem generated on the fly. The price I need is inside divs like these. However, these don't exist in the page source and or the cheerio object I am using during runtime. It just disappears.
How common is this technique? It seems like a pretty good way to stop web scrapers. How do I get around it?
If those classes are random, it might be annoying, but it's not a deal-breaker, because the other classes look to be static.
For example, the element that includes the price looks something like:
<p class="jsx-3188494938 Paragraph PdpMasterProductDetails__paragraph">$135</p>
The PdpMasterProductDetails__paragraph does not change. So, you can retrieve the text by using that as a selector:
$('.PdpMasterProductDetails__paragraph').text()
You can also retrieve the price from a meta tag:
<meta property="og:price:amount" content="135">
which can be selected via the selector string:
meta[property="og:price:amount"]
How common is this technique?
Very.
Building websites as Single Page Applications with tools like React is very common.
It seems like a pretty good way to stop web scrapers.
It isn't.
How do I get around it?
Hit the web service the React code fetches the raw data from directly. It's easily discoverable via the Network tab in the browser's developer tools.
I'm developing projects using javascript (React). I'm using modular css which randomizes class name so I cannot have a hold on it using css selectors later in tests.
What are my options if I want to make referencing UI elements easier in tests (be it unit or selenium)?
I locate DOM elements by using special attributes I add to the HTML Element, which always follows a specific naming scheme.
Example (HTML): <div class="randomClass" data-testing-locator="test-locator-attr-example">
My locator: element(by.css('div[data-testing-locator="test-locator-attr-example"]'))
I avoid using class-based locators. We used to use them intensively in a large production application, and minor changes to the HTML (Like adding a new class name to an element) could break the locators. By swapping to the attribute look-up, our tests no longer broke when a designer did relatively minor changes. It really got annoying having to fix locators every second day or so.
Working with RF in recent weeks I noticed a problem, which stuck me for a long time. I have constant error:
Element with locator 'XXX' (this is a template, of course) not found
Investigation of span that wanted to locate revealed, that it has some JavaScript code under it, that, from what I think, enables it dynamically.
input bo-attr="" id="inventory-keyword" ng-attr-placeholder="{{('inventoryMode.' + {true: 'KEYWORD_DEVICE_PLACEHOLDER', false: 'KEYWORD_TEMPLATE_PLACEHOLDER'}[items.currentSeen == VIEWS.EQUIPEMENT]) | translate}}" ng-model="getCurrentFilters().searchString" class="ng-pristine ng-valid" placeholder="Name, description..."
How to have it passed by RobotFramework?
Or maybe source of the problem is different?
There are other elements like this (with sth that appaers to be JavaScript under it), and none of it is seen by RF, except the main menu.
From the Javascript code you have added to post, it seems the underlying Web Application uses AngularJS (I can see ng-model in code).
Sometimes, you cannot identify elements in AngularJS developed Webpage using the default ways the Selenium provides.
You can use AngularJS library or ExtendedSelenium2Library which has new ways to locate elements like model/binding etc.
Check below links for more information :
AngularJSLibrary
ExtendedSelenium2Library
I'm taking my first adventure with javascript, and totally without my bearings. I'd like to show a thumbnail that opens a modal with a larger view of the picture (and this is really the only front end fanciness I'll need, so I'm trying to keep it simple). I've copied this code from w3schools, which uses getElementById. It works great for the first image on the page but clicking subsequent images doesn't pop anything up. Reading around on stack overflow it sounds like that's because I'm matching on the id, but each element on the page will/should have a different id (which makes sense).
I saw a post here where the person made the ids unique by appending the element's id. I could do something like that, but I (a) wanted to check if that's kosher and (b) then obviously the id will no longer match, so is there some different attribute I would tack on to match up my HTML with my styles? This must be a common problem- what's the right way to apply the same behavior to multiple elements on a page? For example I can give them
thanks!
UPDATE: based on everyone's feedback below I've modified the code to use getElementByClassName instead of getElementById- see gist here: https://gist.github.com/dianekaplan/1602a7c0a1c1ec6aa103b61d6530ff15
If I'm reading the code correctly, then the important lines for me to change are from line 115 to line 116- (to set the image info based on ClassName, not id)- and replacing 'myImg' with popup' in the style lines 5 and 11, but clicking the first image no longer opens the modal, so I missed something. Anyone see what's wrong that I need for it to work?
You should use a class name (the same in all img) instead of ids and then use getElementsByClassName() to fetch all of them, instead of getElementsById() which gets only one (as ids must be unique).
Then, you should store the full size image's url somehow in order to fetch it regardless of which img was clicked. One way may be using data attributes.
Example:
<img src="thumb1.jpg" data-fullsize="full1.jpg" class="popup">
<img src="thumb2.jpg" data-fullsize="full2.jpg" class="popup">
<img src="thumb3.jpg" data-fullsize="full3.jpg" class="popup">
var elems=document.getElementsByClassName("popup");
for(var i=0;i<elems.length;i++) {
elems[i].onclick=function() {
var fullsize=this.dataset.fullsize;
//open de popup, fullsize has the clicked image url
}
}
Code not tested, for the idea only.
To answer your primary question ID's are "supposed to" [1] be unique so unless you came up with a convention such as a prefix or regex you couldn't easily use them to group elements together.
If you want to group together multiple elements you could use a class, instead, in which case instead of getElementById you'd use getElementsByClassName.
That being said I wouldn't recommend that either; using vanilla JavaScript can be very time-consuming to make a complex application. You will be tempted to merge the UI with all your functionality. This works great for smaller applications but it can become very unruly, particularly if you don't take steps to allow yourself to refactor in the future, in which case you'll be stuck with an application few can easily be trained on and modify.
You are correct to learn the language, though, prior to a framework. JavaScript is especially quirky.
I would suggest if you're looking to create a web application to look into a modern JavaScript framework after learning JavaScript, HTML and CSS. (And focus on having a practice to being able to refactor/upgrade/improve otherwise you'll be stuck in 2016 and it'll be 2020 - you don't have to worry about this immediately, but start learning about how to do that while you're learning the language.)
To find frameworks I would suggest exploring what's out there. Here's an example of one on GitHub. That's probably a hand-coded list. It's also good to explore exhaustive lists, such as just looking at the "most starred" Repositories on GitHub that are written in JavaScript. And of course check elsewhere besides GitHub, too.
I happen to know AngularJS the best and it happens to be one of the most popular but I would recommend for you to explore and find one that has syntax you like. You might find a different one more intuitive. Here's a plunker that shows how to solve that problem in AngularJS.
Notice how all the functionality is separate from the UI and how declarative it is - the main directive has no idea how the images are being rendered - it just says here are some image url's and descriptions:
scope.images = [{
url: 'http://www.w3schools.com/howto/img_fjords.jpg',
description: 'Trolltunga, Norway'
},{
url: 'http://www.w3schools.com/howto/img_fjords.jpg',
description: 'Other Description'
},{
url: 'http://www.w3schools.com/howto/img_fjords.jpg',
description: 'Another Description'
}];
This is what initializes the app: <html ng-app="plunker"> and <main></main> is akin to the "main method" in that it is the component that calls all the other components.
It's much easier to test an app's functionality if you're careful to separate out the presentation concerns from the rest of the app. It will take a while to learn JavaScript and probably any framework, though, so don't expect too much too soon if you're just getting your hands wet in JavaScript - but if you've programmed for a while you already know this :)
(Disclaimer: What I did isn't necessarily the "best practices" as I tried to simplify it a bit so as to not overwhelm OP too much with information, although the added complexity is useful in more advanced scenarios.)
[1] "Supposed to" meaning browsers may do their best to render a page, even it isn't "compliant" HTML. Web Applications suffer from having to have the same code work on different browsers, operating systems and versions of each all implementing the standards (or choosing not to) differently. It's a nightmare if you haven't ran into it, yet.
I am using firebug to edit my magento theme. In a particular element I am getting an element.style attribute that I want to edit. Now how do I know which JS file is to be edited?
If you want to interact with elements via Javascript, you can use the console function in Firebug. Go to console, and click enable and from there you can start typing code as if it were javascript.
Example, if you wanted to check the z-index property of a specific element you could just type the javascript in the console:
document.getElementById("idOfElement").style.z-index
and when you hit enter it should tell you. You can also see errors in the javascript file if there are any.
If you are looking for the Javascript file of what is committing this change in the z-index property and you are 100% certain it is because of the Javascript, then you can use the debugger Firebug has which is also in the Scripts tab. If you're dealing with multiple javascript files, I'm not entirely sure how you can sift through which JS file is causing it, I believe you'll have to do that digging on your own. The debugger allows you step through your JS file though and see what changes are being made step-by-step.
Here is a tutorial on how to use the debugger if you're not familiar. Hope this helps.
Not sure about firebug,
But if you use linux you may try this command,
grep "element.style" -Rn .
Do you Want to change the Style or Something other.
If you want to change Style of a Particular Element, Just Follow the Steps
F12
Select Inspect Tool
Click on the Element where you want to change
In a FireBug Window look at Right and Make Sure style Tab is Selected
Just Single Click on value of a Particular Property
If you are not finding solution, Please Determine the Problem bit Clearly.