How to get a BOM test case for a model with an enum field type - Mongoid
EDIT: As suggested by @max, I change my model to use an enum, but cannot check it for the default state:
it { is_expected.to validate_inclusion_of(:status).to_allow("draft", "published") }
Works well with the following code in the model:
validates :status, :inclusion => { :in => ["draft", "published"] }
But this part still doesn't work:
it { is_expected.to have_field(:status).with_default_value_of("draft") }
Please note that I am using Mongoid. I have this in my model spec:
OLD question - saved for reference?
it { is_expected.to have_field(:published).of_type(Boolean).with_default_value_of(false) }
And in my model I have this:
field :published, type: Mongoid::Boolean, default: false
Doesn't work yet. I tried to remove the Mongoid bit but got the same error:
Failure/Error: it { is_expected.to have_field(:published).of_type(Boolean).with_default_value_of(false) }
Expected Post to have field named "published" of type Boolean with default value of false, got field "published" of type Mongoid::Boolean
Note. I've also tried:
field :published, type: Boolean, default: false
And added the following method to my model:
after_initialize :set_published, :if => :new_record?
then
private
def set_published
self.published ||= false
end
But nothing works. What am I missing?
source to share
If I understand correctly, you have tried both Mongoid::Boolean
, and Boolean
in the model, but not in the test.
Given the testing error message, I think it should be:
it { is_expected.to have_field(:published).of_type(Mongoid::Boolean).with_default_value_of(false) }
(and field :published, type: Mongoid::Boolean, default: false
in your model)
Second problem :
Do you know what have_field
tests on views (generated HTML) are supposed to do and not check if this field exists in the database?
We cannot help you without your views code.
To check what the default is draft
, I am not aware of the built-in Rails method, so you have to do it manually. First create a new instance of your model, save it, and then make sure the published field has a value draft
.
I'm not familiar with Rspec and the syntax you are using, but it should be something like (if your model is called Post
):
before {
@post = Post.new
# some initialization code if needed
@post.save
}
expect(@post.published).to be("draft")
source to share
class Article
include Mongoid::Document
field :published, type: Boolean, default: false
end
require 'rails_helper'
RSpec.describe Article, type: :model do
it { is_expected.to have_field(:published)
.of_type(Mongoid::Boolean)
.with_default_value_of(false) }
end
It runs fine on mongoid (4.0.2)
, mongoid-rspec (2.1.0)
.
But quite frankly, using boolean states for model state is sub-optimal.
If you are considering a blog post or article, it could be:
1. draft 2. published 3. deleted 4. ...
Adding N number of switches to the model is icky - an awesome solution is using Enums.
First write the spec:
RSpec.describe Article, type: :model do
specify 'the default status of an article should be :draft' do
expect(subject.status).to eq :draft
end
# or with rspec-its
# its(:status) { should eq :draft }
end
Then add gem "mongoid-enum"
to your Gemfile.
Finally, add an enum field:
class Article
include Mongoid::Document
include Mongoid::Enum
enum :status, [:draft, :published]
end
Enums add all this awesomeness:
Article.published # Scope to get all published articles
article.published? # Interrogation methods for each state.
article.published! # sets the status
source to share