Top Level Namespace

Defined Under Namespace

Modules: RspecApi

Instance Method Summary collapse

Instance Method Details

#accepts(options = {}, &block) ⇒ Object



1
2
3
4
# File 'lib/rspec-api/accept_helper.rb', line 1

def accepts(options = {}, &block)
  parameters = block_given? ? options.merge(block: block) : options
  ([:query_parameters] ||= []).push parameters
end

#apply(method_name, options = {}) ⇒ Object



24
25
26
27
# File 'lib/rspec-api/instances_helper.rb', line 24

def apply(method_name, options = {})
  proc = options[:to]
  -> { proc.call.send method_name }
end

#assert_attribute_types(values, expected_type, can_be_nil) ⇒ Object



37
38
39
40
# File 'lib/rspec-api/attributes_helper.rb', line 37

def assert_attribute_types(values, expected_type, can_be_nil)
  values.compact! if can_be_nil
  expect(values).to all_match_type expected_type
end

#assert_attributes(json) ⇒ Object



8
9
10
11
12
13
14
# File 'lib/rspec-api/attributes_helper.rb', line 8

def assert_attributes(json)
  expect(json).to be_a (example.[:array] ? Array : Hash)
  example.[:attributes].each do |name, options|
    values = Array.wrap(json).map{|item| item[name.to_s]}
    assert_attribute_types(values, options[:type], options[:can_be_nil])
  end
end

#assert_instances(json) ⇒ Object



11
12
13
# File 'lib/rspec-api/instances_helper.rb', line 11

def assert_instances(json)
  expect(json).not_to be_empty
end


14
15
16
17
18
19
# File 'lib/rspec-api/accept_helper.rb', line 14

def assert_pagination_links
  expect(response_headers).to have_key 'Link'
  links = response_headers['Link'].split(',')
  rels = links.map{|link| link[/<.+?>; rel="(.*)"$/, 1]}
  expect(rels).to match_array ['last', 'next']
end

#assert_response(expected_status, &block) ⇒ Object



37
38
39
40
41
42
43
44
45
# File 'lib/rspec-api/api_helper.rb', line 37

def assert_response(expected_status, &block)
  assert_status expected_status
  if block_given? || success? && returns_content?
    json = JSON response_body
    assert_attributes json if success?
    assert_instances json
    instance_exec(json, &block) if block_given?
  end
end

#assert_status(expected_status) ⇒ Object



61
62
63
# File 'lib/rspec-api/api_helper.rb', line 61

def assert_status(expected_status)
  expect(status).to be Rack::Utils.status_code(expected_status)
end

#description_for(request_params = {}) ⇒ Object



33
34
35
# File 'lib/rspec-api/description_helper.rb', line 33

def description_for(request_params = {})
  [description_verb, description_object(request_params)].join ' '
end

#description_object(request_params = {}) ⇒ Object



46
47
48
49
50
51
52
53
54
55
# File 'lib/rspec-api/description_helper.rb', line 46

def description_object(request_params = {})
  attribute = request_params.delete :attribute
  if [:array]
    "a list of #{[:resource_name]}".tap do |objects|
      objects << " by #{request_params.keys.join(', ')}" if request_params.any?
    end
  else
    [attribute, [:resource_name].singularize].join ' '
  end.downcase
end

#description_verbObject



37
38
39
40
41
42
43
44
# File 'lib/rspec-api/description_helper.rb', line 37

def description_verb
  case [:method]
  when :get then 'Getting'
  when :post then 'Creating'
  when :put then 'Updating'
  when :delete then 'Deleting'
  end
end

#evaluate_request_params!Object



47
48
49
50
51
# File 'lib/rspec-api/api_helper.rb', line 47

def evaluate_request_params!
  request_params.each do |name, value|
    request_params[name] = instance_exec(&value) if value.is_a? Proc
  end
end

#existing(key) ⇒ Object



15
16
17
# File 'lib/rspec-api/instances_helper.rb', line 15

def existing(key)
  -> { instances.pluck(key).first }
end

#filter_parameters_requests(params) ⇒ Object



33
34
35
36
37
38
39
40
# File 'lib/rspec-api/accept_helper.rb', line 33

def filter_parameters_requests(params)
  params.except(:given, :block).tap do |req|
    value = params.fetch :given, apply(:as_json, to: existing(params[:on]))
    req[:description] = " filtered by #{params[:filter]}"
    req[:request_params] = {params[:filter] => value}
    req[:block] = params[:block]
  end
end

#has_attribute(name, type, options = {}) ⇒ Object



4
5
6
# File 'lib/rspec-api/attributes_helper.rb', line 4

def has_attribute(name, type, options = {})
  ([:attributes] ||= {})[name] = options.merge(type: type)
end

#instancesObject



7
8
9
# File 'lib/rspec-api/instances_helper.rb', line 7

def instances
  example.[:resource_name].singularize.constantize
end

#invalid(request_params) ⇒ Object



29
30
31
# File 'lib/rspec-api/description_helper.rb', line 29

def invalid(request_params)
  request_params.merge attribute: 'an invalid'
end

#json_response?Boolean



65
66
67
# File 'lib/rspec-api/api_helper.rb', line 65

def json_response?
 response_headers['Content-Type'] == 'application/json; charset=utf-8'
end

#matches_type?(value, type) ⇒ Boolean



42
43
44
45
46
47
# File 'lib/rspec-api/attributes_helper.rb', line 42

