isolated engine, routing helpers, testing? #6573

Closed
jrochkind opened this Issue May 31, 2012 · 19 comments

Projects

None yet

6 participants

@jrochkind
Contributor

I believe there is no way to test isolated engine helpers or use isolated engine helpers in tests. But I'd be pleased if I'm wrong and I'm just missing something.

If you create an isolated engine, then the dummy app has a config/routes that has for instance mount Widget::Engine => "/widget"

If the Widget engines has it's own config/routes, then ordinarily an app with that line in it would be able to access the engine's route path helpers as widget.some_path.

That works in the app. But it does not work in the test environment. No such method widget, the widget. method isn't installed in the test environment.

The main engine root widget_path => /widget is installed in the testing environment, you can use it in tests and test routing involving that named helper and path. But not any of the specific widget routes that would ordinarily, in an actual app, be available at widget.some_path.

Phew, this is confusing to talk about, hope this is understandable.

@rafaelfranca
Member

Please avoid questions in the issues tracker. Use mailing lists as rails talk or stack overflow

@rafaelfranca
Member

Fixed the link.

@jrochkind
Contributor

I believe it's a missing feature/bug, rather than a question.

Rails 3.1/3.2 added isolated engines. But the testing environment has not kept pace to make it possible to test features that were added.

This is not an appropriate thing for the issue tracker? But okay, I'll post it to the listserv, and maybe someone else will post an issue, maybe not, maybe someday it'll get fixed, maybe not, no problem.

@rafaelfranca
Member

@jrochkind you post sound like a question. But I'll ask feedback from @drogus .

@rafaelfranca
Member

@jrochkind it was fixed at 6525002.

Thanks @drogus 👍

@drogus
Member
drogus commented Jun 1, 2012

For me it's valid issue. It's really easy to include those helpers by yourself if you know how to do it, but I see no reason to make it hard for developers. I fixed it here: 6525002

I think that it would be good to also backport it to 3-2-stable. What do you guys think?

@rafaelfranca
Member

I'm fine with the backport.

@jrochkind
Contributor

@drogus, thanks!

It might be good to backport to 3.2 -- but it seems as if it's possible simple instructions could be provided for relatively short code to manually include in your 3.2.x app, to support this behavior?

It's really easy to include those helpers by yourself if you know how to do it,

I'm having trouble figuring out what those instructions would be from the patch, myself. Clearly I don't know how to do it. :)

But if you could provide such instructions, it would be of immediate use to me in my 3.2.x app, and may obviate the need to backport to 3.2.x, if workaround instructions can be provided.

I agree that ideally Rails ought to Just Work here, as per your commit in master, without needing special knowledge for manual workaround. thanks!

@drogus
Member
drogus commented Jun 1, 2012

@jrochkind I've already backported it, but before the release, you may include mounted helpers manually like that:

require 'test_helper'

class FooTest < ActionDispatch::IntegrationTest
  include Rails.application.routes.mounted_helpers

  test "foo" do
    puts blog.foo_path
  end
end
@jrochkind
Contributor

@drogus, also, I use "ordinary" path helpers in ActionView::TestCase tests -- ordinary route path helpers work here, but isolated engine root path helpers do not.

Does your patch apply to ActionView::TestCase tests, or only other 'integration' tests?

@jrochkind
Contributor

@drogus, ah, sorry, we're crossing streams. So i can presumably do the same include Rails.application.routes.mounted_helpers in an ActionView::TestCase rather than an ActionDispatch::IntegrationTest? And/or monkey patch that include into all ActionView::TestCases? I will try it!

Since 'standard' routing helpers are ordinarily available in ActionView::TestCase as well, suggest isolated engine mount route helpers should be as well, yes?

@drogus
Member
drogus commented Jun 1, 2012

@jrockind yup, I think that we could do the same, I wasn't aware that they're also included there, thanks for pointing that out!

@jrochkind
Contributor

thanks @drogus, you're my hero for today.

@drogus
Member
drogus commented Jun 1, 2012

@jrochkind ok, they're actually not included there, but there are available on test controller that's used in those tests, fixed here: 60b4290, I need to run, I will backport it to 3-2-stable as well when I get back

@jrochkind
Contributor

thanks again @drogus! Instructions for monkey patching a workaround into a current 3.2.x release (for ActionView::Test and it's test controller) would be much appreciated, otherwise I'll muddle through trying to reverse engineer your commit and get it eventually probably.

@erichmenge erichmenge pushed a commit to erichmenge/rails that referenced this issue Jun 1, 2012
@drogus drogus Include routes.mounted_helpers into integration tests
In integration tests, you might want to use helpers from engines that
you mounted in your application. It's not hard to add it by yourself,
but it's unneeded boilerplate. mounted_helpers are now included by
default. That means that given engine mounted like:

    mount Foo::Engine => "/foo", :as => "foo"

you will be able to use paths from this engine in tests this way:

    foo.root_path #=> "/foo"

(closes #6573)
8d4f63a
@drogus
Member
drogus commented Jun 1, 2012

@jrochkind unfortunately it's not as easy as just including mounted helpers into your tests, so you can:

  def method_missing(selector, *args)
    if @controller.respond_to?(:_routes) &&
         @controller._routes.mounted_helpers.method_defined?(selector)
      @controller.__send__(selector, *args)
    else
      super
    end
  end

and use it as a superclass for your tests

  • add a module that you will include in tests where you need mounted helpers:
module MountedHelpersFix
  def method_missing(selector, *args)
    if @controller.respond_to?(:_routes) &&
         @controller._routes.mounted_helpers.method_defined?(selector)
      @controller.__send__(selector, *args)
    else
      super
    end
  end
end

class FooHelperTest < ActionView::TestCase
  include MountedHelpersFix

  # tests ...
end

I would probably do the third option if tests using mounted helpers are not the majority and the second one if you need it almost everywhere

@SixArm
SixArm commented Aug 2, 2012

@drogus Can you explain more about your findings and how to do it the right way? I'm having the same issue and I will edit the Rails guides for engines to add your info, so others can see the right way to do it.

@saurabhnanda

Hi, I ran into this issue today. We're having a really hard time figuring out the testing story around engines. Especially how they interact with the host application, routing, fixtures, and dependencies.

I used the monkey-patch given in this thread and it worked (although I monkey-patched ActionController::TestCase and not ActionView::TestCase as suggested here)

If this has still not been merged into the main Rails codebase, please consider this is as "vote" of some sorts to do so. We're on the Rails 3.1.x branch.

@steveklabnik
Member

@saurabhnanda please note that Rails 3.1 is getting no security fixes any more: http://weblog.rubyonrails.org/2013/2/24/maintenance-policy-for-ruby-on-rails/

Please upgrade to at least 3.2 as soon as possible.

@yesmeck yesmeck referenced this issue in blowmage/minitest-rails-capybara Mar 3, 2014
Closed

Inlcude routes.mounted_helpers #25

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment