Permalink
Browse files

Refactor into smaller methods, and allow custom strategies to define

file_name and captured-data stored-structure
  • Loading branch information...
1 parent bb3e03f commit bc33045c8f6a8a056ac28bffeef322e3b71b4cf7 @chischaschos chischaschos committed Feb 13, 2014
Showing with 95 additions and 58 deletions.
  1. +35 −3 lib/api_docs.rb
  2. +38 −33 lib/api_docs/test_helper.rb
  3. +22 −22 test/test_helper_test.rb
View
38 lib/api_docs.rb
@@ -6,15 +6,47 @@
module ApiDocs
class << self
-
+
+ attr_accessor :store_data_strategy, :file_name_strategy
+
def configure
yield configuration
end
-
+
def configuration
@configuration ||= Configuration.new
end
alias :config :configuration
-
+
+ def store_data(api_docs, captured_data)
+ strategy = store_data_strategy || method(:default_store_data)
+ strategy.call(api_docs, captured_data)
+ end
+
+ def file_name(captured_data)
+ strategy = file_name_strategy || method(:default_file_name)
+ strategy.call(captured_data)
+ end
+
+ private
+
+ def default_store_data(api_docs, captured_data)
+ # Marking response as an unique
+ key = ""
+ key << captured_data['method']
+ key << captured_data['path']
+ key << captured_data['meta'].to_s
+ key << captured_data['params'].to_s
+ key << captured_data['status'].to_s
+ hashed_key = 'ID-' + Digest::MD5.hexdigest(key)
+
+ api_docs[captured_data['action']] ||= { }
+ api_docs[captured_data['action']][hashed_key] = captured_data
+ end
+
+ def default_file_name(captured_data)
+ "#{captured_data['controller'].gsub('/', ':')}.yml"
+ end
+
end
end
View
71 lib/api_docs/test_helper.rb
@@ -1,5 +1,5 @@
module ApiDocs::TestHelper
-
+
module InstanceMethods
# Method that allows test creation and will document results in a YAML file
# Example usage:
@@ -11,58 +11,63 @@ def api_call(method, path, params = {}, headers = {})
parsed_path = path.dup
parsed_params = params.dup
-
+
parsed_params.each do |k, v|
parsed_params.delete(k) if parsed_path.gsub!(":#{k}", v.to_s)
end
-
+
# Making actual test request. Based on the example above:
# get '/users/12345'
-
+
send(method, parsed_path, parsed_params, headers)
-
+
meta = Hash.new
yield meta if block_given?
-
+
# Not writing anything to the files unless there was a demand
if ApiDocs.config.generate_on_demand
return unless ENV['API_DOCS']
end
-
- # Assertions inside test block didn't fail. Preparing file
- # content to be written
- c = request.filtered_parameters['controller']
- a = request.filtered_parameters['action']
-
- file_path = File.expand_path("#{c.gsub('/', ':')}.yml", ApiDocs.config.docs_path)
- params = ApiDocs::TestHelper.api_deep_clean_params(params)
-
- # Marking response as an unique
- key = 'ID-' + Digest::MD5.hexdigest("
- #{method}#{path}#{meta}#{params}#{response.status}}
- ")
-
- data = if File.exists?(file_path)
- YAML.load_file(file_path) rescue Hash.new
- else
- Hash.new
- end
-
- data[a] ||= { }
- data[a][key] = {
+
+ @captured_data = {
+ 'controller' => request.filtered_parameters['controller'],
+ 'action' => request.filtered_parameters['action'],
'meta' => meta,
- 'method' => request.method,
+ 'method' => method.upcase.to_s,
'path' => path,
'headers' => headers,
'params' => ApiDocs::TestHelper.api_deep_clean_params(params),
'status' => response.status,
'body' => response.body
}
+
+ ApiDocs.store_data(api_docs, @captured_data)
+
+ write_docs
+ end
+
+ def api_docs
+ @api_docs ||= if File.exists?(file_path)
+ YAML.load_file(file_path) rescue Hash.new
+ else
+ Hash.new
+ end
+ end
+
+ def file_name
+ ApiDocs.file_name(@captured_data)
+ end
+
+ def file_path
+ File.expand_path(file_name, ApiDocs.config.docs_path)
+ end
+
+ def write_docs
FileUtils.mkdir_p(File.dirname(file_path))
- File.open(file_path, 'w'){|f| f.write(data.to_yaml)}
+ File.open(file_path, 'w'){|f| f.write(api_docs.to_yaml)}
end
end
-
+
# Cleans up params. Removes things like File object handlers
# Sets up ignored values so we don't generate new keys for same data
def self.api_deep_clean_params(params)
@@ -74,7 +79,7 @@ def self.api_deep_clean_params(params)
when Array
params.collect{|value| ApiDocs::TestHelper.api_deep_clean_params(value)}
else
- case params
+ case params
when Rack::Test::UploadedFile
'BINARY'
else
@@ -84,4 +89,4 @@ def self.api_deep_clean_params(params)
end
end
-ActionDispatch::IntegrationTest.send :include, ApiDocs::TestHelper::InstanceMethods
+ActionDispatch::IntegrationTest.send :include, ApiDocs::TestHelper::InstanceMethods
View
44 test/test_helper_test.rb
@@ -1,7 +1,7 @@
require File.expand_path('test_helper', File.dirname(__FILE__))
class TestHelperTest < ActionDispatch::IntegrationTest
-
+
def setup
ApiDocs.config.ignored_attributes = %(created_at updated_at)
ApiDocs.config.generate_on_demand = false
@@ -10,26 +10,26 @@ def setup
FileUtils.rm(file_path)
end
end
-
+
def test_api_deep_clean_params
assert_equal ({'a' => 'b'}),
ApiDocs::TestHelper.api_deep_clean_params({:a => 'b'})
-
+
assert_equal ({'a' => {'b' => 'c'}}),
ApiDocs::TestHelper.api_deep_clean_params({:a => {:b => 'c'}})
-
+
assert_equal ([{'a' => 'b'}, {'c' => 'd'}]),
ApiDocs::TestHelper.api_deep_clean_params([{:a => 'b'}, {:c => 'd'}])
-
+
assert_equal ({'a'=>[{'b'=>'c'}]}),
ApiDocs::TestHelper.api_deep_clean_params({:a => [{:b => 'c'}]})
end
-
+
def test_api_deep_clean_params_with_file_handler
assert_equal ({'a' => 'BINARY'}),
ApiDocs::TestHelper.api_deep_clean_params({:a => Rack::Test::UploadedFile.new(__FILE__)})
end
-
+
def test_api_call
api_call(:get, '/users/:id', :id => 12345, :format => 'json') do |doc|
assert_response :success
@@ -38,48 +38,48 @@ def test_api_call
'name' => 'Test User'
}), JSON.parse(response.body)
end
-
+
api_call(:get, '/users/:id', :id => 'invalid', :format => 'json') do |doc|
doc[:description] = 'Invalid user id'
assert_response :not_found
assert_equal ({
'message' => 'User not found'
}), JSON.parse(response.body)
end
-
+
output = begin
YAML.load_file(ApiDocs.config.docs_path.join('application.yml'))
rescue
fail 'api doc file not written'
end
-
+
assert output['show'].present?
assert_equal 2, output['show'].keys.size
-
+
assert_equal 'ID-', output['show'].keys.first[0..2]
-
+
object = output['show'][output['show'].keys.first]
assert_equal 'GET', object['method']
assert_equal '/users/:id', object['path']
assert_equal ({'id' => '12345', 'format' => 'json'}), object['params']
assert_equal 200, object['status']
assert_equal ({'id' => 12345, 'name' => 'Test User'}), JSON.parse(object['body'])
-
+
object = output['show'][output['show'].keys.last]
assert_equal 'GET', object['method']
assert_equal '/users/:id', object['path']
assert_equal ({'id' => 'invalid', 'format' => 'json'}), object['params']
assert_equal 404, object['status']
assert_equal ({'message' => 'User not found'}), JSON.parse(object['body'])
end
-
+
def test_api_call_with_ignored_attribute
api_call(:get, '/users/:id', :id => 12345, :format => 'json') do
assert_response :success
end
output = YAML.load_file(ApiDocs.config.docs_path.join('application.yml'))
assert_equal 1, output['show'].keys.size
-
+
ApiDocs.config.ignored_attributes << 'random'
api_call(:get, '/users/:id', :id => 12345, :random => 1, :format => 'json') do
assert_response :success
@@ -88,7 +88,7 @@ def test_api_call_with_ignored_attribute
assert_equal 2, output['show'].keys.size
object = output['show'][output['show'].keys.last]
assert_not_equal 'IGNORED', object['body']['random']
-
+
api_call(:get, '/users/:id', :id => 12345, :random => 1, :format => 'json') do
assert_response :success
end
@@ -111,36 +111,36 @@ def test_api_call_with_xml
output = YAML.load_file(ApiDocs.config.docs_path.join('application.yml'))
assert_equal 1, output['show'].keys.size
end
-
+
def test_api_call_with_httpauth
auth = ActionController::HttpAuthentication::Basic.encode_credentials('user', 'secret')
api_call(:get, '/authenticate', {:random => 1, :format => 'json'}, 'HTTP_AUTHORIZATION' => auth) do
assert_response :success
assert_equal ({'message' => 'Authenticated'}), JSON.parse(response.body)
end
end
-
+
def test_api_call_with_httpauth_failure
api_call(:get, '/authenticate', :random => 1, :format => 'json') do
assert_response :unauthorized
end
end
-
+
def test_api_call_with_generate_on_demand_off
ApiDocs.config.generate_on_demand = true
api_call(:get, '/users/:id', :id => 12345, :format => 'json') do
assert_response :success
end
assert !File.exists?(ApiDocs.config.docs_path.join('application.yml'))
end
-
+
def test_api_call_with_generate_on_demand_on
ENV['API_DOCS'] = 'true'
ApiDocs.config.generate_on_demand = true
-
+
api_call(:get, '/users/:id', :id => 12345, :format => 'json') do
assert_response :success
end
assert File.exists?(ApiDocs.config.docs_path.join('application.yml'))
end
-end
+end

0 comments on commit bc33045

Please sign in to comment.