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.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +71 -24
  3. data/bin/webspicy +30 -14
  4. data/examples/restful/Gemfile +2 -2
  5. data/examples/restful/Gemfile.lock +53 -33
  6. data/examples/restful/Rakefile +0 -1
  7. data/examples/restful/app.rb +4 -1
  8. data/examples/restful/webspicy/config.rb +8 -0
  9. data/examples/restful/webspicy/rack.rb +1 -1
  10. data/examples/restful/webspicy/real.rb +1 -1
  11. data/examples/restful/webspicy/schema.fio +2 -2
  12. data/examples/restful/webspicy/support/must_be_authenticated.rb +2 -2
  13. data/examples/restful/webspicy/support/todo_removed.rb +18 -0
  14. data/examples/restful/webspicy/todo/deleteTodo.yml +4 -1
  15. data/examples/restful/webspicy/todo/getTodoSingleServiceFormat.yml +46 -0
  16. data/examples/restful/webspicy/todo/options.yml +1 -1
  17. data/examples/restful/webspicy/todo/patchTodo.yml +3 -0
  18. data/examples/restful/webspicy/todo/postFile.yml +1 -1
  19. data/examples/single_spec/spec.yml +59 -0
  20. data/examples/website/config.rb +2 -0
  21. data/examples/website/schema.fio +1 -0
  22. data/examples/website/specification/get-http.yml +30 -0
  23. data/examples/website/specification/get-https.yml +30 -0
  24. data/lib/finitio/webspicy/scalars.fio +25 -0
  25. data/lib/webspicy.rb +48 -17
  26. data/lib/webspicy/checker.rb +2 -2
  27. data/lib/webspicy/configuration.rb +70 -14
  28. data/lib/webspicy/configuration/scope.rb +162 -0
  29. data/lib/webspicy/configuration/single_url.rb +58 -0
  30. data/lib/webspicy/configuration/single_yml_file.rb +30 -0
  31. data/lib/webspicy/formaldoc.fio +23 -8
  32. data/lib/webspicy/mocker.rb +8 -8
  33. data/lib/webspicy/mocker/config.ru +5 -0
  34. data/lib/webspicy/openapi.rb +1 -0
  35. data/lib/webspicy/openapi/generator.rb +127 -0
  36. data/lib/webspicy/{resource.rb → specification.rb} +28 -5
  37. data/lib/webspicy/specification/file_upload.rb +37 -0
  38. data/lib/webspicy/specification/postcondition.rb +16 -0
  39. data/lib/webspicy/specification/precondition.rb +19 -0
  40. data/lib/webspicy/specification/precondition/global_request_headers.rb +35 -0
  41. data/lib/webspicy/specification/precondition/robust_to_invalid_input.rb +68 -0
  42. data/lib/webspicy/{resource → specification}/service.rb +11 -6
  43. data/lib/webspicy/specification/test_case.rb +139 -0
  44. data/lib/webspicy/support.rb +1 -0
  45. data/lib/webspicy/support/colorize.rb +28 -0
  46. data/lib/webspicy/support/status_range.rb +6 -1
  47. data/lib/webspicy/tester.rb +16 -11
  48. data/lib/webspicy/tester/asserter.rb +3 -2
  49. data/lib/webspicy/tester/assertions.rb +5 -1
  50. data/lib/webspicy/tester/client.rb +63 -0
  51. data/lib/webspicy/tester/client/http_client.rb +154 -0
  52. data/lib/webspicy/tester/client/rack_test_client.rb +188 -0
  53. data/lib/webspicy/tester/client/support.rb +65 -0
  54. data/lib/webspicy/tester/invocation.rb +218 -0
  55. data/lib/webspicy/tester/rspec_asserter.rb +108 -0
  56. data/lib/webspicy/tester/rspec_matchers.rb +104 -0
  57. data/lib/webspicy/version.rb +2 -2
  58. data/spec/{unit/spec_helper.rb → spec_helper.rb} +0 -0
  59. data/spec/unit/configuration/scope/test_each_service.rb +49 -0
  60. data/spec/unit/configuration/scope/test_each_specification.rb +68 -0
  61. data/spec/unit/configuration/scope/test_expand_example.rb +65 -0
  62. data/spec/unit/configuration/scope/test_to_real_url.rb +82 -0
  63. data/spec/unit/openapi/test_generator.rb +28 -0
  64. data/spec/unit/specification/precondition/test_global_request_headers.rb +42 -0
  65. data/spec/unit/{resource → specification}/service/test_dress_params.rb +2 -2
  66. data/spec/unit/specification/test_case/test_mutate.rb +24 -0
  67. data/spec/unit/{resource → specification}/test_instantiate_url.rb +5 -5
  68. data/spec/unit/{resource → specification}/test_url_placeholders.rb +4 -4
  69. data/spec/unit/test_configuration.rb +24 -7
  70. data/spec/unit/tester/client/test_around.rb +61 -0
  71. data/spec/unit/tester/test_asserter.rb +51 -0
  72. data/spec/unit/tester/test_assertions.rb +4 -4
  73. data/tasks/test.rake +3 -1
  74. metadata +88 -45
  75. data/LICENSE.md +0 -22
  76. data/lib/webspicy/client.rb +0 -61
  77. data/lib/webspicy/client/http_client.rb +0 -145
  78. data/lib/webspicy/client/rack_test_client.rb +0 -181
  79. data/lib/webspicy/client/support.rb +0 -48
  80. data/lib/webspicy/file_upload.rb +0 -35
  81. data/lib/webspicy/postcondition.rb +0 -14
  82. data/lib/webspicy/precondition.rb +0 -15
  83. data/lib/webspicy/resource/service/invocation.rb +0 -212
  84. data/lib/webspicy/resource/service/test_case.rb +0 -132
  85. data/lib/webspicy/scope.rb +0 -160
  86. data/spec/unit/client/test_around.rb +0 -59
  87. data/spec/unit/scope/test_each_resource.rb +0 -66
  88. data/spec/unit/scope/test_each_service.rb +0 -47
  89. data/spec/unit/scope/test_expand_example.rb +0 -63
  90. data/spec/unit/scope/test_to_real_url.rb +0 -80
@@ -1,8 +1,8 @@
1
1
  module Webspicy
2
2
  module Version
3
3
  MAJOR = 0
4
- MINOR = 15
5
- TINY = 7
4
+ MINOR = 16
5
+ TINY = 3
6
6
  end
7
7
  VERSION = "#{Version::MAJOR}.#{Version::MINOR}.#{Version::TINY}"
8
8
  end
@@ -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 Resource
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 Resource
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 Resource, "instantiate_url" do
3
+ describe Specification, "instantiate_url" do
4
4
 
5
5
  it 'does nothing when the url has no placeholder' do
6
- r = Resource.new(url: "/test/a/url")
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 = Resource.new(url: "/test/{foo}/url")
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 = Resource.new(url: "/test/{foo}/url/{bar}")
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 = Resource.new(url: "/test/{foo.id}/url")
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 Resource, "url_placeholders" do
3
+ describe Specification, "url_placeholders" do
4
4
 
5
5
  it 'returns an empty array on none' do
6
- r = Resource.new(url: "/test/a/url")
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 = Resource.new(url: "/test/{foo}/url/{bar}")
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 = Resource.new(url: "/test/{foo.id}/url/{bar}")
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