apiaryio 0.0.2 → 0.0.3

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.
data/.gitignore CHANGED
@@ -2,8 +2,12 @@
2
2
  .rvmrc
3
3
  .tags
4
4
  .rbenv-version
5
+ *.gem
5
6
  /coverage
6
7
  /pkg
7
8
  /rdoc
8
9
  /vendor
9
10
  !/doc
11
+ /.idea
12
+ /nbproject/
13
+
data/README.md CHANGED
@@ -3,10 +3,18 @@ apiaryio
3
3
 
4
4
  Apiary.io CLI
5
5
 
6
+
7
+ ## Install
8
+
9
+ ``` bash
10
+ gem install apiaryio
11
+ ```
12
+
13
+
6
14
  ## Description
7
15
 
8
- Apiaryio gem provides a way to display your API documentation on your local
9
- machine, either using static files or using a standalone web server
16
+ Apiaryio gem provides a way to test and display your API documentation on your local
17
+ machine, either using static files or using a standalone web server...
10
18
 
11
19
  ## Usage
12
20
 
@@ -23,7 +31,7 @@ machine, either using static files or using a standalone web server
23
31
  preview --api_host [HOST] Specify apiary host
24
32
  preview --server Start standalone web server on port 8080
25
33
  preview --server --port [PORT] Start standalone web server on specified port
26
-
34
+ okapi help Show okapi testing tool help
27
35
  help Show help
28
36
 
29
37
  version Show version
@@ -38,6 +46,7 @@ Copyright 2012 (c) Apiary Ltd.
38
46
  - James Charles Russell
39
47
  - Lukáš Linhart
40
48
  - Emili Parreño
49
+ - Peter Grilli [Tu1ly]
41
50
 
42
51
  ## License
43
52
 
@@ -18,9 +18,9 @@ Gem::Specification.new do |gem|
18
18
 
19
19
  gem.add_dependency "rest-client", "~> 1.6.7"
20
20
  gem.add_dependency "rack", "~> 1.4.1"
21
+ gem.add_dependency "json"
21
22
 
22
23
  gem.add_development_dependency "rspec", "~> 2.11.0"
23
24
  gem.add_development_dependency "yard", "~> 0.8.2.1"
24
25
 
25
- gem.post_install_message = "This gem is a client for http://apiary.io. Apiary is in closed beta version now, you need an invitation. If you don't have one, visit http://apiary.us2.list-manage.com/subscribe?u=b89934a238dcec9533f4a834a&id=08f2bdde55 to get on the waiting list!"
26
26
  end
data/bin/apiary CHANGED
@@ -1,6 +1,12 @@
1
1
  #!/usr/bin/env ruby
2
2
  $:.unshift(File.expand_path(File.join(File.dirname(__FILE__), '..','lib')))
3
3
  require 'apiary'
4
+ require 'okapi'
4
5
 
5
6
  trap(:INT) { abort "" }
6
- Apiary::CLI.new(ARGV)
7
+ if ARGV[0] == 'okapi' || ARGV[0] == 'test'
8
+ ARGV.delete_at(0)
9
+ Apiary::Okapi::CLI.new(ARGV)
10
+ else
11
+ Apiary::CLI.new(ARGV)
12
+ end
@@ -11,7 +11,7 @@ module Apiary
11
11
  end
12
12
 
13
13
  def run(args, options)
14
- command = args.first
14
+ command = args.first || :help
15
15
  command = @command if @command
16
16
  Apiary::Command::Runner.run(command, options)
17
17
  end
@@ -21,7 +21,7 @@ module Apiary
21
21
  options = {}
22
22
  options_parser = OptionParser.new do |opts|
23
23
  opts.on("--path [PATH]") do |path|
24
- options[:apib_path] = path
24
+ options[:path] = path
25
25
  end
26
26
 
27
27
  opts.on("--api_host API_HOST") do |api_host|
@@ -22,8 +22,9 @@ module Apiary
22
22
  puts "\tpreview --api_host [HOST] Specify apiary host"
23
23
  puts "\tpreview --server Start standalone web server on port 8080"
24
24
  puts "\tpreview --server --port [PORT] Start standalone web server on specified port"
25
+ puts "\tokapi help Show okapi testing tool help"
25
26
  puts "\n"
26
- puts "\thelp Show help"
27
+ puts "\thelp Show this help"
27
28
  puts "\n"
28
29
  puts "\tversion Show version"
29
30
  puts "\n"
@@ -1,6 +1,8 @@
1
1
  # encoding: utf-8
2
2
  require 'rest_client'
3
3
  require 'rack'
4
+ require 'ostruct'
5
+
4
6
  module Apiary
5
7
  module Command
6
8
  # Display preview of local blueprint file
@@ -14,13 +16,13 @@ module Apiary
14
16
 
15
17
  attr_reader :options
16
18
 
17
- def initialize(args)
18
- @options = {}
19
- @options[:apib_path] = "apiary.apib"
20
- @options[:api_host] = "api.apiary.io"
21
- @options[:headers] = {:accept => "text/html", :content_type => "text/plain"}
22
- @options[:port] = 8080
23
- @options.merge! args
19
+ # TODO: use OpenStruct to store @options
20
+ def initialize(opts)
21
+ @options = OpenStruct.new(opts)
22
+ @options.path ||= "apiary.apib"
23
+ @options.api_host ||= "api.apiary.io"
24
+ @options.headers ||= {:accept => "text/html", :content_type => "text/plain"}
25
+ @options.port ||= 8080
24
26
  end
