Custom RSpec matcher for allowed values (or assignable_values)

In contrast to RSpec's included allow_value matcher, the attached matcher will also work on associations, which makes it ideal for testing assignable_values.

Usage example

describe Unit do

  describe '#building' do
    it 'should only allow buildings that a user has access to' do
      building = build(:building)
      other_building = build(:building)
      unauthorized_building = build(:building)

      power = Power.new(build(:user))

      Power.with_power(power) do
        expect(power).to receive(:buildings).at_least(1).time.and_return [building, other_building]
        expect(build(:unit)).to allow_association_values(building, other_building).for(:building)
        expect(build(:unit)).not_to allow_association_values(unauthorized_building, nil).for(:building)
      end
    end
  end

end

Alternatively you could test explicitly for the method that assignable_values generates:

...
      Power.with_power(power) do
        expect(power).to receive(:buildings).at_least(1).time.and_return [building, other_building]
        
        unit = build(:unit)
        expect(unit.assignable_buildings).to contain_exactly(building, other_building)
        expect(unit.assignable_buildings).not_to include(unauthorized_building, nil)
      end
...

See RSpec: Where to put custom matchers and other support code

Dominik Schöler Over 10 years ago