Module: HttpApi::Extensions

Defined in:
lib/rspec-sane-http.rb

Class Method Summary collapse

Class Method Details

.extended(base) ⇒ Object



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
# File 'lib/rspec-sane-http.rb', line 5

def self.extended(base)
  base.class_eval do
    def description
      block = Proc.new do ||
        if [:description].match(/^(GET|POST|PUT|DELETE|OPTIONS|PATCH) (.+)$/)
          [:description]
        else
          block.call([:parent_example_group])
        end
      end

      block.call(self.class.)
    end

    def request_method
      self.description.split(' ').first
    end

    def request_path
      self.description.split(' ').last.split('/').
        map { |fragment| fragment.sub(/^:(.+)$/) { |match|
          # instance.send(match[1..-1])
          self.class.[match[1..-1].to_sym]
        } }.join('/')
    end

    let(:attrs) do
      Hash.new
    end

    # let(:factory) do
    #   self.model.factory(attrs)
    # end

    let(:instance) do
      # TODO: maybe inheritance?
      if request_method == 'POST'
        factory
      else
        factory.save
        puts "~ DB: #{factory.values}"
        factory
      end
    end

    let(:url) do
      [RSpec.configuration.base_url, request_path].join('')
    end

    # Rest client docs: https://github.com/rest-client/rest-client
    let(:response) do
      if ['GET', 'DELETE'].include?(request_method)
        headers = self.class.[:headers]
        request = HTTP.with_headers(headers || {})

        log(request_method, request_path, headers)
        request.send(request_method.downcase, url)
      else
        data    = self.class.[:data]
        headers = self.class.[:headers]
        request = HTTP.with_headers(headers || {})

        log(request_method, request_path, headers, data)
        request.send(request_method.downcase, url, body: data)
      end
    end

    def request(request_method, request_path = request_path, headers = {}, data = {})
      url = [RSpec.configuration.base_url, request_path].join('')
      request  = HTTP.with_headers(headers)
      data = data.to_json unless data.is_a?(String) # TODO: Switch to using data as an argument rather than stringified JSON.
      response = request.send(request_method.downcase, url, body: data)
      log(request_method, request_path, headers, data)

      JSON.parse(response.body.readpartial)
    end

    # data = POST('/posts', {Authorization: '...'}, {'title': ...})
    ['POST', 'PUT'].each do |http_method|
      define_method(http_method) do |request_path = request_path, headers = {}, body|
        request(http_method, request_path, headers, body)
      end
    end

    ['GET', 'DELETE'].each do |http_method|
      define_method(http_method) do |request_path = request_path, headers = {}|
        request(http_method, request_path, headers, nil)
      end
    end

    def log(request_method, request_path, headers, data = nil)
      if $DEBUG
        string = "~ #{request_method} #{request_path}"
        string << " #{headers.inspect}" if headers && ! headers.empty?
        string << " data: #{data.inspect}" if data
        warn string
      end
    end

    let(:response_data) do
      data = JSON.parse(response).reduce(Hash.new) do |buffer, (key, value)|
        buffer.merge(key.to_sym => value)
      end

      puts "Code: #{response.code}"
      puts "Data: #{data.inspect}"

      data
    end
  end
end