fuci-team_city 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 939a4a39408afc7289a26b3ebac44769ac73a843
4
- data.tar.gz: 78aec682c9ef7bde8c74a3db71182b062b1521c7
3
+ metadata.gz: 26887219a4a45976ed4b1b41f7012572accc8bab
4
+ data.tar.gz: 7b36cd9c0cf6a38531849d4eec307ca680913f43
5
5
  SHA512:
6
- metadata.gz: 6278ae2cdc5b6e0184c222ed62ce0f66e6d86b5ac7a26989192c465655c4d9a21b484782b42bd11c4c42e93115c10100e92a9e770abc44fc9701dac52b26a35d
7
- data.tar.gz: 7380f52fe971508f0deb3b57bcf20d5fe05a7cf10e67a6a5514ce5172953df4a04c9b99c97fdd09957584ff8a53c9e167201e62baa24c062cce5944d24c86a8d
6
+ metadata.gz: 2f4ead566bffbd57f898a64eed0d43624380969e49c02bfa49f5dd546e9732989eb1f7d88a6b10755203e207d313ffae6b66c9931c8701898a6fd1cd0214be80
7
+ data.tar.gz: d3d1f03fee61c17c3577eeb802f1b44431ffc76bde4e3330dacbcd328746d05eac512a832f43322a4b586e091049cd29f1399f872fad0eb72b16be9cb1d515e3
@@ -0,0 +1,2 @@
1
+ ### version 0.1.0 *August 10, 2013*
2
+ * Initial release
data/README.md CHANGED
@@ -1,24 +1,85 @@
1
1
  # Fuci::TeamCity
2
+ [![Build Status](https://travis-ci.org/davejachimiak/fuci-team_city.png?branch=master)](https://travis-ci.org/davejachimiak/fuci-team_city)
2
3
 
3
- TODO: Write a gem description
4
+ Run TeamCity failures locally. A
5
+ [Fuci](https://github.com/davejachimiak/fuci) server extension.
4
6
 
5
7
  ## Installation
6
8
 
7
9
  Add this line to your application's Gemfile:
8
10
 
9
- gem 'fuci-team_city'
11
+ gem 'fuci-team_city', '~> 0.1'
10
12
 
11
13
  And then execute:
12
14
 
13
15
  $ bundle
14
16
 
15
- Or install it yourself as:
17
+ Bundling the binstub is highly recommended:
16
18
 
17
- $ gem install fuci-team_city
19
+ $ bundle binstubs fuci-team_city
20
+
21
+ ## Configuration file
22
+ To configure itself, fuci-team_city looks for a file called
23
+ ".fuci-team_city.rb" in your project's root directory. You should create
24
+ that file and configure fuci-team_city there. The configuration must
25
+ include your TeamCity username and password. **Therefore, you should
26
+ include ./.fuci-team_city.rb in .gitignore.**
27
+
28
+ You must configure the following variables in .fuci-team_city.rb:
29
+
30
+ 1. TeamCity host site
31
+ 2. project name
32
+ 3. default branch
33
+ 4. username
34
+ 5. password
35
+
36
+ ```ruby
37
+ Fuci::TeamCity.configure do |fu|
38
+ fu.host = 'teamcity.myserver.com:8111'
39
+ fu.project = 'my_app'
40
+ fu.default_branch = 'my-ci'
41
+ fu.username = 'username'
42
+ fu.password = 'password'
43
+ end
44
+ ```
45
+
46
+ ### Adding custom tester plugins
47
+
48
+ Fuci tester plugins should return two things: Whether a failed build has
49
+ failed with a specific testing framework (e.g. RSpec, Cucumber) and the
50
+ command-line command that runs those specific failures. As of now, Fuci
51
+ ships with RSpec and Cucumber tester plugins. If you want to add custom
52
+ testers, add them in the configuration:
53
+ ```ruby
54
+ Fuci::Travis.configure do |fu|
55
+ ...
56
+ ...
57
+ fu.add_testers Fuci::Spec, Fuci::AnotherTestingFramework
58
+ ...
59
+ ...
60
+ end
61
+ ```
62
+
63
+ See the [base Fuci repo](https://github.com/davejachimiak/fuci#creating-tester-extensions)
64
+ for more information on custom testers.
18
65
 
19
66
  ## Usage
20
67
 
21
- TODO: Write usage instructions here
68
+ See the
69
+ [base Fuci repo](https://github.com/davejachimiak/fuci#native-command-line-options)
70
+ for command-line options native to Fuci.
71
+
72
+ Run your latest ci failures locally:
73
+ ```sh
74
+ $ fuci
75
+ ```
76
+
77
+ Call `fuci` with a branch name to run a specific branch's failures
78
+ branch. For example, this will run the failures from the latest master
79
+ build on your local code:
80
+ ```sh
81
+ $ fuci master
82
+ ```
22
83
 
23
84
  ## Contributing
24
85
 
data/Rakefile CHANGED
@@ -1 +1,10 @@
1
1
  require "bundler/gem_tasks"
2
+ require 'rake/testtask'
3
+
4
+ desc 'Run the tests'
5
+ task :default => :test
6
+
7
+ desc 'Run the tests'
8
+ Rake::TestTask.new do |t|
9
+ t.pattern = 'spec/**/*.rb'
10
+ end
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'fuci/team_city'
4
+
5
+ load '.fuci-team_city.rb'
6
+
7
+ Fuci.run
@@ -18,7 +18,8 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_dependency 'fuci', '~> 0.3'
21
+ spec.add_dependency 'fuci', '~> 0.4'
22
+ spec.add_dependency 'nokogiri'
22
23
  spec.add_development_dependency "bundler", "~> 1.3"
23
24
  spec.add_development_dependency "minitest-spec-expect", "~> 0.1"
24
25
  spec.add_development_dependency "mocha", "~> 0.14"
@@ -1,7 +1,22 @@
1
- require "fuci/team_city/version"
1
+ require 'fuci'
2
+ require 'forwardable'
3
+ require 'fuci/configurable'
4
+ require 'fuci/team_city/server'
5
+ require 'fuci/team_city/project'
6
+ require 'fuci/team_city/version'
2
7
 
3
8
  module Fuci
9
+ configure do |fu|
10
+ fu.server = Fuci::TeamCity::Server
11
+ end
12
+
4
13
  module TeamCity
5
- # Your code goes here...
14
+ include Fuci::Configurable
15
+
16
+ class << self
17
+ extend Forwardable
18
+ def_delegator :Fuci, :add_testers
19
+ attr_accessor :host, :project, :default_branch, :username, :password
20
+ end
6
21
  end
7
22
  end
@@ -0,0 +1,64 @@
1
+ require 'fuci/team_city/request'
2
+ require 'fuci/team_city/project'
3
+ require 'fuci/team_city/cli_options'
4
+ require 'fuci/team_city/xml_doc_builder'
5
+
6
+ module Fuci
7
+ module TeamCity
8
+ class Build < Struct.new :element
9
+ ERROR = 'ERROR'
10
+ SUCCESS = 'SUCCESS'
11
+ LOG_RESOURCE = lambda { |id| "/downloadBuildLog.html?buildId=#{id}" }
12
+
13
+ def status_code
14
+ case status
15
+ when ERROR
16
+ :red
17
+ when SUCCESS
18
+ :green
19
+ else
20
+ :yellow
21
+ end
22
+ end
23
+
24
+ def log
25
+ Request.new(log_resource).call
26
+ end
27
+
28
+ def self.create
29
+ if branch_name = Fuci::TeamCity::CliOptions.branch
30
+ project.latest_build_from branch_name
31
+ else
32
+ create_with_default_branch
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ def status
39
+ element['status']
40
+ end
41
+
42
+ def log_resource
43
+ LOG_RESOURCE.(id)
44
+ end
45
+
46
+ def id
47
+ element['id']
48
+ end
49
+
50
+ def self.project
51
+ Fuci::TeamCity::Project.from_name
52
+ end
53
+
54
+ def self.create_with_default_branch
55
+ if branch_name = Fuci::TeamCity.default_branch
56
+ project.latest_build_from branch_name
57
+ else
58
+ puts 'No default branch is configured.'
59
+ exit
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,27 @@
1
+ require 'fuci/team_city/xml_doc_builder'
2
+ require 'fuci/team_city/build'
3
+ require 'forwardable'
4
+
5
+ module Fuci
6
+ module TeamCity
7
+ class Builds < Struct.new :xml_doc
8
+ extend Forwardable
9
+
10
+ def_delegator :xml_doc, :xpath
11
+
12
+ def each
13
+ xpath('//build').each { |element| yield Build.new(element) }
14
+ end
15
+
16
+ def self.from_resource resource
17
+ new xml_doc(resource)
18
+ end
19
+
20
+ private
21
+
22
+ def self.xml_doc resource
23
+ XmlDocBuilder.from_resource resource
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,17 @@
1
+ require 'fuci/cli_options'
2
+
3
+ module Fuci
4
+ module TeamCity
5
+ class CliOptions
6
+ def self.branch
7
+ argv.first
8
+ end
9
+
10
+ private
11
+
12
+ def self.argv
13
+ Fuci::CliOptions.argv
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,44 @@
1
+ require 'fuci/team_city/xml_doc_builder'
2
+ require 'fuci/team_city/builds'
3
+ require 'forwardable'
4
+
5
+ module Fuci
6
+ module TeamCity
7
+ class Project < Struct.new :xml_doc
8
+ extend Forwardable
9
+
10
+ RESOURCE = lambda { |name| "/httpAuth/app/rest/projects/name:#{name}" }
11
+
12
+ def_delegator :xml_doc, :xpath
13
+
14
+ def latest_build_from branch_name
15
+ builds_from(branch_name).first
16
+ end
17
+
18
+ def self.from_name
19
+ new xml_doc
20
+ end
21
+
22
+ private
23
+
24
+ def builds_from branch_name
25
+ Builds.from_resource builds_resource(branch_name)
26
+ end
27
+
28
+ def builds_resource branch_name
29
+ xpath("//buildType[@name=\"#{branch_name}\"]").
30
+ attr('href').
31
+ value +
32
+ '/builds'
33
+ end
34
+
35
+ def self.xml_doc
36
+ XmlDocBuilder.from_resource RESOURCE.(project_name)
37
+ end
38
+
39
+ def self.project_name
40
+ Fuci::TeamCity.project
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,61 @@
1
+ require 'net/http'
2
+
3
+ module Fuci
4
+ module TeamCity
5
+ class Request < Struct.new :resource
6
+ SCHEME = 'http'
7
+
8
+ def call
9
+ request_obj.basic_auth username, password
10
+ start.body
11
+ end
12
+
13
+ private
14
+
15
+ def request_obj
16
+ @request_obj ||=
17
+ begin
18
+ Net::HTTP::Get.new uri
19
+ rescue NoMethodError
20
+ # account for Ruby versions that that have request
21
+ # object initializers that take only strings
22
+ Net::HTTP::Get.new full_url
23
+ end
24
+ end
25
+
26
+ def full_url
27
+ base_url + resource
28
+ end
29
+
30
+ def username
31
+ Fuci::TeamCity.username
32
+ end
33
+
34
+ def password
35
+ Fuci::TeamCity.password
36
+ end
37
+
38
+ def uri
39
+ @uri ||= URI full_url
40
+ end
41
+
42
+ def base_url
43
+ "#{scheme}://#{host}"
44
+ end
45
+
46
+ def scheme
47
+ SCHEME
48
+ end
49
+
50
+ def host
51
+ Fuci::TeamCity.host
52
+ end
53
+
54
+ def start
55
+ Net::HTTP.start uri.host, uri.port do |http|
56
+ http.request request_obj
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,20 @@
1
+ require 'fuci/team_city/build'
2
+ require 'fuci/server'
3
+ require 'forwardable'
4
+
5
+ module Fuci
6
+ module TeamCity
7
+ class Server < Fuci::Server
8
+ extend Forwardable
9
+
10
+ def_delegator :build, :status_code, :build_status
11
+ def_delegator :build, :log, :fetch_log
12
+
13
+ attr_accessor :build
14
+
15
+ def initialize
16
+ @build = Fuci::TeamCity::Build.create
17
+ end
18
+ end
19
+ end
20
+ end
@@ -1,5 +1,5 @@
1
1
  module Fuci
2
2
  module TeamCity
3
- VERSION = "0.0.1"
3
+ VERSION = "0.1.0"
4
4
  end
5
5
  end
@@ -0,0 +1,14 @@
1
+ require 'nokogiri'
2
+
3
+ module Fuci
4
+ module TeamCity
5
+ class XmlDocBuilder
6
+ def self.from_resource resource
7
+ request = Request.new resource
8
+ response = request.call
9
+
10
+ Nokogiri::XML response
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,128 @@
1
+ require_relative '../../../spec_helper'
2
+ require_relative '../../../../lib/fuci/team_city/build'
3
+
4
+ stub_class 'Fuci::TeamCity::CliOptions'
5
+
6
+ describe Fuci::TeamCity::Build do
7
+ before do
8
+ xml = File.read 'spec/sample_data/builds.xml'
9
+ xml_doc = Nokogiri::XML xml
10
+ @element = xml_doc.xpath('//build').first
11
+ @build = Fuci::TeamCity::Build.new @element
12
+ end
13
+
14
+ describe '#initialize' do
15
+ it 'sets the xml_doc passed in' do
16
+ expect(@build.element).to_equal @element
17
+ end
18
+ end
19
+
20
+ describe '#status_code' do
21
+ before { @status = @build.stubs :status }
22
+
23
+ describe 'when status is ERROR' do
24
+ before { @status.returns 'ERROR' }
25
+
26
+ it 'returns :red' do
27
+ expect(@build.status_code).to_equal :red
28
+ end
29
+ end
30
+
31
+ describe 'when status is passed' do
32
+ before { @status.returns 'SUCCESS' }
33
+
34
+ it 'returns :green' do
35
+ expect(@build.status_code).to_equal :green
36
+ end
37
+ end
38
+
39
+ describe 'when status is something else' do
40
+ it 'returns :yellow' do
41
+ expect(@build.status_code).to_equal :yellow
42
+ end
43
+ end
44
+ end
45
+
46
+ describe '#log' do
47
+ it 'makes a request with the log resource' do
48
+ @build.stubs(:id).returns id = 12345
49
+ resource = "/downloadBuildLog.html?buildId=#{id}"
50
+ Fuci::TeamCity::Request.stubs(:new).
51
+ with(resource).returns request = mock
52
+ request.stubs(:call).returns log = mock
53
+
54
+ expect(@build.log).to_equal log
55
+ end
56
+ end
57
+
58
+ describe '#status' do
59
+ it 'returns the status from the xml doc' do
60
+ expect(@build.send :status ).to_equal 'ERROR'
61
+ end
62
+ end
63
+
64
+ describe '#id' do
65
+ it 'returns the id from the xml doc' do
66
+ expect(@build.send :id ).to_equal '8134'
67
+ end
68
+ end
69
+
70
+ describe '.project' do
71
+ it 'Calls Project.from_name' do
72
+ Fuci::TeamCity::Project.stubs(:from_name).returns project = mock
73
+ expect(Fuci::TeamCity::Build.send :project ).to_equal project
74
+ end
75
+ end
76
+
77
+ describe '.create' do
78
+ before do
79
+ @branch = Fuci::TeamCity::CliOptions.stubs :branch
80
+ end
81
+
82
+ describe 'when a branch is passed in the cli' do
83
+ before do
84
+ @branch_name = 'branch'
85
+ @branch.returns @branch_name
86
+ end
87
+
88
+ it 'creates a new build with the branch passed in' do
89
+ Fuci::TeamCity::Build.stubs(:project).
90
+ returns project = mock
91
+ project.stubs(:latest_build_from).
92
+ with(@branch_name).returns build = mock
93
+ expect(Fuci::TeamCity::Build.create).to_equal build
94
+ end
95
+ end
96
+
97
+ describe 'when a branch is not passed in the cli' do
98
+ before do
99
+ @default_branch = Fuci::TeamCity.stubs :default_branch
100
+ end
101
+
102
+ describe 'when a default branch is configured' do
103
+ before do
104
+ @branch_name = 'branch'
105
+ @default_branch.returns @branch_name
106
+ end
107
+
108
+ it 'creates a new build with the default branch' do
109
+ Fuci::TeamCity::Build.stubs(:project).
110
+ returns project = mock
111
+ project.stubs(:latest_build_from).
112
+ with(@branch_name).returns build = mock
113
+ expect(Fuci::TeamCity::Build.create).to_equal build
114
+ end
115
+ end
116
+
117
+ describe 'when a default branch is not configured' do
118
+ it 'logs that no default branch is configured' do
119
+ Fuci::TeamCity::Build.expects(:puts).
120
+ with 'No default branch is configured.'
121
+ Fuci::TeamCity::Build.expects :exit
122
+
123
+ Fuci::TeamCity::Build.create
124
+ end
125
+ end
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,54 @@
1
+ require_relative '../../../spec_helper'
2
+ require_relative '../../../../lib/fuci/team_city/builds'
3
+ require 'nokogiri'
4
+
5
+ describe Fuci::TeamCity::Builds do
6
+ before do
7
+ xml = File.read 'spec/sample_data/builds.xml'
8
+ @xml_doc = Nokogiri::XML xml
9
+ @builds = Fuci::TeamCity::Builds.new @xml_doc
10
+ end
11
+
12
+ describe 'composition' do
13
+ it 'inherits from Enumerable' do
14
+ expect(@builds).to_be_kind_of Enumerable
15
+ end
16
+ end
17
+
18
+ describe '#initialize' do
19
+ it 'sets the xml_doc' do
20
+ expect(@builds.xml_doc).to_equal @xml_doc
21
+ end
22
+ end
23
+
24
+ describe '#each' do
25
+ it 'instantiates each build node with Build' do
26
+ (xml_doc = mock).stubs(:xpath).
27
+ with('//build').
28
+ returns [element = mock]
29
+ @builds.stubs(:xml_doc).returns xml_doc
30
+ Fuci::TeamCity::Build.stubs(:new).
31
+ with(element).
32
+ returns build = mock
33
+
34
+ expects(:puts).with build
35
+
36
+ @builds.each { |build| puts build }
37
+ end
38
+ end
39
+
40
+ describe '.from_resource' do
41
+ it 'returns a new Builds object an xml doc' do
42
+ Fuci::TeamCity::XmlDocBuilder.stubs(:from_resource).
43
+ with(resource = '/resource').
44
+ returns xml_doc = mock
45
+ Fuci::TeamCity::Builds.stubs(:new).
46
+ with(xml_doc).
47
+ returns builds = mock
48
+
49
+ from_resource = Fuci::TeamCity::Builds.from_resource resource
50
+
51
+ expect(from_resource).to_equal builds
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,31 @@
1
+ require_relative '../../../spec_helper'
2
+ require_relative '../../../../lib/fuci/team_city/cli_options'
3
+
4
+ describe Fuci::TeamCity::CliOptions do
5
+ describe '.branch' do
6
+ before { @argv = Fuci::TeamCity::CliOptions.stubs :argv }
7
+
8
+ describe 'when a branch is passed in' do
9
+ before { @argv.returns [@branch = 'cool_ci_branch'] }
10
+
11
+ it 'returns the first argument of argv' do
12
+ expect(Fuci::TeamCity::CliOptions.branch).to_equal @branch
13
+ end
14
+ end
15
+
16
+ describe 'when a branch is not passed in' do
17
+ before { @argv.returns [] }
18
+
19
+ it 'returns nil' do
20
+ expect(Fuci::TeamCity::CliOptions.branch).to_be_nil
21
+ end
22
+ end
23
+ end
24
+
25
+ describe '.argv' do
26
+ it 'delegates to Fuci::CliOptions' do
27
+ Fuci::CliOptions.stubs(:argv).returns argv = ['an option']
28
+ expect(Fuci::TeamCity::CliOptions.argv).to_equal argv
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,71 @@
1
+ require_relative '../../../spec_helper'
2
+ require_relative '../../../../lib/fuci/team_city/project'
3
+
4
+ describe Fuci::TeamCity::Project do
5
+ before do
6
+ xml = File.read('spec/sample_data/project.xml')
7
+ @xml_doc = Nokogiri::XML xml
8
+ @project = Fuci::TeamCity::Project.new @xml_doc
9
+ end
10
+
11
+ describe '#initialize' do
12
+ it 'instantiates the xml_doc' do
13
+ expect(@project.xml_doc).to_equal @xml_doc
14
+ end
15
+ end
16
+
17
+ describe '#latest_build_from' do
18
+ it 'returns a wrapped build from the branch name' do
19
+ @project.stubs(:builds_from).
20
+ with(branch_name = 'branch_name').
21
+ returns builds = OpenStruct.new(first: build = mock)
22
+
23
+ expect(@project.latest_build_from branch_name ).to_equal build
24
+ end
25
+ end
26
+
27
+ describe '#builds_resource' do
28
+ it 'returns the build resource from the xml_doc' do
29
+ resource = '/httpAuth/app/rest/buildTypes/id:bt2/builds'
30
+ expect(@project.send :builds_resource, 'master' ).to_equal resource
31
+ end
32
+ end
33
+
34
+ describe '#builds_from' do
35
+ it 'calls from_resource on Builds with the builds resource' do
36
+ @project.stubs(:builds_resource).
37
+ with(branch_name = 'branch name').
38
+ returns resource = mock
39
+ Fuci::TeamCity::Builds.stubs(:from_resource).
40
+ with(resource).
41
+ returns builds = mock
42
+
43
+ builds_from = @project.send :builds_from, branch_name
44
+
45
+ expect(builds_from).to_equal builds
46
+ end
47
+ end
48
+
49
+ describe '.from_name' do
50
+ it 'creates a new project object with an xml doc from the response' do
51
+ resource = "/httpAuth/app/rest/projects/name:#{name = 'name'}"
52
+ Fuci::TeamCity::Project.stubs(:project_name).returns name
53
+ Fuci::TeamCity::XmlDocBuilder.stubs(:from_resource).
54
+ with(resource).
55
+ returns xml_doc = mock
56
+ Fuci::TeamCity::Project.stubs(:new).
57
+ with(xml_doc).
58
+ returns project = mock
59
+
60
+ from_name = Fuci::TeamCity::Project.from_name
61
+ expect(from_name).to_equal project
62
+ end
63
+ end
64
+
65
+ describe '.name' do
66
+ it 'delegates to Fuci::TeamCity.project' do
67
+ Fuci::TeamCity.stubs(:project).returns project = mock
68
+ expect(Fuci::TeamCity::Project.project_name).to_equal project
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,99 @@
1
+ require_relative '../../../spec_helper'
2
+ require_relative '../../../../lib/fuci/team_city/request'
3
+
4
+ stub_class 'Net::HTTP::Get'
5
+
6
+ describe Fuci::TeamCity::Request do
7
+ before do
8
+ @request = Fuci::TeamCity::Request.new @resource = 'resource'
9
+ end
10
+
11
+ describe '#initialize' do
12
+ it 'sets the resource passed in' do
13
+ expect(@request.resource).to_equal @resource
14
+ end
15
+ end
16
+
17
+ describe '#call' do
18
+ before do
19
+ @body = 'body'
20
+ @request.stubs(:start).returns OpenStruct.new(body: @body)
21
+ @request.stubs(:request_obj).returns request_obj = mock
22
+ @request.stubs(:username).returns username = 'username'
23
+ @request.stubs(:password).returns password = 'password'
24
+ request_obj.expects(:basic_auth).with username, password
25
+ end
26
+
27
+ it 'it returns the body of the response' do
28
+ expect(@request.call).to_equal @body
29
+ end
30
+ end
31
+
32
+ describe '#request_obj' do
33
+ it 'returns a HTTP::Get object' do
34
+ @request.stubs(:uri).returns uri = mock
35
+ Net::HTTP::Get.stubs(:new).with(uri).returns get = mock
36
+ expect(@request.send :request_obj ).to_equal get
37
+ end
38
+ end
39
+
40
+ describe '#username' do
41
+ it 'delegates to Fuci::TeamCity' do
42
+ Fuci::TeamCity.stubs(:username).returns username = 'username'
43
+ expect(@request.send :username ).to_equal username
44
+ end
45
+ end
46
+
47
+ describe '#password' do
48
+ it 'delegates to Fuci::TeamCity' do
49
+ Fuci::TeamCity.stubs(:password).returns password = 'password'
50
+ expect(@request.send :password ).to_equal password
51
+ end
52
+ end
53
+
54
+ describe '#uri' do
55
+ it 'wraps the url passed in a URI' do
56
+ base_url = 'base url'
57
+ url = base_url + @resource
58
+ @request.stubs(:base_url).returns base_url
59
+ @request.stubs(:URI).with(url).returns uri = mock
60
+
61
+ expect(@request.send :uri ).to_equal uri
62
+ end
63
+ end
64
+
65
+ describe '#base_url' do
66
+ it 'concats the scheme and the domain' do
67
+ @request.stubs(:scheme).returns scheme = 'http'
68
+ @request.stubs(:host).returns host = 'www.domain.com'
69
+ base_url = "#{scheme}://#{host}"
70
+
71
+ expect(@request.send :base_url ).to_equal base_url
72
+ end
73
+ end
74
+
75
+ describe '#scheme' do
76
+ it 'returns http' do
77
+ expect(@request.send :scheme ).to_equal 'http'
78
+ end
79
+ end
80
+
81
+ describe '#host' do
82
+ it 'delegates to Fuci::TeamCity' do
83
+ Fuci::TeamCity.stubs(:host).returns host = 'host'
84
+ expect(@request.send :host ).to_equal host
85
+ end
86
+ end
87
+
88
+ describe '#start' do
89
+ it 'starts a request with the uri hostname and uri port' do
90
+ host = 'host'
91
+ port = 8012
92
+ uri = OpenStruct.new(host: host, port: port)
93
+ @request.stubs(:uri).returns uri
94
+ Net::HTTP.expects(:start).with host, port
95
+
96
+ @request.send :start
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,46 @@
1
+ require_relative '../../../spec_helper'
2
+ require_relative '../../../../lib/fuci/team_city/server'
3
+
4
+ stub_class 'Fuci::TeamCity::Build' do
5
+ public
6
+ def self.create
7
+ end
8
+ end
9
+
10
+ describe Fuci::TeamCity::Server do
11
+ before do
12
+ Fuci::TeamCity::Build.stubs(:create).
13
+ returns @build = mock
14
+ @server = Fuci::TeamCity::Server.new
15
+ end
16
+
17
+ describe 'composition' do
18
+ it 'inherits from Fuci::Server' do
19
+ expect(@server).to_be_kind_of Fuci::Server
20
+ end
21
+ end
22
+
23
+ describe '#initialize' do
24
+ it 'sets build' do
25
+ expect(@server.build).to_equal @build
26
+ end
27
+ end
28
+
29
+ describe '#build_status' do
30
+ it 'delegates to #build' do
31
+ @server.stubs(:build).returns build = mock
32
+ build.stubs(:status_code).returns build_status = mock
33
+
34
+ expect(@server.build_status).to_equal build_status
35
+ end
36
+ end
37
+
38
+ describe '#fetch_log' do
39
+ it 'delegates to #build' do
40
+ @server.stubs(:build).returns build = mock
41
+ build.stubs(:log).returns log = mock
42
+
43
+ expect(@server.fetch_log).to_equal log
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,20 @@
1
+ require_relative '../../../spec_helper'
2
+ require_relative '../../../../lib/fuci/team_city/xml_doc_builder'
3
+
4
+ stub_class 'Fuci::TeamCity::Request'
5
+
6
+ describe Fuci::TeamCity::XmlDocBuilder do
7
+ describe '.from_resource' do
8
+ it 'returns an xml document from the resource passed in' do
9
+ response = '<response/>'
10
+ resource = "/httpAuth/app/rest"
11
+ Fuci::TeamCity::Request.stubs(:new).
12
+ with(resource).returns request = mock
13
+ request.stubs(:call).returns response
14
+ Nokogiri.stubs(:XML).with(response).returns xml_doc = mock
15
+
16
+ from_resource = Fuci::TeamCity::XmlDocBuilder.from_resource resource
17
+ expect(from_resource).to_equal xml_doc
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,53 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ module Fuci
4
+ def self.configure; end;
5
+ end
6
+
7
+ require_relative '../../../lib/fuci/team_city'
8
+ stub_class 'Fuci::TeamCity::Project'
9
+
10
+ describe Fuci::TeamCity do
11
+ describe 'composition' do
12
+ it 'includes Fuci::Configurable' do
13
+ expect(Fuci::TeamCity.ancestors).to_include Fuci::Configurable
14
+ end
15
+ end
16
+
17
+ describe '#host' do
18
+ it('is an accessor') { assert_accessor :host }
19
+ end
20
+
21
+ describe '#username' do
22
+ it('is an accessor') { assert_accessor :username }
23
+ end
24
+
25
+ describe '#password' do
26
+ it('is an accessor') { assert_accessor :password }
27
+ end
28
+
29
+ describe '#default_branch' do
30
+ it('is an accessor') { assert_accessor :default_branch }
31
+ end
32
+
33
+ describe '#project' do
34
+ it('is an accessor') { assert_accessor :project }
35
+ end
36
+
37
+ describe '.add_testers' do
38
+ it 'delegates to Fuci' do
39
+ Fuci.expects(:add_testers).with testers = mock
40
+ Fuci::TeamCity.add_testers testers
41
+ end
42
+ end
43
+ end
44
+
45
+ def assert_accessor accessor
46
+ object = Object.new
47
+
48
+ expect(Fuci::TeamCity.send accessor).to_be_nil
49
+ Fuci::TeamCity.send :"#{accessor.to_s}=", object
50
+ expect(Fuci::TeamCity.send accessor).to_equal object
51
+
52
+ Fuci::TeamCity.instance_variable_set :"@#{accessor.to_s}", nil
53
+ end
@@ -0,0 +1,103 @@
1
+ <?xml version="1.0" ?>
2
+ <builds count="100" nextHref="/httpAuth/app/rest/buildTypes/id:bt36/builds?count=100&start=100">
3
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:8134" id="8134" number="354" startDate="20130808T171657-0400" status="ERROR" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=8134&buildTypeId=bt36"/>
4
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:8111" id="8111" number="353" startDate="20130806T100535-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=8111&buildTypeId=bt36"/>
5
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:8110" id="8110" number="352" startDate="20130806T094353-0400" status="ERROR" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=8110&buildTypeId=bt36"/>
6
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:8106" id="8106" number="351" startDate="20130805T165809-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=8106&buildTypeId=bt36"/>
7
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:8105" id="8105" number="350" startDate="20130805T165006-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=8105&buildTypeId=bt36"/>
8
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:8102" id="8102" number="349" startDate="20130805T144634-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=8102&buildTypeId=bt36"/>
9
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:8095" id="8095" number="348" startDate="20130805T111519-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=8095&buildTypeId=bt36"/>
10
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:8093" id="8093" number="347" startDate="20130805T100639-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=8093&buildTypeId=bt36"/>
11
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:8092" id="8092" number="346" startDate="20130802T173345-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=8092&buildTypeId=bt36"/>
12
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:8090" id="8090" number="345" startDate="20130802T151544-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=8090&buildTypeId=bt36"/>
13
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:8083" id="8083" number="344" startDate="20130801T133518-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=8083&buildTypeId=bt36"/>
14
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:8080" id="8080" number="343" startDate="20130801T104827-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=8080&buildTypeId=bt36"/>
15
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:8079" id="8079" number="342" startDate="20130801T102430-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=8079&buildTypeId=bt36"/>
16
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:8078" id="8078" number="341" startDate="20130801T093637-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=8078&buildTypeId=bt36"/>
17
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:8073" id="8073" number="340" startDate="20130731T153803-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=8073&buildTypeId=bt36"/>
18
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:8051" id="8051" number="339" startDate="20130725T170437-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=8051&buildTypeId=bt36"/>
19
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:8045" id="8045" number="338" startDate="20130725T100205-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=8045&buildTypeId=bt36"/>
20
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:8029" id="8029" number="337" startDate="20130718T143027-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=8029&buildTypeId=bt36"/>
21
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:8024" id="8024" number="336" startDate="20130718T105659-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=8024&buildTypeId=bt36"/>
22
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:8005" id="8005" number="335" startDate="20130717T110123-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=8005&buildTypeId=bt36"/>
23
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:8001" id="8001" number="334" startDate="20130717T090737-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=8001&buildTypeId=bt36"/>
24
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7999" id="7999" number="333" startDate="20130716T160512-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7999&buildTypeId=bt36"/>
25
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7997" id="7997" number="332" startDate="20130716T155713-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7997&buildTypeId=bt36"/>
26
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7996" id="7996" number="331" startDate="20130716T155335-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7996&buildTypeId=bt36"/>
27
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7995" id="7995" number="330" startDate="20130716T152619-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7995&buildTypeId=bt36"/>
28
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7982" id="7982" number="329" startDate="20130715T134525-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7982&buildTypeId=bt36"/>
29
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7981" id="7981" number="328" startDate="20130715T114610-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7981&buildTypeId=bt36"/>
30
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7979" id="7979" number="327" startDate="20130715T110008-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7979&buildTypeId=bt36"/>
31
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7978" id="7978" number="326" startDate="20130712T173828-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7978&buildTypeId=bt36"/>
32
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7975" id="7975" number="325" startDate="20130712T160252-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7975&buildTypeId=bt36"/>
33
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7972" id="7972" number="324" startDate="20130712T120627-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7972&buildTypeId=bt36"/>
34
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7971" id="7971" number="323" startDate="20130712T115417-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7971&buildTypeId=bt36"/>
35
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7966" id="7966" number="322" startDate="20130712T093439-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7966&buildTypeId=bt36"/>
36
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7964" id="7964" number="321" startDate="20130711T170753-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7964&buildTypeId=bt36"/>
37
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7962" id="7962" number="320" startDate="20130711T165153-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7962&buildTypeId=bt36"/>
38
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7955" id="7955" number="319" startDate="20130711T155625-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7955&buildTypeId=bt36"/>
39
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7937" id="7937" number="317" startDate="20130710T171042-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7937&buildTypeId=bt36"/>
40
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7934" id="7934" number="316" startDate="20130710T112008-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7934&buildTypeId=bt36"/>
41
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7932" id="7932" number="315" startDate="20130709T163555-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7932&buildTypeId=bt36"/>
42
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7929" id="7929" number="314" startDate="20130709T141530-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7929&buildTypeId=bt36"/>
43
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7928" id="7928" number="313" startDate="20130709T140450-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7928&buildTypeId=bt36"/>
44
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7562" id="7562" number="312" startDate="20130513T135844-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7562&buildTypeId=bt36"/>
45
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7557" id="7557" number="311" startDate="20130509T160943-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7557&buildTypeId=bt36"/>
46
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7548" id="7548" number="310" startDate="20130509T133457-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7548&buildTypeId=bt36"/>
47
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7495" id="7495" number="309" startDate="20130506T090142-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7495&buildTypeId=bt36"/>
48
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7467" id="7467" number="308" startDate="20130502T165608-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7467&buildTypeId=bt36"/>
49
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7434" id="7434" number="307" startDate="20130502T094036-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7434&buildTypeId=bt36"/>
50
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7433" id="7433" number="306" startDate="20130502T093204-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7433&buildTypeId=bt36"/>
51
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7432" id="7432" number="305" startDate="20130502T090611-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7432&buildTypeId=bt36"/>
52
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7431" id="7431" number="304" startDate="20130502T085749-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7431&buildTypeId=bt36"/>
53
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7429" id="7429" number="303" startDate="20130502T084748-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7429&buildTypeId=bt36"/>
54
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7421" id="7421" number="301" startDate="20130501T162212-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7421&buildTypeId=bt36"/>
55
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7413" id="7413" number="300" startDate="20130501T141753-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7413&buildTypeId=bt36"/>
56
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7354" id="7354" number="299" startDate="20130429T142246-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7354&buildTypeId=bt36"/>
57
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7352" id="7352" number="298" startDate="20130429T133346-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7352&buildTypeId=bt36"/>
58
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7350" id="7350" number="297" startDate="20130429T130331-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7350&buildTypeId=bt36"/>
59
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7348" id="7348" number="296" startDate="20130429T115825-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7348&buildTypeId=bt36"/>
60
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7338" id="7338" number="295" startDate="20130426T163023-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7338&buildTypeId=bt36"/>
61
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7291" id="7291" number="293" startDate="20130425T110649-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7291&buildTypeId=bt36"/>
62
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7262" id="7262" number="292" startDate="20130419T101530-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7262&buildTypeId=bt36"/>
63
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7253" id="7253" number="291" startDate="20130418T154947-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7253&buildTypeId=bt36"/>
64
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7244" id="7244" number="290" startDate="20130418T142548-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7244&buildTypeId=bt36"/>
65
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7238" id="7238" number="289" startDate="20130418T114430-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7238&buildTypeId=bt36"/>
66
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7222" id="7222" number="286" startDate="20130417T145041-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7222&buildTypeId=bt36"/>
67
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7221" id="7221" number="285" startDate="20130417T144715-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7221&buildTypeId=bt36"/>
68
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7220" id="7220" number="284" startDate="20130417T144000-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7220&buildTypeId=bt36"/>
69
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7214" id="7214" number="282" startDate="20130417T140830-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7214&buildTypeId=bt36"/>
70
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7190" id="7190" number="281" startDate="20130416T171533-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7190&buildTypeId=bt36"/>
71
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7189" id="7189" number="280" startDate="20130416T170215-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7189&buildTypeId=bt36"/>
72
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7161" id="7161" number="279" startDate="20130411T164736-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7161&buildTypeId=bt36"/>
73
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7160" id="7160" number="278" startDate="20130411T164410-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7160&buildTypeId=bt36"/>
74
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7119" id="7119" number="274" startDate="20130409T090807-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7119&buildTypeId=bt36"/>
75
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7118" id="7118" number="273" startDate="20130409T090213-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7118&buildTypeId=bt36"/>
76
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7089" id="7089" number="272" startDate="20130404T172646-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7089&buildTypeId=bt36"/>
77
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7087" id="7087" number="271" startDate="20130404T172337-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7087&buildTypeId=bt36"/>
78
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7083" id="7083" number="270" startDate="20130404T164748-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7083&buildTypeId=bt36"/>
79
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7080" id="7080" number="269" startDate="20130404T162706-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7080&buildTypeId=bt36"/>
80
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7079" id="7079" number="268" startDate="20130404T162303-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7079&buildTypeId=bt36"/>
81
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7078" id="7078" number="267" startDate="20130404T161833-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7078&buildTypeId=bt36"/>
82
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:7077" id="7077" number="266" startDate="20130404T161448-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=7077&buildTypeId=bt36"/>
83
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:6978" id="6978" number="265" startDate="20130401T144711-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=6978&buildTypeId=bt36"/>
84
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:6976" id="6976" number="264" startDate="20130401T144258-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=6976&buildTypeId=bt36"/>
85
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:6966" id="6966" number="263" startDate="20130401T120137-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=6966&buildTypeId=bt36"/>
86
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:6965" id="6965" number="262" startDate="20130401T115711-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=6965&buildTypeId=bt36"/>
87
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:6943" id="6943" number="261" startDate="20130329T132107-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=6943&buildTypeId=bt36"/>
88
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:6941" id="6941" number="260" startDate="20130329T114849-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=6941&buildTypeId=bt36"/>
89
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:6940" id="6940" number="259" startDate="20130329T114524-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=6940&buildTypeId=bt36"/>
90
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:6938" id="6938" number="258" startDate="20130329T112457-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=6938&buildTypeId=bt36"/>
91
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:6935" id="6935" number="257" startDate="20130329T102402-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=6935&buildTypeId=bt36"/>
92
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:6932" id="6932" number="256" startDate="20130329T090355-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=6932&buildTypeId=bt36"/>
93
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:6931" id="6931" number="255" startDate="20130329T083847-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=6931&buildTypeId=bt36"/>
94
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:6929" id="6929" number="254" startDate="20130328T170512-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=6929&buildTypeId=bt36"/>
95
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:6928" id="6928" number="253" startDate="20130328T160845-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=6928&buildTypeId=bt36"/>
96
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:6927" id="6927" number="252" startDate="20130328T160136-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=6927&buildTypeId=bt36"/>
97
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:6903" id="6903" number="249" startDate="20130328T111616-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=6903&buildTypeId=bt36"/>
98
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:6875" id="6875" number="248" startDate="20130327T103052-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=6875&buildTypeId=bt36"/>
99
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:6873" id="6873" number="247" startDate="20130326T161508-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=6873&buildTypeId=bt36"/>
100
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:6871" id="6871" number="246" startDate="20130326T151415-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=6871&buildTypeId=bt36"/>
101
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:6869" id="6869" number="245" startDate="20130326T142200-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=6869&buildTypeId=bt36"/>
102
+ <build buildTypeId="bt36" href="/httpAuth/app/rest/builds/id:6868" id="6868" number="244" startDate="20130326T134942-0400" status="SUCCESS" webUrl="http://subdomain.domain.com:8101/viewLog.html?buildId=6868&buildTypeId=bt36"/>
103
+ </builds>
@@ -0,0 +1,21 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2
+ <project description="" archived="false" webUrl="http://subdomain.domain.com:8101/project.html?projectId=project2" id="project2" name="sloth_finder" href="/httpAuth/app/rest/projects/id:project2">
3
+ <buildTypes>
4
+ <buildType id="bt15" name="me-ci" href="/httpAuth/app/rest/buildTypes/id:bt15" projectName="sloth_finder" projectId="project2" webUrl="http://subdomain.domain.com:8101/viewType.html?buildTypeId=bt15"/>
5
+ <buildType id="bt36" name="you-ci" href="/httpAuth/app/rest/buildTypes/id:bt36" projectName="sloth_finder" projectId="project2" webUrl="http://subdomain.domain.com:8101/viewType.html?buildTypeId=bt36"/>
6
+ <buildType id="bt38" name="ya-ci" href="/httpAuth/app/rest/buildTypes/id:bt38" projectName="sloth_finder" projectId="project2" webUrl="http://subdomain.domain.com:8101/viewType.html?buildTypeId=bt38"/>
7
+ <buildType id="bt14" name="durk-ci" href="/httpAuth/app/rest/buildTypes/id:bt14" projectName="sloth_finder" projectId="project2" webUrl="http://subdomain.domain.com:8101/viewType.html?buildTypeId=bt14"/>
8
+ <buildType id="bt16" name="moin-ci" href="/httpAuth/app/rest/buildTypes/id:bt16" projectName="sloth_finder" projectId="project2" webUrl="http://subdomain.domain.com:8101/viewType.html?buildTypeId=bt16"/>
9
+ <buildType id="bt2" name="master" href="/httpAuth/app/rest/buildTypes/id:bt2" projectName="sloth_finder" projectId="project2" webUrl="http://subdomain.domain.com:8101/viewType.html?buildTypeId=bt2"/>
10
+ <buildType id="bt32" name="cray-ci" href="/httpAuth/app/rest/buildTypes/id:bt32" projectName="sloth_finder" projectId="project2" webUrl="http://subdomain.domain.com:8101/viewType.html?buildTypeId=bt32"/>
11
+ <buildType id="bt11" name="kurnk-ci" href="/httpAuth/app/rest/buildTypes/id:bt11" projectName="sloth_finder" projectId="project2" webUrl="http://subdomain.domain.com:8101/viewType.html?buildTypeId=bt11"/>
12
+ <buildType id="bt9" name="norla-ci" href="/httpAuth/app/rest/buildTypes/id:bt9" projectName="sloth_finder" projectId="project2" webUrl="http://subdomain.domain.com:8101/viewType.html?buildTypeId=bt9"/>
13
+ <buildType id="bt10" name="production" href="/httpAuth/app/rest/buildTypes/id:bt10" projectName="sloth_finder" projectId="project2" webUrl="http://subdomain.domain.com:8101/viewType.html?buildTypeId=bt10"/>
14
+ <buildType id="bt12" name="larry-ci" href="/httpAuth/app/rest/buildTypes/id:bt12" projectName="sloth_finder" projectId="project2" webUrl="http://subdomain.domain.com:8101/viewType.html?buildTypeId=bt12"/>
15
+ </buildTypes>
16
+ <templates>
17
+ <buildType id="btTemplate3" name="BranchExtractedFromName" href="/httpAuth/app/rest/buildTypes/id:(template:btTemplate3)" projectName="sloth_finder" projectId="project2"/>
18
+ <buildType id="btTemplate6" name="BranchExtractedFromNameBackup" href="/httpAuth/app/rest/buildTypes/id:(template:btTemplate6)" projectName="sloth_finder" projectId="project2"/>
19
+ </templates>
20
+ <parameters/>
21
+ </project>
@@ -0,0 +1,30 @@
1
+ require 'minitest/spec/expect'
2
+ require 'minitest/autorun'
3
+ require 'mocha/setup'
4
+ require 'ostruct'
5
+
6
+ def stub_class klass
7
+ objects = klass.split '::'
8
+
9
+ klass = objects.inject(Object) do |memo, obj|
10
+ unless obj == objects.last
11
+ begin
12
+ memo.const_get obj
13
+ rescue
14
+ memo.const_set obj, Module.new
15
+ end
16
+ else
17
+ begin
18
+ memo.const_get obj
19
+ rescue
20
+ memo.const_set obj, Class.new
21
+ end
22
+ end
23
+
24
+ memo.const_get obj
25
+ end
26
+
27
+ klass.class_eval do
28
+ yield if block_given?
29
+ end
30
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fuci-team_city
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dave Jachimiak
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-08-07 00:00:00.000000000 Z
11
+ date: 2013-08-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fuci
@@ -16,14 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - ~>
18
18
  - !ruby/object:Gem::Version
19
- version: '0.3'
19
+ version: '0.4'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ~>
25
25
  - !ruby/object:Gem::Version
26
- version: '0.3'
26
+ version: '0.4'
27
+ - !ruby/object:Gem::Dependency
28
+ name: nokogiri
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: bundler
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -83,18 +97,39 @@ dependencies:
83
97
  description: A local runner for your TeamCity build failures.
84
98
  email:
85
99
  - dave.jachimiak@gmail.com
86
- executables: []
100
+ executables:
101
+ - fuci
87
102
  extensions: []
88
103
  extra_rdoc_files: []
89
104
  files:
90
105
  - .gitignore
106
+ - CHANGELOG.md
91
107
  - Gemfile
92
108
  - LICENSE.txt
93
109
  - README.md
94
110
  - Rakefile
111
+ - bin/fuci
95
112
  - fuci-team_city.gemspec
96
113
  - lib/fuci/team_city.rb
114
+ - lib/fuci/team_city/build.rb
115
+ - lib/fuci/team_city/builds.rb
116
+ - lib/fuci/team_city/cli_options.rb
117
+ - lib/fuci/team_city/project.rb
118
+ - lib/fuci/team_city/request.rb
119
+ - lib/fuci/team_city/server.rb
97
120
  - lib/fuci/team_city/version.rb
121
+ - lib/fuci/team_city/xml_doc_builder.rb
122
+ - spec/lib/fuci/team_city/build_spec.rb
123
+ - spec/lib/fuci/team_city/builds_spec.rb
124
+ - spec/lib/fuci/team_city/cli_options_spec.rb
125
+ - spec/lib/fuci/team_city/project_spec.rb
126
+ - spec/lib/fuci/team_city/request_spec.rb
127
+ - spec/lib/fuci/team_city/server_spec.rb
128
+ - spec/lib/fuci/team_city/xml_doc_builder_spec.rb
129
+ - spec/lib/fuci/team_city_spec.rb
130
+ - spec/sample_data/builds.xml
131
+ - spec/sample_data/project.xml
132
+ - spec/spec_helper.rb
98
133
  homepage: https://github.com/davejachimiak/fuci-team_city
99
134
  licenses:
100
135
  - MIT
@@ -119,5 +154,16 @@ rubygems_version: 2.0.6
119
154
  signing_key:
120
155
  specification_version: 4
121
156
  summary: Run failures from your recent TeamCity builds locally.
122
- test_files: []
157
+ test_files:
158
+ - spec/lib/fuci/team_city/build_spec.rb
159
+ - spec/lib/fuci/team_city/builds_spec.rb
160
+ - spec/lib/fuci/team_city/cli_options_spec.rb
161
+ - spec/lib/fuci/team_city/project_spec.rb
162
+ - spec/lib/fuci/team_city/request_spec.rb
163
+ - spec/lib/fuci/team_city/server_spec.rb
164
+ - spec/lib/fuci/team_city/xml_doc_builder_spec.rb
165
+ - spec/lib/fuci/team_city_spec.rb
166
+ - spec/sample_data/builds.xml
167
+ - spec/sample_data/project.xml
168
+ - spec/spec_helper.rb
123
169
  has_rdoc: