mongoid7-rspec-callbacks 1.0.0.pre.816289031

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ # Specify your gem's dependencies in evostream-event.gemspec
6
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,14 @@
1
+ Copyright (c) 2013 Luis Ciudad
2
+
3
+ This program is free software: you can redistribute it and/or modify
4
+ it under the terms of the GNU General Public License as published by
5
+ the Free Software Foundation, either version 3 of the License, or
6
+ (at your option) any later version.
7
+
8
+ This program is distributed in the hope that it will be useful,
9
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ GNU General Public License for more details.
12
+
13
+ You should have received a copy of the GNU General Public License
14
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
data/README.md ADDED
@@ -0,0 +1,65 @@
1
+ # Mongoid::Rspec::Callbacks
2
+ [![RSpec](https://github.com/dazzl-tv/mongoid-rspec-callbacks/actions/workflows/rspec.yml/badge.svg?branch=develop&event=pull_request)](https://github.com/dazzl-tv/mongoid-rspec-callbacks/actions/workflows/rspec.yml)
3
+ [![Linter](https://github.com/dazzl-tv/mongoid-rspec-callbacks/actions/workflows/linter.yml/badge.svg)](https://github.com/dazzl-tv/mongoid-rspec-callbacks/actions/workflows/linter.yml)
4
+ [![Gem Version](https://badge.fury.io/rb/mongoid-rspec-callbacks.svg)](https://badge.fury.io/rb/mongoid-rspec-callbacks)
5
+ [![Docs](https://inch-ci.org/github/dazzl-tv/mongoid-rspec-callbacks.svg)](https://inch-ci.org/github/dazzl-tv/mongoid-rspec-callbacks)
6
+ [![Maintainability](https://api.codeclimate.com/v1/badges/2538546ea7419c1d5ea1/maintainability)](https://codeclimate.com/github/dazzl-tv/mongoid-rspec-callbacks/maintainability)
7
+ [![Test Coverage](https://api.codeclimate.com/v1/badges/2538546ea7419c1d5ea1/test_coverage)](https://codeclimate.com/github/dazzl-tv/mongoid-rspec-callbacks/test_coverage)
8
+ [![Known Vulnerabilities](https://snyk.io/test/github/dazzl-tv/mongoid-rspec-callbacks/badge.svg)](https://snyk.io/test/github/dazzl-tv/mongoid-rspec-callbacks)
9
+
10
+ http://rubygems.org/gems/mongoid-rspec-callbacks
11
+
12
+ RSpec Callbacks matchers for Mongoid 7.x and ActiveSupport 6.x
13
+
14
+ This gem is meant to be use with [mongoid-rpsec](http://rubygems.org/gems/mongoid-rspec), altought it works by itself.
15
+
16
+ Syntax is the same as [shoulda-callback-matchers](https://github.com/beatrichartz/shoulda-callback-matchers).
17
+
18
+ By now, only ``on`` option is supported.
19
+
20
+ ## Installation
21
+
22
+ Add to your Gemfile
23
+
24
+ ```
25
+ gem 'mongoid-rspec-callbacks'
26
+ ```
27
+
28
+ Drop in existing or dedicated support file in spec/support (spec/support/mongoid.rb)
29
+
30
+ ```
31
+ RSpec.configure do |configuration|
32
+ configuration.include Mongoid::Matchers
33
+ end
34
+ ```
35
+
36
+ ## Callbacks Matchers
37
+
38
+ ```
39
+ describe User do
40
+ it { should callback(:method).before(:save) }
41
+ it { should callback(:method).after(:save) }
42
+ it { should callback(:method, :method2).before(:validation) }
43
+ it { should callback(:method).after(:validation).on(:create) }
44
+ end
45
+ ```
46
+
47
+ ## Set Callbacks Matchers
48
+
49
+ ```
50
+ describe User do
51
+ it { is_expected.to set_callback(:save, :arround) }
52
+ it { is_expected.to set_callback(:validation, :after) }
53
+ end
54
+ ```
55
+
56
+ ## Association Callbacks Matchers
57
+
58
+ ```
59
+ describe User do
60
+ it { is_expected.to association_callback(:has_many,
61
+ :add,
62
+ :after,
63
+ :send_email_to_subscribers) }
64
+ end
65
+ ```
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mongoid
4
+ module Matchers
5
+ # Create an matcher for set_callback method
6
+ #
7
+ # Usage:
8
+ #
9
+ # it { is_expected.to association_callback(:has_many,
10
+ # :add,
11
+ # :after,
12
+ # :send_email_to_subscribers) }
13
+ class HaveAssociationCallbackMatcher
14
+ CONTEXTS = %i[before after].freeze
15
+ OPERATIONS = %i[add remove].freeze
16
+ RELATIONS = %i[embeds_many has_many and has_and_belongs_to_many].freeze
17
+
18
+ def initialize(*args)
19
+ @relation = args[0]
20
+ @type = args[1]
21
+ @hook = args[2]
22
+ @method = args[3]
23
+ end
24
+
25
+ def matches?(klass)
26
+ @model = klass
27
+
28
+ return false unless \
29
+ relation_is_correct? ||
30
+ context_is_correct? ||
31
+ operation_is_correct? ||
32
+ callback_is_correct?
33
+
34
+ testings_presence_method_callback
35
+ end
36
+
37
+ def description
38
+ "be association_callback(:#{@type}, :#{@hook})"
39
+ end
40
+
41
+ def failure_message
42
+ message_error
43
+ end
44
+
45
+ def failure_message_when_negated
46
+ message_error
47
+ end
48
+
49
+ private
50
+
51
+ def relation_is_correct?
52
+ RELATIONS.include?(@relation)
53
+ end
54
+
55
+ def context_is_correct?
56
+ CONTEXTS.include?(@hook)
57
+ end
58
+
59
+ def operation_is_correct?
60
+ OPERATIONS.include?(@type)
61
+ end
62
+
63
+ def callback_is_correct?
64
+ @model.class.respond_to?(:"_#{@type}_callbacks")
65
+ end
66
+
67
+ def testings_presence_method_callback
68
+ @model.methods.include?(:"#{@method}")
69
+ end
70
+
71
+ def message_error
72
+ <<-ERROR
73
+ expected #{@model} have method callback to association :
74
+ has_many <relation>, #{@hook}: :#{@method}
75
+
76
+ def #{@method}
77
+ end
78
+ ERROR
79
+ end
80
+ end
81
+
82
+ def association_callback(*args)
83
+ HaveAssociationCallbackMatcher.new(*args)
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,157 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mongoid
4
+ module Matchers
5
+ # Create an matcher for callback method
6
+ #
7
+ # Usage:
8
+ #
9
+ # it { is_expected.to callback(:callback1).before(:save) }
10
+ # it { is_expected.to callback(:callback2).after(:save) }
11
+ # it { is_expected.to callback(:callback1, :callback2).before(:validation) }
12
+ # it { is_expected.to callback(:callback3).after(:validation).on(:create) }
13
+ class HaveCallbackMatcher
14
+ KINDS = %w[before around after].freeze
15
+
16
+ # Set methods to look for
17
+ def initialize(*args)
18
+ @methods = args || []
19
+ end
20
+
21
+ # Set when callback is fired using @kind and @operation
22
+ KINDS.each do |kind|
23
+ define_method(kind.to_sym) do |op|
24
+ @operation = op
25
+ @kind = kind.to_sym
26
+ self
27
+ end
28
+ end
29
+
30
+ # Set on condition
31
+ def on(action)
32
+ @context = action
33
+ self
34
+ end
35
+
36
+ def matches?(klass)
37
+ return false unless @kind
38
+ if @no_op == !klass.class.respond_to?(:"_#{@operation}_callbacks")
39
+ return false
40
+ end
41
+
42
+ @guess = nil
43
+ @methods.each do |method|
44
+ filter = filters_method(klass, method)
45
+
46
+ return false unless filter
47
+ end
48
+ end
49
+
50
+ def failure_message
51
+ message(true)
52
+ end
53
+
54
+ def failure_message_when_negated
55
+ message(false)
56
+ end
57
+
58
+ def description
59
+ methods = @methods
60
+
61
+ "be callback(:#{methods.join(', ')})#{expl_operation}#{expl_context}"
62
+ end
63
+
64
+ protected
65
+
66
+ def expl_operation
67
+ @operation ? ".#{@kind}(:#{@operation})" : ''
68
+ end
69
+
70
+ def expl_context
71
+ @context ? ".on(:#{@context})" : ''
72
+ end
73
+
74
+ def message(should)
75
+ return msg_op_invalid if @no_op
76
+
77
+ @kind ? message_kind(should) : message_not_kind
78
+ end
79
+
80
+ def msg_op_invalid
81
+ 'Invalid operation. Use :initialize, :build, :validation,' \
82
+ ':create, :find, :update, :upsert, :save or :destroy'
83
+ end
84
+
85
+ def message_kind(should)
86
+ <<-MESSAGE
87
+ Expected method#{@methods.size > 1 ? 's' : ''}#{expr_called(should)}
88
+ #{"#{@kind}" "#{@operation}" if @operation}
89
+ #{"on #{@context}" if @context}
90
+ #{msg_guess}
91
+ #{"#{@guess.kind} #{@operation}" if @guess}
92
+ #{'on another context' if @guess && !@context_match}
93
+ MESSAGE
94
+ end
95
+
96
+ def expr_called(should)
97
+ "#{@methods.join(', ')} #{should ? '' : 'not '}to be called"
98
+ end
99
+
100
+ def msg_guess
101
+ if @guess
102
+ ", but got method #{@guess.filter} called"
103
+ else
104
+ ', but no callback found'
105
+ end
106
+ end
107
+
108
+ def message_not_kind
109
+ <<-MESSAGE
110
+ Callback#{@methods.size > 1 ? 's' : ''} #{@methods.join(', ')} can
111
+ not be tested against undefined lifecycle.
112
+ Use .before, .after or .around
113
+ MESSAGE
114
+ end
115
+
116
+ private
117
+
118
+ def filters_method(klass, method)
119
+ klass.class.send(:"_#{@operation}_callbacks").detect do |callback|
120
+ # Save callback instance in order to print information
121
+ # about it in case of failure
122
+ @guess = callback if callback.filter == method
123
+ check_filter?(callback,
124
+ method) and check_kind?(callback,
125
+ @kind) and check_context?(
126
+ callback, @context
127
+ )
128
+ end
129
+ end
130
+
131
+ def check_filter?(callback, method)
132
+ callback.filter == method
133
+ end
134
+
135
+ def check_kind?(callback, kind)
136
+ callback.kind == kind
137
+ end
138
+
139
+ def check_context?(callback, context)
140
+ return true unless context
141
+
142
+ options = callback.instance_variable_get(:@if)
143
+ @context_match = options.select { |option| option.is_a?(Proc) }
144
+
145
+ @context_match.detect do |option|
146
+ option.call(ValidationContext.new(context))
147
+ end
148
+ end
149
+ end
150
+
151
+ ValidationContext = Struct.new :validation_context
152
+
153
+ def callback(*args)
154
+ HaveCallbackMatcher.new(*args)
155
+ end
156
+ end
157
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mongoid
4
+ module Matchers
5
+ # Create an matcher for set_callback method
6
+ #
7
+ # Usage:
8
+ #
9
+ # it { is_expected.to set_callback(:save, :arround) }
10
+ # it { is_expected.to set_callback(:validation, :after) }
11
+ class HaveSetCallbackMatcher
12
+ CONTEXTS = %i[before arround after].freeze
13
+ OPERATIONS = %i[initialize build validation create
14
+ find update upsert save destroy].freeze
15
+
16
+ def initialize(*args)
17
+ @type = args[0]
18
+ @hook = args[1]
19
+ end
20
+
21
+ def matches?(klass)
22
+ @model = klass
23
+
24
+ return false unless \
25
+ context_is_correct? ||
26
+ operation_is_correct? ||
27
+ callback_is_correct?
28
+
29
+ testings_presence_callback
30
+ end
31
+
32
+ def description
33
+ "be set_callback(:#{@type}, :#{@hook})"
34
+ end
35
+
36
+ def failure_message
37
+ message_error
38
+ end
39
+
40
+ def failure_message_when_negated
41
+ message_error
42
+ end
43
+
44
+ private
45
+
46
+ def context_is_correct?
47
+ CONTEXTS.include?(@hook)
48
+ end
49
+
50
+ def operation_is_correct?
51
+ OPERATIONS.include?(@type)
52
+ end
53
+
54
+ def callback_is_correct?
55
+ @model.class.respond_to?(:"_#{@type}_callbacks")
56
+ end
57
+
58
+ def testings_presence_callback
59
+ @model.class.send("_#{@type}_callbacks".to_sym).select do |cb|
60
+ cb.filter.eql?(@hook.to_sym)
61
+ end
62
+ end
63
+
64
+ def message_error
65
+ <<-ERROR
66
+ expected #{@model} have method callback :
67
+ set_callback(:#{@type}, :#{@hook}) |document|
68
+ # My callback execution ...
69
+ end
70
+ ERROR
71
+ end
72
+ end
73
+
74
+ def set_callback(*args)
75
+ HaveSetCallbackMatcher.new(*args)
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mongoid
4
+ module Rspec
5
+ module Callbacks
6
+ # Define version to gem
7
+ VERSION = '1.0.0'
8
+
9
+ # Name to gem
10
+ GEM_NAME = 'mongoid7-rspec-callbacks'
11
+
12
+ # Authors
13
+ AUTHORS = ['VAILLANT Jeremy'].freeze
14
+
15
+ # Emails
16
+ EMAILS = ['jeremy@dazzl.tv'].freeze
17
+
18
+ # Licence
19
+ LICENSE = 'GPL-3.0'
20
+
21
+ # Define a summary description to gem
22
+ SUMMARY = 'RSpec Callbacks matchers for Mongoid'
23
+
24
+ # Define a long description to gem
25
+ DESCRIPTION = <<-DESC
26
+ This gem is meant to be use with mongoid-rpsec,
27
+ altought it works by itself. Syntax is the same
28
+ as shoulda-callback-matchers.
29
+ DESC
30
+
31
+ # Define homepage
32
+ HOMEPAGE = 'http://github.com/dazzl-tv/mongoid-rspec-callbacks'
33
+ end
34
+ end
35
+ end