Module: SpecyDocs::Capturable

Defined in:
lib/specy_docs/capturable.rb

Class Method Summary collapse

Class Method Details

.filtered_headers(request) ⇒ Object



89
90
91
92
# File 'lib/specy_docs/capturable.rb', line 89

def self.filtered_headers(request)
  request.headers.env
         .select { |k, _| k.start_with?('HTTP_') || k == 'CONTENT_TYPE' }
end

.included(base) ⇒ Object



9
10
11
12
13
14
15
16
# File 'lib/specy_docs/capturable.rb', line 9

def self.included(base)
  base.after(:each) do |example|
    next unless SpecyDocs::Capturable.should_capture?(example)
    next unless defined?(response) && response.present?

    SpecyDocs::Capturable.record(example, request, response)
  end
end

.load_captures(capture_file = SpecyDocs.configuration.resolved_capture_path) ⇒ Object



72
73
74
75
76
77
78
# File 'lib/specy_docs/capturable.rb', line 72

def self.load_captures(capture_file = SpecyDocs.configuration.resolved_capture_path)
  return {} unless capture_file.exist?

  JSON.parse(File.read(capture_file))
rescue JSON::ParserError
  {}
end

.matches_capture_path?(example) ⇒ Boolean

Returns:

  • (Boolean)


28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/specy_docs/capturable.rb', line 28

def self.matches_capture_path?(example)
  configured = Array(SpecyDocs.configuration.capture_paths).map(&:to_s).reject(&:empty?)
  return true if configured.empty?

  file_path = example.[:absolute_file_path].presence || example.[:file_path]
  return false if file_path.blank?

  absolute = Pathname(file_path).expand_path.to_s

  configured.any? do |capture_path|
    base = Pathname(capture_path)
    base = Rails.root.join(capture_path) unless base.absolute?
    prefix = "#{base.expand_path}#{File::SEPARATOR}"
    absolute == base.expand_path.to_s || absolute.start_with?(prefix)
  end
end

.parsed_body(response) ⇒ Object



94
95
96
97
98
99
100
# File 'lib/specy_docs/capturable.rb', line 94

def self.parsed_body(response)
  return nil if response.body.blank?

  JSON.parse(response.body)
rescue JSON::ParserError
  response.body
end

.raw_body(request) ⇒ Object



80
81
82
83
84
85
86
87
# File 'lib/specy_docs/capturable.rb', line 80

def self.raw_body(request)
  request_body = request.body
  return nil unless request_body

  body = request_body.read
  request_body.rewind
  body.presence
end

.record(example, request, response) ⇒ Object



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
# File 'lib/specy_docs/capturable.rb', line 45

def self.record(example, request, response)
  capture_file = SpecyDocs.configuration.resolved_capture_path
  FileUtils.mkdir_p(capture_file.dirname)

  key = example.id
  captures = load_captures(capture_file)
  captures[key] = {
    description: example.full_description,
    location: "#{example.[:file_path]}:#{example.[:line_number]}",
    request: {
      method: request.request_method,
      path: request.path,
      query_string: request.query_string.presence,
      headers: filtered_headers(request),
      body: raw_body(request)
    },
    response: {
      status: response.status,
      headers: response.headers.slice('Content-Type', 'Location'),
      body: parsed_body(response)
    },
    captured_at: Time.current.iso8601
  }

  File.write(capture_file, JSON.pretty_generate(captures))
end

.should_capture?(example) ⇒ Boolean

Returns:

  • (Boolean)


18
19
20
21
22
23
24
25
26
# File 'lib/specy_docs/capturable.rb', line 18

def self.should_capture?(example)
  return false unless matches_capture_path?(example)

  if SpecyDocs.configuration.opt_in
    !!example.[:specy]
  else
    example.[:specy] != false
  end
end