How can I test JQuery UI Sortable with Cucumber - testing

I'm tryting to write a cucumber/capybara test to reorder some items and then save them back. Any thoughts on how to best do this?

I have developed a JQuery plugin to solve this problem, check out jquery.simulate.drag-sortable.js which includes a plugin along with a suite of tests and examples.
Hope you find this useful! Feedback is welcome.
Matt

the drag_to method did not work for me. But I was able to cause the first element in my list to be dragged to the last position by including the following in my capybara selenium test using jquery.simulate.js :
page.execute_script %Q{
$.getScript("/javascripts/jquery.simulate.js", function(){
distance_between_elements = $('.task:nth-child(2)').offset().top - $('.task:nth-child(1)').offset().top;
height_of_elements = $('.task:nth-child(1)').height();
dy = (distance_between_elements * ( $('.task').size() - 1 )) + height_of_elements/2;
first = $('.task:first');
first.simulate('drag', {dx:0, dy:dy});
});
}

I'm using a web step like this and it works fine:
When /^I drag "([^"]*)" on top$/ do |name|
item = Item.find_by_name(name)
sleep 0.2
src = find("#item_id_#{item.id}")
dest = find("div.title")
src.drag_to(dest)
end

For me, #drag_to did work, however, its powers seem to be limited.
In order to move a UI-sortable table row down, I had to create a table with three rows, then run this Cucumber step:
# Super-primitive step
When /^I drag the first table row down$/ do
element = find('tbody tr:nth-child(1)')
# drag_to needs to drag the element beyond the actual target to really perform
# the reordering
target = find('tbody tr:nth-child(3)')
element.drag_to target
end
This would swap the first with the second row. My interpretation is that Capybara does not drag far enough, so I gave it a target beyond my actual target.
Note: I have configured UI-sortable with tolerance: 'pointer'.

I followed #codener's solution and it works! The only thing I changed in my code is configuring the UI-sortable with tolerance: 'pointer'.
The limitation described in #codener's answer is not gone, too. (I'm using capybara 2.18.0.) It doesn't need the third row to swap the first with the second row.
When /^I drag the first table row down$/ do
element = find('tbody tr:nth-child(1)')
target = find('tbody tr:nth-child(2)')
element.drag_to target
end

Related

Swithcpage or new tab is not working in karate framework - it is always pointing to first page [duplicate]

I am having an issue with switching tabs using Karate UI. My code is as follows:
Scenario: SwitchPage Test
Given driver 'original URL'
* retry(5, 10000).waitFor('#someID')
* input('#someID', ['numbers', 'input', Key.ENTER]) // this will open the new page
* print driver.title \\ this prints the original title of the original URL
* switchPage('NewURL')
* delay(10000) // I've put this just in case but it doesn't work without it either
Then print driver.title // this still prints the original title of the original URL
Any help would be really appreciated, I think it is a great tool but I'm having difficulty with this scenario and our application opens new tabs with every module.
Thank you
Yes I know this can be hard. In 0.9.6 we have an option to switch tab by a) index and b) sub-string of the URL of that tab
Do consider submitting a simple example that can help us simulate and improve Karate if needed: https://github.com/intuit/karate/tree/develop/examples/ui-test
Finally I recommend this option if possible. If there is some way for you to derive the URL of the tab that will get opened, try to re-use the current tab, and that makes for a simpler test. See this thread for more details: https://github.com/intuit/karate/issues/1269#issuecomment-682553602
Also see: https://stackoverflow.com/a/62727612/143475

How to switch to a window (NOT TAB) in karate? [duplicate]

I am having an issue with switching tabs using Karate UI. My code is as follows:
Scenario: SwitchPage Test
Given driver 'original URL'
* retry(5, 10000).waitFor('#someID')
* input('#someID', ['numbers', 'input', Key.ENTER]) // this will open the new page
* print driver.title \\ this prints the original title of the original URL
* switchPage('NewURL')
* delay(10000) // I've put this just in case but it doesn't work without it either
Then print driver.title // this still prints the original title of the original URL
Any help would be really appreciated, I think it is a great tool but I'm having difficulty with this scenario and our application opens new tabs with every module.
Thank you
Yes I know this can be hard. In 0.9.6 we have an option to switch tab by a) index and b) sub-string of the URL of that tab
Do consider submitting a simple example that can help us simulate and improve Karate if needed: https://github.com/intuit/karate/tree/develop/examples/ui-test
Finally I recommend this option if possible. If there is some way for you to derive the URL of the tab that will get opened, try to re-use the current tab, and that makes for a simpler test. See this thread for more details: https://github.com/intuit/karate/issues/1269#issuecomment-682553602
Also see: https://stackoverflow.com/a/62727612/143475

Capybara, selecting 1st option from dropdown?

I've done a search and most of the related google results have returned just in general selecting an element from a dropdown. However the ID's in this case for the elements in the dropdown are dynamically generated unfortunately.
This is for a base test case, so I basically just need to select for example the first one. The text is also the same for the elements in the dropdown (not sure if that helps).
Is there such an example of this?
Im using cucumber with caybara(using selenium driver) integration
You can find the first option element and then use the select_option method to select it.
For example, if the select list has an id "select_id", you can do:
first('#select_id option').select_option
As #TomWalpole mentions, this will not wait for the element to appear. It would be safer to do one of the following:
first('#select_id option', minimum: 1).select_option
or
find('#select_id option:first-of-type').select_option
Alternatively you can get the first element text then select it by select function:
first_element = find("#id_of_dropdown > option:nth-child(1)").text
select(first_element, :from => "id_of_dropdown")
After two days of searching and reading, this article was amongst one of a few that was helpful. Hopefully, this can help someone else!
I created a few methods like so, excuse the naming..I changed it.
def some_dropdown(id, text)
dropdown = find(id).click
dropdown.first('option', text: text).select_option
end
def select_form
within 'content#id' do
some_dropdown('#id', text)
click_link_or_button 'Submit'
end
end
I also referenced this.
I've tried to select an option from a modal dropdown. After trying all listed methods, and many other from other threads - I totally gave up and instead of using clicks or select_option just used keyboard keys
find(:select, "funding").send_keys :enter, :down, :enter
In case it still complains - try:
find(:select, "funding", visible: false).send_keys :enter, :down, :enter
Worked like a charm, selecting first option from a dropdown.

