webspicy 0.20.4 → 0.20.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/webspicy +2 -2
- data/lib/finitio/webspicy/shared.fio +10 -0
- data/lib/webspicy.rb +22 -53
- data/lib/webspicy/configuration.rb +3 -1
- data/lib/webspicy/configuration/scope.rb +2 -2
- data/lib/webspicy/configuration/single_url.rb +35 -25
- data/lib/webspicy/configuration/single_yml_file.rb +7 -2
- data/lib/webspicy/specification.rb +5 -56
- data/lib/webspicy/specification/service.rb +1 -5
- data/lib/webspicy/specification/test_case.rb +0 -49
- data/lib/webspicy/support/colorize.rb +1 -1
- data/lib/webspicy/tester.rb +5 -3
- data/lib/webspicy/tester/fakesmtp.rb +1 -1
- data/lib/webspicy/tester/fakesmtp/email.rb +13 -0
- data/lib/webspicy/tester/file_checker.rb +1 -1
- data/lib/webspicy/tester/reporter.rb +2 -1
- data/lib/webspicy/tester/reporter/documentation.rb +11 -5
- data/lib/webspicy/tester/reporter/exceptions.rb +3 -1
- data/lib/webspicy/tester/reporter/junit_xml_file.rb +151 -0
- data/lib/webspicy/tester/reporter/progress.rb +1 -1
- data/lib/webspicy/tester/reporter/success_or_not.rb +14 -0
- data/lib/webspicy/tester/reporter/summary.rb +6 -2
- data/lib/webspicy/tester/result.rb +1 -0
- data/lib/webspicy/version.rb +1 -1
- data/lib/webspicy/web.rb +46 -0
- data/lib/webspicy/{formaldoc.fio → web/formaldoc.fio} +5 -13
- data/lib/webspicy/web/specification.rb +68 -0
- data/lib/webspicy/web/specification/file_upload.rb +39 -0
- data/lib/webspicy/web/specification/service.rb +13 -0
- data/lib/webspicy/web/specification/test_case.rb +58 -0
- data/spec/unit/configuration/scope/test_expand_example.rb +11 -5
- data/spec/unit/specification/pre/test_global_request_headers.rb +3 -3
- data/spec/unit/specification/service/test_dress_params.rb +2 -2
- data/spec/unit/test_configuration.rb +1 -0
- data/spec/unit/tester/fakesmtp/test_email.rb +93 -0
- data/spec/unit/web/specification/test_instantiate_url.rb +36 -0
- data/spec/unit/web/specification/test_url_placeholders.rb +23 -0
- data/tasks/test.rake +5 -1
- metadata +40 -23
- data/lib/webspicy/specification/file_upload.rb +0 -37
- data/lib/webspicy/tester/reporter/error_count.rb +0 -29
- data/spec/blackbox/commandline.yml +0 -24
- data/spec/blackbox/fixtures/passing/config.rb +0 -9
- data/spec/blackbox/fixtures/passing/formaldef/get.yml +0 -30
- data/spec/unit/specification/test_instantiate_url.rb +0 -34
- data/spec/unit/specification/test_url_placeholders.rb +0 -21
@@ -0,0 +1,68 @@
|
|
1
|
+
module Webspicy
|
2
|
+
module Web
|
3
|
+
class Specification < Webspicy::Specification
|
4
|
+
|
5
|
+
class << self
|
6
|
+
def info(raw)
|
7
|
+
new(raw)
|
8
|
+
end
|
9
|
+
|
10
|
+
def singleservice(raw)
|
11
|
+
converted = {
|
12
|
+
name: raw[:name],
|
13
|
+
url: raw[:url],
|
14
|
+
services: [
|
15
|
+
Webspicy::Web.service(raw.reject{|k| k==:url or k==:name }, Webspicy.current_scope)
|
16
|
+
]
|
17
|
+
}
|
18
|
+
info(converted)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def url
|
23
|
+
@raw[:url]
|
24
|
+
end
|
25
|
+
|
26
|
+
def url_pattern
|
27
|
+
@url_pattern ||= Mustermann.new(url, type: :template)
|
28
|
+
end
|
29
|
+
|
30
|
+
def url_placeholders
|
31
|
+
url.scan(/\{([a-zA-Z]+(\.[a-zA-Z]+)*)\}/).map{|x| x.first }
|
32
|
+
end
|
33
|
+
|
34
|
+
def instantiate_url(params)
|
35
|
+
url, rest = self.url, params.dup
|
36
|
+
url_placeholders.each do |placeholder|
|
37
|
+
value, rest = extract_placeholder_value(rest, placeholder)
|
38
|
+
url = url.gsub("{#{placeholder}}", value.to_s)
|
39
|
+
end
|
40
|
+
[ url, rest ]
|
41
|
+
end
|
42
|
+
|
43
|
+
def to_singleservice
|
44
|
+
raise NotImplementedError
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def extract_placeholder_value(params, placeholder, split = nil)
|
50
|
+
return extract_placeholder_value(params, placeholder, placeholder.split(".")) unless split
|
51
|
+
|
52
|
+
key = [ split.first, split.first.to_sym ].find{|k| params.has_key?(k) }
|
53
|
+
raise "Missing URL parameter `#{placeholder}`" unless key
|
54
|
+
|
55
|
+
if split.size == 1
|
56
|
+
[ params[key], params.dup.delete_if{|k| k == key } ]
|
57
|
+
else
|
58
|
+
value, rest = extract_placeholder_value(params[key], placeholder, split[1..-1])
|
59
|
+
[ value, params.merge(key => rest) ]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
end # class Specification
|
64
|
+
end # module Web
|
65
|
+
end # module Webspicy
|
66
|
+
require_relative 'specification/service'
|
67
|
+
require_relative 'specification/test_case'
|
68
|
+
require_relative 'specification/file_upload'
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Webspicy
|
2
|
+
module Web
|
3
|
+
class Specification
|
4
|
+
class FileUpload
|
5
|
+
|
6
|
+
def initialize(raw)
|
7
|
+
@path = raw[:path]
|
8
|
+
@content_type = raw[:content_type]
|
9
|
+
@param_name = raw[:param_name] || "file"
|
10
|
+
end
|
11
|
+
|
12
|
+
attr_reader :path, :content_type, :param_name
|
13
|
+
|
14
|
+
def self.info(raw)
|
15
|
+
new(raw)
|
16
|
+
end
|
17
|
+
|
18
|
+
def locate(specification)
|
19
|
+
FileUpload.new({
|
20
|
+
path: specification.locate(path),
|
21
|
+
content_type: content_type
|
22
|
+
})
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_info
|
26
|
+
{ path: path.to_s,
|
27
|
+
content_type: content_type,
|
28
|
+
param_name: param_name }
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_s
|
32
|
+
"FileUpload(#{to_info})"
|
33
|
+
end
|
34
|
+
alias :inspect :to_s
|
35
|
+
|
36
|
+
end # class FileUpload
|
37
|
+
end # class Specification
|
38
|
+
end # module Web
|
39
|
+
end # module Webspicy
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Webspicy
|
2
|
+
module Web
|
3
|
+
class Specification
|
4
|
+
class TestCase < Webspicy::Specification::TestCase
|
5
|
+
|
6
|
+
def headers
|
7
|
+
@raw[:headers] ||= {}
|
8
|
+
end
|
9
|
+
|
10
|
+
def dress_params
|
11
|
+
@raw.fetch(:dress_params){ true }
|
12
|
+
end
|
13
|
+
alias :dress_params? :dress_params
|
14
|
+
|
15
|
+
def params
|
16
|
+
@raw[:params] || {}
|
17
|
+
end
|
18
|
+
|
19
|
+
def body
|
20
|
+
@raw[:body]
|
21
|
+
end
|
22
|
+
|
23
|
+
def file_upload
|
24
|
+
@raw[:file_upload]
|
25
|
+
end
|
26
|
+
|
27
|
+
def located_file_upload
|
28
|
+
file_upload ? file_upload.locate(specification) : nil
|
29
|
+
end
|
30
|
+
|
31
|
+
def expected_content_type
|
32
|
+
expected[:content_type]
|
33
|
+
end
|
34
|
+
|
35
|
+
def expected_status
|
36
|
+
expected[:status]
|
37
|
+
end
|
38
|
+
|
39
|
+
def is_expected_status?(status)
|
40
|
+
expected_status === status
|
41
|
+
end
|
42
|
+
|
43
|
+
def has_expected_status?
|
44
|
+
not expected[:status].nil?
|
45
|
+
end
|
46
|
+
|
47
|
+
def expected_headers
|
48
|
+
expected[:headers] || {}
|
49
|
+
end
|
50
|
+
|
51
|
+
def has_expected_headers?
|
52
|
+
!expected_headers.empty?
|
53
|
+
end
|
54
|
+
|
55
|
+
end # class TestCase
|
56
|
+
end # class Specification
|
57
|
+
end # module Web
|
58
|
+
end # module Webspicy
|
@@ -3,11 +3,17 @@ module Webspicy
|
|
3
3
|
class Configuration
|
4
4
|
describe Scope, "expand_example" do
|
5
5
|
|
6
|
-
|
6
|
+
let(:config){
|
7
|
+
Configuration.new(Path.dir)
|
8
|
+
}
|
9
|
+
|
10
|
+
subject{
|
11
|
+
Scope.new(config).send(:expand_example, service, example)
|
12
|
+
}
|
7
13
|
|
8
14
|
context 'when the service has no default example' do
|
9
15
|
let(:service) {
|
10
|
-
Webspicy.service({
|
16
|
+
Webspicy::Web.service({
|
11
17
|
method: "GET",
|
12
18
|
description: "Test service",
|
13
19
|
preconditions: "Foo",
|
@@ -18,7 +24,7 @@ module Webspicy
|
|
18
24
|
}
|
19
25
|
|
20
26
|
let(:example) {
|
21
|
-
Webspicy.test_case({
|
27
|
+
Webspicy::Web.test_case({
|
22
28
|
description: "Hello world"
|
23
29
|
})
|
24
30
|
}
|
@@ -30,7 +36,7 @@ module Webspicy
|
|
30
36
|
|
31
37
|
context 'when the service has a default example' do
|
32
38
|
let(:service) {
|
33
|
-
Webspicy.service({
|
39
|
+
Webspicy::Web.service({
|
34
40
|
method: "GET",
|
35
41
|
description: "Test service",
|
36
42
|
preconditions: "Foo",
|
@@ -44,7 +50,7 @@ module Webspicy
|
|
44
50
|
}
|
45
51
|
|
46
52
|
let(:example) {
|
47
|
-
Webspicy.test_case({
|
53
|
+
Webspicy::Web.test_case({
|
48
54
|
description: "Hello world",
|
49
55
|
expected: { content_type: "application/json" }
|
50
56
|
})
|
@@ -15,13 +15,13 @@ module Webspicy
|
|
15
15
|
|
16
16
|
describe "instrument" do
|
17
17
|
it 'injects the headers' do
|
18
|
-
tc = TestCase.new({})
|
18
|
+
tc = Web::Specification::TestCase.new({})
|
19
19
|
instrument(tc)
|
20
20
|
expect(tc.headers['Accept']).to eql("application/json")
|
21
21
|
end
|
22
22
|
|
23
23
|
it 'keeps original headers unchanged' do
|
24
|
-
tc = TestCase.new({
|
24
|
+
tc = Web::Specification::TestCase.new({
|
25
25
|
headers: {
|
26
26
|
'Content-Type' => 'text/plain'
|
27
27
|
}
|
@@ -32,7 +32,7 @@ module Webspicy
|
|
32
32
|
end
|
33
33
|
|
34
34
|
it 'has low precedence' do
|
35
|
-
tc = TestCase.new({
|
35
|
+
tc = Web::Specification::TestCase.new({
|
36
36
|
headers: {
|
37
37
|
'Accept' => 'text/plain'
|
38
38
|
}
|
@@ -4,7 +4,7 @@ module Webspicy
|
|
4
4
|
describe Service, "dress_params" do
|
5
5
|
|
6
6
|
it 'symbolizes keys' do
|
7
|
-
service = Webspicy.service({
|
7
|
+
service = Webspicy::Web.service({
|
8
8
|
method: "GET",
|
9
9
|
description: "Test service",
|
10
10
|
preconditions: "Foo",
|
@@ -17,7 +17,7 @@ module Webspicy
|
|
17
17
|
end
|
18
18
|
|
19
19
|
it 'supports an array' do
|
20
|
-
service = Webspicy.service({
|
20
|
+
service = Webspicy::Web.service({
|
21
21
|
method: "GET",
|
22
22
|
description: "Test service",
|
23
23
|
preconditions: "Foo",
|
@@ -36,6 +36,7 @@ module Webspicy
|
|
36
36
|
expect(c).to be_a(Configuration)
|
37
37
|
expect(c.folder).to eq(Path.pwd)
|
38
38
|
expect(c.each_scope.to_a.size).to eql(1)
|
39
|
+
expect(c.each_scope.to_a.first.each_specification_file.to_a.size).to eql(1)
|
39
40
|
expect(c.each_scope.to_a.first.each_specification.to_a.size).to eql(1)
|
40
41
|
end
|
41
42
|
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'webspicy/tester/fakesmtp'
|
3
|
+
module Webspicy
|
4
|
+
class Tester
|
5
|
+
class Fakesmtp
|
6
|
+
describe Email do
|
7
|
+
|
8
|
+
DATA = JSON.parse <<~J
|
9
|
+
{
|
10
|
+
"attachments": [],
|
11
|
+
"headerLines": [
|
12
|
+
{
|
13
|
+
"key": "date",
|
14
|
+
"line": "Date: Tue, 20 Apr 2021 14:06:13 +0000"
|
15
|
+
},
|
16
|
+
{
|
17
|
+
"key": "from",
|
18
|
+
"line": "From: info@mydomain.be"
|
19
|
+
},
|
20
|
+
{
|
21
|
+
"key": "reply-to",
|
22
|
+
"line": "Reply-To: test@email.be"
|
23
|
+
},
|
24
|
+
{
|
25
|
+
"key": "to",
|
26
|
+
"line": "To: support@mydomain.fr"
|
27
|
+
},
|
28
|
+
{
|
29
|
+
"key": "message-id",
|
30
|
+
"line": "Message-ID: <607edfd56836e_1b0492af@1d3356d02030.mail>"
|
31
|
+
},
|
32
|
+
{
|
33
|
+
"key": "subject",
|
34
|
+
"line": "Subject: Hello World"
|
35
|
+
},
|
36
|
+
{
|
37
|
+
"key": "mime-version",
|
38
|
+
"line": "Mime-Version: 1.0"
|
39
|
+
}
|
40
|
+
],
|
41
|
+
"html": "<p>Hello World!!</p>",
|
42
|
+
"text": "Hello World!!",
|
43
|
+
"textAsHtml": "Hello World!!",
|
44
|
+
"subject": "Hello World",
|
45
|
+
"date": "2021-04-20T14:06:13.000Z",
|
46
|
+
"to": {
|
47
|
+
"value": [
|
48
|
+
{
|
49
|
+
"address": "support@mydomain.fr",
|
50
|
+
"name": ""
|
51
|
+
}
|
52
|
+
],
|
53
|
+
"html": "<span class=\\"mp_address_group\\"><a href=\\"mailto:support@mydomain.fr\\" class=\\"mp_address_email\\">support@mydomain.fr</a></span>",
|
54
|
+
"text": "support@mydomain.fr"
|
55
|
+
},
|
56
|
+
"from": {
|
57
|
+
"value": [
|
58
|
+
{
|
59
|
+
"address": "info@mydomain.be",
|
60
|
+
"name": ""
|
61
|
+
}
|
62
|
+
],
|
63
|
+
"html": "<span class=\\"mp_address_group\\"><a href=\\"mailto:info@mydomain.be\\" class=\\"mp_address_email\\">info@mydomain.be</a></span>",
|
64
|
+
"text": "info@mydomain.be"
|
65
|
+
},
|
66
|
+
"messageId": "<607edfd56836e_1b0492af@1d3356d02030.mail>",
|
67
|
+
"replyTo": {
|
68
|
+
"value": [
|
69
|
+
{
|
70
|
+
"address": "test@email.be",
|
71
|
+
"name": ""
|
72
|
+
}
|
73
|
+
],
|
74
|
+
"html": "<span class=\\"mp_address_group\\"><a href=\\"mailto:test@email.be\\" class=\\"mp_address_email\\">test@email.be</a></span>",
|
75
|
+
"text": "test@email.be"
|
76
|
+
}
|
77
|
+
}
|
78
|
+
J
|
79
|
+
|
80
|
+
subject{
|
81
|
+
Email.new(DATA)
|
82
|
+
}
|
83
|
+
|
84
|
+
it 'works as expected' do
|
85
|
+
expect(subject.from).to eql("info@mydomain.be")
|
86
|
+
expect(subject.to).to eql(["support@mydomain.fr"])
|
87
|
+
expect(subject.subject).to eql("Hello World")
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
module Webspicy
|
3
|
+
module Web
|
4
|
+
describe Specification, "instantiate_url" do
|
5
|
+
|
6
|
+
it 'does nothing when the url has no placeholder' do
|
7
|
+
r = Specification.new(url: "/test/a/url")
|
8
|
+
url, params = r.instantiate_url(foo: "bar")
|
9
|
+
expect(url).to eq("/test/a/url")
|
10
|
+
expect(params).to eq(foo: "bar")
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'instantiates placeholders and strips corresponding params' do
|
14
|
+
r = Specification.new(url: "/test/{foo}/url")
|
15
|
+
url, params = r.instantiate_url(foo: "bar", baz: "coz")
|
16
|
+
expect(url).to eq("/test/bar/url")
|
17
|
+
expect(params).to eq(baz: "coz")
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'instantiates placeholders and strips corresponding params even when multiple' do
|
21
|
+
r = Specification.new(url: "/test/{foo}/url/{bar}")
|
22
|
+
url, params = r.instantiate_url(foo: "bar", bar: "baz", baz: "coz")
|
23
|
+
expect(url).to eq("/test/bar/url/baz")
|
24
|
+
expect(params).to eq(baz: "coz")
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'supports placeholders corresponding to subentities' do
|
28
|
+
r = Specification.new(url: "/test/{foo.id}/url")
|
29
|
+
url, params = r.instantiate_url(foo: {id: "bar"}, baz: "coz")
|
30
|
+
expect(url).to eq("/test/bar/url")
|
31
|
+
expect(params).to eq(foo: {}, baz: "coz")
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
module Webspicy
|
3
|
+
module Web
|
4
|
+
describe Specification, "url_placeholders" do
|
5
|
+
|
6
|
+
it 'returns an empty array on none' do
|
7
|
+
r = Specification.new(url: "/test/a/url")
|
8
|
+
expect(r.url_placeholders).to eq([])
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'returns all placeholders' do
|
12
|
+
r = Specification.new(url: "/test/{foo}/url/{bar}")
|
13
|
+
expect(r.url_placeholders).to eq(["foo", "bar"])
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'returns all placeholders expr' do
|
17
|
+
r = Specification.new(url: "/test/{foo.id}/url/{bar}")
|
18
|
+
expect(r.url_placeholders).to eq(["foo.id", "bar"])
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/tasks/test.rake
CHANGED
@@ -5,8 +5,12 @@ namespace :test do
|
|
5
5
|
|
6
6
|
desc "Runs unit tests on the library itself"
|
7
7
|
RSpec::Core::RakeTask.new(:unit) do |t|
|
8
|
+
require 'path'
|
9
|
+
root_folder = Path.dir.parent
|
10
|
+
test_results = root_folder/"test-results"
|
11
|
+
puts (test_results/"unit-tests.xml").inspect
|
8
12
|
t.pattern = "spec/unit/**/test_*.rb"
|
9
|
-
t.rspec_opts = ["-Ilib", "-Ispec/unit", "--color", "--backtrace", "--format=progress"]
|
13
|
+
t.rspec_opts = ["-Ilib", "-Ispec/unit", "--color", "--backtrace", "--format=progress", "--format RspecJunitFormatter", "--out #{test_results}/unit-tests.xml"]
|
10
14
|
end
|
11
15
|
tests << :unit
|
12
16
|
|