def matches_type?(value, type)
  case type
    when :url then value =~ URI::regexp
    else value.is_a? type.to_s.classify.constantize
  end
end

#no_paramsObject



21
22
23
# File 'lib/rspec-api/description_helper.rb', line 21

def no_params
  {}
end

#page_parameters_requests(params) ⇒ Object



52
53
54
55
56
57
58
59
# File 'lib/rspec-api/accept_helper.rb', line 52

def page_parameters_requests(params)
  {}.tap do |req|
    req[:description] = " paginated by #{params[:page]}"
    (req[:request_params] = {})[params[:page]] = 1
    req[:min_pages] = 2
    req[:block] = -> _ { assert_pagination_links }
  end
end

#query_parameters_requestsObject



21
22
23
24
25
26
27
28
29
30
31
# File 'lib/rspec-api/accept_helper.rb', line 21

def query_parameters_requests
  .fetch(:query_parameters, []).map do |params|
    if params.has_key? :filter
      filter_parameters_requests params
    elsif params.has_key? :sort
      sort_parameters_requests params
    elsif params.has_key? :page
      page_parameters_requests params
    end
  end.flatten
end

#random_attribute_value(options) ⇒ Object



25
26
27
28
29
30
31
32
33
34
35
# File 'lib/rspec-api/attributes_helper.rb', line 25

def random_attribute_value(options)
  if options[:can_be_nil] && [true, false].sample
    nil
  else
    case options[:type]
      when :string then [*('a'..'z'), *('A'..'Z')].sample(Random.rand 32).join
      when :integer then Random.rand(2**16)
      when :url then "http://example.com/#{SecureRandom.urlsafe_base64}"
    end
  end
end

#random_values_for_attributesObject



16
17
18
19
20
21
22
23
# File 'lib/rspec-api/attributes_helper.rb', line 16

def random_values_for_attributes
  {}.tap do |values|
    example.[:attributes].each do |name, options|
      can_be_nil = options[:can_be_nil] && (name != example.[:on])
      values[name] = random_attribute_value options.merge(can_be_nil: can_be_nil)
    end
  end
end

#request(description, request_params = {}) ⇒ Object



10
11
12
13
14
15
16
17
18
19
20
21
# File 'lib/rspec-api/api_helper.rb', line 10

def request(description, request_params = {})
  default_request = {}
  example_requests = [default_request]
  example_requests.concat query_parameters_requests if [:array]

  example_requests.each do ||
    ([:description] ||= '').prepend description
    ([:request_params] ||= {}).merge! request_params
    .merge! 
    yield if block_given?
  end
end

#request_paramsObject



23
24
25
# File 'lib/rspec-api/api_helper.rb', line 23

def request_params
  example.[:request_params]
end

#respond_with(expected_status, &block) ⇒ Object



27
28
29
30
31
32
33
34
35
# File 'lib/rspec-api/api_helper.rb', line 27

def respond_with(expected_status, &block)
  description = [:description]
  example description do
    setup_instances
    evaluate_request_params!
    do_request request_params.dup
    assert_response expected_status, &example..fetch(:block, block)
  end
end

#returns_content?Boolean



57
58
59
# File 'lib/rspec-api/api_helper.rb', line 57

def returns_content?
  [100, 101, 102, 204, 205, 304].exclude? status
end

#setup_instancesObject



1
2
3
4
5
# File 'lib/rspec-api/instances_helper.rb', line 1

def setup_instances
  instances.create random_values_for_attributes
  instances.create random_values_for_attributes
  stub_instances_total_pages example.[:min_pages]
end

#sort_parameters_requests(params) ⇒ Object



42
43
44
45
46
47
48
49
50
# File 'lib/rspec-api/accept_helper.rb', line 42

def sort_parameters_requests(params)
  [true, false].map do |ascending|
    params.except(:block).tap do |req|
      req[:description] = " sorted by #{params[:sort]} #{ascending ? '' : ''}"
      req[:request_params] = {sort: "#{ascending ? '' : '-'}#{params[:sort]}"}
      req[:block] = params[:block]
    end
  end
end

#stub_instances_total_pages(total_pages) ⇒ Object



29
30
31
32
33
34
35
36
37
# File 'lib/rspec-api/instances_helper.rb', line 29

def stub_instances_total_pages(total_pages)
  return unless instances.respond_to?(:page) and total_pages.present?
  page_method = instances.method :page
  instances.stub(:page) do |page|
    page_method.call(page).tap do |proxy|
      proxy.stub(:total_pages).and_return total_pages
    end
  end
end

#success?Boolean



53
54
55
# File 'lib/rspec-api/api_helper.rb', line 53

def success?
  status < 400
end

#unknown(key) ⇒ Object



19
20
21
22
# File 'lib/rspec-api/instances_helper.rb', line 19

def unknown(key)
  keys = 0.downto(-Float::INFINITY).lazy
  -> { keys.reject {|value| instances.exists? key => value}.first }
end

#valid(request_params) ⇒ Object



25
26
27
# File 'lib/rspec-api/description_helper.rb', line 25

def valid(request_params)
  request_params.merge attribute: 'an valid'
end

#with(request_params = {}) ⇒ Object



16
17
18
19
# File 'lib/rspec-api/description_helper.rb', line 16

def with(request_params = {})
  request_params[:attribute] ||= .delete :description_attribute
  request description_for(request_params), request_params, &Proc.new
end