25
27
 
26
28
  def self.execute(args)
@@ -32,7 +34,7 @@ module Apiary
32
34
  end
33
35
 
34
36
  def show
35
- generate_static(apib_path)
37
+ generate_static(path)
36
38
  end
37
39
 
38
40
  def validate_apib_file(apib_file)
@@ -41,20 +43,12 @@ module Apiary
41
43
  end
42
44
  end
43
45
 
44
- def apib_path
45
- @options[:apib_path] || "#{File.basename(Dir.pwd)}.apib"
46
+ def path
47
+ @options.path || "#{File.basename(Dir.pwd)}.apib"
46
48
  end
47
49
 
48
50
  def browser
49
- BROWSERS[@options[:browser]] || nil
50
- end
51
-
52
- def api_host
53
- @options[:api_host]
54
- end
55
-
56
- def port
57
- @options[:port]
51
+ BROWSERS[@options.browser] || nil
58
52
  end
59
53
 
60
54
  def rack_app(&block)
@@ -65,21 +59,21 @@ module Apiary
65
59
 
66
60
  def run_server
67
61
  app = self.rack_app do
68
- self.query_apiary(api_host, apib_path)
62
+ self.query_apiary(@options.api_host, @options.path)
69
63
  end
70
64
 
71
- Rack::Server.start(:Port => port, :app => app)
65
+ Rack::Server.start(:Port => @options.port, :app => app)
72
66
  end
73
67
 
74
- def preview_path(apib_path)
75
- basename = File.basename(apib_path)
68
+ def preview_path(path)
69
+ basename = File.basename(@options.path)
76
70
  "/tmp/#{basename}-preview.html"
77
71
  end
78
72
 
79
- def query_apiary(host, apib_path)
73
+ def query_apiary(host, path)
80
74
  url = "https://#{host}/blueprint/generate"
81
- data = File.read(apib_path)
82
- RestClient.post(url, data, @options[:headers])
75
+ data = File.read(path)
76
+ RestClient.post(url, data, @options.headers)
83
77
  end
84
78
 
85
79
  # TODO: add linux and windows systems
@@ -87,16 +81,16 @@ module Apiary
87
81
  exec "open #{browser_options} #{path}"
88
82
  end
89
83
 
90
- def generate_static(apib_path)
91
- File.open(preview_path(apib_path), "w") do |file|
92
- file.write(query_apiary(api_host, apib_path))
84
+ def generate_static(path)
85
+ File.open(preview_path(path), "w") do |file|
86
+ file.write(query_apiary(@options.api_host, path))
93
87
  open_generated_page(file.path)
94
88
  end
95
89
  end
96
90
 
97
91
  private
98
92
  def browser_options
99
- "-a #{BROWSERS[@options[:browser].to_sym]}" if @options[:browser]
93
+ "-a #{BROWSERS[@options.browser.to_sym]}" if @options.browser
100
94
  end
101
95
  end
102
96
  end