What is the functioning of fireevent() in HP QTP / UFT?

I am learning HP UFT.
Recently I came across fireevent and I tried to implement it on the website of Flipkart. I was trying to use firevent("onmouseover") for the link Men on the homepage of the website.
I used ChildObjects to find out the Link and WebElement (in two different tests), first Highlighted it and then used object.fireevent("onmouseover") as well as object.fireevent("OnClick"). The OnClick is working and it is showing the link as selected (i.e. the dotted box covering the link when we press tab), but it is not showing the Menu Under Men Section.
I had googled and bingged a lot. But was unable to find the exact working of FireEvent in QTP/UFT.
Please Help me solving the above problem as well as some tutorials on FireEvent.
EDIT: I am using IE 11 for testing.
Motti has already answered the technical definition, but I shall attempt to give you a solution to your functional issue.
In my experience .FireEvent often doesn't work as you would expect. An alternative for something like onmouseover is to simulate user behaviour a bit more closely by actually moving the mouse to the desired location. In our framework we have a little extension function to do just that, a pared-down version of which is shown here:
Sub My_MouseOver(objSender)
Dim absX : absX = objSender.GetROProperty("abs_x")
Dim absY : absY = objSender.GetROProperty("abs_y")
Dim width : width = objSender.GetROProperty("width")
Dim height : height = objSender.GetROProperty("height")
Dim x : x = (absX + (width / 2))
Dim y : y = (absY + (height / 2))
Dim deviceReplay : Set deviceReplay = CreateObject("Mercury.DeviceReplay")
deviceReplay.MouseMove x, y
Reporter.ReportEvent micDone, "A step name", "A useful step description"
End Sub
RegisterUserFunc "Link", "MouseOver", "My_MouseOver"
RegisterUserFunc "WebButton", "MouseOver", "My_MouseOver"
RegisterUserFunc "WebElement", "MouseOver", "My_MouseOver"
As an example you can then do as follows to bring up the "ELECTRONICS" menu overlay on flipkart.com (obviously substitute your own Browser and Page definitions):
Browser("Flipkart").Page("Main Nav").Link("xpath:=//a[#data-tracking-id='electronics']").MouseOver
In the original version there's various extra bits of error handling and custom reporting so it tells you what you clicked on, but the essence is the same. It locates the object on screen, calculates the centre and moves the mouse there. You might want to wait a small amount of time for the menu overlay to appear after doing so before calling .Click on one of the newly-displayed sub-elements.
I found a solution to my problem and it is working perfectly.
Setting.WebPackage("ReplayType") = 2
object.FireEvent "onmouseover"
Setting.WebPackage("ReplayType") = 1
In this case, the object will be:
Browser("name:=Online Shopping.*").Page("name:=Online Shopping.*").Link("innertext:=Men")
I have tried this and it is working fine. I guess, we do not need any alternatives. But I really don't know is, Ctrl+Space is not working for this in UFT. Don't know the reason.
This actually depends on what browser you're using.
Warning: There are exceptions to the information presented in this answer and it also may change in the future. The answer is meant to give a basic understanding but don't depend on it to be true without checking the behaviour for your specific version/use-case.
Originally QTP's FireEvent was supposed to call IE's non-standard fireEvent method.
On Firefox and Chrome this is implemented using the standard dispatchEvent. You should check which events the web site expects to get.
Things get complicated if you mix the event models (the standard DOM level 2 and Microsofts) as explained in this blog post.

Assert css locator is equal to it's expected value

I'm doing some drag and drop js testing with selenium-client. It works (taking screengrabs before and after clearly show the elements to switch places), but I'm having trouble programatically asserting the change happened.
Am I mental, or can I not do something like:
selenium.assert_equal("css locator", "expected id of element")
which, in this case, would look something like:
selenium.assert_equal("css=li:nth-child(1)", "li#list_item_2")
Any tips on how to implement this would be great.
Thanks,
Adam
Edit: if I had selenium.get_element that would take a selector and return what it was, I could then perform the assertion in the next step.
i.e.
element = selenium.get_element("css=li:nth-child(1)")
assert_equal(element, "li#list_item_2")
(I think).
Your example won't work because you're comparing two strings that aren't equal. One way to assert that your element has moved would be to use isElementPreset as demonstrated below:
//before drag and drop
assertTrue(selenium.isElementPresent("css=#source li:nth-child(1)"));
assertFalse(selenium.isElementPresent("css=#target li:nth-child(1)"));
//drag and drop code here
...
//after drag and drop
assertTrue(selenium.isElementPresent("css=#target li:nth-child(1)"));
assertFalse(selenium.isElementPresent("css=#source li:nth-child(1)"));
This example uses the Java client API, but it should be easy to work out how to do it in your preferred client API. It will also depend heavily on your application, as the above will check that the element with id of 'target' has one child li element before the drag and drop, and none afterwards. If you have a snippet of your HTML source I might be able to prove a more robust example.