fictium 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/pull_request_template.md +15 -0
- data/.gitignore +22 -0
- data/.rspec +3 -0
- data/.rubocop.yml +32 -0
- data/.ruby-version +1 -0
- data/.travis.yml +13 -0
- data/CHANGELOG.md +28 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +216 -0
- data/LICENSE +201 -0
- data/LICENSE.txt +21 -0
- data/README.md +108 -0
- data/Rakefile +10 -0
- data/app/.keep +0 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/fictium.gemspec +57 -0
- data/lib/fictium/configurations/configuration.rb +87 -0
- data/lib/fictium/configurations/info.rb +12 -0
- data/lib/fictium/engine.rb +6 -0
- data/lib/fictium/evaluators/parameter_evaluator.rb +57 -0
- data/lib/fictium/evaluators/schema_evaluator.rb +7 -0
- data/lib/fictium/exporters/open_api/schemas/3.0.0.json +1654 -0
- data/lib/fictium/exporters/open_api/v3_exporter/content_formatter.rb +20 -0
- data/lib/fictium/exporters/open_api/v3_exporter/example_formatter.rb +46 -0
- data/lib/fictium/exporters/open_api/v3_exporter/param_formatter.rb +45 -0
- data/lib/fictium/exporters/open_api/v3_exporter/path_formatter.rb +60 -0
- data/lib/fictium/exporters/open_api/v3_exporter/path_generator.rb +37 -0
- data/lib/fictium/exporters/open_api/v3_exporter.rb +79 -0
- data/lib/fictium/loader.rb +15 -0
- data/lib/fictium/poros/action.rb +43 -0
- data/lib/fictium/poros/document.rb +19 -0
- data/lib/fictium/poros/example.rb +15 -0
- data/lib/fictium/poros/model.rb +4 -0
- data/lib/fictium/poros/resource.rb +16 -0
- data/lib/fictium/railtie.rb +4 -0
- data/lib/fictium/rspec/actions.rb +40 -0
- data/lib/fictium/rspec/autocomplete/action.rb +52 -0
- data/lib/fictium/rspec/autocomplete/example.rb +45 -0
- data/lib/fictium/rspec/autocomplete/params.rb +79 -0
- data/lib/fictium/rspec/autocomplete/resource.rb +20 -0
- data/lib/fictium/rspec/examples.rb +48 -0
- data/lib/fictium/rspec/proxies/action.rb +11 -0
- data/lib/fictium/rspec/proxies/base.rb +25 -0
- data/lib/fictium/rspec/proxies/example.rb +15 -0
- data/lib/fictium/rspec/proxy_handler.rb +11 -0
- data/lib/fictium/rspec/resources.rb +41 -0
- data/lib/fictium/rspec.rb +39 -0
- data/lib/fictium/version.rb +5 -0
- data/lib/fictium.rb +29 -0
- data/tasks/.keep +0 -0
- data/tasks/travis/analyze.rb +12 -0
- metadata +321 -0
@@ -0,0 +1,20 @@
|
|
1
|
+
module Fictium
|
2
|
+
module OpenApi
|
3
|
+
class V3Exporter
|
4
|
+
class ContentFormatter
|
5
|
+
def format(http_object, default = nil)
|
6
|
+
type = (http_object.presence && http_object[:content_type].presence) || default
|
7
|
+
return if type.blank?
|
8
|
+
|
9
|
+
{}.tap do |content|
|
10
|
+
media_type = {
|
11
|
+
example: http_object[:body]
|
12
|
+
}
|
13
|
+
media_type[:schema] = http_object[:schema] if http_object[:schema].present?
|
14
|
+
content[type.to_sym] = media_type
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Fictium
|
2
|
+
module OpenApi
|
3
|
+
class V3Exporter
|
4
|
+
class ExampleFormatter
|
5
|
+
def format_default(operation, responses, default_example)
|
6
|
+
responses[:default] = format(default_example)
|
7
|
+
return if default_example.request[:content_type].blank?
|
8
|
+
|
9
|
+
operation[:requestBody] = {
|
10
|
+
content: content_formatter.format(default_example.request)
|
11
|
+
}
|
12
|
+
operation[:requestBody][:required] = true if default_example.request[:required]
|
13
|
+
end
|
14
|
+
|
15
|
+
def format(example)
|
16
|
+
{ description: example.summary }.tap do |format|
|
17
|
+
content = content_formatter.format(example.response, default_response_content_type)
|
18
|
+
format[:content] = content if content.present?
|
19
|
+
headers = extract_headers(example)
|
20
|
+
format[:headers] = headers if headers.present?
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def default_response_content_type
|
25
|
+
Fictium.configuration.default_response_content_type
|
26
|
+
end
|
27
|
+
|
28
|
+
def extract_headers(example)
|
29
|
+
{}.tap do |headers|
|
30
|
+
example.headers.each do |name, value|
|
31
|
+
headers[name] = header_formatter.format(name, :header, value)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def content_formatter
|
37
|
+
@content_formatter ||= ContentFormatter.new
|
38
|
+
end
|
39
|
+
|
40
|
+
def header_formatter
|
41
|
+
@header_formatter ||= ParamFormatter.new(ignore_name: true, ignore_in: true)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Fictium
|
2
|
+
module OpenApi
|
3
|
+
class V3Exporter
|
4
|
+
class ParamFormatter
|
5
|
+
def initialize(ignore_name: false, ignore_in: false)
|
6
|
+
@ignore_name = ignore_name
|
7
|
+
@ignore_in = ignore_in
|
8
|
+
end
|
9
|
+
|
10
|
+
def format(name, section, hash)
|
11
|
+
param = (hash || {})
|
12
|
+
description = param.slice(:description, :required, :deprecated, :schema)
|
13
|
+
description[:allowEmptyValue] = param[:allow_empty] if param[:allow_empty].present?
|
14
|
+
add_required_fields(description)
|
15
|
+
add_optional_fields(name, section, description)
|
16
|
+
description
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def ignore_in?
|
22
|
+
@ignore_in
|
23
|
+
end
|
24
|
+
|
25
|
+
def ignore_name?
|
26
|
+
@ignore_name
|
27
|
+
end
|
28
|
+
|
29
|
+
def add_required_fields(description)
|
30
|
+
description[:description] ||= ''
|
31
|
+
|
32
|
+
return if description[:schema] || description[:content]
|
33
|
+
|
34
|
+
description[:schema] = {}
|
35
|
+
end
|
36
|
+
|
37
|
+
def add_optional_fields(name, section, description)
|
38
|
+
description[:name] = name unless ignore_name?
|
39
|
+
description[:in] = section unless ignore_in?
|
40
|
+
description[:required] = true if section.to_s == 'path'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Fictium
|
2
|
+
module OpenApi
|
3
|
+
class V3Exporter
|
4
|
+
class PathFormatter
|
5
|
+
def add_path(paths, action)
|
6
|
+
path_object = paths[action.full_path] || default_path_object
|
7
|
+
path_object[action.method.to_sym] = create_operation(action)
|
8
|
+
paths[action.full_path] = path_object
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def default_path_object
|
14
|
+
{ description: '' }
|
15
|
+
end
|
16
|
+
|
17
|
+
def create_operation(action)
|
18
|
+
{}.tap do |operation|
|
19
|
+
operation[:tags] = action.combined_tags
|
20
|
+
operation[:description] = action.summary
|
21
|
+
operation[:parameters] = format_parameters(action)
|
22
|
+
operation[:responses] = format_responses(operation, action)
|
23
|
+
operation[:deprecated] = action.deprecated?
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def format_parameters(action)
|
28
|
+
[].tap do |result|
|
29
|
+
action.params.each do |section, values|
|
30
|
+
values.each do |name, data|
|
31
|
+
result << param_formatter.format(name, section, data)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def format_responses(operation, action)
|
38
|
+
{}.tap do |responses|
|
39
|
+
default_example = action.default_example
|
40
|
+
break if default_example.blank?
|
41
|
+
|
42
|
+
example_formatter.format_default(operation, responses, default_example)
|
43
|
+
other_examples = action.examples.reject { |example| example == default_example }
|
44
|
+
other_examples.each do |example|
|
45
|
+
responses[example.response[:status]] = example_formatter.format(example)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def example_formatter
|
51
|
+
@example_formatter ||= ExampleFormatter.new
|
52
|
+
end
|
53
|
+
|
54
|
+
def param_formatter
|
55
|
+
@param_formatter ||= ParamFormatter.new
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Fictium
|
2
|
+
module OpenApi
|
3
|
+
class V3Exporter
|
4
|
+
class PathGenerator
|
5
|
+
attr_reader :document
|
6
|
+
|
7
|
+
def initialize(document)
|
8
|
+
@document = document
|
9
|
+
end
|
10
|
+
|
11
|
+
def generate
|
12
|
+
{}.tap do |paths|
|
13
|
+
document.resources.each do |resource|
|
14
|
+
generate_from_resource(paths, resource)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def generate_from_resource(paths, resource)
|
22
|
+
resource.actions.each do |action|
|
23
|
+
generate_from_action(paths, action)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def generate_from_action(paths, action)
|
28
|
+
path_formatter.add_path(paths, action)
|
29
|
+
end
|
30
|
+
|
31
|
+
def path_formatter
|
32
|
+
@path_formatter ||= PathFormatter.new
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require_relative 'v3_exporter/content_formatter'
|
2
|
+
require_relative 'v3_exporter/example_formatter'
|
3
|
+
require_relative 'v3_exporter/param_formatter'
|
4
|
+
|
5
|
+
require_relative 'v3_exporter/path_formatter'
|
6
|
+
require_relative 'v3_exporter/path_generator'
|
7
|
+
|
8
|
+
module Fictium
|
9
|
+
module OpenApi
|
10
|
+
class V3Exporter
|
11
|
+
DEFAULT_PROPERTIES = {
|
12
|
+
openapi: '3.0.0'
|
13
|
+
}.freeze
|
14
|
+
FIXTURE_TYPES = %w[servers security tags].freeze
|
15
|
+
INFO_OPTIONS = %w[title description terms_of_service contract license version].freeze
|
16
|
+
|
17
|
+
def export(document)
|
18
|
+
result = DEFAULT_PROPERTIES
|
19
|
+
.merge(create_fixtures)
|
20
|
+
.merge(info: create_info, paths: create_paths(document))
|
21
|
+
validate!(result)
|
22
|
+
FileUtils.mkdir_p(File.dirname(export_file))
|
23
|
+
File.write(export_file, pretty_print? ? JSON.pretty_generate(result) : result.to_json)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def export_file
|
29
|
+
@export_file ||=
|
30
|
+
File.join(Fictium.configuration.export_path, 'open_api', '3.0.0', 'swagger.json')
|
31
|
+
end
|
32
|
+
|
33
|
+
def create_fixtures
|
34
|
+
{}.tap do |fixtures|
|
35
|
+
FIXTURE_TYPES.each do |name|
|
36
|
+
result = load_fixtures(name)
|
37
|
+
fixtures[name.camelize(:lower)] = result if result.present?
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def create_info
|
43
|
+
{}.tap do |info|
|
44
|
+
INFO_OPTIONS.each do |option|
|
45
|
+
value = Fictium.configuration.info.public_send(option)
|
46
|
+
info[option.camelize(:lower)] = value if value.present?
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def create_paths(document)
|
52
|
+
V3Exporter::PathGenerator.new(document).generate
|
53
|
+
end
|
54
|
+
|
55
|
+
def load_fixtures(name)
|
56
|
+
fixture_file = File.join(fixture_path, "#{name}.json")
|
57
|
+
return unless File.exist?(fixture_file)
|
58
|
+
|
59
|
+
JSON.parse(File.read(fixture_file))
|
60
|
+
end
|
61
|
+
|
62
|
+
def fixture_path
|
63
|
+
Fictium.configuration.fixture_path
|
64
|
+
end
|
65
|
+
|
66
|
+
def validate!(result)
|
67
|
+
JSON::Validator.validate!(schema, result)
|
68
|
+
end
|
69
|
+
|
70
|
+
def schema
|
71
|
+
@schema ||= JSON.parse(File.read(File.join(__dir__, 'schemas', '3.0.0.json')))
|
72
|
+
end
|
73
|
+
|
74
|
+
def pretty_print?
|
75
|
+
Fictium.configuration.pretty_print
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require_relative 'configurations/configuration'
|
2
|
+
require_relative 'configurations/info'
|
3
|
+
|
4
|
+
require_relative 'evaluators/parameter_evaluator'
|
5
|
+
require_relative 'evaluators/schema_evaluator'
|
6
|
+
|
7
|
+
require_relative 'poros/model'
|
8
|
+
|
9
|
+
require_relative 'poros/action'
|
10
|
+
require_relative 'poros/document'
|
11
|
+
require_relative 'poros/example'
|
12
|
+
require_relative 'poros/resource'
|
13
|
+
|
14
|
+
# Require default (OpenApi v3) exporter
|
15
|
+
require_relative 'exporters/open_api/v3_exporter'
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Fictium
|
2
|
+
class Action < Fictium::Model
|
3
|
+
attr_reader :resource, :examples, :params
|
4
|
+
attr_accessor :path, :summary, :description, :method, :tags, :deprecated, :docs
|
5
|
+
|
6
|
+
def initialize(resource)
|
7
|
+
@resource = resource
|
8
|
+
@params = ActiveSupport::HashWithIndifferentAccess.new
|
9
|
+
@examples = []
|
10
|
+
@tags = []
|
11
|
+
@deprecated = false
|
12
|
+
end
|
13
|
+
|
14
|
+
def full_path
|
15
|
+
"#{resource.base_path}#{path}"
|
16
|
+
end
|
17
|
+
|
18
|
+
def [](section)
|
19
|
+
@params[section] ||= ActiveSupport::HashWithIndifferentAccess.new
|
20
|
+
end
|
21
|
+
|
22
|
+
def add_params_in(section, &block)
|
23
|
+
self[section].merge!(Fictium::ParameterEvaluator.new.evaluate_params(&block))
|
24
|
+
nil
|
25
|
+
end
|
26
|
+
|
27
|
+
def add_example
|
28
|
+
Fictium::Example.new(self).tap { |example| examples << example }
|
29
|
+
end
|
30
|
+
|
31
|
+
def combined_tags
|
32
|
+
resource.tags + tags
|
33
|
+
end
|
34
|
+
|
35
|
+
def deprecated?
|
36
|
+
deprecated
|
37
|
+
end
|
38
|
+
|
39
|
+
def default_example
|
40
|
+
examples.find(&:default?).presence || examples.first
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Fictium
|
2
|
+
class Document < Fictium::Model
|
3
|
+
attr_reader :resources
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@resources = []
|
7
|
+
end
|
8
|
+
|
9
|
+
def create_resource
|
10
|
+
Fictium::Resource.new(self).tap { |resource| resources << resource }
|
11
|
+
end
|
12
|
+
|
13
|
+
def export
|
14
|
+
Fictium.configuration.exporters.each do |exporter|
|
15
|
+
exporter.export(self)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Fictium
|
2
|
+
class Example < Fictium::Model
|
3
|
+
attr_reader :action
|
4
|
+
attr_accessor :summary, :description, :response, :request, :default, :headers
|
5
|
+
|
6
|
+
def initialize(action)
|
7
|
+
@action = action
|
8
|
+
@headers = ActiveSupport::HashWithIndifferentAccess.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def default?
|
12
|
+
default
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Fictium
|
2
|
+
class Resource < Fictium::Model
|
3
|
+
attr_reader :document, :actions
|
4
|
+
attr_accessor :name, :base_path, :summary, :description, :tags
|
5
|
+
|
6
|
+
def initialize(document)
|
7
|
+
@document = document
|
8
|
+
@actions = []
|
9
|
+
@tags = []
|
10
|
+
end
|
11
|
+
|
12
|
+
def create_action
|
13
|
+
Fictium::Action.new(self).tap { |action| actions << action }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Fictium
|
2
|
+
module RSpec
|
3
|
+
module Actions
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
metadata[:fictium_action] = metadata[:fictium_resource].create_action
|
8
|
+
Fictium::RSpec::Autocomplete::Action.description_attributes(
|
9
|
+
metadata[:fictium_action],
|
10
|
+
metadata[:description]
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
class_methods do
|
15
|
+
def path(path)
|
16
|
+
metadata[:fictium_action].path = path
|
17
|
+
end
|
18
|
+
|
19
|
+
def params_in(section, &block)
|
20
|
+
metadata[:fictium_action].add_params_in(section, &block)
|
21
|
+
end
|
22
|
+
|
23
|
+
def example(*args, **kwargs)
|
24
|
+
Fictium::RSpec::Proxies::Example.new(self, args, kwargs)
|
25
|
+
end
|
26
|
+
|
27
|
+
def deprecate!
|
28
|
+
metadata[:fictium_action].deprecated = true
|
29
|
+
end
|
30
|
+
|
31
|
+
def action_docs(description: nil, url:)
|
32
|
+
metadata[:fictium_action].docs = {}.tap do |docs|
|
33
|
+
docs[:url] = url
|
34
|
+
docs[:description] = description if description.present?
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Fictium
|
2
|
+
module RSpec
|
3
|
+
module Autocomplete
|
4
|
+
module Action
|
5
|
+
ACTION_NAME = /#([A-Z_]+)/i.freeze
|
6
|
+
DEFAULT_PATHS = {
|
7
|
+
index: '',
|
8
|
+
create: '',
|
9
|
+
new: '/new',
|
10
|
+
show: '/{id}',
|
11
|
+
update: '/{id}',
|
12
|
+
destroy: '/{id}'
|
13
|
+
}.freeze
|
14
|
+
class << self
|
15
|
+
def description_attributes(action, description)
|
16
|
+
name = find_action_name(description)&.downcase
|
17
|
+
find_summary(action, name)
|
18
|
+
find_path(action, name)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def find_summary(action, name)
|
24
|
+
return if name.blank?
|
25
|
+
|
26
|
+
key = :"default_summary_for_#{name}"
|
27
|
+
summary_method = descriptors[key] || Fictium.configuration.unknown_action_descriptor
|
28
|
+
one_argument = summary_method.arity == 1
|
29
|
+
action.summary =
|
30
|
+
one_argument ? summary_method.call(action) : summary_method.call(action, name)
|
31
|
+
end
|
32
|
+
|
33
|
+
def descriptors
|
34
|
+
@descriptors ||= Fictium.configuration.default_action_descriptors || {}
|
35
|
+
end
|
36
|
+
|
37
|
+
def find_path(action, name)
|
38
|
+
return if name.blank?
|
39
|
+
|
40
|
+
key = name.to_sym
|
41
|
+
action.path = DEFAULT_PATHS[key] || "/{id}/#{name}"
|
42
|
+
end
|
43
|
+
|
44
|
+
def find_action_name(description)
|
45
|
+
match = description.match(ACTION_NAME)
|
46
|
+
match.presence && match[1]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Fictium
|
2
|
+
module RSpec
|
3
|
+
module Autocomplete
|
4
|
+
module Example
|
5
|
+
class << self
|
6
|
+
def process_http_response(example, response)
|
7
|
+
example.response ||= {}
|
8
|
+
example.response.merge!(
|
9
|
+
status: response.status,
|
10
|
+
body: response.body,
|
11
|
+
content_type: response.content_type
|
12
|
+
)
|
13
|
+
process_http_request(example, response.request)
|
14
|
+
return unless example.default?
|
15
|
+
|
16
|
+
autocomplete_params.extract_from_response(example, response)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def autocomplete_params
|
22
|
+
Fictium::RSpec::Autocomplete::Params
|
23
|
+
end
|
24
|
+
|
25
|
+
def process_http_request(example, request)
|
26
|
+
example.request ||= {}
|
27
|
+
example.request.merge!(
|
28
|
+
content_type: request.content_type,
|
29
|
+
body: request.body.string
|
30
|
+
)
|
31
|
+
extract_method(example, request)
|
32
|
+
return unless example.default?
|
33
|
+
|
34
|
+
autocomplete_params.extract_from_request(example.action, request)
|
35
|
+
end
|
36
|
+
|
37
|
+
def extract_method(example, request)
|
38
|
+
action = example.action
|
39
|
+
action.method = request.method.downcase.to_sym if action.method.blank?
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module Fictium
|
2
|
+
module RSpec
|
3
|
+
module Autocomplete
|
4
|
+
module Params
|
5
|
+
REQUEST_SECTIONS = %i[query header path cookie].freeze
|
6
|
+
PATH_TEMPLATE = /{([A-Z_\-][A-Z0-9_\-]*)}/i.freeze
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def extract_from_request(action, request)
|
10
|
+
REQUEST_SECTIONS.each do |section|
|
11
|
+
action.params[section] ||= ActiveSupport::HashWithIndifferentAccess.new
|
12
|
+
send(:"parse_request_#{section}", action.params[section], action, request)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def extract_from_response(example, response)
|
17
|
+
example.headers ||= ActiveSupport::HashWithIndifferentAccess.new
|
18
|
+
response.headers.each do |name, value|
|
19
|
+
next unless valid_header?(name)
|
20
|
+
|
21
|
+
example.headers[name] ||= {}
|
22
|
+
example.headers[name].merge!(
|
23
|
+
example: value
|
24
|
+
)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def parse_request_query(params, _action, request)
|
31
|
+
request.query_parameters.each do |key, value|
|
32
|
+
params[key] ||= {}
|
33
|
+
params[key].merge!(
|
34
|
+
example: value
|
35
|
+
)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def parse_request_header(params, _action, request)
|
40
|
+
request.headers.to_h.each do |name, value|
|
41
|
+
next unless valid_header?(name)
|
42
|
+
|
43
|
+
params[name] ||= {}
|
44
|
+
params[name].merge!(
|
45
|
+
example: value
|
46
|
+
)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def parse_request_path(params, action, _request)
|
51
|
+
action.full_path.scan(PATH_TEMPLATE).flatten.each do |name|
|
52
|
+
params[name] ||= {}
|
53
|
+
# TODO: Extract example from request
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def parse_request_cookie(params, _action, request)
|
58
|
+
request.cookies.each do |key, value|
|
59
|
+
params[key] ||= {}
|
60
|
+
params[key].merge!(
|
61
|
+
example: value
|
62
|
+
)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def valid_header?(name)
|
67
|
+
return false if ignored_header_groups.any? { |group| name.downcase.start_with?(group) }
|
68
|
+
|
69
|
+
!Fictium.configuration.ignored_header_values.include?(name.downcase)
|
70
|
+
end
|
71
|
+
|
72
|
+
def ignored_header_groups
|
73
|
+
Fictium.configuration.ignored_header_groups
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Fictium
|
2
|
+
module RSpec
|
3
|
+
module Autocomplete
|
4
|
+
module Resource
|
5
|
+
CONTROLLER_TERMINATION = /Controller$/.freeze
|
6
|
+
|
7
|
+
class << self
|
8
|
+
def name_attributes(resource, controller_name)
|
9
|
+
resource_path = controller_name.sub(CONTROLLER_TERMINATION, '').underscore
|
10
|
+
resource.base_path = "/#{resource_path}"
|
11
|
+
path_sections = resource_path.split('/')
|
12
|
+
plural = path_sections.last
|
13
|
+
resource.name = plural.singularize.humanize(capitalize: false)
|
14
|
+
resource.summary = Fictium.configuration.summary_format.call(plural)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|