Skip to content

Commit

Permalink
add RSpec matcher
Browse files Browse the repository at this point in the history
closes #77
  • Loading branch information
nashby committed Jun 9, 2013
1 parent 72dfff3 commit 752a5ee
Show file tree
Hide file tree
Showing 11 changed files with 191 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
@@ -1,6 +1,7 @@
### master

### enhancements
* Add RSpec matcher (by [@nashby](https://github.com/nashby))
* Add `*_value` method that returns actual value of the enumerized attribute (useful for attributes with custom values)
(by [@tkyowa](https://github.com/tkyowa))

Expand Down
1 change: 1 addition & 0 deletions Gemfile
Expand Up @@ -4,6 +4,7 @@ gemspec

gem 'rake'
gem 'minitest', '~> 4.1'
gem 'rspec', :require => false

gem 'activerecord', '~> 3.2.0'
gem 'sqlite3', :platform => [:ruby, :mswin, :mingw]
Expand Down
1 change: 1 addition & 0 deletions Gemfile.rails4
Expand Up @@ -4,6 +4,7 @@ gemspec

gem 'rake'
gem 'minitest', '~> 4.1'
gem 'rspec', :require => false

gem 'activerecord', '4.0.0.rc1'
gem 'sqlite3', :platform => [:ruby, :mswin, :mingw]
Expand Down
17 changes: 17 additions & 0 deletions README.md
Expand Up @@ -258,6 +258,23 @@ and if you want it as radio buttons:
<% end %>
```

### RSpec

Also you can use builtin RSpec matcher:

```ruby
class User
extend Enumerize

enumerize :sex, in: [:male, :female], default: :male
end

describe User do
it { should enumerize(:sex).in(:male, :female) }
it { should enumerize(:sex).in(:male, :female).with_default(:male) }
end
```

### Other Integrations

Enumerize integrates with the following automatically:
Expand Down
6 changes: 6 additions & 0 deletions Rakefile
Expand Up @@ -2,10 +2,16 @@
require "bundler/gem_tasks"

require 'rake/testtask'
require 'rspec/core/rake_task'

Rake::TestTask.new do |t|
t.libs << 'test'
t.pattern = 'test/*_test.rb'
t.verbose = true
end

RSpec::Core::RakeTask.new('default') do |t|
t.pattern = FileList['test/rspec_spec.rb']
end

task :default => :test
4 changes: 4 additions & 0 deletions lib/enumerize.rb
Expand Up @@ -47,4 +47,8 @@ def self.extended(base)
require 'enumerize/hooks/formtastic'
rescue LoadError
end

if defined?(::RSpec)

This comment has been minimized.

Copy link
@ka8725

ka8725 Sep 2, 2013

Contributor

I think it would be better to require this matcher in tests manually to spec_helper, because this line doesn't work with spork. I have to require it manually like this:

Spork.prefork do
  require 'enumerize/integrations/rspec'
end

or just add this note to readme?

This comment has been minimized.

Copy link
@nashby

nashby Sep 2, 2013

Author Member

I think it's ok to add this note to README /cc @lest

require 'enumerize/integrations/rspec'
end
end
2 changes: 2 additions & 0 deletions lib/enumerize/attribute_map.rb
@@ -1,5 +1,7 @@
module Enumerize
class AttributeMap
attr_reader :attributes

def initialize
@attributes = {}
@dependants = []
Expand Down
17 changes: 17 additions & 0 deletions lib/enumerize/integrations/rspec.rb
@@ -0,0 +1,17 @@
require 'enumerize/integrations/rspec/matcher'

module Enumerize
module Integrations
module RSpec
def enumerize(attr)
::Enumerize::Integrations::RSpec::Matcher.new(attr)
end
end
end
end

module RSpec
module Matchers
include Enumerize::Integrations::RSpec
end
end
76 changes: 76 additions & 0 deletions lib/enumerize/integrations/rspec/matcher.rb
@@ -0,0 +1,76 @@
module Enumerize
module Integrations
module RSpec
class Matcher
attr_accessor :attr, :values, :subject, :default

def initialize(attr)
self.attr = attr
end

def in(*values)
self.values = values.map(&:to_s).sort
self
end

def with_default(default)
self.default = default.to_s
self
end

def failure_message
message = " expected :#{attr} to allow value#{values.size == 1 ? nil : 's'}: #{quote_values(values)},"
message += " but it allows #{quote_values(enumerized_values)} instead"

if default
message = " expected :#{attr} to have #{default.inspect} as default value,"
message += " but it sets #{enumerized_default.inspect} instead"
end

message
end

def description
description = "enumerize :#{attr} in: #{quote_values(values)}"
description += " with #{default.inspect} as default value" if default
end

def matches?(subject)
self.subject = subject
matches = true

matches &= matches_attributes?
matches &= matches_default_value? if default

matches
end

private

def matches_attributes?
values == enumerized_values
end

def matches_default_value?
default == enumerized_default
end

def enumerized_values
@enumerized_values ||= attributes[attr.to_s].values.sort
end

def enumerized_default
@enumerized_default ||= attributes[attr.to_s].default_value
end

def attributes
subject.class.enumerized_attributes.attributes
end

def quote_values(values)
values.map(&:inspect).join(', ')
end
end
end
end
end
53 changes: 53 additions & 0 deletions test/rspec_matcher_test.rb
@@ -0,0 +1,53 @@
require 'test_helper'
require 'enumerize/integrations/rspec'

describe Enumerize::Integrations::RSpec do
class Should
include Enumerize::Integrations::RSpec
end

let(:klass) do
Class.new do
extend Enumerize
end
end

let(:should) { Should.new }
let(:object) { klass.new }

describe '#matches?' do
before do
klass.enumerize(:sex, :in => [:male, :female])
end

it 'returns true' do
matcher = should.enumerize(:sex).in(:male, :female)
matcher.matches?(object).must_equal true
end

it 'returns false' do
matcher = should.enumerize(:sex).in(:bar)
matcher.matches?(object).must_equal false
end
end

describe '#failure_message' do
before do
klass.enumerize(:sex, :in => [:male, :female], :default => :male)
end

it 'returns failure message for invalid :in option' do
matcher = should.enumerize(:sex).in(:bar)
matcher.subject = object
expected = ' expected :sex to allow value: "bar", but it allows "female", "male" instead'
matcher.failure_message.must_equal expected
end

it 'returns failure message for invalid :with_default option' do
matcher = should.enumerize(:sex).in(:male, :female).with_default(:foo)
matcher.subject = object
expected = ' expected :sex to have "foo" as default value, but it sets "male" instead'
matcher.failure_message.must_equal expected
end
end
end
13 changes: 13 additions & 0 deletions test/rspec_spec.rb
@@ -0,0 +1,13 @@
require 'enumerize'
require 'rspec'

class RSpecUser
extend Enumerize

enumerize :sex, in: [:male, :female], default: :male
end

describe RSpecUser do
it { should enumerize(:sex).in(:male, :female) }
it { should enumerize(:sex).in(:male, :female).with_default(:male) }
end

0 comments on commit 752a5ee

Please sign in to comment.