webspicy 0.15.7 → 0.16.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +71 -24
- data/bin/webspicy +30 -14
- data/examples/restful/Gemfile +2 -2
- data/examples/restful/Gemfile.lock +53 -33
- data/examples/restful/Rakefile +0 -1
- data/examples/restful/app.rb +4 -1
- data/examples/restful/webspicy/config.rb +8 -0
- data/examples/restful/webspicy/rack.rb +1 -1
- data/examples/restful/webspicy/real.rb +1 -1
- data/examples/restful/webspicy/schema.fio +2 -2
- data/examples/restful/webspicy/support/must_be_authenticated.rb +2 -2
- data/examples/restful/webspicy/support/todo_removed.rb +18 -0
- data/examples/restful/webspicy/todo/deleteTodo.yml +4 -1
- data/examples/restful/webspicy/todo/getTodoSingleServiceFormat.yml +46 -0
- data/examples/restful/webspicy/todo/options.yml +1 -1
- data/examples/restful/webspicy/todo/patchTodo.yml +3 -0
- data/examples/restful/webspicy/todo/postFile.yml +1 -1
- data/examples/single_spec/spec.yml +59 -0
- data/examples/website/config.rb +2 -0
- data/examples/website/schema.fio +1 -0
- data/examples/website/specification/get-http.yml +30 -0
- data/examples/website/specification/get-https.yml +30 -0
- data/lib/finitio/webspicy/scalars.fio +25 -0
- data/lib/webspicy.rb +48 -17
- data/lib/webspicy/checker.rb +2 -2
- data/lib/webspicy/configuration.rb +70 -14
- data/lib/webspicy/configuration/scope.rb +162 -0
- data/lib/webspicy/configuration/single_url.rb +58 -0
- data/lib/webspicy/configuration/single_yml_file.rb +30 -0
- data/lib/webspicy/formaldoc.fio +23 -8
- data/lib/webspicy/mocker.rb +8 -8
- data/lib/webspicy/mocker/config.ru +5 -0
- data/lib/webspicy/openapi.rb +1 -0
- data/lib/webspicy/openapi/generator.rb +127 -0
- data/lib/webspicy/{resource.rb → specification.rb} +28 -5
- data/lib/webspicy/specification/file_upload.rb +37 -0
- data/lib/webspicy/specification/postcondition.rb +16 -0
- data/lib/webspicy/specification/precondition.rb +19 -0
- data/lib/webspicy/specification/precondition/global_request_headers.rb +35 -0
- data/lib/webspicy/specification/precondition/robust_to_invalid_input.rb +68 -0
- data/lib/webspicy/{resource → specification}/service.rb +11 -6
- data/lib/webspicy/specification/test_case.rb +139 -0
- data/lib/webspicy/support.rb +1 -0
- data/lib/webspicy/support/colorize.rb +28 -0
- data/lib/webspicy/support/status_range.rb +6 -1
- data/lib/webspicy/tester.rb +16 -11
- data/lib/webspicy/tester/asserter.rb +3 -2
- data/lib/webspicy/tester/assertions.rb +5 -1
- data/lib/webspicy/tester/client.rb +63 -0
- data/lib/webspicy/tester/client/http_client.rb +154 -0
- data/lib/webspicy/tester/client/rack_test_client.rb +188 -0
- data/lib/webspicy/tester/client/support.rb +65 -0
- data/lib/webspicy/tester/invocation.rb +218 -0
- data/lib/webspicy/tester/rspec_asserter.rb +108 -0
- data/lib/webspicy/tester/rspec_matchers.rb +104 -0
- data/lib/webspicy/version.rb +2 -2
- data/spec/{unit/spec_helper.rb → spec_helper.rb} +0 -0
- data/spec/unit/configuration/scope/test_each_service.rb +49 -0
- data/spec/unit/configuration/scope/test_each_specification.rb +68 -0
- data/spec/unit/configuration/scope/test_expand_example.rb +65 -0
- data/spec/unit/configuration/scope/test_to_real_url.rb +82 -0
- data/spec/unit/openapi/test_generator.rb +28 -0
- data/spec/unit/specification/precondition/test_global_request_headers.rb +42 -0
- data/spec/unit/{resource → specification}/service/test_dress_params.rb +2 -2
- data/spec/unit/specification/test_case/test_mutate.rb +24 -0
- data/spec/unit/{resource → specification}/test_instantiate_url.rb +5 -5
- data/spec/unit/{resource → specification}/test_url_placeholders.rb +4 -4
- data/spec/unit/test_configuration.rb +24 -7
- data/spec/unit/tester/client/test_around.rb +61 -0
- data/spec/unit/tester/test_asserter.rb +51 -0
- data/spec/unit/tester/test_assertions.rb +4 -4
- data/tasks/test.rake +3 -1
- metadata +88 -45
- data/LICENSE.md +0 -22
- data/lib/webspicy/client.rb +0 -61
- data/lib/webspicy/client/http_client.rb +0 -145
- data/lib/webspicy/client/rack_test_client.rb +0 -181
- data/lib/webspicy/client/support.rb +0 -48
- data/lib/webspicy/file_upload.rb +0 -35
- data/lib/webspicy/postcondition.rb +0 -14
- data/lib/webspicy/precondition.rb +0 -15
- data/lib/webspicy/resource/service/invocation.rb +0 -212
- data/lib/webspicy/resource/service/test_case.rb +0 -132
- data/lib/webspicy/scope.rb +0 -160
- data/spec/unit/client/test_around.rb +0 -59
- data/spec/unit/scope/test_each_resource.rb +0 -66
- data/spec/unit/scope/test_each_service.rb +0 -47
- data/spec/unit/scope/test_expand_example.rb +0 -63
- data/spec/unit/scope/test_to_real_url.rb +0 -80
data/lib/webspicy/version.rb
CHANGED
File without changes
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Webspicy
|
3
|
+
class Configuration
|
4
|
+
describe Scope, 'each_service' do
|
5
|
+
|
6
|
+
let(:scope) {
|
7
|
+
Scope.new(configuration)
|
8
|
+
}
|
9
|
+
|
10
|
+
let(:specification) {
|
11
|
+
scope.each_specification.first
|
12
|
+
}
|
13
|
+
|
14
|
+
subject {
|
15
|
+
scope.each_service(specification).to_a
|
16
|
+
}
|
17
|
+
|
18
|
+
context 'without any filter' do
|
19
|
+
|
20
|
+
let(:configuration) {
|
21
|
+
Configuration.new(restful_folder){|c|
|
22
|
+
c.file_filter = /getTodo.yml/
|
23
|
+
}
|
24
|
+
}
|
25
|
+
|
26
|
+
it 'returns all services' do
|
27
|
+
expect(subject.size).to eql(1)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'with a service filter as a proc' do
|
32
|
+
|
33
|
+
let(:configuration) {
|
34
|
+
Configuration.new(restful_folder){|c|
|
35
|
+
c.file_filter = /getTodo.yml/
|
36
|
+
c.service_filter = ->(s) {
|
37
|
+
s.method == "POST"
|
38
|
+
}
|
39
|
+
}
|
40
|
+
}
|
41
|
+
|
42
|
+
it 'returns nothing' do
|
43
|
+
expect(subject.size).to eql(0)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Webspicy
|
3
|
+
class Configuration
|
4
|
+
describe Scope, 'each_specification' do
|
5
|
+
|
6
|
+
let(:scope) {
|
7
|
+
Scope.new(configuration)
|
8
|
+
}
|
9
|
+
|
10
|
+
subject {
|
11
|
+
scope.each_specification.to_a
|
12
|
+
}
|
13
|
+
|
14
|
+
context 'without any filter' do
|
15
|
+
|
16
|
+
let(:configuration) {
|
17
|
+
Configuration.new(restful_folder)
|
18
|
+
}
|
19
|
+
|
20
|
+
it 'returns all files' do
|
21
|
+
expect(subject.size).to eql(restful_folder.glob('**/*.yml').size)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'with a file filter as a proc' do
|
26
|
+
|
27
|
+
let(:configuration) {
|
28
|
+
Configuration.new(restful_folder){|c|
|
29
|
+
c.file_filter = ->(f) {
|
30
|
+
f.basename.to_s == "getTodo.yml"
|
31
|
+
}
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
35
|
+
it 'returns only that file' do
|
36
|
+
expect(subject.size).to eql(1)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context 'with a file filter as a Regex' do
|
41
|
+
|
42
|
+
let(:configuration) {
|
43
|
+
Configuration.new(restful_folder){|c|
|
44
|
+
c.file_filter = /getTodo.yml/
|
45
|
+
}
|
46
|
+
}
|
47
|
+
|
48
|
+
it 'returns only that file' do
|
49
|
+
expect(subject.size).to eql(1)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'when having children folders' do
|
54
|
+
|
55
|
+
let(:configuration) {
|
56
|
+
Configuration.new(restful_folder) do |c|
|
57
|
+
c.folder 'todo'
|
58
|
+
end
|
59
|
+
}
|
60
|
+
|
61
|
+
it 'returns all files' do
|
62
|
+
expect(subject.size).to eql(restful_folder.glob('**/*.yml').size)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Webspicy
|
3
|
+
class Configuration
|
4
|
+
describe Scope, "expand_example" do
|
5
|
+
|
6
|
+
subject{ Scope.new({}).send(:expand_example, service, example) }
|
7
|
+
|
8
|
+
context 'when the service has no default example' do
|
9
|
+
let(:service) {
|
10
|
+
Webspicy.service({
|
11
|
+
method: "GET",
|
12
|
+
description: "Test service",
|
13
|
+
preconditions: "Foo",
|
14
|
+
input_schema: "{ id: Integer }",
|
15
|
+
output_schema: "{}",
|
16
|
+
error_schema: "{}"
|
17
|
+
})
|
18
|
+
}
|
19
|
+
|
20
|
+
let(:example) {
|
21
|
+
Webspicy.test_case({
|
22
|
+
description: "Hello world"
|
23
|
+
})
|
24
|
+
}
|
25
|
+
|
26
|
+
it 'returns the example itself' do
|
27
|
+
expect(subject).to be(example)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'when the service has a default example' do
|
32
|
+
let(:service) {
|
33
|
+
Webspicy.service({
|
34
|
+
method: "GET",
|
35
|
+
description: "Test service",
|
36
|
+
preconditions: "Foo",
|
37
|
+
input_schema: "{ id: Integer }",
|
38
|
+
output_schema: "{}",
|
39
|
+
error_schema: "{}",
|
40
|
+
default_example: {
|
41
|
+
expected: { status: 200 }
|
42
|
+
}
|
43
|
+
})
|
44
|
+
}
|
45
|
+
|
46
|
+
let(:example) {
|
47
|
+
Webspicy.test_case({
|
48
|
+
description: "Hello world",
|
49
|
+
expected: { content_type: "application/json" }
|
50
|
+
})
|
51
|
+
}
|
52
|
+
|
53
|
+
it 'deep merges the default example and the example as expected' do
|
54
|
+
expect(subject).to be_a(Specification::TestCase)
|
55
|
+
expect(subject.description).to eql("Hello world")
|
56
|
+
expect(subject.expected).to eql({
|
57
|
+
status: Support::StatusRange.int(200),
|
58
|
+
content_type: "application/json"
|
59
|
+
})
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Webspicy
|
3
|
+
class Configuration
|
4
|
+
describe Scope, 'to_real_url' do
|
5
|
+
|
6
|
+
let(:scope) {
|
7
|
+
Scope.new(configuration)
|
8
|
+
}
|
9
|
+
|
10
|
+
context 'when no host at all' do
|
11
|
+
|
12
|
+
let(:configuration) {
|
13
|
+
Configuration.new
|
14
|
+
}
|
15
|
+
|
16
|
+
it 'does nothing on absolute URLs already' do
|
17
|
+
url = 'http://127.0.0.1:4567/todo'
|
18
|
+
got = scope.to_real_url(url)
|
19
|
+
expect(got).to eql(url)
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'yields the block relative URLs' do
|
23
|
+
got = scope.to_real_url("/todo"){ "hello" }
|
24
|
+
expect(got).to eql("hello")
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'fails on relative URLs and no block is given' do
|
28
|
+
expect(->(){
|
29
|
+
scope.to_real_url("/todo")
|
30
|
+
}).to raise_error(/Unable to resolve `\/todo`/)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'with a static host' do
|
35
|
+
|
36
|
+
let(:configuration) {
|
37
|
+
Configuration.new do |c|
|
38
|
+
c.host = "http://127.0.0.1:4568"
|
39
|
+
end
|
40
|
+
}
|
41
|
+
|
42
|
+
it 'does nothing on absolute URLs already' do
|
43
|
+
url = 'http://127.0.0.1:4567/todo'
|
44
|
+
got = scope.to_real_url(url)
|
45
|
+
expect(got).to eql(url)
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'resolves relative URLs as expected' do
|
49
|
+
url = '/todo'
|
50
|
+
got = scope.to_real_url(url)
|
51
|
+
expect(got).to eql("http://127.0.0.1:4568/todo")
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
context 'with a dynamic host resolver' do
|
57
|
+
|
58
|
+
let(:configuration) {
|
59
|
+
Configuration.new do |c|
|
60
|
+
c.host = ->(url, tc) {
|
61
|
+
"http://127.0.0.1:4568#{url}"
|
62
|
+
}
|
63
|
+
end
|
64
|
+
}
|
65
|
+
|
66
|
+
it 'resolves absolute URLs' do
|
67
|
+
url = 'http://127.0.0.1:4567/todo'
|
68
|
+
got = scope.to_real_url(url)
|
69
|
+
expect(got).to eql("http://127.0.0.1:4568#{url}")
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'resolves relative URLs as expected' do
|
73
|
+
url = '/todo'
|
74
|
+
got = scope.to_real_url(url)
|
75
|
+
expect(got).to eql("http://127.0.0.1:4568/todo")
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'webspicy/openapi'
|
3
|
+
require 'openapi3_parser'
|
4
|
+
module Webspicy
|
5
|
+
module Openapi
|
6
|
+
describe Generator do
|
7
|
+
|
8
|
+
let(:config) {
|
9
|
+
Configuration.new(restful_folder)
|
10
|
+
}
|
11
|
+
|
12
|
+
subject {
|
13
|
+
ruby_objs = Generator.new(config).call
|
14
|
+
JSON.parse(ruby_objs.to_json)
|
15
|
+
}
|
16
|
+
|
17
|
+
it 'works fine' do
|
18
|
+
document = Openapi3Parser.load(subject)
|
19
|
+
#puts JSON.pretty_generate(subject)
|
20
|
+
document.errors.each do |err|
|
21
|
+
puts err.inspect
|
22
|
+
end unless document.errors.empty?
|
23
|
+
expect(document.errors).to be_empty
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Webspicy
|
4
|
+
class Specification
|
5
|
+
module Precondition
|
6
|
+
describe GlobalRequestHeaders do
|
7
|
+
let(:gbr){
|
8
|
+
GlobalRequestHeaders.new('Accept' => 'application/json')
|
9
|
+
}
|
10
|
+
|
11
|
+
describe "instrument" do
|
12
|
+
it 'injects the headers' do
|
13
|
+
tc = TestCase.new({})
|
14
|
+
gbr.instrument(tc, nil)
|
15
|
+
expect(tc.headers['Accept']).to eql("application/json")
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'keeps original headers unchanged' do
|
19
|
+
tc = TestCase.new({
|
20
|
+
headers: {
|
21
|
+
'Content-Type' => 'text/plain'
|
22
|
+
}
|
23
|
+
})
|
24
|
+
gbr.instrument(tc, nil)
|
25
|
+
expect(tc.headers['Content-Type']).to eql("text/plain")
|
26
|
+
expect(tc.headers['Accept']).to eql("application/json")
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'has low precedence' do
|
30
|
+
tc = TestCase.new({
|
31
|
+
headers: {
|
32
|
+
'Accept' => 'text/plain'
|
33
|
+
}
|
34
|
+
})
|
35
|
+
gbr.instrument(tc, nil)
|
36
|
+
expect(tc.headers['Accept']).to eql("text/plain")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
module Webspicy
|
3
|
-
class
|
3
|
+
class Specification
|
4
4
|
describe Service, "dress_params" do
|
5
5
|
|
6
6
|
it 'symbolizes keys' do
|
@@ -30,5 +30,5 @@ module Webspicy
|
|
30
30
|
end
|
31
31
|
|
32
32
|
end
|
33
|
-
end # class
|
33
|
+
end # class Specification
|
34
34
|
end # module Webspicy
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
module Webspicy
|
3
|
+
class Specification
|
4
|
+
describe TestCase, "mutate" do
|
5
|
+
|
6
|
+
it 'helps easily creating a new test by mutation' do
|
7
|
+
tc = TestCase.new({
|
8
|
+
:params => {
|
9
|
+
"id" => 1
|
10
|
+
}
|
11
|
+
})
|
12
|
+
tc2 = tc.mutate({
|
13
|
+
:params => {
|
14
|
+
"id" => 2
|
15
|
+
}
|
16
|
+
})
|
17
|
+
expect(tc2).to be_a(TestCase)
|
18
|
+
expect(tc.params["id"]).to eql(1)
|
19
|
+
expect(tc2.params["id"]).to eql(2)
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -1,30 +1,30 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
module Webspicy
|
3
|
-
describe
|
3
|
+
describe Specification, "instantiate_url" do
|
4
4
|
|
5
5
|
it 'does nothing when the url has no placeholder' do
|
6
|
-
r =
|
6
|
+
r = Specification.new(url: "/test/a/url")
|
7
7
|
url, params = r.instantiate_url(foo: "bar")
|
8
8
|
expect(url).to eq("/test/a/url")
|
9
9
|
expect(params).to eq(foo: "bar")
|
10
10
|
end
|
11
11
|
|
12
12
|
it 'instantiates placeholders and strips corresponding params' do
|
13
|
-
r =
|
13
|
+
r = Specification.new(url: "/test/{foo}/url")
|
14
14
|
url, params = r.instantiate_url(foo: "bar", baz: "coz")
|
15
15
|
expect(url).to eq("/test/bar/url")
|
16
16
|
expect(params).to eq(baz: "coz")
|
17
17
|
end
|
18
18
|
|
19
19
|
it 'instantiates placeholders and strips corresponding params even when multiple' do
|
20
|
-
r =
|
20
|
+
r = Specification.new(url: "/test/{foo}/url/{bar}")
|
21
21
|
url, params = r.instantiate_url(foo: "bar", bar: "baz", baz: "coz")
|
22
22
|
expect(url).to eq("/test/bar/url/baz")
|
23
23
|
expect(params).to eq(baz: "coz")
|
24
24
|
end
|
25
25
|
|
26
26
|
it 'supports placeholders corresponding to subentities' do
|
27
|
-
r =
|
27
|
+
r = Specification.new(url: "/test/{foo.id}/url")
|
28
28
|
url, params = r.instantiate_url(foo: {id: "bar"}, baz: "coz")
|
29
29
|
expect(url).to eq("/test/bar/url")
|
30
30
|
expect(params).to eq(foo: {}, baz: "coz")
|
@@ -1,19 +1,19 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
module Webspicy
|
3
|
-
describe
|
3
|
+
describe Specification, "url_placeholders" do
|
4
4
|
|
5
5
|
it 'returns an empty array on none' do
|
6
|
-
r =
|
6
|
+
r = Specification.new(url: "/test/a/url")
|
7
7
|
expect(r.url_placeholders).to eq([])
|
8
8
|
end
|
9
9
|
|
10
10
|
it 'returns all placeholders' do
|
11
|
-
r =
|
11
|
+
r = Specification.new(url: "/test/{foo}/url/{bar}")
|
12
12
|
expect(r.url_placeholders).to eq(["foo", "bar"])
|
13
13
|
end
|
14
14
|
|
15
15
|
it 'returns all placeholders expr' do
|
16
|
-
r =
|
16
|
+
r = Specification.new(url: "/test/{foo.id}/url/{bar}")
|
17
17
|
expect(r.url_placeholders).to eq(["foo.id", "bar"])
|
18
18
|
end
|
19
19
|
|