Skip to content

Conversation

danrasband
Copy link
Contributor

After seeing the pull request at #471, I took it upon myself to push this along.

I've replicated the changes made in the above pull request, adding a few more changes for consistency, and also included tests.

To rehash what is in the above pull request, basically it makes it possible to run controller, mailer, requests, and routing specs when your site uses a rails engine to handle its routing. So, if you're using an engine like Spree, for example, you can add the following to your spec_helper.rb:

RSpec.configure do |config|
  config.application = MyApp::Engine
end

or, in the case of Spree:

RSpec.configure do |config|
  config.application = Spree::Core::Engine
end

Please let me know if you need any more information or if more work needs to be done.

@travisbot
Copy link

This pull request fails (merged 83e24bc into 0677052).

@danrasband
Copy link
Contributor Author

None of the rspec tests fail for me on this one, but about half of the cucumber tests do. I tried running the cucumber tests on the unchanged master in my fork with the same result, though, so I think my changes are good.

@justinko
Copy link
Contributor

Thanks for the pull! Tried it on Rails 3.0.12 and got this error:

/Users/justinko/code/rspec-dev/repos/rspec-rails/spec/support/engine_example.rb:9:in `<top (required)>': undefined method `routes' for RSpec::EngineExample:Class (NoMethodError)

Let me know if you have trouble setting up to test with different Rails versions.

@danrasband
Copy link
Contributor Author

Ah, that makes sense. This was my first pull request ever And I'm still pretty new to rails, so I didn't even think of testing across multiple versions of rails. My guess is that I'll somehow have to write version-specific code for rack applications. Is that an accepted practice for gems?

@justinko
Copy link
Contributor

Should be pretty simple to support Rails 3.0.x. You'll have to dig in and find the differences - you can do Rails.version to get the Rails version. I'd like to make it very explicit that "this code is for Rails 3.0.x" instead of just using a respond_to? or something - so we know to remove it when the time comes.

This commit adds Rails version checking to the RSpec application
configuration to handle Rails 3.0.x. The Rails::Engine class, while
available in Rails 3.0, does not have the capability to draw routes as
it does in 3.1 and above.
@travisbot
Copy link

This pull request passes (merged acd46c2 into 0677052).

@justinko
Copy link
Contributor

Just to be clear, this feature will not work on Rails 3.0.x?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's change this file name (and module name) to "application" - it really has nothing to do with "engines".

Also, let's always load this file (I know I said not to in a previous comment). We can then override the writer method to raise an error if it's not supported:

RSpec.configuration.add_setting :application, :default => ::Rails.application

unless rails_3_0?
  def Rails.configuration.application=(*)
    raise "Setting the application is only support on Rails 3.1 and above"
  end
end

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should I add the override method to the application support file (I have now changed it to application.rb)?

It seems like you can't override a method this way, because I'm getting this error:

rspec-rails/lib/rspec/rails/application.rb:7: syntax error, unexpected '.', expecting ';' or '\n' (SyntaxError)
        def Rails.configuration.application=(*)

It doesn't seem to like this form of overriding...

@justinko
Copy link
Contributor

BTW, thanks for your patience! I know we'll emerge with some clean code :)

@danrasband
Copy link
Contributor Author

Thank you for reviewing all of my code!!! All of your suggestions are extremely helpful. I'll work on implementing them as soon as I can.

And yes, I'm pretty sure that we'd have to make the application configuration option only available for Rails 3.1+.

@zamith
Copy link

zamith commented May 25, 2012

I solved this problem with

before(:each) { @routes = MyApp::Engine.routes }

which I don't feel is really nice, would love to have this pulled and documented, since I found it hard to get working.

Keep up the good work. ;)

@danrasband
Copy link
Contributor Author

Unfortunately I found some bugs with the most recent commit (acd46c2). Using the configuration option makes some controller tests fail. I'll do some more research when I have the time to figure out what's going on.

@danrasband
Copy link
Contributor Author

I've gotten everything working (and tests passing) except for one thing: overriding the RSpec.configuration.application= method. I also opted to name the method for determining rails version compatibility as follows:

at_least_rails_3_1?

I put this method in lib/rspec/rails.rb as a global method, but I'm not sure if this is a good idea:

# ... some code ...

# METHOD TO BE ADDED HERE
def at_least_rails_3_1?
  Gem::Version.new(Rails.version) >= Gem::Version.new('3.1.0')
end

require 'rspec/rails/extensions'
# ... some more code ...

Any suggestions?

@justinko
Copy link
Contributor

justinko commented Jun 2, 2012

@danrasband can you push the code please?

