mongoid-rspec 3.0.0 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/LICENSE +1 -1
- data/README.md +217 -111
- data/Rakefile +8 -5
- data/lib/matchers/accept_nested_attributes.rb +22 -23
- data/lib/matchers/allow_mass_assignment.rb +12 -12
- data/lib/matchers/associations.rb +36 -37
- data/lib/matchers/be_dynamic_document.rb +26 -0
- data/lib/matchers/be_mongoid_document.rb +26 -0
- data/lib/matchers/be_stored_in.rb +55 -0
- data/lib/matchers/have_field.rb +90 -0
- data/lib/matchers/have_timestamps.rb +61 -0
- data/lib/matchers/indexes/have_index_for.rb +16 -0
- data/lib/matchers/indexes/v3/have_index_for.rb +59 -0
- data/lib/matchers/indexes/v4/have_index_for.rb +54 -0
- data/lib/matchers/validations.rb +30 -11
- data/lib/matchers/validations/associated.rb +1 -1
- data/lib/matchers/validations/confirmation_of.rb +0 -7
- data/lib/matchers/validations/custom_validation_of.rb +1 -4
- data/lib/matchers/validations/exclusion_of.rb +5 -5
- data/lib/matchers/validations/format_of.rb +2 -2
- data/lib/matchers/validations/inclusion_of.rb +5 -5
- data/lib/matchers/validations/length_of.rb +13 -35
- data/lib/matchers/validations/numericality_of.rb +32 -16
- data/lib/matchers/validations/presence_of.rb +1 -1
- data/lib/matchers/validations/uniqueness_of.rb +7 -10
- data/lib/mongoid/rspec.rb +17 -5
- data/lib/mongoid/rspec/version.rb +2 -2
- data/spec/models/article.rb +6 -6
- data/spec/models/comment.rb +1 -1
- data/spec/models/log.rb +3 -3
- data/spec/models/message.rb +11 -0
- data/spec/models/movie_article.rb +1 -2
- data/spec/models/person.rb +1 -1
- data/spec/models/profile.rb +2 -2
- data/spec/models/record.rb +1 -1
- data/spec/models/user.rb +11 -11
- data/spec/spec_helper.rb +9 -9
- data/spec/unit/accept_nested_attributes_spec.rb +1 -1
- data/spec/unit/associations_spec.rb +11 -7
- data/spec/unit/be_dynamic_document_spec.rb +21 -0
- data/spec/unit/be_mongoid_document_spec.rb +25 -0
- data/spec/unit/be_stored_in.rb +54 -0
- data/spec/unit/document_spec.rb +5 -14
- data/spec/unit/have_index_for_spec.rb +46 -0
- data/spec/unit/have_timestamps_spec.rb +71 -0
- data/spec/unit/validations_spec.rb +22 -15
- data/spec/validators/ssn_validator.rb +6 -6
- metadata +63 -29
- data/.document +0 -5
- data/.gitignore +0 -6
- data/.ruby-gemset +0 -1
- data/.ruby-version +0 -1
- data/.travis.yml +0 -10
- data/Gemfile +0 -4
- data/lib/matchers/collections.rb +0 -9
- data/lib/matchers/document.rb +0 -173
- data/lib/matchers/indexes.rb +0 -69
- data/lib/matchers/validations/with_message.rb +0 -27
- data/mongoid-rspec.gemspec +0 -26
- data/spec/unit/collections_spec.rb +0 -7
- data/spec/unit/indexes_spec.rb +0 -17
@@ -2,8 +2,19 @@ module Mongoid
|
|
2
2
|
module Matchers
|
3
3
|
module Validations
|
4
4
|
class ValidateNumericalityOfMatcher < HaveValidationMatcher
|
5
|
-
|
6
|
-
|
5
|
+
ALLOWED_OPTIONS =
|
6
|
+
%i[
|
7
|
+
allow_nil
|
8
|
+
equal_to
|
9
|
+
even
|
10
|
+
greater_than
|
11
|
+
greater_than_or_equal_to
|
12
|
+
less_than
|
13
|
+
less_than_or_equal_to
|
14
|
+
nil
|
15
|
+
odd
|
16
|
+
only_integer
|
17
|
+
].freeze
|
7
18
|
|
8
19
|
def initialize(field)
|
9
20
|
super(field, :numericality)
|
@@ -12,9 +23,15 @@ module Mongoid
|
|
12
23
|
|
13
24
|
def to_allow(options)
|
14
25
|
options[:equal_to] = options if options.is_a?(Numeric)
|
15
|
-
options[:allow_nil] = options.delete(:nil) if options.
|
16
|
-
|
17
|
-
|
26
|
+
options[:allow_nil] = options.delete(:nil) if options.key?(:nil)
|
27
|
+
|
28
|
+
if !options.is_a?(Hash) || options.empty? || (options.keys - ALLOWED_OPTIONS).any?
|
29
|
+
message =
|
30
|
+
'validate_numericality_of#to_allow requires a Hash parameter containing' \
|
31
|
+
"any of the following keys: #{ALLOWED_OPTIONS.map(&:inspect).join(', ')}"
|
32
|
+
raise ArgumentError, message
|
33
|
+
end
|
34
|
+
|
18
35
|
@options.merge!(options)
|
19
36
|
self
|
20
37
|
end
|
@@ -22,11 +39,10 @@ module Mongoid
|
|
22
39
|
def matches?(actual)
|
23
40
|
return false unless result = super(actual)
|
24
41
|
|
25
|
-
|
26
|
-
|
27
|
-
result &= (@validator.options[comparator] == @options[comparator])
|
28
|
-
end
|
42
|
+
@options.each do |comparator, expected_value|
|
43
|
+
result &= (@validator.options[comparator] == expected_value)
|
29
44
|
end
|
45
|
+
|
30
46
|
@positive_result_message <<= options_message(@validator.options)
|
31
47
|
@negative_result_message <<= options_message(@validator.options)
|
32
48
|
result
|
@@ -45,19 +61,19 @@ module Mongoid
|
|
45
61
|
case key
|
46
62
|
when :allow_nil
|
47
63
|
when :only_integer
|
48
|
-
type_msg <<
|
64
|
+
type_msg << 'integer' if value
|
49
65
|
when :odd, :even
|
50
|
-
type_msg << "#{key
|
66
|
+
type_msg << "#{key}-numbered" if value
|
51
67
|
else
|
52
|
-
comp_msg << "#{key.to_s.
|
68
|
+
comp_msg << "#{key.to_s.tr('_', ' ')} #{value.inspect}"
|
53
69
|
end
|
54
70
|
end
|
55
|
-
allow_nil = (options[:allow_nil] ?
|
56
|
-
[
|
71
|
+
allow_nil = (options[:allow_nil] ? 'nil' : 'non-nil') if options.key?(:allow_nil)
|
72
|
+
['', 'allowing', allow_nil, type_msg.any? ? type_msg.to_sentence : nil, 'values', comp_msg.any? ? comp_msg.to_sentence : nil].compact.join(' ')
|
57
73
|
end
|
58
74
|
|
59
75
|
def method_missing(m, *args, &block)
|
60
|
-
if
|
76
|
+
if ALLOWED_OPTIONS.include?(m.to_sym)
|
61
77
|
raise ArgumentError, "wrong number of arguments (#{args.length} for 1)" if args.length > 1
|
62
78
|
send :to_allow, m.to_sym => args.first
|
63
79
|
else
|
@@ -71,4 +87,4 @@ module Mongoid
|
|
71
87
|
end
|
72
88
|
end
|
73
89
|
end
|
74
|
-
end
|
90
|
+
end
|
@@ -2,7 +2,6 @@ module Mongoid
|
|
2
2
|
module Matchers
|
3
3
|
module Validations
|
4
4
|
class ValidateUniquenessOfMatcher < HaveValidationMatcher
|
5
|
-
include WithMessage
|
6
5
|
def initialize(field)
|
7
6
|
super(field, :uniqueness)
|
8
7
|
end
|
@@ -11,7 +10,7 @@ module Mongoid
|
|
11
10
|
@scope = [scope].flatten.map(&:to_sym)
|
12
11
|
self
|
13
12
|
end
|
14
|
-
|
13
|
+
alias scoped_on scoped_to
|
15
14
|
|
16
15
|
def case_insensitive
|
17
16
|
@case_insensitive = true
|
@@ -29,7 +28,6 @@ module Mongoid
|
|
29
28
|
check_scope if @scope
|
30
29
|
check_allow_blank if @allow_blank
|
31
30
|
check_case_sensitivity if @case_insensitive
|
32
|
-
check_expected_message if @expected_message
|
33
31
|
|
34
32
|
@result
|
35
33
|
end
|
@@ -37,9 +35,8 @@ module Mongoid
|
|
37
35
|
def description
|
38
36
|
options_desc = []
|
39
37
|
options_desc << " scoped to #{@scope.inspect}" if @scope
|
40
|
-
options_desc <<
|
41
|
-
options_desc <<
|
42
|
-
options_desc << " with message '#{@expected_message}'" if @expected_message
|
38
|
+
options_desc << ' allowing blank values' if @allow_blank
|
39
|
+
options_desc << ' allowing case insensitive values' if @case_insensitive
|
43
40
|
super << options_desc.to_sentence
|
44
41
|
end
|
45
42
|
|
@@ -47,9 +44,9 @@ module Mongoid
|
|
47
44
|
|
48
45
|
def check_allow_blank
|
49
46
|
if @validator.options[:allow_blank] == @allow_blank
|
50
|
-
@positive_result_message <<
|
47
|
+
@positive_result_message << ' with blank values allowed'
|
51
48
|
else
|
52
|
-
@negative_result_message <<
|
49
|
+
@negative_result_message << ' with no blank values allowed'
|
53
50
|
@result = false
|
54
51
|
end
|
55
52
|
end
|
@@ -66,9 +63,9 @@ module Mongoid
|
|
66
63
|
|
67
64
|
def check_case_sensitivity
|
68
65
|
if @validator.options[:case_sensitive] == false
|
69
|
-
@positive_result_message <<
|
66
|
+
@positive_result_message << ' with case insensitive values'
|
70
67
|
else
|
71
|
-
@negative_result_message <<
|
68
|
+
@negative_result_message << ' without case insensitive values'
|
72
69
|
@result = false
|
73
70
|
end
|
74
71
|
end
|
data/lib/mongoid/rspec.rb
CHANGED
@@ -1,18 +1,19 @@
|
|
1
1
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
2
2
|
|
3
3
|
require 'mongoid'
|
4
|
+
require 'mongoid-compatibility'
|
4
5
|
require 'rspec/core'
|
5
6
|
require 'rspec/expectations'
|
6
7
|
require 'rspec/mocks'
|
7
|
-
require
|
8
|
-
require '
|
8
|
+
require 'active_support/core_ext/hash/keys'
|
9
|
+
require 'active_support/core_ext/hash/transform_values' if Mongoid::Compatibility::Version.mongoid4_or_newer?
|
10
|
+
require 'active_support/core_ext/object/blank'
|
11
|
+
require 'active_support/core_ext/string/inflections'
|
12
|
+
|
9
13
|
require 'matchers/associations'
|
10
|
-
require 'matchers/collections'
|
11
|
-
require 'matchers/indexes'
|
12
14
|
require 'matchers/allow_mass_assignment'
|
13
15
|
require 'matchers/accept_nested_attributes'
|
14
16
|
require 'matchers/validations'
|
15
|
-
require 'matchers/validations/with_message'
|
16
17
|
require 'matchers/validations/associated'
|
17
18
|
require 'matchers/validations/confirmation_of'
|
18
19
|
require 'matchers/validations/exclusion_of'
|
@@ -24,6 +25,17 @@ require 'matchers/validations/presence_of'
|
|
24
25
|
require 'matchers/validations/uniqueness_of'
|
25
26
|
require 'matchers/validations/acceptance_of'
|
26
27
|
require 'matchers/validations/custom_validation_of'
|
28
|
+
require 'matchers/be_mongoid_document'
|
29
|
+
require 'matchers/be_dynamic_document'
|
30
|
+
require 'matchers/be_stored_in'
|
31
|
+
require 'matchers/have_field'
|
32
|
+
require 'matchers/indexes/have_index_for'
|
33
|
+
if Mongoid::Compatibility::Version.mongoid3?
|
34
|
+
require 'matchers/indexes/v3/have_index_for'
|
35
|
+
else
|
36
|
+
require 'matchers/indexes/v4/have_index_for'
|
37
|
+
end
|
38
|
+
require 'matchers/have_timestamps'
|
27
39
|
|
28
40
|
module Mongoid
|
29
41
|
module Matchers
|
data/spec/models/article.rb
CHANGED
@@ -9,21 +9,21 @@ class Article
|
|
9
9
|
field :number_of_comments, type: Integer
|
10
10
|
field :status, type: Symbol
|
11
11
|
|
12
|
-
embeds_many :comments, cascade_callbacks: true
|
13
|
-
embeds_one :permalink
|
12
|
+
embeds_many :comments, cascade_callbacks: true, inverse_of: :article
|
13
|
+
embeds_one :permalink, inverse_of: :linkable
|
14
14
|
belongs_to :author, class_name: 'User', inverse_of: :articles, index: true
|
15
15
|
|
16
16
|
validates :title, presence: true
|
17
17
|
|
18
18
|
validates_inclusion_of :status, in: [:pending], on: :create
|
19
|
-
validates_inclusion_of :status, in: [
|
19
|
+
validates_inclusion_of :status, in: %i[approved rejected], on: :update
|
20
20
|
|
21
21
|
validates_length_of :title, within: 8..16
|
22
22
|
validates_length_of :content, minimum: 200
|
23
23
|
|
24
|
-
index({ title: 1 },
|
25
|
-
index(
|
26
|
-
index(
|
24
|
+
index({ title: 1 }, unique: true, background: true, drop_dups: true)
|
25
|
+
index(published: 1)
|
26
|
+
index('permalink._id' => 1)
|
27
27
|
|
28
28
|
accepts_nested_attributes_for :permalink
|
29
29
|
end
|
data/spec/models/comment.rb
CHANGED
data/spec/models/log.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
class Log
|
2
2
|
include Mongoid::Document
|
3
3
|
include Mongoid::Timestamps
|
4
|
-
include Mongoid::Attributes::Dynamic
|
4
|
+
include Mongoid::Attributes::Dynamic if Mongoid::Compatibility::Version.mongoid4_or_newer?
|
5
5
|
|
6
|
-
store_in collection:
|
6
|
+
store_in collection: 'logs'
|
7
7
|
|
8
|
-
index({ created_at: 1 },
|
8
|
+
index({ created_at: 1 }, bucket_size: 100, expire_after_seconds: 3600)
|
9
9
|
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class Message
|
2
|
+
include Mongoid::Document
|
3
|
+
|
4
|
+
field :identifier
|
5
|
+
field :from
|
6
|
+
field :to
|
7
|
+
|
8
|
+
validates :identifier, uniqueness: { message: 'uniqueness' }
|
9
|
+
validates :from, presence: { message: 'required' }
|
10
|
+
validates :to, format: { with: /[a-z]+/, message: 'format' }
|
11
|
+
end
|
@@ -1,8 +1,7 @@
|
|
1
1
|
class MovieArticle < Article
|
2
|
-
|
3
2
|
field :rating, type: Float
|
4
3
|
field :classification, type: Integer
|
5
4
|
|
6
5
|
validates :rating, numericality: { greater_than: 0, less_than_or_equal_to: 5 }
|
7
6
|
validates :classification, numericality: { even: true, only_integer: true, allow_nil: false }
|
8
|
-
end
|
7
|
+
end
|
data/spec/models/person.rb
CHANGED
data/spec/models/profile.rb
CHANGED
@@ -10,7 +10,7 @@ class Profile
|
|
10
10
|
|
11
11
|
validates :age, numericality: { greater_than: 0 }
|
12
12
|
validates :terms_of_service, acceptance: true
|
13
|
-
validates :hobbies, length: { minimum: 1, message:
|
13
|
+
validates :hobbies, length: { minimum: 1, message: 'requires at least one hobby' }
|
14
14
|
|
15
|
-
index(
|
15
|
+
index(first_name: 1, last_name: 1)
|
16
16
|
end
|
data/spec/models/record.rb
CHANGED
data/spec/models/user.rb
CHANGED
@@ -13,21 +13,21 @@ class User
|
|
13
13
|
belongs_to :site, inverse_of: :users
|
14
14
|
has_many :articles, foreign_key: :author_id, order: :title
|
15
15
|
has_many :comments, dependent: :destroy, autosave: true
|
16
|
-
has_and_belongs_to_many :children, class_name:
|
17
|
-
has_one :record, autobuild: true
|
16
|
+
has_and_belongs_to_many :children, class_name: 'User'
|
17
|
+
has_one :record, autobuild: true, inverse_of: :user
|
18
18
|
|
19
|
-
embeds_one :profile
|
19
|
+
embeds_one :profile, inverse_of: :user
|
20
20
|
|
21
|
-
validates :login, presence: true, uniqueness: { scope: :site }, format: { with: /\A[\w\-]+\z/ }, exclusion: { in: [
|
22
|
-
validates :email, uniqueness: { case_sensitive: false, scope: :site, message:
|
23
|
-
validates :role, presence: true, inclusion: { in: [
|
21
|
+
validates :login, presence: true, uniqueness: { scope: :site }, format: { with: /\A[\w\-]+\z/ }, exclusion: { in: %w[super index edit] }
|
22
|
+
validates :email, uniqueness: { case_sensitive: false, scope: :site, message: 'is already taken' }, confirmation: true
|
23
|
+
validates :role, presence: true, inclusion: { in: %w[admin moderator member] }
|
24
24
|
validates :profile, presence: true, associated: true
|
25
|
-
validates :age, presence: true, numericality: true, inclusion: { in: 23..42 }, on: [
|
26
|
-
validates :password, presence: true, on: [
|
27
|
-
validates :password, exclusion: { in: ->(
|
28
|
-
validates :password, confirmation: { message:
|
25
|
+
validates :age, presence: true, numericality: true, inclusion: { in: 23..42 }, on: %i[create update]
|
26
|
+
validates :password, presence: true, on: %i[create update]
|
27
|
+
validates :password, exclusion: { in: ->(_user) { ['password'] } }
|
28
|
+
validates :password, confirmation: { message: 'Password confirmation must match given password' }
|
29
29
|
validates :provider_uid, presence: true
|
30
|
-
validates :locale, inclusion: { in: ->(
|
30
|
+
validates :locale, inclusion: { in: ->(_user) { %i[en ru] } }
|
31
31
|
|
32
32
|
accepts_nested_attributes_for :articles, :comments
|
33
33
|
|
data/spec/spec_helper.rb
CHANGED
@@ -1,24 +1,24 @@
|
|
1
1
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
2
|
-
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__),
|
3
|
-
MODELS = File.join(File.dirname(__FILE__),
|
2
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), 'lib'))
|
3
|
+
MODELS = File.join(File.dirname(__FILE__), 'models')
|
4
4
|
$LOAD_PATH.unshift(MODELS)
|
5
|
-
VALIDATORS = File.join(File.dirname(__FILE__),
|
5
|
+
VALIDATORS = File.join(File.dirname(__FILE__), 'validators')
|
6
6
|
$LOAD_PATH.unshift(VALIDATORS)
|
7
7
|
|
8
|
-
require
|
9
|
-
require
|
8
|
+
require 'rubygems'
|
9
|
+
require 'bundler'
|
10
10
|
Bundler.setup
|
11
11
|
|
12
12
|
require 'mongoid'
|
13
13
|
require 'rspec'
|
14
14
|
require 'rspec/core'
|
15
15
|
require 'rspec/expectations'
|
16
|
+
require 'mongoid/compatibility'
|
16
17
|
|
17
|
-
Mongoid.
|
18
|
-
|
19
|
-
end
|
18
|
+
Mongoid::Config.connect_to('mongoid-rspec-test') if Mongoid::Compatibility::Version.mongoid3_or_newer?
|
19
|
+
Mongo::Logger.logger.level = ::Logger::INFO if Mongoid::Compatibility::Version.mongoid5_or_newer?
|
20
20
|
|
21
|
-
Dir[
|
21
|
+
Dir[File.join(MODELS, '*.rb')].sort.each { |file| require File.basename(file) }
|
22
22
|
|
23
23
|
require 'mongoid-rspec'
|
24
24
|
|
@@ -1,14 +1,16 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
RSpec.describe
|
3
|
+
RSpec.describe 'Associations' do
|
4
4
|
describe User do
|
5
|
-
|
5
|
+
if Mongoid::Compatibility::Version.mongoid6_or_newer?
|
6
|
+
it { is_expected.to have_many(:articles).with_foreign_key(:author_id).ordered_by(:title) }
|
7
|
+
end
|
6
8
|
|
7
|
-
it { is_expected.to have_one(:record).with_autobuild }
|
9
|
+
it { is_expected.to have_one(:record).as_inverse_of(:user).with_autobuild }
|
8
10
|
|
9
11
|
it { is_expected.to have_many(:comments).with_dependent(:destroy).with_autosave }
|
10
12
|
|
11
|
-
it { is_expected.to embed_one(:profile) }
|
13
|
+
it { is_expected.to embed_one(:profile).as_inverse_of(:user) }
|
12
14
|
|
13
15
|
it { is_expected.to have_and_belong_to_many(:children).of_type(User) }
|
14
16
|
end
|
@@ -19,8 +21,8 @@ RSpec.describe "Associations" do
|
|
19
21
|
|
20
22
|
describe Article do
|
21
23
|
it { is_expected.to belong_to(:author).of_type(User).as_inverse_of(:articles).with_index }
|
22
|
-
it { is_expected.to embed_many(:comments).with_cascading_callbacks }
|
23
|
-
it { is_expected.to embed_one(:permalink) }
|
24
|
+
it { is_expected.to embed_many(:comments).as_inverse_of(:article).with_cascading_callbacks }
|
25
|
+
it { is_expected.to embed_one(:permalink).as_inverse_of(:linkable) }
|
24
26
|
end
|
25
27
|
|
26
28
|
describe Comment do
|
@@ -37,6 +39,8 @@ RSpec.describe "Associations" do
|
|
37
39
|
end
|
38
40
|
|
39
41
|
describe Site do
|
40
|
-
|
42
|
+
if Mongoid::Compatibility::Version.mongoid6_or_newer?
|
43
|
+
it { is_expected.to have_many(:users).as_inverse_of(:site).ordered_by(:email.desc).with_counter_cache }
|
44
|
+
end
|
41
45
|
end
|
42
46
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Mongoid::Matchers::BeDynamicDocument do
|
4
|
+
context 'when model does\'t include Mongoid::Document' do
|
5
|
+
subject do
|
6
|
+
Class.new
|
7
|
+
end
|
8
|
+
|
9
|
+
it { is_expected.not_to be_mongoid_document }
|
10
|
+
end
|
11
|
+
|
12
|
+
context 'when model doesn\'t include Mongoid::Document' do
|
13
|
+
subject do
|
14
|
+
Class.new do
|
15
|
+
include Mongoid::Document
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
it { is_expected.to be_mongoid_document }
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
if Mongoid::Compatibility::Version.mongoid4_or_newer?
|
3
|
+
RSpec.describe Mongoid::Matchers::BeMongoidDocument do
|
4
|
+
context 'when model does\'t include Mongoid::Attributes::Dynamic' do
|
5
|
+
subject do
|
6
|
+
Class.new do
|
7
|
+
include Mongoid::Document
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
it { is_expected.not_to be_dynamic_document }
|
12
|
+
end
|
13
|
+
|
14
|
+
context 'when model doesn\'t include Mongoid::Attributes::Dynamic' do
|
15
|
+
subject do
|
16
|
+
Class.new do
|
17
|
+
include Mongoid::Document
|
18
|
+
include Mongoid::Attributes::Dynamic
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
it { is_expected.to be_dynamic_document }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|