ruby_tfs 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE.md +7 -0
- data/README.md +55 -0
- data/Rakefile +8 -0
- data/lib/tfs/builds.rb +29 -0
- data/lib/tfs/changesets.rb +13 -0
- data/lib/tfs/class_helpers.rb +19 -0
- data/lib/tfs/client.rb +53 -0
- data/lib/tfs/configuration.rb +78 -0
- data/lib/tfs/projects.rb +19 -0
- data/lib/tfs/query_engine.rb +103 -0
- data/lib/tfs/queryable.rb +42 -0
- data/lib/tfs/work_items.rb +42 -0
- data/lib/tfs.rb +30 -0
- data/ruby_tfs.gemspec +23 -0
- data/spec/fixtures/cassettes/builds.yml +405 -0
- data/spec/fixtures/cassettes/changeset_queries.yml +374 -0
- data/spec/fixtures/cassettes/changesets.yml +237 -0
- data/spec/fixtures/cassettes/project_workitems_queries.yml +793 -0
- data/spec/fixtures/cassettes/projects.yml +210 -0
- data/spec/fixtures/cassettes/workitems.yml +2037 -0
- data/spec/spec_helper.rb +27 -0
- data/spec/tfs/builds_spec.rb +34 -0
- data/spec/tfs/changesets_spec.rb +34 -0
- data/spec/tfs/client_spec.rb +62 -0
- data/spec/tfs/projects_spec.rb +35 -0
- data/spec/tfs/query_engine_spec.rb +37 -0
- data/spec/tfs/work_items_spec.rb +68 -0
- data/spec/tfs_spec.rb +25 -0
- metadata +123 -0
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'vcr'
|
3
|
+
require 'simplecov'
|
4
|
+
require 'pry'
|
5
|
+
|
6
|
+
require_relative "../lib/tfs"
|
7
|
+
|
8
|
+
SimpleCov.start do
|
9
|
+
add_filter "spec/"
|
10
|
+
add_filter ".gems/"
|
11
|
+
end
|
12
|
+
|
13
|
+
VCR.configure do |config|
|
14
|
+
config.cassette_library_dir = 'spec/fixtures/cassettes'
|
15
|
+
config.hook_into :webmock
|
16
|
+
config.default_cassette_options = { :record => :new_episodes }
|
17
|
+
end
|
18
|
+
|
19
|
+
RSpec.configure do |config|
|
20
|
+
config.extend VCR::RSpec::Macros
|
21
|
+
config.mock_with :flexmock
|
22
|
+
end
|
23
|
+
|
24
|
+
def load_result_fixture(fixture)
|
25
|
+
path = File.join File.dirname(__FILE__), 'fixtures', fixture
|
26
|
+
File.open(path) {|f| f.read }
|
27
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
@pending
|
4
|
+
describe TFS::Builds do
|
5
|
+
let(:client) { TFS.client }
|
6
|
+
|
7
|
+
before do
|
8
|
+
TFS.configure do |config|
|
9
|
+
config.endpoint = "https://codeplexodata.cloudapp.net/TFS29"
|
10
|
+
config.username ='snd\plukevdh_cp'
|
11
|
+
config.password = 'garbage'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# TODO: Very poor testing against Codeplex
|
16
|
+
# because we have no builds. Eventually
|
17
|
+
# migrating this over to visualstudio.com
|
18
|
+
context "finders" do
|
19
|
+
use_vcr_cassette 'builds'
|
20
|
+
|
21
|
+
it "can get builds from TFS, limits to 50" do
|
22
|
+
results = TFS::Builds.all
|
23
|
+
results.count.should == 0
|
24
|
+
end
|
25
|
+
|
26
|
+
it "can query in the raw" do
|
27
|
+
results = TFS::Builds.odata_query("Status eq 'Succeeded'").limit(5).run
|
28
|
+
results.each do |build|
|
29
|
+
build.Status.should == 'Succeeded'
|
30
|
+
end
|
31
|
+
results.count.should == 0
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe TFS::Changesets do
|
4
|
+
let(:client) { TFS.client }
|
5
|
+
before do
|
6
|
+
TFS.configure do |config|
|
7
|
+
config.endpoint = "https://codeplexodata.cloudapp.net/TFS29"
|
8
|
+
config.username ='snd\plukevdh_cp'
|
9
|
+
config.password = 'garbage'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
context "finders" do
|
14
|
+
use_vcr_cassette 'changesets'
|
15
|
+
|
16
|
+
it "can get changesets from TFS" do
|
17
|
+
results = TFS::Changesets.all
|
18
|
+
results.count.should == 2
|
19
|
+
end
|
20
|
+
|
21
|
+
it "can get a project by name" do
|
22
|
+
result = TFS::Changesets.find(23460)
|
23
|
+
result.Comment.should =~ /use the repo to persist\/update/
|
24
|
+
end
|
25
|
+
|
26
|
+
it "can query in the raw" do
|
27
|
+
results = TFS::Changesets.odata_query("Committer eq 'plukevdh_cp'").run
|
28
|
+
results.each do |build|
|
29
|
+
build.Committer.should end_with 'plukevdh_cp'
|
30
|
+
end
|
31
|
+
results.count.should == 1
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe TFS::Client do
|
4
|
+
let(:provider) { flexmock(:provider) }
|
5
|
+
let(:client) { TFS::Client.new(provider: provider) }
|
6
|
+
|
7
|
+
it "should be able to connect to tfs with defaults" do
|
8
|
+
client = TFS::Client.new(endpoint: "http://fake.tfs.net/tfs:8080",
|
9
|
+
username: "test", password: "123", provider: provider)
|
10
|
+
|
11
|
+
provider.should_receive(new: true).with("http://fake.tfs.net/tfs:8080",
|
12
|
+
{:username=>"test", :password=>"123",
|
13
|
+
:headers=>{:accept=>"application/json", :user_agent=>"TFS Ruby Gem"},
|
14
|
+
:request=>{:open_timeout=>5, :timeout=>10},
|
15
|
+
:verify_ssl=>false}).once
|
16
|
+
|
17
|
+
client.connect
|
18
|
+
end
|
19
|
+
|
20
|
+
context "with odata" do
|
21
|
+
let(:client) { TFS::Client.new(endpoint: "https://codeplexodata.cloudapp.net/TFS29",
|
22
|
+
username: 'snd\plukevdh_cp', password: 'garbage') }
|
23
|
+
|
24
|
+
context "individual queries" do
|
25
|
+
use_vcr_cassette "changeset_queries"
|
26
|
+
|
27
|
+
before do
|
28
|
+
client.connect
|
29
|
+
end
|
30
|
+
|
31
|
+
it "creates queries for data" do
|
32
|
+
results = client.changesets
|
33
|
+
results.should be_a(TFS::QueryEngine)
|
34
|
+
results.type.should == TFS::Changesets
|
35
|
+
end
|
36
|
+
|
37
|
+
it "can query with a nice api" do
|
38
|
+
project = client.projects("rubytfs").run
|
39
|
+
project.size.should == 1
|
40
|
+
project.first.Name.should == "rubytfs"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context "sub queries" do
|
45
|
+
use_vcr_cassette "project_workitems_queries"
|
46
|
+
|
47
|
+
before do
|
48
|
+
client.connect
|
49
|
+
end
|
50
|
+
|
51
|
+
it "can traverse/filter by sub items (children)" do
|
52
|
+
work_items = client.projects('rubytfs').workitems.run
|
53
|
+
work_items.count.should == 19
|
54
|
+
work_items.first.should be_a WorkItem
|
55
|
+
end
|
56
|
+
|
57
|
+
it "can't traverse unrelated items" do
|
58
|
+
expect { client.projects('rubytfs').weed }.to raise_error(NoMethodError)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe TFS::Projects do
|
4
|
+
let(:client) { TFS.client }
|
5
|
+
|
6
|
+
before do
|
7
|
+
TFS.configure do |config|
|
8
|
+
config.endpoint = "https://codeplexodata.cloudapp.net/TFS29"
|
9
|
+
config.username ='snd\plukevdh_cp'
|
10
|
+
config.password = 'garbage'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
context "finders" do
|
15
|
+
use_vcr_cassette 'projects'
|
16
|
+
|
17
|
+
it "can get projects from TFS" do
|
18
|
+
results = TFS::Projects.all
|
19
|
+
results.count.should == 1
|
20
|
+
end
|
21
|
+
|
22
|
+
it "can get a project by name" do
|
23
|
+
result = TFS::Projects.find('rubytfs')
|
24
|
+
result.Name.should == 'rubytfs'
|
25
|
+
end
|
26
|
+
|
27
|
+
it "can query in the raw" do
|
28
|
+
results = TFS::Projects.odata_query("startswith(Name,'rubytfs')").run
|
29
|
+
results.each do |build|
|
30
|
+
build.Name.should start_with 'rubytfs'
|
31
|
+
end
|
32
|
+
results.count.should == 1
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
|
4
|
+
describe TFS::QueryEngine do
|
5
|
+
class TFS::Builds; end
|
6
|
+
let(:native_query) { flexmock(:queryable) }
|
7
|
+
let(:conn) { flexmock(:connection, "Builds" => native_query) }
|
8
|
+
|
9
|
+
it "raises an error if we try to create a query for a bad object" do
|
10
|
+
expect { TFS::QueryEngine.new(String, conn) }.to raise_error(TypeError, /String is not/)
|
11
|
+
expect { TFS::QueryEngine.new(TFS::Builds, conn) }.to_not raise_error
|
12
|
+
end
|
13
|
+
|
14
|
+
it "can chain queries" do
|
15
|
+
query = TFS::QueryEngine.new(TFS::Builds, conn)
|
16
|
+
|
17
|
+
native_query.should_receive(:top).with(10).and_return(native_query).once
|
18
|
+
native_query.should_receive(:order_by).with("Reason").and_return(native_query).once
|
19
|
+
|
20
|
+
query.limit(10).order_by("Reason")
|
21
|
+
end
|
22
|
+
|
23
|
+
it "can include other results" do
|
24
|
+
query = TFS::QueryEngine.new(TFS::Builds, conn)
|
25
|
+
native_query.should_receive(:expand).with('Changesets').and_return(native_query).once
|
26
|
+
|
27
|
+
query.include(TFS::Changesets)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "raises error if expand by invalid class" do
|
31
|
+
query = TFS::QueryEngine.new(TFS::Builds, conn)
|
32
|
+
|
33
|
+
expect { query.include('String') }.to raise_error(TypeError)
|
34
|
+
|
35
|
+
native_query.should_not have_received(:expand)
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe TFS::WorkItems do
|
4
|
+
let(:client) { TFS.client }
|
5
|
+
before do
|
6
|
+
TFS.configure do |config|
|
7
|
+
config.endpoint = "https://codeplexodata.cloudapp.net/TFS29"
|
8
|
+
config.username ='snd\plukevdh_cp'
|
9
|
+
config.password = 'garbage'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
context "finders" do
|
14
|
+
use_vcr_cassette 'workitems'
|
15
|
+
|
16
|
+
it "can get workitems from TFS" do
|
17
|
+
results = TFS::WorkItems.all
|
18
|
+
results.count.should == 18
|
19
|
+
end
|
20
|
+
|
21
|
+
it "can get a project by name" do
|
22
|
+
result = TFS::WorkItems.find(1234)
|
23
|
+
result.CreatedBy.should == "MCLWEB"
|
24
|
+
result.AssignedTo.should == "plukevdh_cp"
|
25
|
+
end
|
26
|
+
|
27
|
+
it "can query in the raw" do
|
28
|
+
results = TFS::WorkItems.odata_query("AssignedTo eq 'plukevdh_cp'").run
|
29
|
+
results.each do |build|
|
30
|
+
build.AssignedTo.should == 'plukevdh_cp'
|
31
|
+
end
|
32
|
+
results.count.should == 14
|
33
|
+
end
|
34
|
+
|
35
|
+
it "can add a work item" do
|
36
|
+
temp = ::WorkItem.new(client)
|
37
|
+
temp.Title = "A Testing Item."
|
38
|
+
temp.AssignedTo = 'plukevdh_cp'
|
39
|
+
temp.Description = "A Test WorkItem from ruby_tfs wrapper"
|
40
|
+
temp.Type = "Work Item"
|
41
|
+
temp.Project = "rubytfs"
|
42
|
+
|
43
|
+
created = TFS::WorkItems.save(temp)
|
44
|
+
|
45
|
+
item = TFS::WorkItems.where("Title eq '#{created.Title}'").limit(1).run.first
|
46
|
+
item.AssignedTo.should == created.AssignedTo
|
47
|
+
item.Type.should == created.Type
|
48
|
+
end
|
49
|
+
|
50
|
+
it "can update existing work items" do
|
51
|
+
temp = TFS::WorkItems.find(1245)
|
52
|
+
temp.Title = "I'm updated, son!!"
|
53
|
+
|
54
|
+
saved = TFS::WorkItems.update(temp)
|
55
|
+
item = TFS::WorkItems.find(temp.Id)
|
56
|
+
|
57
|
+
saved.should be_true
|
58
|
+
item.Title.should == temp.Title
|
59
|
+
end
|
60
|
+
|
61
|
+
it "throws error if missing param" do
|
62
|
+
temp = ::WorkItem.new(client)
|
63
|
+
temp.Title = "A Testing Item."
|
64
|
+
|
65
|
+
expect { TFS::WorkItems.save(temp) }.to raise_error(TFS::WorkItems::InvalidRecord, /Missing required parameter 'Type'/)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
data/spec/tfs_spec.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe TFS do
|
4
|
+
let(:odata) { flexmock(:odata) }
|
5
|
+
let(:client) { TFS.client }
|
6
|
+
|
7
|
+
before do
|
8
|
+
TFS.configure do |config|
|
9
|
+
config.endpoint = "http://fake.tfs.com:8080/tfs"
|
10
|
+
config.provider = flexmock(:provider, new: odata)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
it "creates a client" do
|
15
|
+
client.should be_a TFS::Client
|
16
|
+
client.endpoint.should == "http://fake.tfs.com:8080/tfs"
|
17
|
+
end
|
18
|
+
|
19
|
+
it "aliases methods to the client" do
|
20
|
+
flexmock(client, :connect_as)
|
21
|
+
client.should_receive(:connect).once
|
22
|
+
|
23
|
+
TFS.connect
|
24
|
+
end
|
25
|
+
end
|
metadata
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ruby_tfs
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Luke van der Hoeven
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-03-06 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: ruby_odata
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: bundler
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '1.0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '1.0'
|
46
|
+
description: A Ruby interface to the TFS OData API.
|
47
|
+
email:
|
48
|
+
- hungerandthirst@gmail.com
|
49
|
+
executables: []
|
50
|
+
extensions: []
|
51
|
+
extra_rdoc_files: []
|
52
|
+
files:
|
53
|
+
- Rakefile
|
54
|
+
- LICENSE.md
|
55
|
+
- README.md
|
56
|
+
- ruby_tfs.gemspec
|
57
|
+
- lib/tfs/builds.rb
|
58
|
+
- lib/tfs/changesets.rb
|
59
|
+
- lib/tfs/class_helpers.rb
|
60
|
+
- lib/tfs/client.rb
|
61
|
+
- lib/tfs/configuration.rb
|
62
|
+
- lib/tfs/projects.rb
|
63
|
+
- lib/tfs/query_engine.rb
|
64
|
+
- lib/tfs/queryable.rb
|
65
|
+
- lib/tfs/work_items.rb
|
66
|
+
- lib/tfs.rb
|
67
|
+
- spec/fixtures/cassettes/builds.yml
|
68
|
+
- spec/fixtures/cassettes/changeset_queries.yml
|
69
|
+
- spec/fixtures/cassettes/changesets.yml
|
70
|
+
- spec/fixtures/cassettes/project_workitems_queries.yml
|
71
|
+
- spec/fixtures/cassettes/projects.yml
|
72
|
+
- spec/fixtures/cassettes/workitems.yml
|
73
|
+
- spec/spec_helper.rb
|
74
|
+
- spec/tfs/builds_spec.rb
|
75
|
+
- spec/tfs/changesets_spec.rb
|
76
|
+
- spec/tfs/client_spec.rb
|
77
|
+
- spec/tfs/projects_spec.rb
|
78
|
+
- spec/tfs/query_engine_spec.rb
|
79
|
+
- spec/tfs/work_items_spec.rb
|
80
|
+
- spec/tfs_spec.rb
|
81
|
+
homepage: https://github.com/BFGCOMMUNICATIONS/ruby_tfs
|
82
|
+
licenses:
|
83
|
+
- APLv2
|
84
|
+
post_install_message:
|
85
|
+
rdoc_options: []
|
86
|
+
require_paths:
|
87
|
+
- lib
|
88
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
segments:
|
95
|
+
- 0
|
96
|
+
hash: -4292206802571305050
|
97
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
98
|
+
none: false
|
99
|
+
requirements:
|
100
|
+
- - ! '>='
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: 1.3.6
|
103
|
+
requirements: []
|
104
|
+
rubyforge_project:
|
105
|
+
rubygems_version: 1.8.23
|
106
|
+
signing_key:
|
107
|
+
specification_version: 3
|
108
|
+
summary: A Ruby interface to the TFS OData API.
|
109
|
+
test_files:
|
110
|
+
- spec/fixtures/cassettes/builds.yml
|
111
|
+
- spec/fixtures/cassettes/changeset_queries.yml
|
112
|
+
- spec/fixtures/cassettes/changesets.yml
|
113
|
+
- spec/fixtures/cassettes/project_workitems_queries.yml
|
114
|
+
- spec/fixtures/cassettes/projects.yml
|
115
|
+
- spec/fixtures/cassettes/workitems.yml
|
116
|
+
- spec/spec_helper.rb
|
117
|
+
- spec/tfs/builds_spec.rb
|
118
|
+
- spec/tfs/changesets_spec.rb
|
119
|
+
- spec/tfs/client_spec.rb
|
120
|
+
- spec/tfs/projects_spec.rb
|
121
|
+
- spec/tfs/query_engine_spec.rb
|
122
|
+
- spec/tfs/work_items_spec.rb
|
123
|
+
- spec/tfs_spec.rb
|