rspec-api 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 302b0ee6e8cfaf3d3e65b088f190e1c36cd210af
4
- data.tar.gz: 4f27c81817901a1108c8d0fc6e28706fcb06cecd
3
+ metadata.gz: 80ddaf39a5b7ad64bec2e973e89771183f139ed2
4
+ data.tar.gz: c5b3280cd6f9b23bd127fd43db4487ded01c8a9c
5
5
  SHA512:
6
- metadata.gz: f15362494296d9866eaba1fc49100e7f2031ab78cd8a76d26336851909ea1a65f5fd273379a573e527e88f1dec62180575b4b38ee8ba9eaf9014c0e9bbe61341
7
- data.tar.gz: 6d94a2b103b77e0fd61affaac2a48c89fcea87731237fc2f5e7709772228cdfee7d5da4278c37ed494b4911cab056c9c5ac7b524fdbca760dfbfee9394c4cfa1
6
+ metadata.gz: fe877acbc40ca26a6dde50984ce03c62a485d7833fc2c175389a323a74debb9c189fd531a120cb83cf8541d8e6461afefeb36a43954a4a8d208ad9520e35f52a
7
+ data.tar.gz: d80f970b130815b361bac32f81f6d4623ae6345a514c6a0917a709596fc066bea127f6a1e2fbc112b6cf5597c33ab1e273972fadc5da1887ed8cfbe1391ed728
@@ -1,6 +1,4 @@
1
- Copyright (c) 2013 claudiob
2
-
3
- MIT License
1
+ Copyright 2013 claudiob
4
2
 
5
3
  Permission is hereby granted, free of charge, to any person obtaining
6
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -1,29 +1,2 @@
1
- # Rspec::Api
1
+ # RSpec API
2
2
 