This commit removes most if-statements from the example groups,
consolidating to a global method called `at_least_rails_3_1`. It
also adds filters to the rspec tests and changes engine_support.rb
to application.rb.
@travisbot
Copy link

This pull request passes (merged 1c451f8 into 0677052).

@justinko
Copy link
Contributor

justinko commented Jun 6, 2012

I've gotten everything working (and tests passing) except for one thing: overriding the RSpec.configuration.application= method.

What problem is it giving you? Looks like your implementation should work.

Adds an override of Rails.configuration.application=(*) setter to
raise an error when Rails.configuration.application is set in Rails
3.0. Also moves at_least_rails_3_1? method to the RSpec::Rails module
as a public module method.
@danrasband
Copy link
Contributor Author

I got everything working now (I think). Thanks for all the help!

@travisbot
Copy link

This pull request passes (merged b694543 into 0677052).

@justinko
Copy link
Contributor

Awesome! Going to merge this in a bit.

justinko added a commit that referenced this pull request Jun 23, 2012
Added configuration to allow for custom application engine.
@justinko justinko merged commit 248ce66 into rspec:master Jun 23, 2012
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@danrasband @justinko Does this need to happen via RSpec config? Any reason not to just set Rails.application = xxx?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dchelimsky Side note: the implementation of this feature on master is drastically simpler.

@danrasband Can you please confirm @dchelimsky's question? Thanks.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I saw the implementation and agree it's clean - my issue is that this is not really an RSpec concern - it's a Rails concern.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dchelimsky I don't really know the answer to your question. I'll try to do some experimentation, and if doing Rails.application = xxx works and doesn't have unintended side effects, then I think that may be the way to go.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm planning to release 2.11 this weekend, but I don't want to include this as/is. @danrasband - will you have time to look at this before then?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I should be able to look at this today or tomorrow.

dchelimsky added a commit that referenced this pull request Jul 7, 2012
- not ready for release so backing out
- changes are stored in engine-support branch
@dchelimsky
Copy link
Contributor

I branched off master to the engine-support branch and then backed out these changes on master for the 2.11 release. We can revisit for the next release.

@jfirebaugh
Copy link
Contributor

Should this be reopened? It seems like it's still an issue in 2.12.

@alindeman
Copy link
Contributor

@jfirebaugh, you mean the code here didn't actually fix the issue?

@jfirebaugh
Copy link
Contributor

From my reading of the comments, the changes got backed out in 2.11, to be revisited for 2.12. Did it actually get reinstated in 2.12?

@alindeman
Copy link
Contributor

Oh. Right. Let me restore my context on this (might be Sunday or Monday) and get back to you.

@alindeman
Copy link
Contributor

As far as I can tell, setting ::Rails.application = MyEngine::Engine (e.g., in spec_helper.rb) removes the need to use the use_route option (described in the Testing Rails Engines guide) in controller specs.

Does this work for everyone?

/cc: @jfirebaugh, @danrasband

@jfirebaugh
Copy link
Contributor

No, that doesn't work. My specs fail with all sorts of errors, most prominently:

ActionView::Template::Error: undefined method `assets' for #<Rails::Engine::Configuration:0x007f7f9a27b5e8>

I'm pretty sure that for engine tests, a full dummy application is needed.

@jfirebaugh
Copy link
Contributor

BTW, I'm coming here from rails/rails#4364, if that context helps.

@alindeman
Copy link
Contributor

Good point. I hadn't tried a view spec.

Given that the Rails guides themselves recommend the use_route option, I am inclined (at this point) to leave routing as-is. What do you think?

@alindeman
Copy link
Contributor

BTW, I'm coming here from rails/rails#4364, if that context helps.

Whoops, saw this after my previous comment.

This does help a bit. I probably need to spin up a Rails application that fully demonstrates the problem to poke around. I've added this to my list, but if you have time, feel free to do so and push it up to GitHub.

@Exoth
Copy link

Exoth commented Jan 8, 2013

It would be nice to have it added in the next version as starting from version 2.12.1 this good old hack stopped working for routing specs:

before { @routes = CmsEngine::Engine.routes }

Now I need to do:

before do
  @routes = CmsEngine::Engine.routes
  assertion_instance.instance_variable_set(:@routes, CmsEngine::Engine.routes)
end

Which is quite clumsy.

@jcoyne
Copy link

jcoyne commented Jan 9, 2013

I also have the same use-case / complaint as @Exoth. Can we have a simple way to test our engine routes?

@alindeman
Copy link
Contributor

It would be nice to have it added in the next version as starting from version 2.12.1 this good old hack stopped working for routing specs

2.12.2 will be released soon with the relevant code reverted. We should figure out a better way to expose the engine's routes, but I'm not sure what that will look like yet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants