fictium 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +7 -0
  2. data/.github/pull_request_template.md +15 -0
  3. data/.gitignore +22 -0
  4. data/.rspec +3 -0
  5. data/.rubocop.yml +32 -0
  6. data/.ruby-version +1 -0
  7. data/.travis.yml +13 -0
  8. data/CHANGELOG.md +28 -0
  9. data/CODE_OF_CONDUCT.md +74 -0
  10. data/Gemfile +4 -0
  11. data/Gemfile.lock +216 -0
  12. data/LICENSE +201 -0
  13. data/LICENSE.txt +21 -0
  14. data/README.md +108 -0
  15. data/Rakefile +10 -0
  16. data/app/.keep +0 -0
  17. data/bin/console +14 -0
  18. data/bin/setup +8 -0
  19. data/fictium.gemspec +57 -0
  20. data/lib/fictium/configurations/configuration.rb +87 -0
  21. data/lib/fictium/configurations/info.rb +12 -0
  22. data/lib/fictium/engine.rb +6 -0
  23. data/lib/fictium/evaluators/parameter_evaluator.rb +57 -0
  24. data/lib/fictium/evaluators/schema_evaluator.rb +7 -0
  25. data/lib/fictium/exporters/open_api/schemas/3.0.0.json +1654 -0
  26. data/lib/fictium/exporters/open_api/v3_exporter/content_formatter.rb +20 -0
  27. data/lib/fictium/exporters/open_api/v3_exporter/example_formatter.rb +46 -0
  28. data/lib/fictium/exporters/open_api/v3_exporter/param_formatter.rb +45 -0
  29. data/lib/fictium/exporters/open_api/v3_exporter/path_formatter.rb +60 -0
  30. data/lib/fictium/exporters/open_api/v3_exporter/path_generator.rb +37 -0
  31. data/lib/fictium/exporters/open_api/v3_exporter.rb +79 -0
  32. data/lib/fictium/loader.rb +15 -0
  33. data/lib/fictium/poros/action.rb +43 -0
  34. data/lib/fictium/poros/document.rb +19 -0
  35. data/lib/fictium/poros/example.rb +15 -0
  36. data/lib/fictium/poros/model.rb +4 -0
  37. data/lib/fictium/poros/resource.rb +16 -0
  38. data/lib/fictium/railtie.rb +4 -0
  39. data/lib/fictium/rspec/actions.rb +40 -0
  40. data/lib/fictium/rspec/autocomplete/action.rb +52 -0
  41. data/lib/fictium/rspec/autocomplete/example.rb +45 -0
  42. data/lib/fictium/rspec/autocomplete/params.rb +79 -0
  43. data/lib/fictium/rspec/autocomplete/resource.rb +20 -0
  44. data/lib/fictium/rspec/examples.rb +48 -0
  45. data/lib/fictium/rspec/proxies/action.rb +11 -0
  46. data/lib/fictium/rspec/proxies/base.rb +25 -0
  47. data/lib/fictium/rspec/proxies/example.rb +15 -0
  48. data/lib/fictium/rspec/proxy_handler.rb +11 -0
  49. data/lib/fictium/rspec/resources.rb +41 -0
  50. data/lib/fictium/rspec.rb +39 -0
  51. data/lib/fictium/version.rb +5 -0
  52. data/lib/fictium.rb +29 -0
  53. data/tasks/.keep +0 -0
  54. data/tasks/travis/analyze.rb +12 -0
  55. metadata +321 -0
