I am struggling with something at work. I am a newbie, so excuse me if I ask something easy. I coulnd't find it personally on the internet, so I hope you can provide me from (easily understandable) information.
I am building an automated test. I am using Cypress.
At my work we have the following situation;
1) There is 1 file. We want to copy this. So we have to count the initial state first (1 file)
2) We will copy this file
3) We now have 2 files. We want to count that there are indeed 2 files
I have the following code for this;
// count initialstate (1 file) =
let InitialStateCopy =
cy.getScoped('catalog-> item:case_type:link').contains('filename').should('have.length', 1 )
// press copy
// copy the file, execute actions here
// check if file is copied correctly (2 files)
let NewState =
cy.getScoped('catalog-> item:case_type:link').contains('filename').should('have.length', 2 )
I get the message
CypressError: cy.contains() cannot be passed a length option because it will only ever return 1 element.
And I see that Cypress only finds 1 element.
Does somebody know how I can count how many objects there are? Which code should I use for this ? Basically, I just want to know how I can count elements on a page.
cy.contains('blah') will automatically assert that the element containing blah exists:
.contains() will automatically retry itself until the element(s) exist in the DOM.
So you don't need to do a .should('have.length', 1) to assert this. The .contains itself performs an implicit assertion.
Cypress is trying to warn you that .contains only returns 1 element, so you might be doing something wrong if you're trying to assert on the length of it. In this case, you're trying to assert that length is 2, which is impossible.
I don't know what your .getScoped is, but this just uses regular CSS syntax. To do what you're trying to do, try this JQuery selector, which works because Cypress uses JQuery's selector engine:
cy.get(".catalog .item:contains('filename')").should('have.length', 2)
Related
I'm currently using selenium-webdriver with Mocha & Chai in a JavaScript environment & I'm looking for a way to return a false value if an item does not exist in the DOM; basically to see if a user is logged in or not.
If they are logged in then the following exists in the DOM (and doesn't exist at all if your not signed in).
<a class="account-panel-controls__link" role="link" id="sign-out-nav" data-log-out="">Sign out</a>
I'm looking for a way to find out if it exists & click it if present, otherwise I want to click something else (which only exists when the other snippet above does not).
<a class="account-panel-controls__link" role="link" id="registration-sign-in-nav" data-log-out="">Sign in</a>
I've tried a few variations of the follow but it's gotten me nowhere. It works fine if the element with Id 'sign-out-nav' is present initially but if it's not then the test fails, saying that it was unable to find that element (I'm guess because it's not in the DOM at all?).
driver.findElement(By.id('sign-out-nav')).isDisplayed().then(function (displayed) {
if (displayed) {
driver.findElement(By.id('sign-out-nav')).click();
}
else{
driver.findElement(By.id('registration-sign-in-nav')).click();
}
});
I've search a number of posts & tried stuff like .getSize() & seeing if it's over 0 but can't get anything to run that way. I've also tried using 'findElements' together with .length but it also returns a value of [Object object] and a length of 1 so I can't seem to tell the values apart.
Is there something I'm missing?
Thanks
Not sure if this helps in your instance, but using a webdriverio + mocha + assertjs + selenium, I used the following:
assert.doesNotThrow(() => { browser.getText('#registration-sign-in-nav') });
This works for the stack I work with, because when the element doesn't exist, it throws an error.
To find elements on a page it is recommended to use .findElements():
// find an element on the page sample:
driver.findElements(By.id('sign-out-nav')) .then(found => console.log('Element found? %s', !!found.length));
Now if the .length > 0 the element is found, you can continue with .elementIsVisible() & .elementIsEnabled() for additional validation and then do the clicks (as per your example) or anything you need.
Oh, not to forget, depending of what you want to do you might need to use indexes if there are multiple elements found either to the .findElement() in case you have only one.
Selenium is really, really fickle when it is trying to find page elements. Surround your driver.findElement with a driver.wait() and see if that allows it to be found.
I have no script abilitiy, but i'd like to edit an existing script which is currently restricting the script from running on any page other then the one that has a certain string in the URL.
Here is the snippet of the script which limits it from running
if(location.href.indexOf("MODULE=MESSAGE")>0||location.href.indexOf("/message")>0)
This only allows the script to run on these pages
mysite/2014/home/11609?MODULE=MESSAGE1
and the pages range from Message1 to Message20
mysite/2014/home/11609?MODULE=MESSAGE20
I would like to also allow the script to be loaded and ran on these pages
mysite/2014/options?L=11609&O=247&SEQNO=1&PRINTER=1
where the SEQNO=1 ranges from 1 to SEQNO=20, just like the MESSAGE1-MESSAGE20 do
Can someone show me how i can edit that small snippet of script to allow the SEQNO string found in the url to work also.
Thanks
If you can't just remove the condition altogether (there's not enough context to know if that's an option), you can just add another or condition (||) like so:
if(location.href.indexOf("MODULE=MESSAGE")>0
||location.href.indexOf("/message")>0
||location.href.indexOf("SEQNO=")>0)
Note that the second clause there isn't actually being used in any of your examples, so could potentially be removed. Also note that this isn't actually checking for a number so it isn't restricted to Message1 to Message20 as you suggest. It would match Message21 or even MessageFoo. That may or may not be a problem for you. You can make the conditions as restrictive or as lose as makes sense.
If you just want to check for the existence of "SEQNO", simply duplicate what is being done for "MODULE_MESSAGE".
if(location.href.indexOf("MODULE=MESSAGE")>0 ||
location.href.indexOf("SEQNO=")>0 ||
location.href.indexOf("/message")>0)
If you want to also ensure that "MESSAGE" ends in 1-20, and "SEQNO=" ends in 1-20, you can use a regex.
// create the end part of the regex, which checks for numbers 1-20
var regexEnd = "([1-9]|1[0-9]|20)[^0-9]*$";
// create the individual regexes
var messageRegex = new RegExp("MODULE=MESSAGE" + regexEnd);
var seqnoRegex = new RegExp("SEQNO=" + regexEnd);
// now comes your if statement, using the regex test() function, which returns true if it matches
if(messageRegex.test(location.href) ||
seqnoRegex.test(location.href) ||
location.href.indexOf("/message")>0)
I would like to count the number of, let's say, div elements with 'nice' class. I've got the selector div.nice, but don't know which casperjs class/method to use.
There is a tester.assertElementCount method in fact, but is there anything that simply returns the number of elements?
Just
document.querySelectorAll("div.nice").length
If you can use jquery its fairly simple:
var count = $('div.classname').length;
Found an SO Post that seems to explain using jquery with casperjs, I have no experience with casperjs so I can't help much there.
One of the examples for CasperJS 1.1-beta3 involves checking the number of Google search results for CasperJS. It references __utils__.findAll(), which takes a selector as its argument. It allows you to check the number of items returned using the length property available to any JS object:
test.assertEval(function() {
return __utils__.findAll("h3.r").length >= 10;
}, "google search for \"casperjs\" retrieves 10 or more results");
I've never tried it, but it seems like this utility function can be used outside a conditional, and it will allow you to report the number of elements without using jQuery, as a previous answer recommended.
Casper provides getElementsInfo, you can use the attribute length to get the number of elements.
e.g.
casper.getElementsInfo('myElement').length
you also can use assertElementCount to assert the count of the elment
test.assertElementCount("div.nice", 1)
I did not find the answers above to be helpful to my cause.
I think the goal was to count the number of elements without having to evaluate the js code in the page context, which could be frustrating overtime and have conflicting variables and functions.
Instead, it would be nice to leverage the casper automation context. This can be done with a combination of ".exists()" and the css psuedo-selector ":nth-of-type(i)"
The code below does this...
var counter = 1; //set to one, for css selector setup
casper.then(function() { //wait your turn
//loop through our element
while(casper.exists( 'div span:nth-of-type(' + counter + ')' )) {
counter++; //count the results
}
});
You could make this a function and pass in all the arguments, or just copy and paste it as a step.
Best part, you could follow it with a repeat statement for a pretty cool loop.
casper.then(function(){
this.repeat(counter, function() {
console.log("Another one - item #" + counter);
});
});
I'm currently writing a javascript game module that takes the following parameter as constructor argument:
{
gameId : "string for unique game id",
cssSelector: "selector for target (used to initialze game)"
}
I have found a way to get around this, see new comment below
I have a pretty good test coverage on everything else, but I can't figure out how to write the following Jasmine test:
describe("Initialization of game", function() {
it("Should throw expection if css selector is not found", function() {
// what goes here?
//negative scenario
expect(function(){
var game = new Game({gameId : '1', cssSelector : "#not-found"});
}).toThrow("Cannot find the element corresponding to cssSelector");
//positive senario
expect(function(){
var game = new Game({gameId : '1', cssSelector : "#found"});
}).not.toThrow("Cannot find the element corresponding to cssSelector");
});
"Solution"
I say "solution", because it feels a bit like a hack to get around this. I use the fact that the test is run in HTML and that I can manipulate the environment. So what I did was:
In the negative scenario, use a specifier that is not found. The first expectation will then not fail.
In between on the positive and negative test case, I used jQuerys .append() method to add a div with id "found" to the body
That's it!
If you need more in depth DOM testing, Jasmine won't do it alone.
For a simple DOM requirements and single test, you can continue doing what you're doing.
For simple, but repeated tests, use beforeEach and afterEach to set up and destroy the DOM elements you need during testing.
For anything but the most simple DOM tests, you could use something like: https://github.com/jeffwatkins/jasmine-dom to extend Jasmine in to the DOM.
Maybe because you are missing a ); after the "#not-found"}?
In jQuery this will work.
If there's such DOM node it will have length greater than 0.
var exists = $('cssSelector').length > 0;
I've set textmate to use softtabs 2 spaces on my file. But when I try to reformat the entire document, it uses 2 hard tabs as the indents.
Regular indents work as I want it to, just the document format doesn't. Anyway to get textmate to be obedient?
Thanks.
The JavaScript bundle's "Reformat Document / Selection" command is passing the document's text to the js_beautify function in the bundle's beautify.php file (found on my system and probably by default at /Applications/TextMate.app/Contents/SharedSupport/Bundles/JavaScript.tmbundle/Support/lib/beautify.php). If you take a look at the function definition you'll see that there's a second parameter, $tab_size, with a default value of 4. There's a line in the bundle that reads print js_beautify($input);. Change this to print js_beautify($input, 2); and you should, I expect, get tab stops with two spaces.
To make it a bit more flexible, use the TextMate environment variable TM_TAB_SIZE, as in print js_beautify( $input, getenv('TM_TAB_SIZE' ) );, which should update how the command operates if you ever change your tab size.
Note, I've tested none of this. :) Just took a look at the bundle and tracked down what seems to be necessary.
So, I tried chuck's suggestion and it gave me an error. I did this to "fix it". I'm sure it could be done more elegantly, but this worked for me.
Open up the same file Chuck says to open up, line 50 (or so) should look like this:
function js_beautify($js_source_text, $tab_size = 4)
change $tab_size to 1
function js_beautify($js_source_text, $tab_size = 1)
Now, around line 56 where it says:
$tab_string = str_repeat(' ', $tab_size);
change the space to a tab like so:
$tab_string = str_repeat("\t", $tab_size);
That worked for me.