3
- TODO: Write a gem description
4
-
5
- ## Installation
6
-
7
- Add this line to your application's Gemfile:
8
-
9
- gem 'rspec-api'
10
-
11
- And then execute:
12
-
13
- $ bundle
14
-
15
- Or install it yourself as:
16
-
17
- $ gem install rspec-api
18
-
19
- ## Usage
20
-
21
- TODO: Write usage instructions here
22
-
23
- ## Contributing
24
-
25
- 1. Fork it
26
- 2. Create your feature branch (`git checkout -b my-new-feature`)
27
- 3. Commit your changes (`git commit -am 'Add some feature'`)
28
- 4. Push to the branch (`git push origin my-new-feature`)
29
- 5. Create new Pull Request
@@ -0,0 +1,59 @@
1
+ def accepts(options = {}, &block)
2
+ parameters = block_given? ? options.merge(block: block) : options
3
+ (metadata[:query_parameters] ||= []).push parameters
4
+ end
5
+
6
+ RSpec::Matchers.define :be_sorted_by do |attribute|
7
+ match do |items|
8
+ values = items.map{|item| item[attribute.to_s]}
9
+ values.reverse! if example.metadata[:request_params][:sort][0] == '-'
10
+ values == values.sort
11
+ end
12
+ end
13
+
14
+ def assert_pagination_links
15
+ expect(response_headers).to have_key 'Link'
16
+ links = response_headers['Link'].split(',')
17
+ rels = links.map{|link| link[/<.+?>; rel="(.*)"$/, 1]}
18
+ expect(rels).to match_array ['last', 'next']
19
+ end
20
+
21
+ def query_parameters_requests
22
+ metadata.fetch(:query_parameters, []).map do |params|
23
+ if params.has_key? :filter
24
+ filter_parameters_requests params
25
+ elsif params.has_key? :sort
26
+ sort_parameters_requests params
27
+ elsif params.has_key? :page
28
+ page_parameters_requests params
29
+ end
30
+ end.flatten
31
+ end
32
+
33
+ def filter_parameters_requests(params)
34
+ params.except(:given, :block).tap do |req|
35
+ value = params.fetch :given, apply(:as_json, to: existing(params[:on]))
36
+ req[:description] = " filtered by #{params[:filter]}"
37
+ req[:request_params] = {params[:filter] => value}
38
+ req[:block] = params[:block]
39
+ end
40
+ end
41
+
42
+ def sort_parameters_requests(params)
43
+ [true, false].map do |ascending|
44
+ params.except(:block).tap do |req|
45
+ req[:description] = " sorted by #{params[:sort]} #{ascending ? '↑' : '↓'}"
46
+ req[:request_params] = {sort: "#{ascending ? '' : '-'}#{params[:sort]}"}
47
+ req[:block] = params[:block]
48
+ end
49
+ end
50
+ end
51
+
52
+ def page_parameters_requests(params)
53
+ {}.tap do |req|
54
+ req[:description] = " paginated by #{params[:page]}"
55
+ (req[:request_params] = {})[params[:page]] = 1
56
+ req[:min_pages] = 2
57
+ req[:block] = -> _ { assert_pagination_links }
58
+ end
59
+ end
@@ -0,0 +1,67 @@
1
+ # encoding: UTF-8
2
+ shared_context 'accept_json', accepts: :json do
3
+ header 'Accept', 'application/json'
4
+ end
5
+
6
+ shared_context 'return_json', returns: :json do
7
+ after { expect(json_response?) }
8
+ end
9
+
10
+ def request(description, request_params = {})
11
+ default_request = {}
12
+ example_requests = [default_request]
13
+ example_requests.concat query_parameters_requests if metadata[:array]
14
+
15
+ example_requests.each do |request_metadata|
16
+ (request_metadata[:description] ||= '').prepend description
17
+ (request_metadata[:request_params] ||= {}).merge! request_params
18
+ metadata.merge! request_metadata
19
+ yield if block_given?
20
+ end
21
+ end
22
+
23
+ def request_params
24
+ example.metadata[:request_params]
25
+ end
26
+
27
+ def respond_with(expected_status, &block)
28
+ description = metadata[:description]
29
+ example description do
30
+ setup_instances
31
+ evaluate_request_params!
32
+ do_request request_params.dup
33
+ assert_response expected_status, &example.metadata.fetch(:block, block)
34
+ end
35
+ end
36
+
37
+ def assert_response(expected_status, &block)
38
+ assert_status expected_status
39
+ if block_given? || success? && returns_content?
40
+ json = JSON response_body
41
+ assert_attributes json if success?
42
+ assert_instances json
43
+ instance_exec(json, &block) if block_given?
44
+ end
45
+ end
46
+
47
+ def evaluate_request_params!
48
+ request_params.each do |name, value|
49
+ request_params[name] = instance_exec(&value) if value.is_a? Proc
50
+ end
51
+ end
52
+
53
+ def success?
54
+ status < 400
55
+ end
56
+
57
+ def returns_content?
58
+ [100, 101, 102, 204, 205, 304].exclude? status
59
+ end
60
+
61
+ def assert_status(expected_status)
62
+ expect(status).to be Rack::Utils.status_code(expected_status)
63
+ end
64
+
65
+ def json_response?
66
+ response_headers['Content-Type'] == 'application/json; charset=utf-8'
67
+ end
@@ -0,0 +1,53 @@
1
+ require 'spec_helper'
2
+ require 'rspec_api_documentation/dsl'
3
+
4
+ def has_attribute(name, type, options = {})
5
+ (metadata[:attributes] ||= {})[name] = options.merge(type: type)
6
+ end
7
+
8
+ def assert_attributes(json)
9
+ expect(json).to be_a (example.metadata[:array] ? Array : Hash)
10
+ example.metadata[:attributes].each do |name, options|
11
+ values = Array.wrap(json).map{|item| item[name.to_s]}
12
+ assert_attribute_types(values, options[:type], options[:can_be_nil])
13
+ end
14
+ end
15
+
16
+ def random_values_for_attributes
17
+ {}.tap do |values|
18
+ example.metadata[:attributes].each do |name, options|
19
+ can_be_nil = options[:can_be_nil] && (name != example.metadata[:on])
20
+ values[name] = random_attribute_value options.merge(can_be_nil: can_be_nil)
21
+ end
22
+ end
23
+ end
24
+
25
+ def random_attribute_value(options)
26
+ if options[:can_be_nil] && [true, false].sample
27
+ nil
28
+ else
29
+ case options[:type]
30
+ when :string then [*('a'..'z'), *('A'..'Z')].sample(Random.rand 32).join
31
+ when :integer then Random.rand(2**16)
32
+ when :url then "http://example.com/#{SecureRandom.urlsafe_base64}"
33
+ end
34
+ end
35
+ end
36
+
37
+ def assert_attribute_types(values, expected_type, can_be_nil)
38
+ values.compact! if can_be_nil
39
+ expect(values).to all_match_type expected_type
40
+ end
41
+
42
+ def matches_type?(value, type)
43
+ case type
44
+ when :url then value =~ URI::regexp
45
+ else value.is_a? type.to_s.classify.constantize
46
+ end
47
+ end
48
+
49
+ RSpec::Matchers.define :all_match_type do |type|
50
+ match do |values|
51
+ values.all? {|value| matches_type? value, type}
52
+ end
53
+ end
@@ -0,0 +1,55 @@
1
+ def existing(key)
2
+ metadata[:description_attribute] = 'an existing'
3
+ -> { instances.any key }
4
+ end
5
+
6
+ def unknown(key)
7
+ metadata[:description_attribute] = 'an unknown'
8
+ -> { instances.none key }
9
+ end
10
+
11
+ def apply(method_name, options = {})
12
+ proc = options[:to]
13
+ -> { proc.call.send method_name }
14
+ end
15
+
16
+ def with(request_params = {})
17
+ request_params[:attribute] ||= metadata.delete :description_attribute
18
+ request description_for(request_params), request_params, &Proc.new
19
+ end
20
+
21
+ def no_params
22
+ {}
23
+ end
24
+
25
+ def valid(request_params)
26
+ request_params.merge attribute: 'an valid'
27
+ end
28
+
29
+ def invalid(request_params)
30
+ request_params.merge attribute: 'an invalid'
31
+ end
32
+
33
+ def description_for(request_params = {})
34
+ [description_verb, description_object(request_params)].join ' '
35
+ end
36
+
37
+ def description_verb
38
+ case metadata[:method]
39
+ when :get then 'Getting'
40
+ when :post then 'Creating'
41
+ when :put then 'Updating'
42
+ when :delete then 'Deleting'
43
+ end
44
+ end
45
+
46
+ def description_object(request_params = {})
47
+ attribute = request_params.delete :attribute
48
+ if metadata[:array]
49
+ "a list of #{metadata[:resource_name]}".tap do |objects|
50
+ objects << " by #{request_params.keys.join(', ')}" if request_params.any?
51
+ end
52
+ else
53
+ [attribute, metadata[:resource_name].singularize].join ' '
54
+ end.downcase
55
+ end
@@ -0,0 +1,8 @@
1
+ require 'rspec_api_documentation'
2
+ require 'rspec_api_documentation/dsl'
3
+
4
+ require 'rspec-api/accept_helper'
5
+ require 'rspec-api/attributes_helper'
6
+ require 'rspec-api/description_helper'
7
+ require 'rspec-api/api_helper'
8
+ require 'rspec-api/instances_helper'
@@ -0,0 +1,37 @@
1
+ def setup_instances
2
+ instances.create random_values_for_attributes
3
+ instances.create random_values_for_attributes
4
+ stub_instances_total_pages example.metadata[:min_pages]
5
+ end
6
+
7
+ def instances
8
+ example.metadata[:resource_name].singularize.constantize
9
+ end
10
+
11
+ def assert_instances(json)
12
+ expect(json).not_to be_empty
13
+ end
14
+
15
+ def existing(key)
16
+ -> { instances.pluck(key).first }
17
+ end
18
+
19
+ def unknown(key)
20
+ keys = 0.downto(-Float::INFINITY).lazy
21
+ -> { keys.reject {|value| instances.exists? key => value}.first }
22
+ end
23
+
24
+ def apply(method_name, options = {})
25
+ proc = options[:to]
26
+ -> { proc.call.send method_name }
27
+ end
28
+
29
+ def stub_instances_total_pages(total_pages)
30
+ return unless instances.respond_to?(:page) and total_pages.present?
31
+ page_method = instances.method :page
32
+ instances.stub(:page) do |page|
33
+ page_method.call(page).tap do |proxy|
34
+ proxy.stub(:total_pages).and_return total_pages
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,3 @@
1
+ module RspecApi
2
+ VERSION = '0.0.2'
3
+ end
metadata CHANGED
@@ -1,59 +1,46 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - claudiob
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-08-28 00:00:00.000000000 Z
11
+ date: 2013-09-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: bundler
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - ~>
18
- - !ruby/object:Gem::Version
19
- version: '1.3'
20
- type: :development
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ~>
25
- - !ruby/object:Gem::Version
26
- version: '1.3'
27
- - !ruby/object:Gem::Dependency
28
- name: rake
14
+ name: rspec-api-documentation
29
15
  requirement: !ruby/object:Gem::Requirement
