简体   繁体   中英

Test helpers with RSpec in Padrino (Sinatra)

I'm trying to test a helper in a Padrino (Sinatra) app. My helper method is itself calling Padrino core helper methods but they are undefined. The error appears only in RSpec, while the app works fine. So the way I'm including my helper in RSpec makes it loose "Padrino scope" but I don't know how to bring Padrino helper's scope properly in my RSpec environment.

My helper:

module AdminHelper
  Sort = Struct.new(:column, :order)

  def sort_link(model, column)
    order = sorted_by_this?(column) ? 'desc' : 'asc'
    link_to mat(model, column), url(:pages, :index, sort: column, order: order)
  end

  def sorted_by_this?(column)
    column.to_s == @sort.column && @sort.order == 'asc'
  end
end

Lenstroy::Admin.helpers AdminHelper

My spec:

describe AdminHelper do
  before(:all) do
    class AdminHelperClass
      include AdminHelper
    end
  end
  subject(:helper) { AdminHelperClass.new }

  describe '#sort_link' do
    context "with :pages and :title parameters" do
      before do
        sort = AdminHelperClass::Sort.new('title', 'asc')
        helper.instance_variable_set('@sort', sort)
      end

      subject { helper.sort_link(:pages, :title) }

      it { should match(/<a href=([^ ]+)pages/) }
    end
  end
end

Results in error:

1) AdminHelper#sort_link with :pages and :title parameters 
     Failure/Error: subject { helper.sort_link(:pages, :title) }
     NoMethodError:
       undefined method `mat' for #<AdminHelperClass:0x007f1d951dc4a0>

Including a helper where mat is defined doesn't work, as one method is dependent on another helper and it goes on and on...

Update
In my spec helper I have:

def app(app = nil, &blk)
  @app ||= block_given? ? app.instance_eval(&blk) : app
  @app ||= Lenstroy::Admin
  @app.register Padrino::Helpers
  @app.register Padrino::Rendering
  @app
end

in my spec I have:

it "returns link to resource with sort parameters" do
  app do
    get '/' do
      sort_link(:pages, :title)
    end
  end
  get "/"
  last_response.body.should =~ /<a href=([^ >]+)pages/
end

And now tests fail, last_response.body is '' .

Method #mat is defined in Padrino::Admin::Helpers::ViewHelpers . You can do

class AdminHelperClass
  include Padrino::Admin::Helpers::ViewHelpers
  include AdminHelper
end

Update:

If your methods are really dependent on all these routes and helpers you should consider doing full mockup of your app like this:

def mock_app(base=Padrino::Application, &block)
  @app = Sinatra.new(base, &block)
  @app.register Padrino::Helpers
  @app.register Padrino::Rendering
  # register other things
end

def app
  Rack::Lint.new(@app)
end

mock_app do
  get '/' do
    sort_link(my_model, my_column)
  end
end

get "/"
assert_equal "some test text", body

Here's how it's done in padrino-admin: https://github.com/padrino/padrino-framework/blob/master/padrino-admin/test/test_admin_application.rb

I was having the same problem (and getting very frustrated tracking down the modules and including them). So far, I've got my specs working by:

1) Explicitly defining my module (as explained in how to use padrino helper methods in rspec )

module MyHelper
  ...
end

MyApp::App.helpers MyHelper

2) Automatically including helpers at the top of my spec. (Right now I only have one helper spec, but in the future I might try to move this into spec_helper.rb.)

describe MyHelper do
  let(:helpers) { Class.new }
  before { MyApp::App.included_modules.each { |m| helpers.extend m } }
  subject { helpers }

  it 'blah' do
    expect(subject.helper_method).to eq 'foo'
  end
end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM