Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error with nested describe blocks #166

Closed
pbougie opened this issue Jan 8, 2015 · 3 comments
Closed

Error with nested describe blocks #166

pbougie opened this issue Jan 8, 2015 · 3 comments
Assignees

Comments

@pbougie
Copy link

pbougie commented Jan 8, 2015

I've recently updated my Rails app to 4.2.0 on Ruby 2.2.0. I'm using version 2.1.1 of minitest-rails. In certain situations, I get this error: NameError: wrong constant name ... when nesting describe blocks. Here's my test file:

require 'test_helper'

describe BudgetPolicy do
  before do
    @account = create(:account)
    @account.toggle(:budgets) # activate budgets
    @administrator = create(:employee, account: @account)
  end

  describe "for an administrator" do
    describe "budgets enabled" do
      it { assert_permit @administrator, :budget, :summary }
      it { assert_permit @administrator, :budget, :index }
      it { assert_permit @administrator, :budget, :new }
      it { assert_permit @administrator, :budget, :create }
    end

    describe "budgets disabled" do
      before { @account.toggle(:budgets) } # deactivate budgets

      it { refute_permit @administrator, :budget, :summary }
      it { refute_permit @administrator, :budget, :index }
      it { refute_permit @administrator, :budget, :new }
      it { refute_permit @administrator, :budget, :create }
    end
  end

  ...
end

The error for all 8 tests above is NameError: wrong constant name for an administrator. If I remove a level of describe blocks, all tests pass as expected.

@blowmage blowmage self-assigned this Jan 26, 2015
@rpearce
Copy link

rpearce commented Mar 4, 2016

I don't believe this is a minitest-rails issue.


I think I found the source of this problem. Given the following,

class EventPolicyTest < ActiveSupport::TestCase
  Given(:event) { Event.new }

  describe 'for an admin' do
    Given(:user) { users(:admin) }

    describe 'when not bookable' do
      Given(:event) { Event.new(is_bookable: false) }
      Then { assert_permit(user, event, :show) }
    end
  end
end

and that you're probably using the following base permit method,

def permit(user, record, action)
  klass = self.class.superclass.to_s.gsub(/Test/, '')
  klass.constantize.new(user, record).public_send("#{action.to_s}?")
end

then here are the class values, when turned to a string:

[5] pry(#<for an admin::when not bookable>)> self.class.to_s
=> "for an admin::when not bookable"
[6] pry(#<for an admin::when not bookable>)> self.class.superclass.to_s
=> "for an admin"
[7] pry(#<for an admin::when not bookable>)> self.class.superclass.superclass.to_s
=> "EventPolicyTest"

Thus the problem here is that there is too much inheritance.

How to fix:

Change your permit helper to the following:

def permit(user, record, action)
  test_name = self.class.ancestors.select { |a| a.to_s.match(/PolicyTest/) }.first
  klass = test_name.to_s.gsub(/Test/, '')
  klass.constantize.new(user, record).public_send("#{action.to_s}?")
end

Instead of just assuming the superclass is the correct policy you're trying to assert against, specifically select it.

@zenspider
Copy link
Collaborator

@rpearce select {...}.first can simply be rewritten to detect {...}

@pbougie
Copy link
Author

pbougie commented May 20, 2016

Unfortunately this didn't work as expected. See solution here.

@blowmage blowmage closed this as completed May 6, 2019
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

No branches or pull requests

4 participants