30
16
  requirements:
31
17
  - - '>='
32
18
  - !ruby/object:Gem::Version
33
19
  version: '0'
34
- type: :development
20
+ type: :runtime
35
21
  prerelease: false
36
22
  version_requirements: !ruby/object:Gem::Requirement
37
23
  requirements:
38
24
  - - '>='
39
25
  - !ruby/object:Gem::Version
40
26
  version: '0'
41
- description: Write a gem description
27
+ description: Helpers to write specs for web APIs
42
28
  email:
43
29
  - claudiob@gmail.com
44
30
  executables: []
45
31
  extensions: []
46
32
  extra_rdoc_files: []
47
33
  files:
48
- - .gitignore
49
- - Gemfile
50
- - LICENSE.txt
34
+ - lib/rspec-api/accept_helper.rb
35
+ - lib/rspec-api/api_helper.rb
36
+ - lib/rspec-api/attributes_helper.rb
37
+ - lib/rspec-api/description_helper.rb
38
+ - lib/rspec-api/dsl.rb
39
+ - lib/rspec-api/instances_helper.rb
40
+ - lib/rspec-api/version.rb
41
+ - MIT-LICENSE
51
42
  - README.md
52
- - Rakefile
53
- - lib/rspec/api.rb
54
- - lib/rspec/api/version.rb
55
- - rspec-api.gemspec
56
- homepage: ''
43
+ homepage: https://github.com/claudiob/rspec-api
57
44
  licenses:
