Capybara not following javascript redirection after select - coffeescript

I have a simple select tag:
<strong>Choose: </strong><%= select_tag(:topic_id, options_for_select([
['Choose','#'],
['Schools',schools_path],
['Spells', spells_path],
['Traits', traits_path],
['Clans', clans_path],
['Skills', skills_path]])) %>
And I have an coffeescript redirector:
$(document).on 'change','#topic_id', ->
window.location.replace($(this).val())
By hand everything works great but when I try to test it with capybara it won`t fallow the redirect after select.
feature "legend school page" do
background do
visit legend_path
select('Schools', from: 'topic_id' )
end
scenario "it should have right topic" do
expect(page).to have_title "Schools"
end
From what I have read capybara should use javascript, and it should work like this. But I just start learning, so I am probably wrong.

The default driver for Capybara is racktest which doesn't support JS. You'll need to use a js capable driver for your test to work - see drivers

Related

Karate: How to wait for a spinner to disappear? [duplicate]

Firstly, Karate UI automation is really awesome tool. I am kind of enjoying it while writing the UI tests using Karate. I ran into a situation where in, i was trying to fetch the shadowRoot elements. I read few similar posts related to javascript executor with karate and learnt that it is already answered. it is recommended to use driver.eval. But in Karate 0.9.5 there is no eval, it has script() or scriptAll(). I have gone through documentation couple of times to figure out how i can fetch element inside an element but no luck.
Using traditional selenium+java, we can fetch shadowRoot like this way:
something like shadowRoot which sits inside a parent element like div or body.
//downloads-manager is the tagname and under that downloads-manager, a shadowRoot element exists
The HTML looks like this. it is from chrome://downloads.
<downloads-manager>
#shadow-root(open)
</download-manager>
WebElement downloadManager =driver.findElement(By.tagName("downloads-manager");
WebElement shadowRoot= (WebElement)((JavaScriptExecutor)driver)
.executeScript("return arguments[0].shadowRoot",downloadManager);
So i tried the following in Karate UI
script("downloads-manager","return _.shadowRoot"); //js injection error
script('downloads-manager', "function(e){ return e.shadowRoot;}"); // same injection error as mentioned above.
def shadowRoot = locate("downloads-manager").script("function(e){return e.shadowRoot};"); //returns an empty string.
I bet there is a way to get this shadowRoot element using Karate UI but i am kind of running out of options and not able to figure out this.
Can someone please look into this & help me?
-San
Can you switch to XPath and see if that helps:
* def temp = script('//downloads-manager', '_.innerHTML')
Else please submit a sample in this format so we can debug: https://github.com/intuit/karate/tree/develop/examples/ui-test
EDIT: after you posted the link to that hangouts example in the comments, I figured out the JS that would work:
* driver 'http://html5-demos.appspot.com/hangouts'
* waitFor('#hangouts')
* def heading = script('hangout-module', "_.shadowRoot.querySelector('h1').textContent")
* match heading == 'Paul Irish'
It took some trial and error and fiddling with the DevTools console to figure this out. So the good news is that it is possible, you can use any JS you need, and you do need to know which HTML element to call .shadowRoot on.
EDIT: for other examples of JS in Karate: https://stackoverflow.com/a/60800181/143475

hyperHTML seemingly fails to call (attach?) onload events

I'm attempting to dynamically conditionally load additional JavaScript while using hyperHTML. I've narrowed the failure to the onload event.
Here's an attempt at a minimal, complete, and verifiable example:
class ScriptLoader extends hyperHTML.Component {
onload(event) {
notie.alert({ text: "notie loaded" });
}
render() {
return this.html`
<script
src=https://unpkg.com/notie
type=text/javascript
async=false
onload=${this}
/>
`;
}
}
hyperHTML.bind(document.body)`
<h2>onload test (notie)</h2>
${new ScriptLoader}
`;
<script src="https://unpkg.com/hyperhtml#2.4.0/min.js"></script>
As you can see notie.alert is never called, even though the script is inserted correctly.
This some process works correctly using vanilla JS with addEventListener('load', and appendChild(.
Update this was an issue with Firefox and Web (Safari) considering death nodes scripts injected via innerHTML, even if through a template and after imported.
That means the issue was not with the onload per-se, rather the fact no network request was ever triggered so that onload would never happen indeed.
As you can verify now in the Code Pen eaxmple, which uses your exact same snippet I rewrite in part to make SO happy about me linking Code Pen, both Firefox and Safari, as well as Chrome and Edge should work just fine.
hyperHTML.bind(document.body)`
<h2>onload test (notie)</h2>
${new ScriptLoader}
`;
I am keeping part of the old edit just to make you, or any other reader, aware of a little caveat that JSX affectionate might overuse.
There is one thing you should be careful with: hyperHTML does not parse HTML and <script/> is not valid HTML.
You are risking to find nodes where you shouldn't if you don't close non-void tags regularly, and this is beyond hyperHTML capabilities, unfortunately how HTML works in general.
<p/><b>unexpected</b>
I understand for this demo case you had to do that or the parse would complain with a closing script in the page but remember, you can always do this instead, when necessary:
`<script><\x2fscript>`

coffeescript - run after page load

I'm very new to CoffeScript and want to edit some code that I found. Right now, it runs this function right when the DOM is loaded:
jQuery ->
$('#s3-uploader').S3Uploader
How can I rewrite it such that it only runs after the page is loaded? I need to wait so I can get the correct instance variables:
(on page load) ->
$('#s3-uploader').S3Uploader
additional_data: {project_id: #project.id, step_id: #step.id, user_id: current_user.id}
This is quite an old question, and no doubt you have found a solution already. But for the benefit of anyone coming here from Google....
It is also not 100% clear from your question, but you appear to be using a framework such as Ruby on Rails.
If so, then the correct answer of course is that you should not be accessing instance variables from Coffeescript. Coffeescript files in the asset pipeline are compiled during deployment, and have no knowledge of the controller or instance variables.
The correct way is to assign these variables to data attributes in the DOM, and then reference the data attributes.
#view.html.erb
<div id="uploader" data-project_id="<%= #project.id %>" ></div>
#script.coffee.js
(on page load) ->
$('#s3-uploader').S3Uploader
additional_data: {project_id: $('#uploader').data('project_id') .... }
For rails, this worked for me when all the other answers here did not:
$(document).on "turbolinks:load", ->
You're looking for $(document).ready event handler.
$(document).ready ->
$('#s3-uploader').S3Uploader
checkVariable = ->
if variableLoaded == true
# here is your next action
else
return
setTimeout 'checkVariable()', 1000

#javascript cucumber tests pass using selenium driver but fail when using poltergiest

I'm trying to test an jquery UI autocomplete, I've got the tests passing using the selenium driver. I want to switch to poltergiest for some headless testing, but now my tests are now failing.
It doesn't seem to select the autocomplete option for some reason that I have yet been able to figure out
Step
When /^select contract$/ do
VCR.use_cassette("contract") do
selector =
'.ui-menu-item a:contains("John Smith (123456)")'
within("div#review") do
fill_in("contract", with: "john")
end
sleep 2
page.execute_script "$('#{selector}').trigger(\"mouseenter\").click();"
within("div#myPerformaceReview") do
find_field("contract").value.should ==
"John Smith (123456)"
end
end
end
The test passes using the Selenium driver without any changes to the step.
Any advice on how I could debug this?
Version
selenium-webdriver (2.27.2)
poltergeist (1.0.2)
cucumber (1.2.1)
cucumber-rails (1.0.6)
capybara (1.1.4)
phantomjs 1.8.1
I've managed to figure it out, it seems capybara-poltergeist driver doesn't trigger any of the events that jquery-ui uses to display the dropdown list.
I found the answer here: https://github.com/thoughtbot/capybara-webkit/issues/50
I created a form helper in features/support
module FormHelper
def fill_in_autocomplete(selector, value)
page.execute_script %Q{$('#{selector}').val('#{value}').keydown()}
end
def choose_autocomplete(text)
find('ul.ui-autocomplete').should have_content(text)
page.execute_script("$('.ui-menu-item:contains(\"#{text}\")').find('a').trigger('mouseenter').click()")
end
end
World(FormHelper)
I then used those method to fill in the form and select the desired option.
Martin's answer almost worked for me, but I found that the input needs to be focused as well to make it work:
module FormHelper
def fill_in_autocomplete(selector, value)
page.execute_script %Q{$('#{selector}').focus().val('#{value}').keydown()}
end
def choose_autocomplete(text)
find('ul.ui-autocomplete').should have_content(text)
page.execute_script("$('.ui-menu-item:contains(\"#{text}\")').find('a').trigger('mouseenter').click()")
end
end
Found this on the same page: https://github.com/thoughtbot/capybara-webkit/issues/50#issuecomment-4978108

How can I make a rich web application in Perl?

I have a Perl command-line script that I want to convert to a rich. cross-platform desktop GUI application. What's the best method to do it. I want to the internal and the logic code in Perl but the GUI should be rich web application.
I have been working on the Perl module XUL::Gui on CPAN which uses Firefox as a host platform to render cross platform gui's from Perl. All you need is Firefox installed on the target platforms. It is currently in development, but may be stable enough for your needs. Here is a brief example of how the syntax looks:
use XUL::Gui;
display Window title => 'Foo Processor',
Hbox(
(map {
my $id = $_;
CheckBox id => $id,
label => "use $id",
option => sub {shift->checked eq 'true' ? " -$id" : ()}
} qw/foo bar baz/
),
TextBox( id => 'num',
type => 'number',
option => sub {' -num ' . shift->value}
),
Button( label => 'run', oncommand => sub {
my #opts = map {$ID{$_}->option} qw/foo bar baz num/;
$ID{txt}->value = `fooproc #opts`;
}),
),
TextBox( FILL, id => 'txt' );
Since it is under development, if you have any feature requests (or find any bugs) let me know.
Also, since you are inside of Firefox, any web technologies that Firefox supports (canvas, iframes, flash...) are fully usable from Perl. For gui components, you can use any combination of HTML and XUL tags.
Mojolicious is a light but yet powerful Web framework which is particularly useful to wrap scripts into quick and well done Web apps.
We are using it extensively on the local network to let colleagues make use of the scripts we develop on our Unix boxes, whatever their platform. For simple tasks, you can even pack everything (templates and routing) in one file: check Mojolicous::Lite.
Does it need to be a rich, native-OS style GUI? Or just any old user interface? You could get something up and running very quickly with CGI::Application - it's probably the best balance between clean, maintainable code and a short learning curve. For more heavily duty work, Catalyst seems to be the weapon of choice.
If you want to make a full-featured GUI with menus and draggable dialog boxes etc. Perl is probably not the best candidate.
If by the gui should be web for cross platfrom you mean it should be written using HTML / CSS /JavaScript, one solution is to use HTTP::Server::Simple::CGI in conjunction with CGI::Application and HTML::Template. Browser::Open completes the required minimal functionality.