I am using cypress for some e2e tests on a react application and I am having problems clicking on an element.
I have this simple script:
it('can bookmark/unbookmark the posting', () => {
cy.visit(pdfPosting.url)
.wait(1000)
.contains('Save')
.should('be.visible')
.click();
cy.visit('/jobs/jobbox')
.contains(pdfPosting.title)
.should('be.visible');
cy.visit(pdfPosting.url)
.wait(1000)
.contains('Saved')
.should('be.visible')
.click();
cy.visit('/jobs/jobbox')
.findByText(pdfPosting.title)
.should('not.exist');
}
});
My problem starts because the Save and Saved buttons are inside a react component that is refreshed several times, for unknown reasons, when page is loaded. Test fails because sometimes the component is refreshed between the contains and the click on the button.
Right now the only way to workaround this problem was adding the waits you see on the test, but I really hate this hack.
First thing I tried to do, was catching the error and retrying the contains.should.click block, but cypress does not allows this (https://docs.cypress.io/guides/core-concepts/conditional-testing.html#Error-Recovery) and ever worst the workarounds proposed on this article are not working to me (or I do not know how to do it)
I also tried to work with events (https://docs.cypress.io/api/events/catalog-of-events.html#Uncaught-Exceptions) but I could not found any that I could use to retry only a part of the code and continue with the execution of the test.
I tried to talk with developers, if they could fix the refresh issue, but the short story is that they won't. Final user does not realize about this refresh on the component and there is not budget to investigate the problem.
Also I was discussing with developers if we could add something, somewhere, to indicate that the loading of the component had finished, but, again, this seems to be not possible. They cant not grant that loading of the component has finished because they do not know where these refreshes come from.
Do you know how I can use cypress to handle this situation?
It's a bad practice use waits in cypress.
I'd suggest use the playground
https://docs.cypress.io/guides/core-concepts/test-runner.html#Selector-Playground
to find your items. Try to follow the Uniqueness principle and use the cy.get('[data-test-selector=you-selector']); instead of wait. It'll wait for you.
For example, visit and cy.get the title page.
Also, if you have animations, it might cause DOM issues with back and forth. If you remove them it'll be faster and more stable.
I need to test if Javascript alert is being displayed in validation proccess after checking one checkbox.
I'm using RSpec, Capybara with Webkit and Database Cleaner.
My test without JS: true :
it "alerts to choose two players" do
set_and_visit
first("input[type='checkbox']").set(true)
expect(page).to have_content('Remember that you must choose two players to start a game.')
end
Finds a checkbox but cannot find the alert message.
When I add JS - "alerts to choose two players", js: true do it returns an error
NoMethodError:
undefined method `set' for nil:NilClass
I've tried using check 'John Doe' and first("input[type='checkbox']").check but it still didn't work.
There are two possible issues that seem likely:
Asynchronous Issues
The default driver (rack-test) is synchronous, so the page will always be fully loaded by the time you run first. When using asynchronous drivers like capybara-webkit, you need to watch out for race conditions. The page may still be loading (or updating via Ajax) when first is called, so the input element may not have appeared yet.
Solution: use find("input[type='checkbox']").set(true) instead of first. This will cause Capybara to wait up to two seconds for the input to appear before giving up and raising an error, instead of immediately returning nil.
I wrote more about writing asynchronous tests in a blog post.
Hidden Elements
Because the default driver (rack-test) doesn't parse CSS or run JavaScript, it doesn't understand which elements are hidden or visible. This means that you can interact with hidden elements that real users can't click on or fill in.
On the other hand, drivers like capybara-webkit know which elements are actually visible to the user. By default, Capybara ignores all elements that it knows are hidden.
Solution: use find("input[type='checkbox']", visible: false).set(true)
Note that this won't work if the element is actually visible, and that it's probably better to figure out why the element is hidden. After all, if capybara-webkit can't find it, your users probably can't, either.
You can read more about how Capybara handles visibility on the elabs blog.
So, silly as it sounds the mistake I made was in a url - in my set_and_visit method I was visiting 'matches/new' instead of '/matches/new'. When tested, puts page.body was returning an empty string because it couldn't find that url.
Still I'm not sure why test including check 'John Doe' wasn't returning any error like the one with js: true.
I'd like to do things like this;
elem1 = document.getElementById(id1);
elem1.click()
// The page has been changed
elem2 = document.getElementById(id2);
elem2.click()
My problem is, if the second 'getElementById(id2)' is called before the HTML of document.documentElement completes its change, it sometimes fails to get elem2 because there is no HTML element that has id2. (Every javascript sentence in the above code is sent from 3rd party like Selenium Server, and there is a javascript loop that gets the sentence and runs it one by one. You can think the loop as a thing like Selenium Core)
I'm trying to write a tool like Selenium or Watir. So I can't use those tools. I think Selenium or Watir has a way to send the second command after it waits until the page has been completely changed as the result of the first command. I tried events like window.onwebkittransitionend because I'm trying this on Webkit, but it did not work.
I don't think promise or async can solve this problem, because it needs more than enforcing sequences. It needs to verify if the second page is fully loaded, because the second command can be the others like fetching the information of rendered images rather than just click.
Is there any event or a way to check if page change is completed? Oh, and I can't use jQuery unfortunately. I need to do it with plain Javascript.
Thanks for reading my question.
A JavaScript plugin that I've been writing recently has various failsafes built in that tell either the whole plugin or parts of it to hide itself and die under circumstances where it can't function. For example, let's say that one piece of functionality we offer is automatically generating a popover that shows competitors' prices for an item when the user hovers over it in an online store. Then we'd also have some checks that say that if we don't know any of the competitor's prices, or we can't identify the item, then don't show a popover.
I want to test that functionality-disabling using tests that follow roughly this structure:
Load our plugin onto a page where certain functionality ought to be disabled
Spoof some user action that would otherwise trigger that functionality
Assert that no visible changes have been made to the DOM. (i.e. no styling changes to visible elements, no addition or removal of elements unless they have display:none on)
Step #3 is the interesting one, of course. Is there an easy way to write that 'DOM unchanged' test in JavaScript? (Or alternatively in Selenium for Python, which is what I'm using to write my tests - but writing the check in JavaScript is probably more broadly useful since it can then be used in any JavaScript-testing environment.)
P.S. A couple of notes to head off the "You're doing it wrong!" crowd:
Yes, I know that I could just replace step #3 in the test above with a check that the specific changes that the plugin would otherwise make have not been made, and I may even decide to do this. But where those specific changes are poorly-specced and liable to change, this catch-all approach could be useful.
Yes, I also realise that just checking there are no immediate visual changes to the DOM when a event that's meant to be effect-free is triggered isn't strictly sufficient to prove that the nothing has broken. It's what'd be best for my current purposes, though. Plus it's interesting and fun even if it turns out not to be useful.
Use Mutation observers to detect that no mutations have occurred. You might want to checkout Mutation Summary, a very nice high-level wrapper for mutation observers. Checking that no mutations have occurred could be easy as checking that the returned array has length 0. See https://code.google.com/p/mutation-summary/.
I run into a common problem when trying to do AJAX development. Where possible, I like to try and just update data in an existing layout, and not the layout itself. For example, take the div below:
<div id="content-5">Here is some content</div>
I would get the updated value for content-5 from the server and just replace the contents of content-5 with the value. This makes a lot of sense for simple data replacements where the value is always going to be displayed in its pure form.
Sometimes the content is more complicated, and I have to actually get more than just raw data... maybe there is some logic to determine how a value is displayed and perhaps the style needs to be different depending on the data inside. In that case, I generally produce the HTML on the server side and inject the HTML into the element instead of just raw data.
Example: A status field from the controller comes back as "complete", but from the design doc, "complete" is supposed to show the user the text "Available" and it needs to be styled in a way different from other statuses.
Doing this in Javascript would require some in-depth view knowledge that the template layer probably already handles. The end result would be the same (code snippet below), but the difference is that there could possibly be some code duplication and a far more complicated Javascript layer.
<div id="content-5"><span class="success">Available</span></div>
Without fail, the requirement comes up that the system will need to handle "new" contents as well. The easiest solution to implement is to just get all of the content's at the same time so that I do not need to handle the extra complexity of injecting a new element instead of just replacing existing content.
So, I create a new template, wrap the contents in another element with an ID, and bulk replace all of the content divs at the same time any time there is a change.
<div id="allContent">
<div id="content-1">Some content A</div>
<div id="content-2">Some content B</div>
<div id="content-3">Some content C</div>
<div id="content-4">Some content D</div>
<div id="content-5">Some content E</div>
</div>
At some point, I have to wonder: Where is the line? At some point it feels like I'll eventually just be replacing the whole page with an AJAX request. Would this really be a problem?
I realize this may be pretty subjective, but what are some good strategies for determining to which level you should be replacing content with AJAX? Replacing just the data seems to be my preferred method when possible as it makes the AJAX controllers very simple. Replacing larger chunks of HTML from a template seems to be the easiest for handling more complicating layout and design issues and also feels like it could be more easily maintained. Are there other options I have not considered?
I expect there will be some discussion about manipulating the DOM programatically, but I personally really dislike this. The code ends up looking pretty horrible and really starts to integrate too much layout and design into the JS layer for my liking. Since I generally work with template libraries of some sort (whether raw PHP, PHP templates like Smarty or JSP in Java) it seems to make more sense to leave as much visual design there as possible.
EDIT
Based on the first few answers, it seems like this is being read as trying to keep the user on the same page but navigating around around the site or otherwise changing the page in a radical way with each update. The question is more about how to determine where the layout work for AJAX calls should happen and whether or not it is an acceptable practice to change large chunks of code with an AJAX request, knowing that replacement code may look nearly identical to what had been there before.
I think the most important requirement is the refresh requirement. If after several AJAX updates I hit refresh, the page I was just looking at should be the page that arrives. If the page reverts to a previous state for any reason then the URL is wrong. If for any reason your AJAX data is going to make the URL in the browser invalid then you should not be using AJAX to fetch that data.
There are exceptions, of course for data the is even newer than the last AJAX request. But that's obviously not what I'm talking about. A live chat screen could receive an update between the last AJAX request and the refresh. No big deal. I'm talking about the logical content and the URL describing it should always be in sync.
Complete personal opinion ex nihil, my rule of thumb is to change no more than 1 "panel" unit or 33% of the page whichever is less.
The basis for this is that the user should be able to clearly recognise the previous page state is related to the new state - how would you feel if you were suddenly teleported into the building to your right? Be gentle with your poor user.
There are also serious technical questions about the benefits of moving and inserting basically a page worth of data, which I think is a bit of an AJAX anti-pattern. What benefit does AJAX provide if you're going to do that?
Your specific question seems dependant on the supposition that the response coming back from your AJAX request isn't "just" data. This feels wrong to me from a separation of concerns point of view: I would expect a page to have all the layout information it requires already, the AJAX response itself to provide nothing more than dumb data/markup, and the JS event handler which created the request to sew the two together, MVC style. In that respect I think, yes, you're doing too much.
(by panel, I mean one logical design element - a menu, a ribbon, an item metadata panel, etc..)
edit: now that I think about it, I think SO's user profile page breaks my rule of thumb with those tab clicks
Depending on whether you want people to be able to to link to / bookmark etc the current page, you might want to navigate the user's browser.
This isn't a concern for some apps like GMail etc, and they won't ever refresh the page.
For myself, I tend to think it's a good practice to navigate the browser when navigating to a logically different place. eg. a person's profile vs. a list of their messages.
Sorry if this is vague, it's rather subjective :-)
A good guideline for something like this is to ask yourself, "Is this dynamic application 'content', or is it content-content?" Your use case sounds like application content that will change with each user. This is probably the best place for Ajax, but with everything, it's always nice not to just have one hammer. You don't want to do too much on one page. For instance, if one part breaks, the entire thing might, thereby frustrating the user.
Anywhere you're looking at actual page content or anything where the information is static, I strongly suggest avoiding the use of JavaScript, as it runs the risk of being invisible to search engines. Make sure anything linking to information like this is crawlable. The first step towards this is dynamic generation on the server side rather than browser side.
If you're using Smarty templates to produce a page, just fragment a template into various meaningful sections - news.tpl, email.tpl, weather.tpl - and have a master.tpl producing the structure of the page and calling child templates.
Then, if you're for example using an AJAX call triggered by a timeout to refresh the news, you can just call the server, cram the necessary data into news.tpl, and return the results into the news div you set up with master.tpl. This way your news layout is always following the pattern of news.tpl. (If you used JavaScript to manipulate formatting bits or set up event handling on document load, you'll need to attach that post-processing to fire after the AJAX call.)
You haven't really gotten specific about the types of things you're trying to replace here, and my initial reaction is that, if a single event is triggering multiple sections of the page to update at once, that's a sign that maybe you should be coallating those sections into a single display.
How much formatting gets done on the server end versus how much gets done on the client end with JavaScript? I'd say server-side formatting if possible, that way you have code that reflects discussions you've made about display layout and logic. Client-side formatting can be used for more interface-based issues - sorting rows in a table and alternating row colors with :odd and :even selectors, showing and hiding divs to create a "tabbed display" without hitting the server since the data won't change just from selecting a new tab, that sort of thing.
Finally, AJAX is one-way. If your web page is a view on a database, this isn't as much of a problem, but using AJAX manipulation to take the place of normal navigation is a terrible idea.
If you were habitually replacing the entire contents of a page using AJAX calls, I would agree that you have a problem. However, it appears to me that you are attempting to carefully think through the implications of your design and attempting, where possible, to avoid what annakata has called this "AJAX anti-pattern."
My rule is a bit simpler: as long as a substantial amount of context (e.g. menu on the left, header, various controls, page title, etc.) remains on a page, I am Ok with replacing almost anything with an AJAX call. That being said, I've never struggled with a page that has as much AJAX-generated code as you are.
I do have one question though: isn't it possible to encode state so that you can just replace some of the Divs in your example rather than all of them? If not, have you thought about doing so?