Module: Explicit::TestHelper

Extended by:
ActiveSupport::Concern
Defined in:
lib/explicit/test_helper.rb

Defined Under Namespace

Classes: ExampleRecorder

Instance Method Summary collapse

Instance Method Details

#ensure_response_matches_documented_type!(request, response) ⇒ Object



101
102
103
104
105
106
107
108
# File 'lib/explicit/test_helper.rb', line 101

def ensure_response_matches_documented_type!(request, response)
  responses_type = request.responses_type(status: response.status)

  case responses_type.validate(response.data.with_indifferent_access)
  in [:ok, _] then :all_good
  in [:error, err] then raise Explicit::Request::InvalidResponseError.new(response, err)
  end
end

#fetch(request, params: {}, headers: {}, **opts) ⇒ Object



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
# File 'lib/explicit/test_helper.rb', line 36

def fetch(request, params: {}, headers: {}, **opts)
  route = request.send(:routes).first

  if route.nil?
    raise <<-DESC
    The request #{request} must define at least one route. For example:

      get "/customers/:customer_id"
      post "/article/:article_id/comments"
      put "/user/preferences"

    Important: adding a route to the request does not substitute the entry
    on `routes.rb`.
    DESC
  end

  method = route.method
  path = (request.get_base_path || "") + route.replace_path_params(params)

  if missing_path_param?(route, params)
    raise <<~DESC
      The request #{route} needs the following path parameters: #{route.params.join(", ")}
    DESC
  end

  process(method, path, params:, headers:)

  if @response.headers["content-type"]&.include?("text/html")
    html = @response.parsed_body

    html.search("style").each { _1.remove }
    html.search("script").each { _1.remove }

    raise <<~TXT
      Unexpected HTML response:

      #{html.text.gsub(/^\s+$\n/, '')}
    TXT
  end

  response = Explicit::Request::Response.new(
    status: @response.status,
    data: @response.parsed_body.deep_symbolize_keys
  )

  ensure_response_matches_documented_type!(request, response)

  if opts[:save_as_example]
    params = replace_uploaded_files_with_filenames(params)

    ExampleRecorder.instance.add(
      request_gid: request.gid,
      params:,
      headers:,
      response:
    )
  end

  response
end

#missing_path_param?(route, params) ⇒ Boolean

Returns:

  • (Boolean)


97
98
99
# File 'lib/explicit/test_helper.rb', line 97

def missing_path_param?(route, params)
  route.params.any? { params.fetch(_1, nil).nil? }
end

#replace_uploaded_files_with_filenames(hash) ⇒ Object



110
111
112
113
114
115
116
117
118
119
120
# File 'lib/explicit/test_helper.rb', line 110

def replace_uploaded_files_with_filenames(hash)
  hash.to_h do |key, value|
    if Explicit::Type::File::FILE_CLASSES.any? { value.is_a?(_1) }
      [key, "@#{value.original_filename}"]
    elsif value.is_a?(::Hash)
      [key, replace_uploaded_files_with_filenames(value)]
    else
      [key, value]
    end
  end
end