58
45
  - MIT
59
46
  metadata: {}
@@ -65,16 +52,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
65
52
  requirements:
66
53
  - - '>='
67
54
  - !ruby/object:Gem::Version
68
- version: '0'
55
+ version: 1.9.0
69
56
  required_rubygems_version: !ruby/object:Gem::Requirement
70
57
  requirements:
71
58
  - - '>='
72
59
  - !ruby/object:Gem::Version
73
- version: '0'
60
+ version: 1.3.6
74
61
  requirements: []
75
62
  rubyforge_project:
76
- rubygems_version: 2.0.3
63
+ rubygems_version: 2.1.0
77
64
  signing_key:
78
65
  specification_version: 4
79
- summary: Write a gem summary
66
+ summary: Extends rspec_api_documentation with methods to write more compact and meaningful,
67
+ auto-documented specs for web APIs.
80
68
  test_files: []
69
+ has_rdoc:
data/.gitignore DELETED
@@ -1,17 +0,0 @@
1
- *.gem
2
- *.rbc
3
- .bundle
4
- .config
5
- .yardoc
6
- Gemfile.lock
7
- InstalledFiles
8
- _yardoc
9
- coverage
10
- doc/
11
- lib/bundler/man
12
- pkg
13
- rdoc
14
- spec/reports
15
- test/tmp
16
- test/version_tmp
17
- tmp
data/Gemfile DELETED
@@ -1,4 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- # Specify your gem's dependencies in rspec-api.gemspec
4
- gemspec
data/Rakefile DELETED
@@ -1 +0,0 @@
1
- require "bundler/gem_tasks"
data/lib/rspec/api.rb DELETED
@@ -1,7 +0,0 @@
1
- require "rspec/api/version"
2
-
3
- module Rspec
4
- module Api
5
- # Your code goes here...
6
- end
7
- end
@@ -1,5 +0,0 @@
1
- module Rspec
2
- module Api
3
- VERSION = "0.0.1"
4
- end
5
- end
data/rspec-api.gemspec DELETED
@@ -1,23 +0,0 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
3
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'rspec/api/version'
5
-
6
- Gem::Specification.new do |spec|
7
- spec.name = "rspec-api"
8
- spec.version = Rspec::Api::VERSION
9
- spec.authors = ["claudiob"]
10
- spec.email = ["claudiob@gmail.com"]
11
- spec.description = %q{Write a gem description}
12
- spec.summary = %q{Write a gem summary}
13
- spec.homepage = ""
14
- spec.license = "MIT"
15
-
16
- spec.files = `git ls-files`.split($/)
17
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
- spec.require_paths = ["lib"]
20
-
21
- spec.add_development_dependency "bundler", "~> 1.3"
22
- spec.add_development_dependency "rake"
23
- end