File: request_stub.rb

package info (click to toggle)
ruby-webmock 3.25.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,172 kB
  • sloc: ruby: 12,829; makefile: 6
file content (134 lines) | stat: -rw-r--r-- 3,647 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# frozen_string_literal: true

module WebMock
  class RequestStub

    attr_accessor :request_pattern

    def initialize(method, uri)
      @request_pattern = RequestPattern.new(method, uri)
      @responses_sequences = []
      self
    end

    def with(params = {}, &block)
      @request_pattern.with(params, &block)
      self
    end

    def to_return(*response_hashes, &block)
      if block
        @responses_sequences << ResponsesSequence.new([ResponseFactory.response_for(block)])
      else
        @responses_sequences << ResponsesSequence.new([*response_hashes].flatten.map {|r| ResponseFactory.response_for(r)})
      end
      self
    end
    alias_method :and_return, :to_return

    def to_return_json(*response_hashes)
      raise ArgumentError, '#to_return_json does not support passing a block' if block_given?

      json_response_hashes = [*response_hashes].flatten.map do |resp_h|
        headers, body = resp_h.values_at(:headers, :body)

        json_body = if body.respond_to?(:call)
          ->(request_signature) {
            b = if body.respond_to?(:arity) && body.arity == 1
              body.call(request_signature)
            else
              body.call
            end
            b = b.to_json unless b.is_a?(String)
            b
          }
        elsif !body.is_a?(String)
          body.to_json
        else
          body
        end

        resp_h.merge(
          headers: {content_type: 'application/json'}.merge(headers.to_h),
          body: json_body
        )
      end

      to_return(json_response_hashes)
    end
    alias_method :and_return_json, :to_return_json

    def to_rack(app, options={})
      @responses_sequences << ResponsesSequence.new([RackResponse.new(app)])
    end

    def to_raise(*exceptions)
      @responses_sequences << ResponsesSequence.new([*exceptions].flatten.map {|e|
        ResponseFactory.response_for(exception: e)
      })
      self
    end
    alias_method :and_raise, :to_raise

    def to_timeout
      @responses_sequences << ResponsesSequence.new([ResponseFactory.response_for(should_timeout: true)])
      self
    end
    alias_method :and_timeout, :to_timeout

    def response
      if @responses_sequences.empty?
        WebMock::Response.new
      elsif @responses_sequences.length > 1
        @responses_sequences.shift if @responses_sequences.first.end?
        @responses_sequences.first.next_response
      else
        @responses_sequences[0].next_response
      end
    end

    def has_responses?
      !@responses_sequences.empty?
    end

    def then
      self
    end

    def times(number)
      raise "times(N) accepts integers >= 1 only" if !number.is_a?(Integer) || number < 1
      if @responses_sequences.empty?
        raise "Invalid WebMock stub declaration." +
          " times(N) can be declared only after response declaration."
      end
      @responses_sequences.last.times_to_repeat += number-1
      self
    end

    def matches?(request_signature)
      self.request_pattern.matches?(request_signature)
    end

    def to_s
      self.request_pattern.to_s
    end

    def self.from_request_signature(signature)
      stub = self.new(signature.method.to_sym, signature.uri.to_s)

      if signature.body.to_s != ''
        body = if signature.url_encoded?
          WebMock::Util::QueryMapper.query_to_values(signature.body, notation: Config.instance.query_values_notation)
        else
          signature.body
        end
        stub.with(body: body)
      end

      if (signature.headers && !signature.headers.empty?)
        stub.with(headers: signature.headers)
      end
      stub
    end
  end
end