Skip to content

Commit

Permalink
Ignores possible version segments in path. (#37)
Browse files Browse the repository at this point in the history
  • Loading branch information
LeFnord authored Aug 31, 2023
1 parent d83eb52 commit 513dc7b
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 22 deletions.
2 changes: 1 addition & 1 deletion lib/starter/import.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def load_spec(path)
JSON.load_file(path)
end

Importer::Specification.new(spec)
Importer::Specification.new(spec:)
end

def create_files_from(spec)
Expand Down
25 changes: 15 additions & 10 deletions lib/starter/importer/specification.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,25 @@ class Error < StandardError; end
attr_accessor :openapi, :info,
:paths, :components, :webhooks

def initialize(raw)
def initialize(spec:)
# mandatory
@openapi = raw.fetch('openapi')
@info = raw.fetch('info')
@openapi = spec.fetch('openapi')
@info = spec.fetch('info')

# in contrast to the spec, paths are required
@paths = raw.fetch('paths').except('/').sort.to_h
@paths = spec.fetch('paths').except('/').sort.to_h

# optional -> not used atm
@components = raw.fetch('components', false)
@webhooks = raw.fetch('webhooks', false)
@components = spec.fetch('components', false)
@webhooks = spec.fetch('webhooks', false)
end

def namespaces
validate_paths

@namespaces ||= paths.keys.each_with_object({}) do |path, memo|
segments = path.split('/').delete_if(&:empty?)
namespace = segments.shift
rest_path = "/#{segments.join('/')}"
namespace, rest_path = segmentize(path)

# TODO: build additional stuff from `paths[path]`
memo[namespace] ||= {}
memo[namespace][rest_path] = prepare_verbs(paths[path])
end
Expand All @@ -42,6 +39,14 @@ def validate_paths
raise Error, 'only template given' if paths.keys.one? && paths.keys.first.match?(%r{/\{\w*\}})
end

def segmentize(path)
segments = path.split('/').delete_if(&:empty?)
ignore = segments.take_while { |x| x =~ /(v)*(\.\d)+/ || x =~ /(v\d)+/ || x == 'api' }
rest = segments - ignore

[rest.shift, rest.empty? ? '/' : "/#{rest.join('/')}"]
end

def prepare_verbs(spec)
path_params = nil
spec.each_with_object({}) do |(verb, content), memo|
Expand Down
14 changes: 7 additions & 7 deletions spec/lib/import_spec.rb
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
# frozen_string_literal: false

RSpec.describe Starter::Import do
describe '.do_it!' do
let(:path) { './spec/fixtures/links.json' }
# describe '.do_it!' do
# let(:path) { './spec/fixtures/links.json' }

subject { described_class.do_it!(path) }
# subject { described_class.do_it!(path) }

specify do
subject
end
end
# specify do
# subject
# end
# end

describe '.load_spec' do
subject { described_class.load_spec(path) }
Expand Down
100 changes: 96 additions & 4 deletions spec/lib/importer/specification_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
JSON.load_file('./spec/fixtures/tictactoe.json')
end

subject { described_class.new(spec) }
subject { described_class.new(spec:) }

describe 'mandatory attributes' do
specify do
Expand Down Expand Up @@ -67,7 +67,7 @@
end

describe '#namespaces' do
subject { described_class.new(spec).namespaces }
subject { described_class.new(spec:).namespaces }

describe 'paths empty -> valid, but senseless' do
let(:spec) do
Expand Down Expand Up @@ -130,18 +130,110 @@

describe 'unusual endpoints' do
let(:spec) do
default_specification[:paths] = { '/' => {}, '/2.0/{c}' => {}, '/a-c' => {}, '/2.0/u' => {} }
default_specification[:paths] = { '/' => {}, '/u/{c}' => {}, '/a-c' => {}, '/u' => {} }
default_specification.deep_stringify_keys
end

specify do
expect(subject).to eql(
{
'2.0' => { '/u' => {}, '/{c}' => {} },
'u' => { '/' => {}, '/{c}' => {} },
'a-c' => { '/' => {} }
}
)
end
end

describe 'ignores possible versioning' do
let(:spec) do
default_specification[:paths] = {
'/' => {},
'/2.0/a' => {},
'/2.0/a/{c}' => {},
'/v3/b' => {},
'/v3/b/{c}' => {},
'/api/v3/c' => {},
'/api/v3/c/{c}' => {},
'/api/v3.1/d' => {},
'/api/v3.1/d/{c}' => {}
}
default_specification.deep_stringify_keys
end

specify do
expect(subject).to eql(
{
'a' => { '/' => {}, '/{c}' => {} },
'b' => { '/' => {}, '/{c}' => {} },
'c' => { '/' => {}, '/{c}' => {} },
'd' => { '/' => {}, '/{c}' => {} }
}
)
end
end
end

describe '#segmentizen' do
let(:spec) do
default_specification.deep_stringify_keys
end

subject { described_class.new(spec:).send(:segmentize, path) }

describe '/2.0/a' do
let(:path) { '/2.0/a' }
specify do
expect(subject).to match_array ['a', '/']
end
end

describe '/2.0/a/{c}' do
let(:path) { '/2.0/a/{c}' }
specify do
expect(subject).to match_array ['a', '/{c}']
end
end

describe '/v3/b' do
let(:path) { '/v3/b' }
specify do
expect(subject).to match_array ['b', '/']
end
end

describe '/v3/b/{c}' do
let(:path) { '/v3/b/{c}' }
specify do
expect(subject).to match_array ['b', '/{c}']
end
end

describe '/api/v3/c' do
let(:path) { '/api/v3/c' }
specify do
expect(subject).to match_array ['c', '/']
end
end

describe '/api/v3/c/{c}' do
let(:path) { '/api/v3/c/{c}' }
specify do
expect(subject).to match_array ['c', '/{c}']
end
end

describe '/api/v3.1/c' do
let(:path) { '/api/v3/c' }
specify do
expect(subject).to match_array ['c', '/']
end
end

describe '/api/v3.1/c/{c}' do
let(:path) { '/api/v3/c/{c}' }
specify do
expect(subject).to match_array ['c', '/{c}']
end
end
end
end

0 comments on commit 513dc7b

Please sign in to comment.