data/README.md ADDED
@@ -0,0 +1,108 @@
1
+ # Fictium
2
+
3
+ [![Build Status](https://travis-ci.org/Wolox/fictium.svg?branch=master)](https://travis-ci.org/Wolox/fictium) [![Maintainability](https://api.codeclimate.com/v1/badges/52afbf838f92fe260b6e/maintainability)](https://codeclimate.com/github/Wolox/fictium/maintainability) [![Test Coverage](https://api.codeclimate.com/v1/badges/52afbf838f92fe260b6e/test_coverage)](https://codeclimate.com/github/Wolox/fictium/test_coverage)
4
+
5
+ This gem is a documentation helper. The goal of this gem is, by adding small modifications into your existing tests,
6
+ you can then transform it into easy REST documentation.
7
+
8
+ For the initial release, the support is focused explicitly on generating documentation from [RSpec](https://rspec.info/) tests, and generate an [OpenAPI](https://github.com/OAI/OpenAPI-Specification) [V3.0.2](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md) Document.
9
+
10
+ Future versions may allow to export to other OpenAPI versions, or even API Bluepint formats.
11
+
12
+ ## Installation
13
+
14
+ Add this line to your application's Gemfile:
15
+
16
+ ```ruby
17
+ gem 'fictium'
18
+ ```
19
+
20
+ And then execute:
21
+
22
+ $ bundle
23
+
24
+ Or install it yourself as:
25
+
26
+ $ gem install fictium
27
+
28
+ ## Usage
29
+
30
+ Fictium is a Gem to generate documentation from your tests.
31
+ Instead of you having to write entirely new tests, the goal of this gem is to provide easy to use,
32
+ tags and annotations on your existing tests.
33
+
34
+ Fictium is closely tied to RSpec and Rails, but it's developed in a way to support more testing suites or engines in future versions.
35
+
36
+ The primary goal is for generating OpenAPI Documentation, but, just like with RSpec, future versions may provide other output types.
37
+
38
+ [Check out the wiki too!](./wiki)
39
+
40
+
41
+ ### Common terminology of this gem
42
+
43
+ Because this GEM is used to represent REST APIs, this gem, provides some common objects, which are used as a documentation naming scheme. They are independant from the actual documentation format, so each exporter should transform this abstract representation into the actual document representation.
44
+
45
+ The base object, is de [Fictium::Document](./lib/fictoum/poros/fictium/document). This class represent your whole API.
46
+ One is created when the testing starts.
47
+
48
+ The document, then is divided in resources. The class [Fictium::Resource](./lib/fictoum/poros/fictium/resource) is the one dedicated to handle them. A resource is a Rest object, for example, Posts, Users or Tags.
49
+
50
+ Each resource is sub divided in actions, [Fictium::Action](./lib/fictoum/poros/fictium/action). Actions are enpoints associated with a REST method.
51
+
52
+ ### Configuration
53
+
54
+ This gem attemps to complete the documentation for you, so you don't have to constantly document it yourself.
55
+ To configure how this gem completes your documentation, you have some configurations available [here](https://github.com/Wolox/fictium/wiki).
56
+
57
+
58
+ ### RSpec Integration
59
+
60
+ Just `require 'fictium/rspec'` in your spec helper and your RSpec test will include everything you need to work in your environment.
61
+
62
+ At any test of type: :controller, you can just add the following helpers:
63
+
64
+ ```rb
65
+ describe PostsController do
66
+ describe action 'GET #index' do
67
+ describe example 'without errors' do
68
+ default_example # You can select an example to be marked as default in your action
69
+
70
+ before do
71
+ get :index
72
+ end
73
+
74
+ # ... your tests
75
+ end
76
+ end
77
+ end
78
+ ```
79
+
80
+ The idea, is that your controller has actions, and each actions has examples.
81
+ You can, for now, check `spec/controllers` at this repository to
82
+
83
+ You can deeply customize your endpoints using RSpec.
84
+ Check out details [here](./wiki/RSpec-definitions).
85
+
86
+ ## Development
87
+
88
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
89
+
90
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
91
+
92
+ ## Contributing
93
+
94
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/fictium. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
95
+
96
+ ## License
97
+
98
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
99
+
100
+ This gem is developed by (Wolox)[https://wolox.com.ar].
101
+
102
+ Maintainers: [Ramiro Rojo](https://github.com/holywyvern)
103
+ Contributors: None (for now...)
104
+ ![Wolox](https://raw.githubusercontent.com/Wolox/press-kit/master/logos/logo_banner.png)
105
+
106
+ ## Code of Conduct
107
+
108
+ Everyone interacting in the Fictium project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/Wolox/fictium/blob/master/CODE_OF_CONDUCT.md).
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ Dir[File.join(__dir__, 'tasks', '**', '*.rb')].each do |f|
7
+ require f
8
+ end
9
+
10
+ task default: :spec
data/app/.keep ADDED
File without changes
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'fictium'
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require 'irb'
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/fictium.gemspec ADDED
@@ -0,0 +1,57 @@
1
+ lib = File.expand_path('lib', __dir__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'fictium/version'
4
+
5
+ Gem::Specification.new do |spec| # rubocop:disable Metrics/BlockLength
6
+ spec.name = 'fictium'
7
+ spec.version = Fictium::VERSION
8
+ spec.authors = ['Ramiro Rojo']
9
+ spec.email = ['ramiro.rojo@wolox.com.ar']
10
+
11
+ spec.summary = 'A gem to generate documentation out of tests.'
12
+ spec.homepage = 'https://github.com/Wolox/fictium'
13
+ spec.license = 'MIT'
14
+
15
+ spec.metadata['homepage_uri'] = spec.homepage
16
+ spec.metadata['source_code_uri'] = 'https://github.com/Wolox/fictium'
17
+ spec.metadata['changelog_uri'] = 'https://github.com/Wolox/fictium/CHANGELOG.md'
18
+
19
+ # Specify which files should be added to the gem when it is released.
20
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
21
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
22
+ `git ls-files -z`.split("\x0").reject do |f|
23
+ f.match(%r{^(test|spec|features)/})
24
+ end
25
+ end
26
+ spec.bindir = 'exe'
27
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
+ spec.require_paths = ['lib']
29
+
30
+ spec.required_ruby_version = '>= 2.6.0'
31
+
32
+ spec.add_runtime_dependency 'activesupport',
33
+ Fictium::RAILS_MIN_VERSION,
34
+ Fictium::RAILS_MAX_VERSION
35
+
36
+ spec.add_runtime_dependency 'json-schema', '~> 2.8'
37
+ spec.add_runtime_dependency 'verbs', '~> 2.1.4'
38
+
39
+ spec.add_development_dependency 'bundler', '~> 2.0'
40
+
41
+ spec.add_development_dependency 'byebug'
42
+
43
+ spec.add_development_dependency 'brakeman'
44
+
45
+ spec.add_development_dependency 'faker', '~> 2.6.0'
46
+
47
+ spec.add_development_dependency 'rails',
48
+ Fictium::RAILS_MIN_VERSION,
49
+ Fictium::RAILS_MAX_VERSION
50
+ spec.add_development_dependency 'rake', '~> 12.3.3'
51
+ spec.add_development_dependency 'rspec', '~> 3.9'
52
+ spec.add_development_dependency 'rspec-rails', '~> 3.9'
53
+ spec.add_development_dependency 'rubocop', '0.75'
54
+ spec.add_development_dependency 'rubocop-rails', '2.3.2'
55
+ spec.add_development_dependency 'rubocop-rspec', '1.36.0'
56
+ spec.add_development_dependency 'simplecov', '~> 0.17.0'
57
+ end
@@ -0,0 +1,87 @@
1
+ module Fictium
2
+ class Configuration
3
+ VOWEL = /[aeiou]/i.freeze
4
+ DEFAULT_IGNORED_HEADERS_GROUPS = %w[rack. action_dispatch. action_controller.].freeze
5
+ DEFAULT_IGNORED_HEADERS = %w[
6
+ accept content-type authorization http_accept content_type
7
+ request_method server_name server_port query_string
8
+ http_cookie path_info x-frame-options x-xss-protection x-content-type-options
9
+ x-download-options x-permitted-cross-domain-policies referrer-policy
10
+ https script_name http_host remote_addr http_user_agent
11
+ http_authorization content_length raw_post_data
12
+ ].freeze
13
+ private_constant :VOWEL
14
+
15
+ attr_reader :info
16
+ attr_accessor :exporters, :summary_format, :default_action_descriptors,
17
+ :unknown_action_descriptor, :default_subject, :fixture_path,
18
+ :export_path, :default_response_content_type, :pretty_print,
19
+ :ignored_header_values, :ignored_header_groups
20
+
21
+ def initialize
22
+ @info = Fictium::Configuration::Info.new
23
+ @exporters = [Fictium::OpenApi::V3Exporter.new]
24
+
25
+ @summary_format = method(:default_summary_format)
26
+ @pretty_print = true
27
+ setup_descriptors
28
+ setup_strings
29
+ @ignored_header_values = DEFAULT_IGNORED_HEADERS.dup
30
+ @ignored_header_groups = DEFAULT_IGNORED_HEADERS_GROUPS.dup
31
+ end
32
+
33
+ private
34
+
35
+ def setup_descriptors
36
+ @default_action_descriptors = {
37
+ default_summary_for_index: method(:default_summary_for_index),
38
+ default_summary_for_show: method(:default_summary_for_show),
39
+ default_summary_for_update: method(:default_summary_for_update),
40
+ default_summary_for_destroy: method(:default_summary_for_destroy)
41
+ }
42
+ @unknown_action_descriptor = method(:default_unknown_action_descriptor)
43
+ end
44
+
45
+ def setup_strings
46
+ @default_subject = 'This endpoint'
47
+ @export_path = 'doc'
48
+ @default_response_content_type = 'text/plain'
49
+ end
50
+
51
+ def default_summary_format(resources)
52
+ "Handles API #{resources}."
53
+ end
54
+
55
+ def default_unknown_action_descriptor(action, action_name)
56
+ name = action_name.humanize
57
+ "#{conjugate(name)} an existing #{action.resource.name}."
58
+ end
59
+
60
+ def default_summary_for_index(action)
61
+ "#{default_subject} lists all available #{action.resource.name.pluralize}"
62
+ end
63
+
64
+ def default_summary_for_show(action)
65
+ name = action.resource.name
66
+ "#{default_subject} shows details of #{get_preposition(name)} #{name}."
67
+ end
68
+
69
+ def default_summary_for_update(action)
70
+ name = action.resource.name
71
+ "#{default_subject} updates #{get_preposition(name)} #{name}."
72
+ end
73
+
74
+ def default_summary_for_destroy(action)
75
+ name = action.resource.name
76
+ "#{default_subject} destroys #{get_preposition(name)} #{name}."
77
+ end
78
+
79
+ def conjugate(name)
80
+ ::Verbs::Conjugator.conjugate name, subject: default_subject, tense: :present, person: :third
81
+ end
82
+
83
+ def get_preposition(resource_name)
84
+ resource_name.start_with?(VOWEL) ? 'an' : 'a'
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,12 @@
1
+ module Fictium
2
+ class Configuration
3
+ class Info
4
+ attr_accessor :title, :description, :terms_of_service, :contract, :license, :version
5
+
6
+ def initialize
7
+ self.title = 'TODO: Change me at Fictium.configuration.api'
8
+ self.version = '0.1.0'
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,6 @@
1
+ module Fictium
2
+ class Engine < Rails::Engine
3
+ engine_name 'fictium'
4
+ isolate_namespace Fictium
5
+ end
6
+ end
@@ -0,0 +1,57 @@
1
+ module Fictium
2
+ class ParameterEvaluator
3
+ attr_reader :params
4
+
5
+ def initialize
6
+ @params = ActiveSupport::HashWithIndifferentAccess.new
7
+ end
8
+
9
+ def evaluate_params(&block)
10
+ if block.arity == 1
11
+ block.call(self)
12
+ else
13
+ instance_eval(&block)
14
+ end
15
+ @params
16
+ end
17
+
18
+ def method_missing(name, *_, **kwargs) # rubocop:disable Style/MethodMissingSuper
19
+ self[name] = validate_keys(**kwargs) if respond_to_missing?(name)
20
+ end
21
+
22
+ def [](name)
23
+ @params[name]
24
+ end
25
+
26
+ def []=(name, value)
27
+ @params[name] = value
28
+ end
29
+
30
+ private
31
+
32
+ def respond_to_missing?(_method_name, _include_private = false)
33
+ true
34
+ end
35
+
36
+ def validate_keys(required: false, deprecated: false, allow_empty: false, **kwargs)
37
+ {
38
+ description: kwargs[:description],
39
+ required: required,
40
+ deprecated: deprecated,
41
+ allow_empty: allow_empty,
42
+ schema: format_schema(kwargs)
43
+ }
44
+ end
45
+
46
+ def format_schema(args)
47
+ return unless args[:schema].present?
48
+
49
+ schema_evaluator.format(ref: args[:schema][:ref]) if args[:schema][:ref].present?
50
+ schema_evaluator.format(args[:schema])
51
+ end
52
+
53
+ def schema_evaluator
54
+ @schema_evaluator ||= Fictium::SchemaEvaluator.new
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,7 @@
1
+ module Fictium
2
+ class SchemaEvaluator
3
+ def format(obj)
4
+ obj[:ref].present? ? { '$ref': obj[:ref] } : obj
5
+ end
6
+ end
7
+ end