Module: ActiveInteraction::Extras::Rspec

Defined in:
lib/active_interaction/extras/rspec.rb

Instance Method Summary collapse

Instance Method Details

#alias_delay_method(klass) ⇒ Object



214
215
216
217
218
# File 'lib/active_interaction/extras/rspec.rb', line 214

def alias_delay_method(klass)
  return if klass.respond_to?(:original_delay)

  klass.define_singleton_method :original_delay, &klass.method(:delay)
end

#alias_new_method(klass) ⇒ Object



207
208
209
210
211
# File 'lib/active_interaction/extras/rspec.rb', line 207

def alias_new_method(klass)
  return if klass.respond_to?(:original_new)

  klass.define_singleton_method :original_new, &klass.method(:new)
end

#allow_to_delay_execute(klass, opts = {}) ⇒ Object

see allow_to_execute

additional params

Parameters:

  • opts (Hash) (defaults to: {})

    a customizable set of options

Options Hash (opts):

  • (see (Object)

    Rspec::Mocks::MessageExpectation#with) :with_job (any_args) queueing params for the job



113
114
115
# File 'lib/active_interaction/extras/rspec.rb', line 113

def allow_to_delay_execute(klass, opts = {})
  stub_service_delay :allow, :allow_to_execute, klass, opts
end

#allow_to_delay_run(klass, opts = {}) ⇒ Object

see allow_to_run

additional params

Parameters:

  • opts (Hash) (defaults to: {})

    a customizable set of options

Options Hash (opts):

  • (see (Object)

    Rspec::Mocks::MessageExpectation#with) :with_job (any_args) queueing params for the job



102
103
104
# File 'lib/active_interaction/extras/rspec.rb', line 102

def allow_to_delay_run(klass, opts = {})
  stub_service_delay :allow, :allow_to_run, klass, opts
end

#allow_to_execute(klass, opts = {}) ⇒ Object

See Also:



29
30
31
# File 'lib/active_interaction/extras/rspec.rb', line 29

def allow_to_execute(klass, opts = {})
  stub_service_execute(:allow, klass, opts)
end

#allow_to_run(klass, opts = {}) ⇒ Object

See Also:



41
42
43
# File 'lib/active_interaction/extras/rspec.rb', line 41

def allow_to_run(klass, opts = {})
  stub_service_run(:allow, klass, opts)
end

#expect_not_to_run(klass, opts = {}) ⇒ Object Also known as: expect_to_not_run

Make sure the service is not initialized

Parameters:

  • klass (Class)

    Service class to stub

  • opts (Hash) (defaults to: {})

Options Hash (opts):

  • (see (Object)

    Rspec::Mocks::MessageExpectation#with) :with (any_args) Inputs for the service



53
54
55
56
57
58
# File 'lib/active_interaction/extras/rspec.rb', line 53

def expect_not_to_run(klass, opts = {})
  alias_new_method(klass)
  with = service_parse_with_option(opts)

  expect(klass).to_not receive(:new).with(*with)
end

#expect_to_delay_execute(klass, opts = {}) ⇒ Object

see expect_to_execute same but for the .delay and background queueing

additional params

Parameters:

  • opts (Hash) (defaults to: {})

    a customizable set of options

Options Hash (opts):

  • (see (Object)

    Rspec::Mocks::MessageExpectation#with) :with_job (any_args) queueing params for the job



91
92
93
# File 'lib/active_interaction/extras/rspec.rb', line 91

def expect_to_delay_execute(klass, opts = {})
  stub_service_delay :expect, :expect_to_execute, klass, opts
end

#expect_to_delay_run(klass, opts = {}) ⇒ Object

see expect_to_run

additional params

Parameters:

  • opts (Hash) (defaults to: {})

    a customizable set of options

Options Hash (opts):

  • (see (Object)

    Rspec::Mocks::MessageExpectation#with) :with_job (any_args) queueing params for the job



79
80
81
# File 'lib/active_interaction/extras/rspec.rb', line 79

def expect_to_delay_run(klass, opts = {})
  stub_service_delay :expect, :expect_to_run, klass, opts
end

#expect_to_execute(klass, opts = {}) ⇒ void

This method returns an undefined value.

Helper method to stub service objects in unit tests, while verifying that they are called with valid arguments.

This stub does NOT run after_run callbacks.

Examples:

Simple stub

expect_to_execute(X)

With all arguments

expect_to_execute(X, with: hash_including(:key), return: 1, fail: false)

Parameters:

  • klass (Class)

    Service class to stub

  • opts (Hash) (defaults to: {})

Options Hash (opts):

  • :fail (Boolean) — default: false

    If execution should add error

  • (see (Object)

    Rspec::Mocks::MessageExpectation#with) :with (any_args) Inputs for the service

  • (void) (Object)

    :return (nil) Execution return value

  • (void) (Object)

    :execute (Proc) Execution proc



24
25
26
# File 'lib/active_interaction/extras/rspec.rb', line 24

def expect_to_execute(klass, opts = {})
  stub_service_execute(:expect, klass, opts)
end

#expect_to_not_run_delayed(klass, opts = {}) ⇒ Object Also known as: expect_not_to_run_delayed



62
63
64
65
66
67
68
# File 'lib/active_interaction/extras/rspec.rb', line 62

def expect_to_not_run_delayed(klass, opts = {})
  alias_delay_method(klass)

  with = service_parse_job_with_option(opts)

  expect(klass).to_not receive(:delay).with(*with)
end

#expect_to_run(klass, opts = {}) ⇒ Object

Stub service run method. Does not validate inputs

See Also:



36
37
38
# File 'lib/active_interaction/extras/rspec.rb', line 36

def expect_to_run(klass, opts = {})
  stub_service_run(:expect, klass, opts)
end

#service_parse_job_with_option(opts) ⇒ Object



227
228
229
230
231
# File 'lib/active_interaction/extras/rspec.rb', line 227

def service_parse_job_with_option(opts)
  with_opts = {}
  with_opts[:with] = opts.delete(:job_with) if opts.key? :job_with
  service_parse_with_option(with_opts)
end

#service_parse_with_option(opts) ⇒ Object



221
222
223
224
225
# File 'lib/active_interaction/extras/rspec.rb', line 221

def service_parse_with_option(opts)
  with = opts.fetch(:with, [any_args])
  with = [with] unless with.is_a? Array
  with
end

#stub_service_delay(expectation, expect_helper, klass, opts) ⇒ Object



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/active_interaction/extras/rspec.rb', line 118

def stub_service_delay(expectation, expect_helper, klass, opts)
  alias_delay_method(klass)

  with = service_parse_job_with_option(opts)

  send(expectation, klass).to(
    # ^^^^^
    # If failed here, the .delay method was not called
    # or called with invalid arguments
    #
    receive(:delay).with(*with) do |*args|
      # get the original .delay return value
      delayed_run = klass.original_delay(*args)

      opts[:execute] ||= proc do |instance|
        # call original queueing logic, so the argument serialisation is triggered
        delayed_run.run(instance.raw_inputs)
      end

      send(expect_helper, klass, opts)
      klass
    end,
  )
end

#stub_service_execute(expectation, klass, opts) ⇒ Object



173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
# File 'lib/active_interaction/extras/rspec.rb', line 173

def stub_service_execute(expectation, klass, opts)
  stub_service_validate_opts opts
  alias_new_method(klass)
  with = service_parse_with_option(opts)

  # TODO: change so rspec displays correct message
  send(expectation, klass).to(
    # ^^^^^^^^^^^^^^^^^^^^^^^
    # If failed here, the service was not called
    #
    receive(:new).with(*with) do |*args|
      instance = klass.original_new(*args)
      instance.disable_after_run_callback
      send(expectation, instance).to(
        #
        # If failed here, the service was called, but failed because it's invalid
        #
        receive(:execute) do
          instance.errors.add :base, 'forced test failure' if opts[:fail]

          if opts[:execute].respond_to? :call
            opts[:execute].call(instance)
          else
            opts[:return]
          end
        end,
      )

      instance
    end,
  )
end

#stub_service_run(expectation, klass, opts) ⇒ Object



144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# File 'lib/active_interaction/extras/rspec.rb', line 144

def stub_service_run(expectation, klass, opts)
  stub_service_validate_opts opts
  alias_new_method(klass)
  with = service_parse_with_option(opts)

  send(expectation, klass).to(
    # ^^^^^^^^^^^^^^^^^^^^^^^^
    # If failed here, the service did not run
    #
    receive(:new).with(*with) do |*args|
      instance = klass.original_new(*args)
      send(expectation, instance).to receive(:run) do
        instance.errors.add :base, 'forced test failure' if opts[:fail]

        instance.result =
          if opts[:execute].respond_to? :call
            opts[:execute].call(instance)
          else
            opts[:return]
          end

        instance
      end
      instance
    end,
  )
end

#stub_service_validate_opts(opts) ⇒ Object

Raises:

  • (ArgumentError)


234
235
236
237
238
239
# File 'lib/active_interaction/extras/rspec.rb', line 234

def stub_service_validate_opts(opts)
  raise ArgumentError, 'Pick one :return or :execute, but not both' if opts.key?(:return) && opts.key?(:execute)

  invalid_keys = opts.except(:fail, :return, :with, :execute).keys
  raise ArgumentError, 'Unknown options: ' + invalid_keys.to_s if invalid_keys.any?
end