@@ -1,3 +1,3 @@
1
1
  module Apiary
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -0,0 +1,13 @@
1
+ # encoding: utf-8
2
+ require 'rubygems'
3
+ require "okapi/config"
4
+ require "okapi/output"
5
+ require "okapi/apiary_connector"
6
+ require "okapi/resources"
7
+ require "okapi/spec_parser"
8
+ require "okapi/test"
9
+ require "okapi/cli"
10
+ require "okapi/help"
11
+
12
+ module Okapi
13
+ end
@@ -0,0 +1,98 @@
1
+ # encoding: utf-8
2
+ require 'rest_client'
3
+ require 'json'
4
+
5
+ module Apiary
6
+ module Okapi
7
+ class ApiaryConnector
8
+ attr_reader :apiary_url, :blueprint
9
+
10
+ def initialize(apiary_url, req_path, res_path)
11
+ @apiary_url = apiary_url
12
+ @req_path = req_path
13
+ @res_path = res_path
14
+ end
15
+
16
+ def get_response(raw_resp, json_data, error, code)
17
+ { :resp => raw_resp,
18
+ :data => json_data ? json_data['requests'] : nil,
19
+ :status => json_data ? json_data['status'] : nil ,
20
+ :error => json_data ? json_data['error'] || error : error,
21
+ :code => code
22
+ }
23
+ end
24
+
25
+ def get_requests(resources, blueprint, all_resources = false, global_vars = {})
26
+ resources_list = []
27
+
28
+ resources.each() do |res|
29
+ resources_list << {
30
+ :resource => res['resource'],
31
+ :method => res['method'],
32
+ :params => res['params']
33
+ }
34
+ end
35
+
36
+ data = {
37
+ :resources => resources_list,
38
+ :blueprint => blueprint,
39
+ :all_resources => all_resources,
40
+ :global_vars => global_vars
41
+ }.to_json()
42
+
43
+ begin
44
+ response = RestClient.post @apiary_url + @req_path, data, :content_type => :json, :accept => :json
45
+ get_response(response, JSON.parse(response.to_str), nil, response.code.to_i)
46
+ rescue RestClient::BadRequest, RestClient::InternalServerError => e
47
+ begin
48
+ data = JSON.parse(e.http_body)
49
+ get_response(nil, JSON.parse(e.http_body), data['error'], e.http_code.to_i)
50
+ rescue
51
+ get_response(nil, nil, e.to_s, e.http_code.to_i)
52
+ end
53
+ rescue Exception => e
54
+ get_response(nil, nil, e.to_s, nil)
55
+ end
56
+
57
+ end
58
+
59
+ def get_results(resources, blueprint)
60
+ resources_list = []
61
+ resources.each() do |res|
62
+ resources_list << {
63
+ :request => {
64
+ :uri => res.uri,
65
+ :expandedUri => res.expanded_uri,
66
+ :method => res.method,
67
+ :headers => res.headers,
68
+ :body => res.body,
69
+ },
70
+ :response => {
71
+ :status => res.response.status,
72
+ :headers => res.response.headers ,
73
+ :body => res.response.body
74
+ }
75
+ }
76
+ end
77
+
78
+ data = {
79
+ :resources => resources_list,
80
+ :blueprint => blueprint
81
+ }.to_json()
82
+
83
+ begin
84
+ response = RestClient.post @apiary_url + @res_path, data, :content_type => :json, :accept => :json
85
+ get_response(response, JSON.parse(response.to_str), nil, response.code.to_i)
86
+ rescue RestClient::BadRequest, RestClient::InternalServerError => e
87
+ begin
88
+ get_response(nil, JSON.parse(e.http_body), data['error'], e.http_code.to_i)
89
+ rescue
90
+ get_response(nil, nil, e.to_s, e.http_code.to_i)
91
+ end
92
+ rescue Exception => e
93
+ get_response(nil, nil, e.to_s, nil)
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,122 @@
1
+ # encoding: utf-8
2
+ require 'optparse'
3
+ require 'yaml'
4
+
5
+ module Apiary
6
+ module Okapi
7
+ class CLI
8
+
9
+ def initialize(args)
10
+ case args.first
11
+ when 'help'
12
+ Apiary::Okapi::Help.show
13
+ exit 0
14
+ when 'okapi'
15
+ Apiary::Okapi::Help.okapi
16
+ exit 0
17
+ else
18
+ parse_options!(args)
19
+ parse_config
20
+ @options[:blueprint] ||= BLUEPRINT_PATH
21
+ @options[:test_spec] ||= TEST_SPEC_PATHS
22
+ @options[:output] ||= OUTPUT
23
+ @options[:test_url] ||= TEST_URL
24
+ @options[:apiary_url] ||= APIARY_URL
25
+
26
+ @options[:test_spec] ||= TEST_SPEC_PATHS.gsub(' ','').split(',')
27
+
28
+ if @options[:params]
29
+ puts "running with :"
30
+ p @options
31
+ puts "\n"
32
+ end
33
+
34
+ exit run
35
+ end
36
+ end
37
+
38
+ def run
39
+ pass = true
40
+ @options[:test_spec].each { |spec|
41
+ pass = Apiary::Okapi::Test.new(@options[:blueprint], spec, @options[:test_url], @options[:output], @options[:apiary_url]).run()
42
+ }
43
+ if pass
44
+ 0
45
+ else
46
+ 1
47
+ end
48
+ end
49
+
50
+ def parse_config
51
+ begin
52
+ if tests = YAML.load_file(@options[:config_path])['tests']
53
+ @options[:test_url] ||= tests['host'] if tests['host']
54
+ @options[:test_spec] ||= tests['specs'] if tests['specs']
55
+ end
56
+ rescue Errno::ENOENT => e
57
+ puts "Config file (#{@options[:config_path]}) not accessible ... skiping"
58
+ puts "\n"
59
+ rescue Exception => e
60
+ puts "Config file (#{@options[:config_path]}) loading problem :#{e}"
61
+ puts "\n"
62
+ exit 1
63
+ end
64
+ end
65
+
66
+ def parse_options!(args)
67
+ @options = {}
68
+ options_parser = OptionParser.new do |opts|
69
+ opts.on("-c", "--config CONFIG",
70
+ "path config file (default: " + CONFIG_PATH + " )") do |config|
71
+ @options[:config_path] = config
72
+ end
73
+
74
+ opts.on("-b", "--blueprint BLUEPRINT",
75
+ "path to the blueprint (default: " + BLUEPRINT_PATH + " )") do |blueprint|
76
+ @options[:blueprint] = blueprint
77
+ end
78
+
79
+ opts.on("-t","--test_spec TEST_SPEC",
80
+ "comma separated paths to the test specifications (default: " + TEST_SPEC_PATHS + " )") do |test_spec|
81
+ @options[:test_spec] = test_spec
82
+ end
83
+
84
+ opts.on("-o","--output OUTPUT",
85
+ "output format (default" + OUTPUT + ")") do |output|
86
+ @options[:output] = output
87
+ end
88
+
89
+ opts.on("-u","--test_url TEST_URL",
90
+ "url to test (default" + TEST_URL + ")") do |test_url|
91
+ @options[:test_url] = test_url
92
+ end
93
+
94
+ opts.on("-a","--apiary APIARY",
95
+ "apiary url (default" + APIARY_URL + ")") do |apiary|
96
+ @options[:apiary_url] = apiary
97
+ end
98
+
99
+ opts.on("-p","--params [PARAMS]",
100
+ "show parameters" ) do |params|
101
+ @options[:params] = true
102
+ end
103
+ end
104
+
105
+ options_parser.parse!
106
+
107
+ @options[:config_path] ||= CONFIG_PATH
108
+ @options[:test_spec] = @options[:test_spec].gsub(' ','').split(',') if @options[:test_spec]
109
+
110
+ @options
111
+
112
+ rescue OptionParser::InvalidOption => e
113
+ puts "\n"
114
+ puts e
115
+ Apiary::Okapi::Help.banner
116
+ puts "\n"
117
+ exit 1
118
+ end
119
+
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,13 @@
1
+ # encoding: utf-8
2
+ module Apiary
3
+ module Okapi
4
+ CONFIG_PATH = "apiary.yaml"
5
+ APIARY_URL = "https://api.apiary.io"
6
+ GET_REQUESTS_PATH = "/tests/get-requests"
7
+ GET_RESULTS_PATH = "/tests/get-test-results"
8
+ BLUEPRINT_PATH = "apiary.apib"
9
+ TEST_SPEC_PATHS = "tests.spec"
10
+ TEST_URL = "http://127.0.0.1"
11
+ OUTPUT = 'tap'
12
+ end
13
+ end
@@ -0,0 +1,59 @@
1
+ HOST: http://www.google.com/
2
+
3
+ --- test API ---
4
+
5
+ ---
6
+ Welcome to the our sample API documentation. All comments can be written in (support [Markdown](http://daringfireball.net/projects/markdown/syntax) syntax)
7
+ ---
8
+
9
+ --
10
+ Shopping Cart Resources
11
+ The following is a section of resources related to the shopping cart
12
+ --
13
+
14
+ List products added into your shopping-cart. (comment block again in Markdown)
15
+ GET /shopping-cart/{id}
16
+ < 200
17
+ < Content-Type: application/json
18
+ { "items": [
19
+ { "url": "/shopping-cart/1", "product":"2ZY48XPZ", "quantity": 1, "name": "New socks", "price": 1.25 }
20
+ ] }
21
+
22
+ Save new products in your shopping cart
23
+ POST /shopping-cart/{id2}
24
+ > Content-Type: application/json
25
+ > CCC: aaa
26
+ { "product":"1AB23ORM", "quantity": 2 }
27
+ < 201
28
+ < Content-Type: application/json
29
+ < CCC: aaa
30
+ { "status": "created", "url": "/shopping-cart/2" }
31
+
32
+ -- Payment Resources --
33
+
34
+ This resource allows you to submit payment information to process your *shopping cart* items
35
+ POST /payment
36
+ { "cc": "12345678900", "cvc": "123", "expiry": "0112" }
37
+ < 200
38
+ { "receipt": "/payment/receipt/1" }
39
+
40
+ -- JSON Schema Validations --
41
+
42
+ POST /shopping-cart/{id2}
43
+ {"request":
44
+ { "type": "object",
45
+ "properties": {
46
+ "product": { "type": "string","format": "alphanumeric" },
47
+ "quantity": { "type": "integer" }
48
+ }
49
+ }
50
+ ,
51
+ "response":
52
+ { "type": "object",
53
+ "properties": {
54
+ "product": { "type": "string","format": "alphanumeric" },
55
+ "status": { "type": "integer" }
56
+ }
57
+ }
58
+ }
59
+
@@ -0,0 +1,5 @@
1
+ tests:
2
+ host: http://aptest.apiary.io
3
+ specs:
4
+ - tests.spec
5
+ - tests2.spec
@@ -0,0 +1,6 @@
1
+ VARS {"id2": "eee", "id": "5"}
2
+ POST /shopping-cart/{id2} {"id2": "eee2"}
3
+ POST
4
+ CONTINUE
5
+
6
+
@@ -0,0 +1,3 @@
1
+ POST /shopping-cart/{id2} {"id2": "eee2"}
2
+ POST /payment
3
+
File without changes
@@ -0,0 +1,36 @@
1
+ # encoding: utf-8
2
+ module Apiary
3
+ module Okapi
4
+ class Help
5
+
6
+ def self.show
7
+ banner
8
+ options
9
+ end
10
+
11
+ def self.banner
12
+ puts "\nUsage: okapi [options]"
13
+ puts "Try 'okapi help' for more information."
14
+ end
15
+
16
+ def self.options
17
+ puts "\nCurrently available okapi options are:\n\n"
18
+
19
+ puts "\t-b, --blueprint path to the blueprint (default: " + BLUEPRINT_PATH + " )"
20
+ puts "\t-t, --test_spec path to the test specification (default: " + TEST_SPEC_PATHS + " )"
21
+ #puts "\t-o, --output output format (default: " + OUTPUT + ")"
22
+ puts "\t-u, --test_url url to test (default: " + TEST_URL + ")"
23
+ puts "\t-a, --apiary apiary url (default: " + APIARY_URL + ")"
24
+ puts "\t-s, --config config file (default: " + CONFIG_PATH + ")"
25
+ puts "\t-p, --params prints used parameters"
26
+ puts "\n"
27
+ puts "\thelp Show this help"
28
+ puts "\n"
29
+ end
30
+
31
+ def self.okapi
32
+ puts File.read(File.dirname(__FILE__) + '/okapi')
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,43 @@
1
+
2
+ ,#.@:
3
+ @;#@@#
4
+ #+#@#@;
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
+ `# `
@@ -0,0 +1,14 @@
1
+ # encoding: utf-8
2
+ Dir["#{File.dirname(__FILE__)}/outputs/*.rb"].each { |f| require(f) }
3
+
4
+ module Apiary
5
+ module Okapi
6
+ class Output
7
+ def self.get(output,resources, error)
8
+ output = Apiary::Okapi::Outputs.const_get(output.to_s.capitalize).send(:new, resources, error)
9
+ output.get()
10
+ output.status
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,91 @@
1
+ module Apiary
2
+ module Okapi
3
+ module Outputs
4
+ class BaseOutput
5
+ attr_reader :status
6
+
7
+ def initialize(resources, error)
8
+ @resources = resources
9
+ @error = error
10
+ @results = {
11
+ :count => 0,
12
+ :give_up => false,
13
+ }
14
+ @status = true
15
+ get_results
16
+ end
17
+
18
+ def get
19
+ p @results[:count].to_s + ' tests'
20
+ p @results[:give_up][:error].to_s if @results[:give_up]
21
+ @results[:tests].each { |test|
22
+ p '-------------------------------------------------'
23
+ p test[:test_no]
24
+ p test[:description]
25
+ if test[:pass]
26
+ p 'OK'
27
+ else
28
+ p "FAILED"
29
+ p test[:exp]
30
+ end
31
+ }
32
+ end
33
+
34
+ def get_results
35
+ @results[:count] = @resources.count
36
+ @results[:tests] = []
37
+
38
+ if @error
39
+ @results[:give_up] = {:error => @error}
40
+ @status = false
41
+ else
42
+ counter = 0
43
+ @resources.each { |res|
44
+ counter += 1
45
+ test_res = {
46
+ :test_no=> counter,
47
+ :pass => (res.validation_result.status and res.response.validation_result.status),
48
+ :description => (res.method + ' ' + res.uri) + ((res.expanded_uri and res.uri != res.expanded_uri['url']) ? " (#{res.expanded_uri['url']}) " : '')
49
+ }
50
+ if not test_res[:pass]
51
+ test_res[:exp] = {:request => {:pass => false}, :response => {:pass => false}}
52
+ if res.validation_result.status
53
+ test_res[:exp][:request][:pass] = true
54
+ else
55
+ test_res[:exp][:request][:reasons] = get_fail_result(res.validation_result)
56
+ @status = false
57
+ end
58
+
59
+ if res.response.validation_result.status
60
+ test_res[:exp][:response][:pass] = true
61
+ else
62
+ test_res[:exp][:response][:reasons] = get_fail_result(res.response.validation_result)
63
+ @status = false
64
+ end
65
+ end
66
+ @results[:tests] << test_res
67
+ }
68
+ end
69
+ end
70
+
71
+ def get_fail_result(result)
72
+ res = []
73
+
74
+ if result.schema
75
+ result.schema_res["errors"]["length"].times {|i|
76
+ res << result.schema_res["errors"][i.to_s]["message"]
77
+ }
78
+ else
79
+ if not result.body_pass
80
+ res << 'Body does not match'
81
+ end
82
+ end
83
+ if not result.header_pass
84
+ res << 'Headers does not match'
85
+ end
86
+ res
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,44 @@
1
+ require "#{File.dirname(__FILE__)}/base.rb"
2
+ require 'yaml'
3
+
4
+ module Apiary
5
+ module Okapi
6
+ module Outputs
7
+ class Tap < Apiary::Okapi::Outputs::BaseOutput
8
+
9
+ def get
10
+ get_int
11
+ puts "\n\n"
12
+ end
13
+
14
+ def get_int
15
+ puts "TAP version 13"
16
+ puts "1..#{@results[:count].to_s}"
17
+ if @results[:give_up]
18
+ puts "Bail out! #{@results[:give_up][:error].to_s.tr("\n"," ")}"
19
+ return
20
+ end
21
+ @results[:tests].each { |test|
22
+ if test[:pass]
23
+ o = 'ok '
24
+ else
25
+ o = 'not ok '
26
+ end
27
+ puts o + test[:test_no].to_s + ' ' + test[:description]
28
+ if not test[:pass]
29
+ error_block(test)
30
+ end
31
+ }
32
+ end
33
+
34
+ def error_block(test)
35
+ test[:exp].to_yaml.split(/\n/).each { |line|
36
+ puts " #{line}"
37
+ }
38
+ puts " ..."
39
+
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,53 @@
1
+ # encoding: utf-8
2
+ module Apiary
3
+ module Okapi
4
+ class Resource
5
+ attr_accessor :uri, :method, :params, :expanded_uri, :headers, :body, :response, :validation_result
6
+
7
+ def initialize(uri, method, params, expanded_uri = nil, headers = nil, body = nil, response = nil, validation_result = nil)
8
+ #p uri, method, params
9
+ @uri = uri
10
+ @method = method
11
+ @params = params
12
+ @expanded_uri = expanded_uri
13
+ @headers = headers
14
+ @body = body
15
+ @response = response
16
+ @validation_result = validation_result
17
+ end
18
+ end
19
+
20
+ class Response
21
+ attr_accessor :status, :headers, :body, :error, :validation_result
22
+
23
+ def initialize(status = nil, headers = nil, body = nil, error = nil, validation_result = nil)
24
+ @headers = headers
25
+ @body = body
26
+ @status = status
27
+ @error = error
28
+ @validation_result = validation_result
29
+ end
30
+ end
31
+
32
+ class ValidationResult
33
+ attr_accessor :status, :error, :schema_res , :body_pass, :body_diff, :header_pass, :header_diff
34
+
35
+ def status
36
+ @status ||= get_status
37
+ end
38
+
39
+ def get_status
40
+ return true if not @error and @header_pass and ((schema and schema_pass) or (not schema and @body_pass))
41
+ return false
42
+ end
43
+
44
+ def schema
45
+ !(@schema_res == false)
46
+ end
47
+
48
+ def schema_pass
49
+ not schema or schema and @schema_res and not @schema_res['errors']
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,82 @@
1
+ # encoding: utf-8
2
+ require 'json'
3
+
4
+ module Apiary
5
+ module Okapi
6
+ class Parser
7
+ attr_reader :data, :resources, :proces_all_bp_resources, :global_vars
8
+
9
+ def initialize(spec_path)
10
+ if not File.exist? spec_path
11
+ raise Exception, "Test spec. file '#{spec_path}' not found"
12
+ end
13
+ @data = read_file(spec_path)
14
+ @proces_all_bp_resources = false
15
+ end
16
+
17
+ def resources
18
+ @resources ||= parse_data
19
+ end
20
+
21
+ def read_file(path)
22
+ @data = []
23
+ File.open(path).each do |line|
24
+ @data << line if line.strip != ""
25
+ end
26
+ @data
27
+ end
28
+
29
+ def substituite_vars(local, global)
30
+ tmp = {}
31
+ global.each {|k,v|
32
+ tmp[k] = v
33
+ }
34
+ local.each {|k,v|
35
+ tmp[k] = v
36
+ }
37
+ tmp
38
+ end
39
+
40
+ def parse_data
41
+ global_vars = {}
42
+ resources = []
43
+ @data.each { |res|
44
+ if res.index('CONTINUE') == 0
45
+ @proces_all_bp_resources = true
46
+ next
47
+ end
48
+
49
+ if res.index('VARS') == 0
50
+ splited = res.split(' ',2)
51
+ begin
52
+ global_vars = JSON.parse splited[1] if splited[1] and splited[1] != ''
53
+ rescue Exception => e
54
+ raise Exception, "can not parse global parameters (#{e})"
55
+ end
56
+ next
57
+ end
58
+
59
+ splited = res.split(' ',3)
60
+
61
+ begin
62
+ splited[2] = JSON.parse splited[2] if splited[2] and splited[2] != ''
63
+ rescue Exception => e
64
+ raise Exception, 'can not parse parameters for resource:' + res + "(#{e})"
65
+ end
66
+
67
+ if splited[1] and splited[1] != '' and splited[0] and splited[0] != ''
68
+ out = {
69
+ 'resource' => splited[1],
70
+ 'method' => splited[0],
71
+ 'params' => substituite_vars(splited[2] || {}, global_vars)
72
+ }
73
+ resources << out
74
+ end
75
+ }
76
+
77
+ @global_vars = global_vars
78
+ resources
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,141 @@
1
+ # encoding: utf-8
2
+ require 'rest_client'
3
+
4
+ module Apiary
5
+ module Okapi
6
+ class Test
7
+ def initialize(blueprint_path, test_spec_path, test_url, output, apiary_url)
8
+ @blueprint_path = blueprint_path
9
+ @test_spec_path = test_spec_path
10
+ @test_url = test_url
11
+ @output_format = output
12
+ @apiary_url = apiary_url
13
+ @req_path = GET_REQUESTS_PATH
14
+ @res_path = GET_RESULTS_PATH
15
+ @connector = Apiary::Okapi::ApiaryConnector.new(@apiary_url, @req_path, @res_path)
16
+ @proces_all_bp_resources = false
17
+ @output = []
18
+ @resources = []
19
+ @error = nil
20
+ end
21
+
22
+ def run
23
+ begin
24
+ test()
25
+ rescue Exception => e
26
+ @resources = []
27
+ @error = e
28
+ end
29
+ Apiary::Okapi::Output.get(@output_format, @resources, @error)
30
+ end
31
+
32
+ def test
33
+ prepare()
34
+ if not @resources.empty?
35
+ get_responses
36
+ evaluate
37
+ else
38
+ raise Exception, 'No resources provided'
39
+ end
40
+ end
41
+
42
+ def prepare
43
+ @resources = []
44
+ parser = get_test_spec_parser(@test_spec_path)
45
+ resources = parser.resources
46
+ counter = 0
47
+
48
+ resources.each { |res|
49
+ counter += 1
50
+ raise Exception, "Rresource not defined for item #{counter.to_d} in #{@test_spec_path}" unless res["resource"]
51
+ raise Exception, "Method not defined for resource #{res["resource"].to_s} in #{@test_spec_path}" unless res["method"]
52
+ }
53
+
54
+ @proces_all_bp_resources = parser.proces_all_bp_resources
55
+ data = get_requests_spec(resources, parser.global_vars)
56
+
57
+ if data[:error] or data[:code] != 200
58
+ raise Exception, 'Can not get request data from Apiary: ' + data[:error] ? data[:error] : ''
59
+ end
60
+
61
+ data[:data].each do |res|
62
+ raise Exception, 'Resource error "' + res['error'] + '" for resource "' + res["method"] + ' ' + res["uri"] + '"' if res['error']
63
+ @resources << Apiary::Okapi::Resource.new(res["uri"], res["method"], res["params"], res["expandedUri"], res["headers"], res["body"])
64
+ end
65
+
66
+ @resources
67
+ end
68
+
69
+ def blueprint
70
+ @blueprint ||= parse_blueprint(@blueprint_path)
71
+ end
72
+
73
+ def get_responses
74
+ @resources.each { |resource|
75
+ params = {:method => resource.method, :url => @test_url + resource.expanded_uri['url'], :headers => resource.headers || {}}
76
+ begin
77
+ response = RestClient::Request.execute(params)
78
+
79
+ raw_headers = response.raw_headers.inject({}) do |out, (key, value)|
80
+ out[key] = %w{ set-cookie }.include?(key.downcase) ? value : value.first
81
+ out
82
+ end
83
+
84
+ resource.response = Apiary::Okapi::Response.new(response.code, raw_headers, response.body)
85
+ rescue Exception => e
86
+ raise Exception, 'Can not get response for: ' + params.to_json + ' (' + e.to_s + ')'
87
+ end
88
+ }
89
+
90
+ end
91
+
92
+ def evaluate
93
+
94
+ data = @connector.get_results(@resources, blueprint)
95
+ if data[:error] or data[:code] != 200
96
+ raise Exception, 'Can not get evaluation data from apiary: ' + data[:error] ? data[:error] : ''
97
+ end
98
+
99
+ data[:data].each { |validation|
100
+ @resources.each { |resource|
101
+ if validation['resource']['uri'] == resource.uri and validation['resource']['method'] == resource.method
102
+ resource.validation_result = Apiary::Okapi::ValidationResult.new()
103
+ resource.validation_result.error = validation['errors']
104
+ resource.validation_result.schema_res = validation["validations"]['reqSchemaValidations']
105
+ resource.validation_result.body_pass = !validation["validations"]['reqData']['body']['isDifferent']
106
+ resource.validation_result.body_diff = validation["validations"]['reqData']['body']['diff']
107
+ resource.validation_result.header_pass = !validation["validations"]['reqData']['headers']['isDifferent']
108
+ resource.validation_result.header_diff = validation["validations"]['reqData']['headers']['diff']
109
+
110
+ resource.response.validation_result = Apiary::Okapi::ValidationResult.new()
111
+ resource.response.validation_result.error = validation['errors']
112
+ resource.response.validation_result.schema_res = validation["validations"]['resSchemaValidations']
113
+ resource.response.validation_result.body_pass = !validation["validations"]['resData']['body']['isDifferent']
114
+ resource.response.validation_result.body_diff = validation["validations"]['resData']['body']['diff']
115
+ resource.response.validation_result.header_pass = !validation["validations"]['resData']['headers']['isDifferent']
116
+ resource.response.validation_result.header_diff = validation["validations"]['resData']['headers']['diff']
117
+ end
118
+
119
+ }
120
+ }
121
+ end
122
+
123
+ def get_test_spec_parser(test_spec)
124
+ Apiary::Okapi::Parser.new(test_spec)
125
+ end
126
+
127
+ def parse_blueprint(blueprint_path)
128
+ if not File.exist? blueprint_path
129
+ raise Exception, "Blueprint file '#{blueprint_path}' not found"
130
+ end
131
+ File.read(blueprint_path)
132
+ end
133
+
134
+ def get_requests_spec(resources, global_vars)
135
+ @connector.get_requests(resources, blueprint, @proces_all_bp_resources, global_vars)
136
+ end
137
+
138
+ end
139
+ end
140
+ end
141
+
metadata CHANGED
@@ -1,88 +1,112 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: apiaryio
3
- version: !ruby/object:Gem::Version
4
- version: 0.0.2
5
- prerelease:
3
+ version: !ruby/object:Gem::Version
4
+ hash: 25
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 3
10
+ version: 0.0.3
6
11
  platform: ruby
7
- authors:
12
+ authors:
8
13
  - Apiary Ltd.
9
14
  autorequire:
10
15
  bindir: bin
11
16
  cert_chain: []
12
- date: 2012-08-09 00:00:00.000000000 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
17
+
18
+ date: 2013-05-09 00:00:00 +02:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
15
22
  name: rest-client
16
- requirement: !ruby/object:Gem::Requirement
17
- none: false
18
- requirements:
19
- - - ~>
20
- - !ruby/object:Gem::Version
21
- version: 1.6.7
22
- type: :runtime
23
23
  prerelease: false
24
- version_requirements: !ruby/object:Gem::Requirement
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
25
  none: false
26
- requirements:
26
+ requirements:
27
27
  - - ~>
28
- - !ruby/object:Gem::Version
28
+ - !ruby/object:Gem::Version
29
+ hash: 1
30
+ segments:
31
+ - 1
32
+ - 6
33
+ - 7
29
34
  version: 1.6.7
30
- - !ruby/object:Gem::Dependency
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
31
38
  name: rack
32
- requirement: !ruby/object:Gem::Requirement
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
33
41
  none: false
34
- requirements:
42
+ requirements:
35
43
  - - ~>
36
- - !ruby/object:Gem::Version
44
+ - !ruby/object:Gem::Version
45
+ hash: 5
46
+ segments:
47
+ - 1
48
+ - 4
49
+ - 1
37
50
  version: 1.4.1
38
51
  type: :runtime
52
+ version_requirements: *id002
53
+ - !ruby/object:Gem::Dependency
54
+ name: json
39
55
  prerelease: false
40
- version_requirements: !ruby/object:Gem::Requirement
56
+ requirement: &id003 !ruby/object:Gem::Requirement
41
57
  none: false
42
- requirements:
43
- - - ~>
44
- - !ruby/object:Gem::Version
45
- version: 1.4.1
46
- - !ruby/object:Gem::Dependency
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ hash: 3
62
+ segments:
63
+ - 0
64
+ version: "0"
65
+ type: :runtime
66
+ version_requirements: *id003
67
+ - !ruby/object:Gem::Dependency
47
68
  name: rspec
48
- requirement: !ruby/object:Gem::Requirement
49
- none: false
50
- requirements:
51
- - - ~>
52
- - !ruby/object:Gem::Version
53
- version: 2.11.0
54
- type: :development
55
69
  prerelease: false
56
- version_requirements: !ruby/object:Gem::Requirement
70
+ requirement: &id004 !ruby/object:Gem::Requirement
57
71
  none: false
58
- requirements:
72
+ requirements:
59
73
  - - ~>
60
- - !ruby/object:Gem::Version
74
+ - !ruby/object:Gem::Version
75
+ hash: 35
76
+ segments:
77
+ - 2
78
+ - 11
79
+ - 0
61
80
  version: 2.11.0
62
- - !ruby/object:Gem::Dependency
63
- name: yard
64
- requirement: !ruby/object:Gem::Requirement
65
- none: false
66
- requirements:
67
- - - ~>
68
- - !ruby/object:Gem::Version
69
- version: 0.8.2.1
70
81
  type: :development
82
+ version_requirements: *id004
83
+ - !ruby/object:Gem::Dependency
84
+ name: yard
71
85
  prerelease: false
72
- version_requirements: !ruby/object:Gem::Requirement
86
+ requirement: &id005 !ruby/object:Gem::Requirement
73
87
  none: false
74
- requirements:
88
+ requirements:
75
89
  - - ~>
76
- - !ruby/object:Gem::Version
90
+ - !ruby/object:Gem::Version
91
+ hash: 5
92
+ segments:
93
+ - 0
94
+ - 8
95
+ - 2
96
+ - 1
77
97
  version: 0.8.2.1
98
+ type: :development
99
+ version_requirements: *id005
78
100
  description: Apiary.io CLI
79
- email:
101
+ email:
80
102
  - team@apiary.io
81
- executables:
103
+ executables:
82
104
  - apiary
83
105
  extensions: []
106
+
84
107
  extra_rdoc_files: []
85
- files:
108
+
109
+ files:
86
110
  - .gitignore
87
111
  - .rspec
88
112
  - Gemfile
@@ -120,36 +144,59 @@ files:
120
144
  - lib/apiary/command/runner.rb
121
145
  - lib/apiary/command/version.rb
122
146
  - lib/apiary/version.rb
147
+ - lib/okapi.rb
148
+ - lib/okapi/apiary_connector.rb
149
+ - lib/okapi/cli.rb
150
+ - lib/okapi/config.rb
151
+ - lib/okapi/examples/apiary.apib
152
+ - lib/okapi/examples/apiary.yaml
153
+ - lib/okapi/examples/tests.spec
154
+ - lib/okapi/examples/tests2.spec
155
+ - lib/okapi/exceptions.rb
156
+ - lib/okapi/help.rb
157
+ - lib/okapi/okapi
158
+ - lib/okapi/output.rb
159
+ - lib/okapi/outputs/base.rb
160
+ - lib/okapi/outputs/tap.rb
161
+ - lib/okapi/resources.rb
162
+ - lib/okapi/spec_parser.rb
163
+ - lib/okapi/test.rb
123
164
  - spec/cli_spec.rb
124
165
  - spec/spec_helper.rb
166
+ has_rdoc: true
125
167
  homepage: http://apiary.io
126
- licenses:
168
+ licenses:
127
169
  - MIT
128
- post_install_message: This gem is a client for http://apiary.io. Apiary is in closed
129
- beta version now, you need an invitation. If you don't have one, visit http://apiary.us2.list-manage.com/subscribe?u=b89934a238dcec9533f4a834a&id=08f2bdde55
130
- to get on the waiting list!
170
+ post_install_message:
131
171
  rdoc_options: []
132
- require_paths:
172
+
173
+ require_paths:
133
174
  - lib
134
- required_ruby_version: !ruby/object:Gem::Requirement
175
+ required_ruby_version: !ruby/object:Gem::Requirement
135
176
  none: false
136
- requirements:
137
- - - ! '>='
138
- - !ruby/object:Gem::Version
139
- version: '0'
140
- required_rubygems_version: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ hash: 3
181
+ segments:
182
+ - 0
183
+ version: "0"
184
+ required_rubygems_version: !ruby/object:Gem::Requirement
141
185
  none: false
142
- requirements:
143
- - - ! '>='
144
- - !ruby/object:Gem::Version
145
- version: '0'
186
+ requirements:
187
+ - - ">="
188
+ - !ruby/object:Gem::Version
189
+ hash: 3
190
+ segments:
191
+ - 0
192
+ version: "0"
146
193
  requirements: []
194
+
147
195
  rubyforge_project:
148
- rubygems_version: 1.8.24
196
+ rubygems_version: 1.3.7
149
197
  signing_key:
150
198
  specification_version: 3
151
199
  summary: Apiary.io CLI
152
- test_files:
200
+ test_files:
153
201
  - spec/cli_spec.rb
154
202
  - spec/spec_helper.rb
155
- has_rdoc: