Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails, Cucumber, Capybara, Selenium, Pow, domains, subdomains and javascript

TL:DR - How can I make Cucumber request a page through the app but pretend that the request came from "http://mysubdomain.mydomain.dev", and run the javascript properly?

Ok, this may take a while to explain, but please bear with me...

I'm a 'relatively' experienced Rails dev, but only recently took the plunge into full BDD/TDD.

The page I'm testing in cucumber has some javascript in it for creating a new nested object (very similar to this RailsCast).

Now the problem lies in the fact that not only do I have variable sub-domains, I have variable Domains too (Just trust me on that one...)

So the app needs to query the request.host to find the current_domain and the current_subdomain before everything ties up in the background and it can carry on serving the right bits of the app.

I've managed to get all of the tests passing fine using the host! domain and Capybara.default_host = domain techniques in the background steps.

However, when I use the @javascript tag on the feature that tests a page with .js on it, I get Firefox grabbing focus, then trying to load the full url.

Now it also happens that I'm running Pow, and have those urls hooked up to the dev server. Unsurprisingly, they don't work as when the user tries to log in, it's looking in the dev DB. I tried running the suite after turning the pow server off, and it just timed out.

Surely the javascript webdriver shouldn't be actually accessing the url, but simply running the app itself and pretending that the host is what I tell it to be???

I'm obviously missing something here - How can I make Cucumber build the page internally, but pretend that the request came from "http://mysubdomain.mydomain.dev"?

edit: Jason - the variable domain trick is achieved exactly the same as subdomains... If you can query the db for an account based on request.subdomains.first, you can query for a domain through request.domain. You just have to double check a few things like capitalisation etc. to minimize the risk of a malformed url breaking stuff, and obviously you need to ensure that the domain record exists in the db first...

Oh - and cache the domain record requests with care...

It means that you can serve the same app, but with different styling and landing pages etc. Useful for PaaS apps with a broad customer base - you can re-brand it and sell it as a specific solution to one group's problems, even though it's the same guts underneath.

like image 447
Jules Copeland Avatar asked Oct 08 '22 18:10

Jules Copeland


1 Answers

I am looking to do something very similar. I thought about adding an additional pow directory for test, then using the pow directives to override the environment. I think this is done within a ".powenv" inside your app directory. Here is an example of a quick fix:

echo export RAILS_ENV=cucumber > .powenv && touch tmp/restart.txt

But it would be better to do something dynamic so that before you start the test, you can tell pow what env to run, then when finished switch back, maybe even run the test server on a different port on a temp basis. Pow is the only great solution I know of so far for handeling subdomains.

EDITED: I have this working now in my environment with the following addition to my features/support/env.rb file.

# Switch Pow to For Cucumber Tests
Capybara.default_driver = :selenium # Subdomain testing will only work with pow and selenium
pow_config = "#{Rails.root}/.powenv" # Dont change, this is the Config Files Location.
pow_config_stash = "#{Rails.root}/.powenv_original" # This is what the config will be stashed as during testing.

Before do

  # Set the default host
  Capybara.app_host = "http://www.resipsa.dev"

  # Stash the existing config
  File.rename(pow_config,pow_config_stash) if File.exists? pow_config

  # Write the new pow config
  f = File.new("#{Rails.root}/.powenv", "w")
  f.write "export RAILS_ENV=test"
  f.close

  # Touch tmp/restart.txt to force a restart
  FileUtils.touch "#{Rails.root}/tmp/restart.txt"

end

After do

  # Delete the temp config
  File.delete(pow_config)

  # Restore the Original Config
  File.rename(pow_config_stash,pow_config) if File.exists? pow_config_stash

  # Touch tmp/restart.txt to force a restart
  FileUtils.touch "#{Rails.root}/tmp/restart.txt"

end
like image 74
Jason Waldrip Avatar answered Oct 12 '22 10:10

Jason Waldrip