fuci-team_city 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml 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: