Coder Social home page Coder Social logo

fictium's Introduction

Fictium

Build Status Maintainability Test Coverage Gem Version

This gem is a documentation helper. The goal of this gem is, by adding small modifications into your existing tests, you can then transform it into easy REST documentation.

For the initial release, the support is focused explicitly on generating documentation from RSpec tests, and generate an OpenAPI V3.0.2 Document.

The current Gem version allows to export into the following formats:

Exporter Class name Notes
OpenApi 3.0 Fictium::OpenApi::V3Exporter The default exporter for the current Gem version. It doesn't include 100% of the OpenAPI specification, but it works for the most common use cases. It's the format Swagger uses for documentation.
API Blueprint Fictium::ApiBlueprintExporter Used by Apiary. A superset of Markdown with special keywords and controls.
Postman Collection Fictium::Postman::V2Exporter Export your test as a Postman collection for easy creation of mock APIs and quick debugging.

Future versions may provide:

  • OpenApi 1.0 and 2.0
  • Custom HTML exporter

Installation

Add this line to your application's Gemfile:

gem 'fictium'

And then execute:

$ bundle

Or install it yourself as:

$ gem install fictium

Usage

Fictium is a Gem to generate documentation from your tests. Instead of you having to write entirely new tests, the goal of this gem is to provide easy to use, tags and annotations on your existing tests.

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.

The primary goal is for generating OpenAPI Documentation, but, just like with RSpec, future versions may provide other output types.

Check out the wiki too!

Common terminology of this gem

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.

The base object, is de Fictium::Document. This class represent your whole API. One is created when the testing starts.

The document, then is divided in resources. The class Fictium::Resource is the one dedicated to handle them. A resource is a Rest object, for example, Posts, Users or Tags.

Each resource is sub divided in actions, Fictium::Action. Actions are enpoints associated with a REST method.

Configuration

This gem attemps to complete the documentation for you, so you don't have to constantly document it yourself. To configure how this gem completes your documentation, you have some configurations available here.

RSpec Integration

Just require 'fictium/rspec' in your rails helper and your RSpec test will include everything you need to work in your environment. (be aware, the current version requires Rails to be previously loaded to work).

At any test of type: :controller, you can just add the following helpers:

describe PostsController do
  describe action 'GET #index' do
    describe example 'without errors' do
        default_example # You can select an example to be marked as default in your action

        before do
            get :index
        end

        # ... your tests
    end
  end
end

The idea, is that your controller has actions, and each actions has examples. You can, for now, check spec/controllers at this repository to

You can deeply customize your endpoints using RSpec. Check out details here.

Development

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.

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.

Contributing

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 code of conduct.

License

The gem is available as open source under the terms of the MIT License.

This gem is developed by Wolox.

Maintainers: Ramiro Rojo Contributors: None (for now...)

Wolox

Code of Conduct

Everyone interacting in the Fictium project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.

fictium's People

Contributors

holywyvern avatar tagonzalez avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fictium's Issues

Mediatype deprecation warning

  • Ruby version: 2.6.5
  • Rails: 6.0.1
DEPRECATION WARNING: Rails 6.1 will return Content-Type header without modification. If you want just the MIME type, please use `#media_type` instead. (called from process_http_response at ~/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/bundler/gems/fictium/lib/fictium/rspec/autocomplete/example.rb:11

Solution

Change this line to content_type: response.media_type

Running specific controller specs (specifying line number) causes an error

Describe the bug
Specifying a specific line when running controller specs causes an error to occur, except when that specific line is the line that describes the controller. The error does not occur when no line number is specified.

To Reproduce
run bundle exec rspec path/to/my/controller/spec.rb:<specific_line>
(where specific_line is a line number that points to a line other than the line that contains describe MyController do)

Expected behavior
The spec should successfully run.

Actual behavior
Specs seem to run fine but an error occurs after running them.

Api::V1::UsersController
  #show
    without errors
      responds with the correct information and format
      responds with unauthorized status
      with documentation
        documents the example
    when the user is logged in
      responds with ok status
      responds with the correct information and format
      with documentation
        documents the example

An error occurred in an `after(:suite)` hook.
Failure/Error: path_object[action.method.to_sym] = create_operation(action)

NoMethodError:
  undefined method `to_sym' for nil:NilClass
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fictium-0.3.0/lib/fictium/exporters/open_api/v3_exporter/path_formatter.rb:7:in `add_path'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fictium-0.3.0/lib/fictium/exporters/open_api/v3_exporter/path_generator.rb:28:in `generate_from_action'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fictium-0.3.0/lib/fictium/exporters/open_api/v3_exporter/path_generator.rb:23:in `block in generate_from_resource'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fictium-0.3.0/lib/fictium/exporters/open_api/v3_exporter/path_generator.rb:22:in `each'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fictium-0.3.0/lib/fictium/exporters/open_api/v3_exporter/path_generator.rb:22:in `generate_from_resource'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fictium-0.3.0/lib/fictium/exporters/open_api/v3_exporter/path_generator.rb:14:in `block (2 levels) in generate'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fictium-0.3.0/lib/fictium/exporters/open_api/v3_exporter/path_generator.rb:13:in `each'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fictium-0.3.0/lib/fictium/exporters/open_api/v3_exporter/path_generator.rb:13:in `block in generate'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fictium-0.3.0/lib/fictium/exporters/open_api/v3_exporter/path_generator.rb:12:in `tap'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fictium-0.3.0/lib/fictium/exporters/open_api/v3_exporter/path_generator.rb:12:in `generate'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fictium-0.3.0/lib/fictium/exporters/open_api/v3_exporter.rb:52:in `create_paths'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fictium-0.3.0/lib/fictium/exporters/open_api/v3_exporter.rb:20:in `export'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fictium-0.3.0/lib/fictium/poros/document.rb:15:in `block in export'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fictium-0.3.0/lib/fictium/poros/document.rb:14:in `each'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fictium-0.3.0/lib/fictium/poros/document.rb:14:in `export'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fictium-0.3.0/lib/fictium/rspec.rb:37:in `block (2 levels) in <top (required)>'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/rspec-core-3.9.0/lib/rspec/core/example.rb:450:in `instance_exec'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/rspec-core-3.9.0/lib/rspec/core/example.rb:450:in `instance_exec'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/rspec-core-3.9.0/lib/rspec/core/hooks.rb:363:in `run'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/rspec-core-3.9.0/lib/rspec/core/configuration.rb:2108:in `block in run_suite_hooks'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/rspec-core-3.9.0/lib/rspec/core/configuration.rb:2106:in `each'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/rspec-core-3.9.0/lib/rspec/core/configuration.rb:2106:in `run_suite_hooks'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/rspec-core-3.9.0/lib/rspec/core/configuration.rb:2033:in `with_suite_hooks'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/rspec-core-3.9.0/lib/rspec/core/runner.rb:116:in `block in run_specs'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/rspec-core-3.9.0/lib/rspec/core/reporter.rb:74:in `report'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/rspec-core-3.9.0/lib/rspec/core/runner.rb:115:in `run_specs'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/rspec-core-3.9.0/lib/rspec/core/runner.rb:89:in `run'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/rspec-core-3.9.0/lib/rspec/core/runner.rb:71:in `run'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/rspec-core-3.9.0/lib/rspec/core/runner.rb:45:in `invoke'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/rspec-core-3.9.0/exe/rspec:4:in `<top (required)>'
# /home/tferrer/.rbenv/versions/2.6.5/bin/rspec:23:in `load'
# /home/tferrer/.rbenv/versions/2.6.5/bin/rspec:23:in `<top (required)>'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bundler-2.0.2/lib/bundler/cli/exec.rb:74:in `load'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bundler-2.0.2/lib/bundler/cli/exec.rb:74:in `kernel_load'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bundler-2.0.2/lib/bundler/cli/exec.rb:28:in `run'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bundler-2.0.2/lib/bundler/cli.rb:465:in `exec'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bundler-2.0.2/lib/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bundler-2.0.2/lib/bundler/vendor/thor/lib/thor/invocation.rb:126:in `invoke_command'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bundler-2.0.2/lib/bundler/vendor/thor/lib/thor.rb:387:in `dispatch'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bundler-2.0.2/lib/bundler/cli.rb:27:in `dispatch'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bundler-2.0.2/lib/bundler/vendor/thor/lib/thor/base.rb:466:in `start'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bundler-2.0.2/lib/bundler/cli.rb:18:in `start'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bundler-2.0.2/exe/bundle:30:in `block in <top (required)>'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bundler-2.0.2/lib/bundler/friendly_errors.rb:124:in `with_friendly_errors'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bundler-2.0.2/exe/bundle:22:in `<top (required)>'
# /home/tferrer/.rbenv/versions/2.6.5/bin/bundle:23:in `load'
# /home/tferrer/.rbenv/versions/2.6.5/bin/bundle:23:in `<main>'
# 
#   Showing full backtrace because every line was filtered out.
#   See docs for RSpec::Configuration#backtrace_exclusion_patterns and
#   RSpec::Configuration#backtrace_inclusion_patterns for more information.

Finished in 1.41 seconds (files took 6.81 seconds to load)
6 examples, 0 failures, 1 error occurred outside of examples

Screenshots
image

Rails version (please complete the following information):
6.0.1
Ruby version (please complete the following information):
2.6.5
Fictium version (please complete the following information):
0.3.0

Additional context
It has been tried with different controller specs but it always seems to happen. No error occurs when no line number is given (or when the line number points to the first describe)

NoMethodError exception may occur after tests finish running

Describe the bug
A NoMethodError is thrown after tests have run (this can happen if one controller test fails).

To Reproduce
Build a spec for an endpoint which throws an uncaught exception.

Expected behavior
It is supposed to check whether an http_object exists before attempting to access one of its keys.

Screenshots
No screenshots available.

Rails version:
6.0.1
Ruby version:
2.6.5
Fictium version:
0.4.1

Additional context
Stack trace:

An error occurred in an `after(:suite)` hook.
Failure/Error: example: http_object[:body]

NoMethodError:
  undefined method `[]' for nil:NilClass
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fictium-0.4.1/lib/fictium/exporters/open_api/v3_exporter/content_formatter.rb:11:in `block in format'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fictium-0.4.1/lib/fictium/exporters/open_api/v3_exporter/content_formatter.rb:9:in `tap'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fictium-0.4.1/lib/fictium/exporters/open_api/v3_exporter/content_formatter.rb:9:in `format'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fictium-0.4.1/lib/fictium/exporters/open_api/v3_exporter/example_formatter.rb:17:in `block in format'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fictium-0.4.1/lib/fictium/exporters/open_api/v3_exporter/example_formatter.rb:16:in `tap'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fictium-0.4.1/lib/fictium/exporters/open_api/v3_exporter/example_formatter.rb:16:in `format'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fictium-0.4.1/lib/fictium/exporters/open_api/v3_exporter/example_formatter.rb:6:in `format_default'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fictium-0.4.1/lib/fictium/exporters/open_api/v3_exporter/path_formatter.rb:44:in `block in format_responses'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fictium-0.4.1/lib/fictium/exporters/open_api/v3_exporter/path_formatter.rb:40:in `tap'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fictium-0.4.1/lib/fictium/exporters/open_api/v3_exporter/path_formatter.rb:40:in `format_responses'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fictium-0.4.1/lib/fictium/exporters/open_api/v3_exporter/path_formatter.rb:24:in `block in create_operation'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fictium-0.4.1/lib/fictium/exporters/open_api/v3_exporter/path_formatter.rb:20:in `tap'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fictium-0.4.1/lib/fictium/exporters/open_api/v3_exporter/path_formatter.rb:20:in `create_operation'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fictium-0.4.1/lib/fictium/exporters/open_api/v3_exporter/path_formatter.rb:9:in `add_path'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fictium-0.4.1/lib/fictium/exporters/open_api/v3_exporter/path_generator.rb:28:in `generate_from_action'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fictium-0.4.1/lib/fictium/exporters/open_api/v3_exporter/path_generator.rb:23:in `block in generate_from_resource'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fictium-0.4.1/lib/fictium/exporters/open_api/v3_exporter/path_generator.rb:22:in `each'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fictium-0.4.1/lib/fictium/exporters/open_api/v3_exporter/path_generator.rb:22:in `generate_from_resource'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fictium-0.4.1/lib/fictium/exporters/open_api/v3_exporter/path_generator.rb:14:in `block (2 levels) in generate'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fictium-0.4.1/lib/fictium/exporters/open_api/v3_exporter/path_generator.rb:13:in `each'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fictium-0.4.1/lib/fictium/exporters/open_api/v3_exporter/path_generator.rb:13:in `block in generate'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fictium-0.4.1/lib/fictium/exporters/open_api/v3_exporter/path_generator.rb:12:in `tap'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fictium-0.4.1/lib/fictium/exporters/open_api/v3_exporter/path_generator.rb:12:in `generate'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fictium-0.4.1/lib/fictium/exporters/open_api/v3_exporter.rb:52:in `create_paths'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fictium-0.4.1/lib/fictium/exporters/open_api/v3_exporter.rb:20:in `export'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fictium-0.4.1/lib/fictium/poros/document.rb:15:in `block in export'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fictium-0.4.1/lib/fictium/poros/document.rb:14:in `each'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fictium-0.4.1/lib/fictium/poros/document.rb:14:in `export'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fictium-0.4.1/lib/fictium/rspec.rb:37:in `block (2 levels) in <top (required)>'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/rspec-core-3.9.0/lib/rspec/core/example.rb:450:in `instance_exec'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/rspec-core-3.9.0/lib/rspec/core/example.rb:450:in `instance_exec'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/rspec-core-3.9.0/lib/rspec/core/hooks.rb:363:in `run'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/rspec-core-3.9.0/lib/rspec/core/configuration.rb:2108:in `block in run_suite_hooks'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/rspec-core-3.9.0/lib/rspec/core/configuration.rb:2106:in `each'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/rspec-core-3.9.0/lib/rspec/core/configuration.rb:2106:in `run_suite_hooks'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/rspec-core-3.9.0/lib/rspec/core/configuration.rb:2033:in `with_suite_hooks'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/rspec-core-3.9.0/lib/rspec/core/runner.rb:116:in `block in run_specs'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/rspec-core-3.9.0/lib/rspec/core/reporter.rb:74:in `report'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/rspec-core-3.9.0/lib/rspec/core/runner.rb:115:in `run_specs'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/rspec-core-3.9.0/lib/rspec/core/runner.rb:89:in `run'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/rspec-core-3.9.0/lib/rspec/core/runner.rb:71:in `run'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/rspec-core-3.9.0/lib/rspec/core/runner.rb:45:in `invoke'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/rspec-core-3.9.0/exe/rspec:4:in `<top (required)>'
# /home/tferrer/.rbenv/versions/2.6.5/bin/rspec:23:in `load'
# /home/tferrer/.rbenv/versions/2.6.5/bin/rspec:23:in `<top (required)>'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bundler-2.0.2/lib/bundler/cli/exec.rb:74:in `load'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bundler-2.0.2/lib/bundler/cli/exec.rb:74:in `kernel_load'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bundler-2.0.2/lib/bundler/cli/exec.rb:28:in `run'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bundler-2.0.2/lib/bundler/cli.rb:465:in `exec'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bundler-2.0.2/lib/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bundler-2.0.2/lib/bundler/vendor/thor/lib/thor/invocation.rb:126:in `invoke_command'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bundler-2.0.2/lib/bundler/vendor/thor/lib/thor.rb:387:in `dispatch'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bundler-2.0.2/lib/bundler/cli.rb:27:in `dispatch'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bundler-2.0.2/lib/bundler/vendor/thor/lib/thor/base.rb:466:in `start'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bundler-2.0.2/lib/bundler/cli.rb:18:in `start'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bundler-2.0.2/exe/bundle:30:in `block in <top (required)>'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bundler-2.0.2/lib/bundler/friendly_errors.rb:124:in `with_friendly_errors'
# /home/tferrer/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bundler-2.0.2/exe/bundle:22:in `<top (required)>'
# /home/tferrer/.rbenv/versions/2.6.5/bin/bundle:23:in `load'
# /home/tferrer/.rbenv/versions/2.6.5/bin/bundle:23:in `<main>'
# 
#   Showing full backtrace because every line was filtered out.
#   See docs for RSpec::Configuration#backtrace_exclusion_patterns and
#   RSpec::Configuration#backtrace_inclusion_patterns for more information.

POST request with attachment with invalid UTF-8 characters causes after hook to fail

Describe the bug
An error may occur when a file attachment is sent in a POST HTTP request if said file contains non-printable/illegal characters.

An error occurred in an `after(:suite)` hook.
Failure/Error: state.generate(obj)

Encoding::UndefinedConversionError:
  "\xFF" from ASCII-8BIT to UTF-8
# /Users/tomasferrer/.rbenv/versions/2.6.6/lib/ruby/2.6.0/json/common.rb:286:in `encode'
# /Users/tomasferrer/.rbenv/versions/2.6.6/lib/ruby/2.6.0/json/common.rb:286:in `generate'
# /Users/tomasferrer/.rbenv/versions/2.6.6/lib/ruby/2.6.0/json/common.rb:286:in `pretty_generate'
# /Users/tomasferrer/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/fictium-0.4.1/lib/fictium/exporters/open_api/v3_exporter.rb:23:in `export'
# /Users/tomasferrer/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/fictium-0.4.1/lib/fictium/poros/document.rb:15:in `block in export'
# /Users/tomasferrer/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/fictium-0.4.1/lib/fictium/poros/document.rb:14:in `each'
# /Users/tomasferrer/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/fictium-0.4.1/lib/fictium/poros/document.rb:14:in `export'
# /Users/tomasferrer/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/fictium-0.4.1/lib/fictium/rspec.rb:37:in `block (2 levels) in <top (required)>'
# /Users/tomasferrer/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rspec-core-3.9.2/lib/rspec/core/example.rb:450:in `instance_exec'
# /Users/tomasferrer/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rspec-core-3.9.2/lib/rspec/core/example.rb:450:in `instance_exec'
# /Users/tomasferrer/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rspec-core-3.9.2/lib/rspec/core/hooks.rb:367:in `run'
# /Users/tomasferrer/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rspec-core-3.9.2/lib/rspec/core/configuration.rb:2135:in `block in run_suite_hooks'
# /Users/tomasferrer/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rspec-core-3.9.2/lib/rspec/core/configuration.rb:2133:in `each'
# /Users/tomasferrer/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rspec-core-3.9.2/lib/rspec/core/configuration.rb:2133:in `run_suite_hooks'
# /Users/tomasferrer/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rspec-core-3.9.2/lib/rspec/core/configuration.rb:2060:in `with_suite_hooks'
# /Users/tomasferrer/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rspec-core-3.9.2/lib/rspec/core/runner.rb:116:in `block in run_specs'
# /Users/tomasferrer/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rspec-core-3.9.2/lib/rspec/core/reporter.rb:74:in `report'
# /Users/tomasferrer/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rspec-core-3.9.2/lib/rspec/core/runner.rb:115:in `run_specs'
# /Users/tomasferrer/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rspec-core-3.9.2/lib/rspec/core/runner.rb:89:in `run'
# /Users/tomasferrer/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rspec-core-3.9.2/lib/rspec/core/runner.rb:71:in `run'
# /Users/tomasferrer/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rspec-core-3.9.2/lib/rspec/core/runner.rb:45:in `invoke'
# /Users/tomasferrer/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rspec-core-3.9.2/exe/rspec:4:in `<top (required)>'
# /Users/tomasferrer/.rbenv/versions/2.6.6/bin/rspec:23:in `load'
# /Users/tomasferrer/.rbenv/versions/2.6.6/bin/rspec:23:in `<top (required)>'
# /Users/tomasferrer/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/bundler-2.2.16/lib/bundler/cli/exec.rb:63:in `load'
# /Users/tomasferrer/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/bundler-2.2.16/lib/bundler/cli/exec.rb:63:in `kernel_load'
# /Users/tomasferrer/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/bundler-2.2.16/lib/bundler/cli/exec.rb:28:in `run'
# /Users/tomasferrer/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/bundler-2.2.16/lib/bundler/cli.rb:494:in `exec'
# /Users/tomasferrer/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/bundler-2.2.16/lib/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
# /Users/tomasferrer/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/bundler-2.2.16/lib/bundler/vendor/thor/lib/thor/invocation.rb:127:in `invoke_command'
# /Users/tomasferrer/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/bundler-2.2.16/lib/bundler/vendor/thor/lib/thor.rb:392:in `dispatch'
# /Users/tomasferrer/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/bundler-2.2.16/lib/bundler/cli.rb:30:in `dispatch'
# /Users/tomasferrer/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/bundler-2.2.16/lib/bundler/vendor/thor/lib/thor/base.rb:485:in `start'
# /Users/tomasferrer/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/bundler-2.2.16/lib/bundler/cli.rb:24:in `start'
# /Users/tomasferrer/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/bundler-2.2.16/exe/bundle:49:in `block in <top (required)>'
# /Users/tomasferrer/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/bundler-2.2.16/lib/bundler/friendly_errors.rb:130:in `with_friendly_errors'
# /Users/tomasferrer/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/bundler-2.2.16/exe/bundle:37:in `<top (required)>'
# /Users/tomasferrer/.rbenv/versions/2.6.6/bin/bundle:23:in `load'
# /Users/tomasferrer/.rbenv/versions/2.6.6/bin/bundle:23:in `<main>'
#
#   Showing full backtrace because every line was filtered out.
#   See docs for RSpec::Configuration#backtrace_exclusion_patterns and
#   RSpec::Configuration#backtrace_inclusion_patterns for more information.

Finished in 11.35 seconds (files took 5.53 seconds to load)
224 examples, 0 failures, 1 error occurred outside of examples

Randomized with seed 16947

Coverage report generated for RSpec to /Users/tomasferrer/order-entry-portal-ror/coverage. 675 / 868 LOC (77.76%) covered.
SimpleCov failed with exit 1

To Reproduce
Steps to reproduce the behavior:

  1. Create a POST endpoint that admits a file attachment
  2. Write an rspec tests for that endpoint and send a file with illegal UTF-8 characters
  3. See error

Expected behavior
This case should be handled especially considering all tests passed.

Screenshots
If applicable, add screenshots to help explain your problem.

Rails version: 6.0.3.2
Ruby version: 2.6.6
Fictium version: 0.4.1

Additional context
Analyzing the gem's method that fails when this happens by modifying it like this:

# lib/fictium/exporters/open_api/v3_exporter.rb
def export(document)
        result = DEFAULT_PROPERTIES
                 .merge(create_fixtures)
                 .merge(info: create_info, paths: create_paths(document))
        validate!(result)
        FileUtils.mkdir_p(File.dirname(export_file))
        File.write(export_file, pretty_print? ? JSON.pretty_generate(result) : result.to_json)
rescue
        byebug
end

It can be seen that the object
result[:paths]["/api/v1/orders"][:post][:requestBody][:content][:"multipart/form-data"][:example]
contains the following:

------------XnJLe9ZIbbGUYtzPQJ16u1\r\nContent-Disposition: form-data; name=\"order[file]\"; filename=\"image.jpeg\"\r\nContent-Type: image/jpeg\r\nContent-Length: 4724\r\n\r\n\xFF\xD8\xFF\xE0\u0000\u0010JFIF\u0000\u0001\u0001\u0000\u0000\u0001\u0000\u0001\u0000\u0000\xFF\xDB\u0000\x84\u0000\t\u0006\a\u0010\u000F\u0012\u0010\u000F\u0010\u0011\u0010\u0010\u0010\u0012\r\u000F\u000E\u0012\u0011\u000F\u0010\u0012\u000F\r\u0010\u0010\u0016\u0011\u0018\u0016\u0016\u0011\u0018\u0015\u0018\u001C) \u0019\u001A%\e\u0018\u0016!1#%)+...\u0018\u001F383-7(-.+\u0001\n\n\n\u000E\r\u000E\u001A\u0010\u0010\e+% %-.----0--5---.------------------------------------\xFF\xC0\u0000\u0011\b\u0000\xDF\u0000\xE2\u0003\u0001\u0011\u0000\u0002\u0011\u0001\u0003\u0011\u0001\xFF\xC4\u0000\e\u0000\u0001\u0000\u0002\u0003\u0001\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0006\a\u0001\u0004\u0005\u0003\u0002\xFF\xC4\u0000D\u0010\u0000\u0002\u0002\u0000\u0003\u0004\u0006\u0004\t\n\u0006\u0003\u0000\u0000\u0000\u0000\u0000\u0001\u0002\u0003\u0004\u0005\u0011\u0006\u0012!1\a\"AQa\x81\u0013q\x91\xB2#234RSs\x93\xD1\u0014\u0015\u0017Brt\x92\xA1\xC1\xE1%bc\xB1\xC2\xD2C\x82\xA2\xFF\xC4\u0000\u001A\u0001\u0001\u0000\u0002\u0003\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0004\u0005\u0001\u0003\u0006\u0002\xFF\xC4\u00002\u0011\u0001\u0000\u0002\u0001\u0002\u0004\u0005\u0002\u0005\u0003\u0005\u0001\u0000\u0000\u0000\u0000\u0000\u0001\u0002\u0003\u0004\u0011\u0005\u0012!1\u00132AQq\"3\u0014
...
\u0000\xFF\xD9\r\n------------XnJLe9ZIbbGUYtzPQJ16u1\r\nContent-Disposition: form-data; name=\"order[client_id]\"\r\n\r\n14\r\n------------XnJLe9ZIbbGUYtzPQJ16u1\r\nContent-Disposition: form-data; name=\"order[delivery_point_id]\"\r\n\r\n14\r\n------------XnJLe9ZIbbGUYtzPQJ16u1\r\nContent-Disposition: form-data; name=\"order[order_number]\"\r\n\r\n666-61-6228\r\n------------XnJLe9ZIbbGUYtzPQJ16u1\r\nContent-Disposition: form-data; name=\"order[comments]\"\r\n\r\nVoluptatum asperiores sit ratione dicta dolore rerum.\r\n------------XnJLe9ZIbbGUYtzPQJ16u1\r\nContent-Disposition: form-data; name=\"order[order_products_attributes][][quantity]\"\r\n\r\n412\r\n------------XnJLe9ZIbbGUYtzPQJ16u1\r\nContent-Disposition: form-data; name=\"order[order_products_attributes][][product_id]\"\r\n\r\n10\r\n------------XnJLe9ZIbbGUYtzPQJ16u1\r\nContent-Disposition: form-data; name=\"order[order_products_attributes][][quantity]\"\r\n\r\n409\r\n------------XnJLe9ZIbbGUYtzPQJ16u1\r\nContent-Disposition: form-data; name=\"order[order_products_attributes][][product_id]\"\r\n\r\n11\r\n------------XnJLe9ZIbbGUYtzPQJ16u1\r\nContent-Disposition: form-data; name=\"order[order_products_attributes][][quantity]\"\r\n\r\n231\r\n------------XnJLe9ZIbbGUYtzPQJ16u1\r\nContent-Disposition: form-data; name=\"order[order_products_attributes][][product_id]\"\r\n\r\n12\r\n------------XnJLe9ZIbbGUYtzPQJ16u1--\r"

As a result, the error occurs when attempting JSON.pretty_generate(result)

Supress Body Type when not present

Describe the bug

The body is added when empty on the operation object, we may ignore it instead.

To Reproduce
Steps to reproduce the behavior:

  • Any endpoint with a default example has this.

Expected behavior

When there isn't any body, it shouldn't add the requestBody object.

Rails version: any
Ruby version: any
Fictium version: 0.4.1

Additional context

It is required to modify the following line here

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.