build_eval 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/build_eval/error.rb +11 -0
- data/lib/build_eval/http.rb +17 -3
- data/lib/build_eval/result/build_result.rb +2 -2
- data/lib/build_eval/result/status.rb +5 -4
- data/lib/build_eval/server/cruise_control_response.rb +22 -0
- data/lib/build_eval/server/decorator.rb +1 -1
- data/lib/build_eval/server/invalid_selector_error.rb +13 -0
- data/lib/build_eval/server/jenkins.rb +23 -0
- data/lib/build_eval/server/team_city.rb +2 -5
- data/lib/build_eval/server/travis.rb +3 -6
- data/lib/build_eval/version.rb +1 -1
- data/lib/build_eval.rb +7 -1
- data/spec/lib/build_eval/error_spec.rb +21 -0
- data/spec/lib/build_eval/http_shared_context.rb +7 -0
- data/spec/lib/build_eval/http_spec.rb +25 -5
- data/spec/lib/build_eval/result/build_result_spec.rb +4 -4
- data/spec/lib/build_eval/result/status_spec.rb +30 -11
- data/spec/lib/build_eval/server/cruise_control_response_spec.rb +115 -0
- data/spec/lib/build_eval/server/decorator_spec.rb +6 -6
- data/spec/lib/build_eval/server/invalid_selector_error_spec.rb +27 -0
- data/spec/lib/build_eval/server/jenkins_integration_spec.rb +52 -0
- data/spec/lib/build_eval/server/jenkins_spec.rb +70 -0
- data/spec/lib/build_eval/server/server_shared_examples.rb +15 -0
- data/spec/lib/build_eval/server/team_city_integration_spec.rb +85 -0
- data/spec/lib/build_eval/server/team_city_spec.rb +24 -88
- data/spec/lib/build_eval/server/travis_integration_spec.rb +53 -0
- data/spec/lib/build_eval/server/travis_spec.rb +33 -55
- data/spec/lib/build_eval_smoke_spec.rb +25 -0
- data/spec/spec_helper.rb +14 -6
- metadata +42 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c9ed39e2bae3a1ef5d1ffd40242183287fae193a
|
4
|
+
data.tar.gz: bff2e6552ad2a28e5d1dbc0cea6b463cd6a82a3a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b6006e6709284a157a71b6b48f09b0706f9112c89706e57de79faf3a40d3b46d8e998366c422420349f5d48e1e2beb6e0f6ff3cdddb59993efb5abe34bc862a6
|
7
|
+
data.tar.gz: 6c2978e0ce2095206a9086b018beef07e409f18dbf3c8e9afb5c7b8210942728b496ac04d8af499f3e9d54deb5df6435dfedef34f18d252661602afc1f1113b1
|
data/lib/build_eval/http.rb
CHANGED
@@ -2,15 +2,29 @@ module BuildEval
|
|
2
2
|
|
3
3
|
class Http
|
4
4
|
|
5
|
-
def
|
5
|
+
def initialize(config)
|
6
|
+
@username = config[:username]
|
7
|
+
@password = config[:password]
|
8
|
+
@ssl_verify_mode = config[:ssl_verify_mode]
|
9
|
+
end
|
10
|
+
|
11
|
+
def get(uri_string)
|
6
12
|
uri = URI.parse(uri_string)
|
7
|
-
Net::HTTP.start(uri.host, uri.port,
|
13
|
+
Net::HTTP.start(uri.host, uri.port, ssl_options(uri)) do |http|
|
8
14
|
request = Net::HTTP::Get.new(uri.request_uri)
|
9
|
-
request.basic_auth(
|
15
|
+
request.basic_auth(@username, @password) if @username && @password
|
10
16
|
http.request(request)
|
11
17
|
end
|
12
18
|
end
|
13
19
|
|
20
|
+
private
|
21
|
+
|
22
|
+
def ssl_options(uri)
|
23
|
+
ssl_options = { use_ssl: uri.scheme == "https" }
|
24
|
+
ssl_options[:ssl_verify_mode] = @ssl_verify_mode if @ssl_verify_mode
|
25
|
+
ssl_options
|
26
|
+
end
|
27
|
+
|
14
28
|
end
|
15
29
|
|
16
30
|
end
|
@@ -9,8 +9,8 @@ module BuildEval
|
|
9
9
|
self.new(build_name: args[:build_name], status: BuildEval::Result::Status.find(args[:status_name]))
|
10
10
|
end
|
11
11
|
|
12
|
-
def
|
13
|
-
self.new(build_name: build_name, status: BuildEval::Result::Status::
|
12
|
+
def indeterminate(build_name)
|
13
|
+
self.new(build_name: build_name, status: BuildEval::Result::Status::INDETERMINATE)
|
14
14
|
end
|
15
15
|
|
16
16
|
end
|
@@ -13,10 +13,11 @@ module BuildEval
|
|
13
13
|
|
14
14
|
public
|
15
15
|
|
16
|
-
SUCCESS
|
17
|
-
UNKNOWN
|
18
|
-
|
19
|
-
|
16
|
+
SUCCESS = self.new(severity: 0, symbol: :success!, description: "succeeded")
|
17
|
+
UNKNOWN = self.new(severity: 1, symbol: :warning!, description: "unknown")
|
18
|
+
INDETERMINATE = self.new(severity: 2, symbol: :warning!, description: "indeterminate")
|
19
|
+
FAILURE = self.new(severity: 3, symbol: :failure!, description: "failed")
|
20
|
+
ERROR = self.new(severity: 4, symbol: :failure!, description: "errored")
|
20
21
|
|
21
22
|
class << self
|
22
23
|
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module BuildEval
|
2
|
+
module Server
|
3
|
+
|
4
|
+
class CruiseControlResponse
|
5
|
+
|
6
|
+
def initialize(raw_response)
|
7
|
+
@raw_response = raw_response
|
8
|
+
end
|
9
|
+
|
10
|
+
def parse_result(project_selector)
|
11
|
+
build_element = Nokogiri::XML(@raw_response.body).xpath(project_selector).first
|
12
|
+
raise BuildEval::Server::InvalidSelectorError.new(@raw_response, project_selector) unless build_element
|
13
|
+
BuildEval::Result::BuildResult.create(
|
14
|
+
build_name: build_element.attribute("name").value.match(/[^\/]+$/)[0],
|
15
|
+
status_name: build_element.attribute("lastBuildStatus").value
|
16
|
+
)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module BuildEval
|
2
|
+
module Server
|
3
|
+
|
4
|
+
class InvalidSelectorError < BuildEval::Error
|
5
|
+
|
6
|
+
def initialize(response, selector)
|
7
|
+
super("Build response did not match selector:\nResponse: #{response.message}\nSelector: #{selector}")
|
8
|
+
end
|
9
|
+
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module BuildEval
|
2
|
+
module Server
|
3
|
+
|
4
|
+
class Jenkins
|
5
|
+
|
6
|
+
def initialize(args)
|
7
|
+
@http = BuildEval::Http.new(args)
|
8
|
+
@base_uri = args[:uri]
|
9
|
+
end
|
10
|
+
|
11
|
+
def build_result(name)
|
12
|
+
raw_response = @http.get("#{@base_uri}/cc.xml")
|
13
|
+
BuildEval::Server::CruiseControlResponse.new(raw_response).parse_result("//Project[@name=\"#{name}\"]")
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_s
|
17
|
+
"Jenkins server #{@base_uri}"
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -4,15 +4,12 @@ module BuildEval
|
|
4
4
|
class TeamCity
|
5
5
|
|
6
6
|
def initialize(args)
|
7
|
+
@http = BuildEval::Http.new(args)
|
7
8
|
@base_uri = args[:uri]
|
8
|
-
@username = args[:username]
|
9
|
-
@password = args[:password]
|
10
9
|
end
|
11
10
|
|
12
11
|
def build_result(name)
|
13
|
-
response =
|
14
|
-
"#{@base_uri}/httpAuth/app/rest/buildTypes/id:#{name}/builds", username: @username, password: @password
|
15
|
-
)
|
12
|
+
response = @http.get("#{@base_uri}/httpAuth/app/rest/buildTypes/id:#{name}/builds")
|
16
13
|
build_element = Nokogiri::XML(response.body).xpath("//build").first
|
17
14
|
raise "Unexpected build response: #{response.message}" unless build_element
|
18
15
|
BuildEval::Result::BuildResult.create(build_name: name, status_name: build_element.attribute("status").value)
|
@@ -4,16 +4,13 @@ module BuildEval
|
|
4
4
|
class Travis
|
5
5
|
|
6
6
|
def initialize(args)
|
7
|
+
@http = BuildEval::Http.new(args)
|
7
8
|
@username = args[:username]
|
8
9
|
end
|
9
10
|
|
10
11
|
def build_result(name)
|
11
|
-
|
12
|
-
|
13
|
-
raise "Unexpected build response: #{response.message}" unless build_element
|
14
|
-
BuildEval::Result::BuildResult.create(
|
15
|
-
build_name: name, status_name: build_element.attribute("lastBuildStatus").value
|
16
|
-
)
|
12
|
+
raw_response = @http.get("https://api.travis-ci.org/repositories/#{@username}/#{name}/cc.xml")
|
13
|
+
BuildEval::Server::CruiseControlResponse.new(raw_response).parse_result("//Project")
|
17
14
|
end
|
18
15
|
|
19
16
|
def to_s
|
data/lib/build_eval/version.rb
CHANGED
data/lib/build_eval.rb
CHANGED
@@ -1,13 +1,19 @@
|
|
1
1
|
require 'nokogiri'
|
2
|
-
|
2
|
+
require 'uri'
|
3
|
+
require 'net/http'
|
4
|
+
require 'net/https'
|
5
|
+
require_relative 'build_eval/error'
|
3
6
|
require_relative 'build_eval/http'
|
4
7
|
require_relative 'build_eval/result/status'
|
5
8
|
require_relative 'build_eval/result/build_result'
|
6
9
|
require_relative 'build_eval/result/server_result'
|
7
10
|
require_relative 'build_eval/result/composite_result'
|
11
|
+
require_relative 'build_eval/server/invalid_selector_error'
|
8
12
|
require_relative 'build_eval/server/decorator'
|
13
|
+
require_relative 'build_eval/server/cruise_control_response'
|
9
14
|
require_relative 'build_eval/server/team_city'
|
10
15
|
require_relative 'build_eval/server/travis'
|
16
|
+
require_relative 'build_eval/server/jenkins'
|
11
17
|
require_relative 'build_eval/monitor/base'
|
12
18
|
require_relative 'build_eval/monitor/server'
|
13
19
|
require_relative 'build_eval/monitor/composite'
|
@@ -0,0 +1,21 @@
|
|
1
|
+
describe BuildEval::Error do
|
2
|
+
|
3
|
+
let(:message) { "some message" }
|
4
|
+
|
5
|
+
let(:error) { described_class.new(message) }
|
6
|
+
|
7
|
+
it "is a standard error" do
|
8
|
+
expect(error).to be_a(::StandardError)
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "#messsage" do
|
12
|
+
|
13
|
+
subject { error.message }
|
14
|
+
|
15
|
+
it "returns the provided message" do
|
16
|
+
expect(subject).to eql(message)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -1,5 +1,9 @@
|
|
1
1
|
describe BuildEval::Http do
|
2
2
|
|
3
|
+
let(:config) { {} }
|
4
|
+
|
5
|
+
let(:http) { described_class.new(config) }
|
6
|
+
|
3
7
|
shared_examples_for "a http method returning a response" do
|
4
8
|
|
5
9
|
let(:response_status) { [ "200", "OK" ] }
|
@@ -19,14 +23,14 @@ describe BuildEval::Http do
|
|
19
23
|
|
20
24
|
end
|
21
25
|
|
22
|
-
describe "
|
26
|
+
describe "#get" do
|
23
27
|
|
24
28
|
let(:scheme) { "http" }
|
25
29
|
let(:host) { "a.host" }
|
26
30
|
let(:path) { "some/path" }
|
27
31
|
let(:uri_string) { "#{scheme}://#{host}/#{path}" }
|
28
32
|
|
29
|
-
subject {
|
33
|
+
subject { http.get(uri_string) }
|
30
34
|
|
31
35
|
context "when the uri is valid" do
|
32
36
|
|
@@ -52,15 +56,31 @@ describe BuildEval::Http do
|
|
52
56
|
|
53
57
|
end
|
54
58
|
|
55
|
-
context "and
|
59
|
+
context "and an ssl verification mode configuration option was established" do
|
60
|
+
|
61
|
+
let(:ssl_verification_mode) { OpenSSL::SSL::VERIFY_NONE }
|
62
|
+
let(:config) { { ssl_verify_mode: ssl_verification_mode } }
|
63
|
+
|
64
|
+
it_behaves_like "a http method returning a response"
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
context "and partial authentication configuration options were established" do
|
69
|
+
|
70
|
+
let(:config) { { username: "some_username" } }
|
71
|
+
|
72
|
+
it_behaves_like "a http method returning a response"
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
context "and basic authentication configuration options were established" do
|
56
77
|
|
57
78
|
let(:username) { "some_username" }
|
58
79
|
let(:password) { "some_password" }
|
80
|
+
let(:config) { { username: username, password: password } }
|
59
81
|
|
60
82
|
let(:expected_request_uri) { "#{scheme}://#{username}:#{password}@#{host}/#{path}" }
|
61
83
|
|
62
|
-
subject { described_class.get(uri_string, basic_authentication: { username: username, password: password }) }
|
63
|
-
|
64
84
|
it_behaves_like "a http method returning a response"
|
65
85
|
|
66
86
|
end
|
@@ -27,18 +27,18 @@ describe BuildEval::Result::BuildResult do
|
|
27
27
|
|
28
28
|
end
|
29
29
|
|
30
|
-
describe "::
|
30
|
+
describe "::indeterminate" do
|
31
31
|
|
32
32
|
let(:build_name) { "Some build name" }
|
33
33
|
|
34
|
-
subject { described_class.
|
34
|
+
subject { described_class.indeterminate(build_name) }
|
35
35
|
|
36
36
|
it "returns a result with the provided build name" do
|
37
37
|
expect(subject.build_name).to eql(build_name)
|
38
38
|
end
|
39
39
|
|
40
|
-
it "returns a result with an
|
41
|
-
expect(subject.status).to eql(BuildEval::Result::Status::
|
40
|
+
it "returns a result with an indeterminate status" do
|
41
|
+
expect(subject.status).to eql(BuildEval::Result::Status::INDETERMINATE)
|
42
42
|
end
|
43
43
|
|
44
44
|
end
|
@@ -50,13 +50,16 @@ describe BuildEval::Result::Status do
|
|
50
50
|
|
51
51
|
end
|
52
52
|
|
53
|
-
context "when the statuses are ordered in
|
53
|
+
context "when the statuses are ordered in ascending severity" do
|
54
54
|
|
55
55
|
let(:statuses) do
|
56
|
-
[
|
56
|
+
[
|
57
|
+
BuildEval::Result::Status::ERROR,
|
57
58
|
BuildEval::Result::Status::FAILURE,
|
58
59
|
BuildEval::Result::Status::UNKNOWN,
|
59
|
-
BuildEval::Result::Status::
|
60
|
+
BuildEval::Result::Status::INDETERMINATE,
|
61
|
+
BuildEval::Result::Status::SUCCESS
|
62
|
+
]
|
60
63
|
end
|
61
64
|
|
62
65
|
it "returns the most severe status" do
|
@@ -65,13 +68,16 @@ describe BuildEval::Result::Status do
|
|
65
68
|
|
66
69
|
end
|
67
70
|
|
68
|
-
context "when the statuses are ordered in
|
71
|
+
context "when the statuses are ordered in descending severity" do
|
69
72
|
|
70
73
|
let(:statuses) do
|
71
|
-
[
|
74
|
+
[
|
75
|
+
BuildEval::Result::Status::SUCCESS,
|
72
76
|
BuildEval::Result::Status::UNKNOWN,
|
77
|
+
BuildEval::Result::Status::INDETERMINATE,
|
73
78
|
BuildEval::Result::Status::FAILURE,
|
74
|
-
BuildEval::Result::Status::ERROR
|
79
|
+
BuildEval::Result::Status::ERROR
|
80
|
+
]
|
75
81
|
end
|
76
82
|
|
77
83
|
it "returns the most severe status" do
|
@@ -97,9 +103,10 @@ describe BuildEval::Result::Status do
|
|
97
103
|
end
|
98
104
|
|
99
105
|
{
|
100
|
-
"UNKNOWN"
|
101
|
-
"FAILURE"
|
102
|
-
"ERROR"
|
106
|
+
"UNKNOWN" => BuildEval::Result::Status::UNKNOWN,
|
107
|
+
"FAILURE" => BuildEval::Result::Status::FAILURE,
|
108
|
+
"ERROR" => BuildEval::Result::Status::ERROR,
|
109
|
+
"INDETERMINATE" => BuildEval::Result::Status::INDETERMINATE
|
103
110
|
}.each do |name, status|
|
104
111
|
|
105
112
|
context "when the status is #{name}" do
|
@@ -120,7 +127,13 @@ describe BuildEval::Result::Status do
|
|
120
127
|
|
121
128
|
subject { status.to_sym }
|
122
129
|
|
123
|
-
{
|
130
|
+
{
|
131
|
+
SUCCESS: :success!,
|
132
|
+
UNKNOWN: :warning!,
|
133
|
+
INDETERMINATE: :warning!,
|
134
|
+
FAILURE: :failure!,
|
135
|
+
ERROR: :failure!
|
136
|
+
}.each do |name, expected_symbol|
|
124
137
|
|
125
138
|
context "when the status is #{name}" do
|
126
139
|
|
@@ -140,7 +153,13 @@ describe BuildEval::Result::Status do
|
|
140
153
|
|
141
154
|
subject { status.to_s }
|
142
155
|
|
143
|
-
{
|
156
|
+
{
|
157
|
+
SUCCESS: "succeeded",
|
158
|
+
UNKNOWN: "unknown",
|
159
|
+
INDETERMINATE: "indeterminate",
|
160
|
+
FAILURE: "failed",
|
161
|
+
ERROR: "errored"
|
162
|
+
}.each do |name, expected_string|
|
144
163
|
|
145
164
|
context "when the status is #{name}" do
|
146
165
|
|
@@ -0,0 +1,115 @@
|
|
1
|
+
describe BuildEval::Server::CruiseControlResponse do
|
2
|
+
|
3
|
+
let(:raw_response) { double("RawResponse", body: response_body) }
|
4
|
+
|
5
|
+
let(:cruise_control_response) { described_class.new(raw_response) }
|
6
|
+
|
7
|
+
describe "#parse_result" do
|
8
|
+
|
9
|
+
let(:build_name) { "some_build_name" }
|
10
|
+
let(:response_build_name) { build_name }
|
11
|
+
let(:project_selector) { "//Project[2]" }
|
12
|
+
|
13
|
+
subject { cruise_control_response.parse_result(project_selector) }
|
14
|
+
|
15
|
+
context "when the response is successful, containing projects" do
|
16
|
+
|
17
|
+
let(:latest_build_status) { "Success" }
|
18
|
+
let(:response_body) do
|
19
|
+
<<-RESPONSE
|
20
|
+
<Projects>
|
21
|
+
<Project name="another_build_name" activity="Sleeping" lastBuildStatus="Unknown" lastBuildLabel="2" lastBuildTime="2015-08-02T00:00:00.000+0000" webUrl="https://my.build.server/another_build_name" />
|
22
|
+
<Project name="#{response_build_name}" activity="Sleeping" lastBuildStatus="#{latest_build_status}" lastBuildLabel="1" lastBuildTime="2015-08-01T00:00:00.000+0000" webUrl="https://my.build.server/#{build_name}" />
|
23
|
+
<Project name="yet_another_build_name" activity="Sleeping" lastBuildStatus="Error" lastBuildLabel="3" lastBuildTime="2015-08-03T00:00:00.000+0000" webUrl="https://my.build.server/yet_another_build_name" />
|
24
|
+
</Projects>
|
25
|
+
RESPONSE
|
26
|
+
end
|
27
|
+
|
28
|
+
context "and the selector matches a project" do
|
29
|
+
|
30
|
+
context "and the build name in the response is not a path" do
|
31
|
+
|
32
|
+
it "creates a build result with the build name from the response" do
|
33
|
+
expect(BuildEval::Result::BuildResult).to receive(:create).with(hash_including(build_name: build_name))
|
34
|
+
|
35
|
+
subject
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
context "and the build name in the response is a path" do
|
41
|
+
|
42
|
+
let(:response_build_name) { "some/path/to/#{build_name}" }
|
43
|
+
|
44
|
+
it "creates a build result with the build name from the response with the path omitted" do
|
45
|
+
expect(BuildEval::Result::BuildResult).to receive(:create).with(hash_including(build_name: build_name))
|
46
|
+
|
47
|
+
subject
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
it "creates a build result containing the latest build status" do
|
53
|
+
expect(BuildEval::Result::BuildResult).to(
|
54
|
+
receive(:create).with(hash_including(status_name: latest_build_status))
|
55
|
+
)
|
56
|
+
|
57
|
+
subject
|
58
|
+
end
|
59
|
+
|
60
|
+
it "returns the created result" do
|
61
|
+
build_result = instance_double(BuildEval::Result::BuildResult)
|
62
|
+
allow(BuildEval::Result::BuildResult).to receive(:create).and_return(build_result)
|
63
|
+
|
64
|
+
expect(subject).to eql(build_result)
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
context "and the selector does not match a project" do
|
70
|
+
|
71
|
+
let(:project_selector) { "does_not_match" }
|
72
|
+
let(:error) { "an error" }
|
73
|
+
|
74
|
+
before(:example) { allow(BuildEval::Server::InvalidSelectorError).to receive(:new).and_return(error) }
|
75
|
+
|
76
|
+
it "creates an invalid selector error" do
|
77
|
+
expect(BuildEval::Server::InvalidSelectorError).to(
|
78
|
+
receive(:new).with(raw_response, project_selector).and_return(error)
|
79
|
+
)
|
80
|
+
|
81
|
+
subject rescue Exception
|
82
|
+
end
|
83
|
+
|
84
|
+
it "raises the error" do
|
85
|
+
expect { subject }.to raise_error(error)
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
context "when the response is in error" do
|
93
|
+
|
94
|
+
let(:response_body) { { "file" => "not found" }.to_json }
|
95
|
+
let(:error) { "an error" }
|
96
|
+
|
97
|
+
before(:example) { allow(BuildEval::Server::InvalidSelectorError).to receive(:new).and_return(error) }
|
98
|
+
|
99
|
+
it "creates an invalid selector error" do
|
100
|
+
expect(BuildEval::Server::InvalidSelectorError).to(
|
101
|
+
receive(:new).with(raw_response, project_selector).and_return(error)
|
102
|
+
)
|
103
|
+
|
104
|
+
subject rescue Exception
|
105
|
+
end
|
106
|
+
|
107
|
+
it "raises an invalid selector error" do
|
108
|
+
expect { subject }.to raise_error(error)
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
@@ -32,17 +32,17 @@ describe BuildEval::Server::Decorator do
|
|
32
32
|
|
33
33
|
before(:example) { allow(server).to receive(:build_result).and_raise("Forced error") }
|
34
34
|
|
35
|
-
it "creates an
|
36
|
-
expect(BuildEval::Result::BuildResult).to receive(:
|
35
|
+
it "creates an indeterminate result" do
|
36
|
+
expect(BuildEval::Result::BuildResult).to receive(:indeterminate).with(build_name)
|
37
37
|
|
38
38
|
subject
|
39
39
|
end
|
40
40
|
|
41
|
-
it "returns the
|
42
|
-
|
43
|
-
allow(BuildEval::Result::BuildResult).to receive(:
|
41
|
+
it "returns the indeterminate result" do
|
42
|
+
indeterminate_result = instance_double(BuildEval::Result::BuildResult)
|
43
|
+
allow(BuildEval::Result::BuildResult).to receive(:indeterminate).and_return(indeterminate_result)
|
44
44
|
|
45
|
-
expect(subject).to eql(
|
45
|
+
expect(subject).to eql(indeterminate_result)
|
46
46
|
end
|
47
47
|
|
48
48
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
describe BuildEval::Server::InvalidSelectorError do
|
2
|
+
|
3
|
+
let(:response_message) { "Some response message" }
|
4
|
+
let(:response) { double("HttpResponse", message: response_message) }
|
5
|
+
let(:selector) { "some/selector" }
|
6
|
+
|
7
|
+
let(:error) { described_class.new(response, selector) }
|
8
|
+
|
9
|
+
describe "#message" do
|
10
|
+
|
11
|
+
subject { error.message }
|
12
|
+
|
13
|
+
it "indicates the selector was not matched" do
|
14
|
+
expect(subject).to match(/response did not match selector/i)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "contains a message describing the response" do
|
18
|
+
expect(subject).to include(response_message)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "contains the selector that was invalid" do
|
22
|
+
expect(subject).to include(selector)
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
describe BuildEval::Server::Jenkins, "integrating with a response parser", integration: true do
|
2
|
+
include_context "stubbed http interactions"
|
3
|
+
|
4
|
+
let(:uri) { "https://some.jenkins.server" }
|
5
|
+
|
6
|
+
let(:jenkins) { described_class.new(uri: uri) }
|
7
|
+
|
8
|
+
describe "#build_result" do
|
9
|
+
|
10
|
+
let(:build_name) { "some_build_name" }
|
11
|
+
let(:response) { instance_double(Net::HTTPResponse, body: response_body) }
|
12
|
+
|
13
|
+
subject { jenkins.build_result(build_name) }
|
14
|
+
|
15
|
+
before(:example) { allow(http).to receive(:get).and_return(response) }
|
16
|
+
|
17
|
+
context "when the server responds successfully with build results" do
|
18
|
+
|
19
|
+
let(:latest_build_status) { "Failure" }
|
20
|
+
let(:response_body) do
|
21
|
+
<<-RESPONSE
|
22
|
+
<Projects>
|
23
|
+
<Project webUrl="#{uri}/job/#{build_name}/" name="#{build_name}" lastBuildLabel="190" lastBuildTime="2015-10-09T02:39:36Z" lastBuildStatus="#{latest_build_status}" activity="Sleeping"/>
|
24
|
+
<Project webUrl="#{uri}/job/another_build_name/" name="another_build_name" lastBuildLabel="71" lastBuildTime="2015-10-12T17:07:00Z" lastBuildStatus="Success" activity="Sleeping"/>
|
25
|
+
<Project webUrl="#{uri}/job/yet_another_build_name/" name="yet_another_build_name" lastBuildLabel="15" lastBuildTime="2015-10-13T01:40:32Z" lastBuildStatus="Success" activity="Sleeping"/>
|
26
|
+
</Projects>
|
27
|
+
RESPONSE
|
28
|
+
end
|
29
|
+
|
30
|
+
it "creates a build result containing the build name" do
|
31
|
+
expect(BuildEval::Result::BuildResult).to receive(:create).with(hash_including(build_name: build_name))
|
32
|
+
|
33
|
+
subject
|
34
|
+
end
|
35
|
+
|
36
|
+
it "creates a build result containing the latest build status" do
|
37
|
+
expect(BuildEval::Result::BuildResult).to receive(:create).with(hash_including(status_name: latest_build_status))
|
38
|
+
subject
|
39
|
+
end
|
40
|
+
|
41
|
+
it "returns the created result" do
|
42
|
+
build_result = instance_double(BuildEval::Result::BuildResult)
|
43
|
+
allow(BuildEval::Result::BuildResult).to receive(:create).and_return(build_result)
|
44
|
+
|
45
|
+
expect(subject).to eql(build_result)
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|