rally_rest_api 0.7.10 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -16,10 +16,18 @@ lib/rally_rest_api/timeout_catching_rest_builder.rb
16
16
  lib/rally_rest_api/typedef.rb
17
17
  lib/rally_rest_api/version.rb
18
18
  setup.rb
19
+ spec/rally_rest_api/attribute_definition_spec.rb
20
+ spec/rally_rest_api/custom_http_header_spec.rb
21
+ spec/rally_rest_api/query_result_spec.rb
22
+ spec/rally_rest_api/rest_builder_spec.rb
23
+ spec/rally_rest_api/rest_object_spec.rb
24
+ spec/rally_rest_api/tc_query_result.rb
25
+ spec/rally_rest_api/tc_rest_api.rb
26
+ spec/rally_rest_api/tc_rest_query.rb
27
+ spec/rally_rest_api/typedef_spec.rb
28
+ spec/test_helper.rb
19
29
  tasks/ann.rake
20
- tasks/annotations.rake
21
30
  tasks/bones.rake
22
- tasks/doc.rake
23
31
  tasks/gem.rake
24
32
  tasks/manifest.rake
25
33
  tasks/post_load.rake
@@ -28,13 +36,3 @@ tasks/setup.rb
28
36
  tasks/spec.rake
29
37
  tasks/svn.rake
30
38
  tasks/test.rake
31
- test/attribute_definition_spec.rb
32
- test/custom_http_header_spec.rb
33
- test/query_result_spec.rb
34
- test/rest_builder_spec.rb
35
- test/rest_object_spec.rb
36
- test/spec_typedef.rb
37
- test/tc_query_result.rb
38
- test/tc_rest_api.rb
39
- test/tc_rest_query.rb
40
- test/test_helper.rb
data/Rakefile CHANGED
@@ -2,6 +2,7 @@
2
2
  # configured in this Rakefile. The .rake files in the tasks directory
3
3
  # are where the options are used.
4
4
 
5
+
5
6
  load 'tasks/setup.rb'
6
7
 
7
8
  ensure_in_path 'lib'
@@ -13,14 +14,14 @@ PROJ.name = 'rally_rest_api'
13
14
  PROJ.authors = 'Bob Cotton'
14
15
  PROJ.email = 'bob.cotton@rallydev.com'
15
16
  PROJ.url = 'http://rally-rest-api.rubyforge.org/rally_rest_api'
16
- PROJ.rubyforge_name = 'rally-rest-api'
17
+ PROJ.rubyforge.name = 'rally-rest-api'
17
18
  PROJ.summary = "A Ruby interface to the Rally REST API"
18
19
  PROJ.version = RallyRestVersion::LIBRARY_VERSION::STRING
19
20
 
20
21
  PROJ.exclude = ['.git/*', 'pkg/*']
21
22
 
22
- PROJ.rdoc_dir = 'doc/output/rally_rest_api'
23
+ PROJ.rdoc.dir = 'doc/output/rally_rest_api'
23
24
 
24
- PROJ.spec_opts << '--color'
25
+ PROJ.spec.opts << '--color'
25
26
 
26
27
  # EOF
@@ -3,7 +3,7 @@ require File.dirname(__FILE__) + '/rest_object'
3
3
  class AttributeDefinition < RestObject # :nodoc:
4
4
 
5
5
  def initialize(rally_rest, values)
6
- @rally_rest = rally_rest
6
+ super(rally_rest)
7
7
  @elements = values
8
8
  end
9
9
 
@@ -32,6 +32,7 @@ class RallyRestAPI
32
32
  #
33
33
  def initialize(options = {})
34
34
  parse_options(options)
35
+ user
35
36
  end
36
37
 
37
38
  def parse_options(options)
@@ -1,6 +1,7 @@
1
1
  require 'logger'
2
2
  require File.dirname(__FILE__) + '/rest_builder'
3
3
  require 'builder/blankslate'
4
+ require 'forwardable'
4
5
 
5
6
  # == An interface to a Rally resource
6
7
  # RestObject is an adapter that is initialized with a resource ref (URL) that represents a Rally object. The adapter
@@ -26,14 +27,17 @@ class FancyHash < Hash # :nodoc: all
26
27
  end
27
28
 
28
29
  class RestObject
30
+ extend Forwardable
29
31
 
30
- attr_reader :username, :password, :rally_rest
32
+ attr_accessor :rally_rest
33
+ def_delegator(:rally_rest, :username)
34
+ def_delegator(:rally_rest, :password)
31
35
 
32
- def initialize(rally_rest, document_content)
36
+ def initialize(rally_rest = nil, document_content = nil)
37
+ @changed_values = {}
33
38
  @rally_rest = rally_rest
34
39
  @document_content = document_content
35
- @username, @password = @rally_rest.username, @rally_rest.password
36
- parse_document
40
+ parse_document if document_content
37
41
  end
38
42
 
39
43
  def parse_document
@@ -46,14 +50,14 @@ class RestObject
46
50
  end
47
51
 
48
52
  def marshal_dump
49
- [@rally_rest, @document_content, @username, @password]
53
+ [@rally_rest, @document_content, @changed_values]
50
54
  end
51
55
 
52
56
  def marshal_load(stuff)
53
- @rally_rest, @document_content, @username, @password = *stuff
57
+ @rally_rest, @document_content, @changed_values = *stuff
54
58
  parse_document
55
59
  end
56
-
60
+
57
61
  private
58
62
  def terminal?(node)
59
63
  !node.has_elements?
@@ -156,14 +160,19 @@ class RestObject
156
160
 
157
161
  # The name of the object, without having to read the entire body
158
162
  def name
159
- @document.root.attributes["refObjectName"]
163
+ @changed_values[:name] || @document.root.attributes["refObjectName"]
160
164
  end
161
165
  alias :to_s :name
162
166
 
163
167
  # The type of the underlying resource
164
168
  def type
165
- @document.root.attributes["type"] || @document.root.name
169
+ @type || @document.root.attributes["type"] || @document.root.name
170
+ end
171
+
172
+ def type=(type)
173
+ @type = type
166
174
  end
175
+ alias :artifact_type= :type=
167
176
 
168
177
  # the type as symbol
169
178
  def type_as_symbol
@@ -191,7 +200,7 @@ class RestObject
191
200
 
192
201
  def elements(read = @elements.nil?) #:nodoc:
193
202
  if read
194
- @document_content = builder.read_rest(self.ref, @username, @password)
203
+ @document_content = builder.read_rest(self.ref, username, password)
195
204
  @document = REXML::Document.new @document_content
196
205
  @elements = parse(@document.root)
197
206
  end
@@ -217,20 +226,33 @@ class RestObject
217
226
  end
218
227
 
219
228
  public
229
+
230
+ def save!
231
+ raise 'missing RallyRestAPI instance' unless rally_rest
232
+ raise 'missing object type' unless @type
233
+ @document_content = builder.create_rest(type, @changed_values, username, password)
234
+ parse_document
235
+ end
220
236
 
221
237
  # update the resource. This will re-read the resource after the update
222
238
  def update(args)
223
- builder.update_rest(self.type, self.ref, args, @username, @password)
239
+ builder.update_rest(type, ref, args, username, password)
224
240
  self.elements(true)
225
241
  end
226
242
 
227
243
  # delete the resource
228
244
  def delete
229
- builder.delete_rest(self.ref, @username, @password)
245
+ builder.delete_rest(ref, username, password)
230
246
  end
231
247
 
232
248
  def method_missing(sym, *args) # :nodoc:
233
- self.elements[sym]
249
+ method = sym
250
+ if sym.to_s.match(/(.*)=$/)
251
+ method = $1.intern
252
+ return @changed_values[method] = args.first
253
+ end
254
+
255
+ @changed_values[method] || self.elements[method]
234
256
  # Sometimes the xml returned has no element for things that are simply null. Without
235
257
  # asking the typedef, I have no way to know if the element exists, or has been ommited.
236
258
  # It would not be hard to ask the typedef, but they are expensive to load. It should be an option
@@ -1,8 +1,8 @@
1
1
  module RallyRestVersion #:nodoc:
2
2
  module LIBRARY_VERSION #:nodoc:
3
3
  MAJOR = 0
4
- MINOR = 7
5
- TINY = 10
4
+ MINOR = 8
5
+ TINY = 0
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
@@ -1,9 +1,7 @@
1
- require 'rubygems'
2
- require 'spec'
3
- require 'builder'
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
4
3
  require 'ostruct'
5
4
  require 'logger'
6
- require 'rally_rest_api'
7
5
 
8
6
 
9
7
  describe "An attribute definition for a custom dropdown" do
@@ -1,4 +1,4 @@
1
- require 'test_helper'
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
2
 
3
3
  describe "A CustomHttpHeader" do
4
4
 
@@ -1,4 +1,4 @@
1
- require 'test_helper'
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
2
 
3
3
  describe "A QueryResult" do
4
4
 
@@ -125,7 +125,7 @@ describe "A QueryResult with full objects" do
125
125
  rest_builder.
126
126
  should_receive(:read_rest).
127
127
  twice.
128
- with(:any_args).
128
+ with(any_args(), nil, nil).
129
129
  and_return( xml do |b|
130
130
  b.iteration {
131
131
  b.Name("name1")
@@ -1,4 +1,4 @@
1
- require 'test_helper'
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
2
 
3
3
  describe "a RestBuilder " do
4
4
 
@@ -20,7 +20,7 @@ describe "a RestBuilder " do
20
20
  b.Name "foo"
21
21
  }
22
22
  end
23
- @builder.should_receive(:post_xml).with(:anything, expected_xml, @username, @password)
23
+ @builder.should_receive(:post_xml).with(anything(), expected_xml, @username, @password)
24
24
  @builder.update_rest(:defect, "url", {:name => "foo"}, @username, @password)
25
25
  end
26
26
 
@@ -35,7 +35,7 @@ describe "a RestBuilder " do
35
35
  }
36
36
  end
37
37
 
38
- @builder.should_receive(:post_xml).with(:anything, expected_xml, @username, @password)
38
+ @builder.should_receive(:post_xml).with(anything(), expected_xml, @username, @password)
39
39
  @builder.update_rest(:defect, "url",
40
40
  {
41
41
  :name => "foo",
@@ -1,5 +1,4 @@
1
-
2
- require 'test_helper'
1
+ require File.dirname(__FILE__) + '/../test_helper'
3
2
 
4
3
  describe RestObject do
5
4
 
@@ -95,7 +94,7 @@ describe RestObject do
95
94
  rest_builder = mock("RestBuilder")
96
95
  rest_builder.
97
96
  should_receive(:read_rest).
98
- with(:any_args).
97
+ with(any_args()).
99
98
  and_return( xml do |b|
100
99
  b.TestCase {
101
100
  b.Name("name1")
@@ -115,7 +114,7 @@ describe RestObject do
115
114
  rest_builder = mock("RestBuilder")
116
115
  rest_builder.
117
116
  should_receive(:read_rest).
118
- with(:any_args).
117
+ with(any_args()).
119
118
  and_return( xml do |b|
120
119
  b.TestCase {
121
120
  b.Name("name1")
@@ -140,7 +139,7 @@ describe RestObject do
140
139
  rest_builder.
141
140
  should_receive(:read_rest).
142
141
  once.
143
- with(:any_args).
142
+ with(any_args()).
144
143
  and_return( xml do |b|
145
144
  b.TestCase {
146
145
  b.Name("name1")
@@ -164,7 +163,7 @@ describe RestObject do
164
163
  rest_builder.
165
164
  should_receive(:read_rest).
166
165
  once.
167
- with(:any_args).
166
+ with(any_args()).
168
167
  and_return( xml do |b|
169
168
  b.iteration {
170
169
  b.Name("name1")
@@ -299,7 +298,7 @@ describe RestObject do
299
298
  rest_builder.
300
299
  should_receive(:read_rest).
301
300
  twice.
302
- with(:any_args).
301
+ with(any_args()).
303
302
  and_return( xml do |b|
304
303
  b.Task {
305
304
  b.Name("name1")
@@ -323,5 +322,63 @@ describe RestObject do
323
322
  object.tasks.first.description.should == "Description"
324
323
  object.tasks.last.description.should == "Description"
325
324
  end
325
+
326
+ it "should allow getting and setting rally_rest" do
327
+ rally_rest = RallyRestAPI.new
328
+ rest_object = RestObject.new
329
+ rest_object.rally_rest = rally_rest
330
+ rest_object.rally_rest.should equal(rally_rest)
331
+ end
326
332
 
333
+ it "should allow the type to be set" do
334
+ rest_object = RestObject.new
335
+ rest_object.type = :defect
336
+ rest_object.type.should == :defect
337
+ end
338
+
339
+ it "should allow the name to be set" do
340
+ rest_object = RestObject.new
341
+ rest_object.name = "name"
342
+ rest_object.name.should == "name"
343
+ end
344
+
345
+ it "should allow the setting and getting of any value" do
346
+ rest_object = RestObject.new
347
+ rest_object.description = "description"
348
+ rest_object.description.should == "description"
349
+ end
350
+
351
+ it "should pass the type and set value to create on rally_rest" do
352
+ builder = mock("builder")
353
+ rally_rest = RallyRestAPI.new(:builder => builder)
354
+ args = {:name => "name", :description => "description"}
355
+ xml = %Q(<Object ref="bla" refObjectName="name">
356
+ <Name>name</Name>
357
+ <Description>description</Description>
358
+ </Object>)
359
+
360
+ builder.should_receive(:create_rest).with(:defect, args, nil, nil).and_return(xml)
361
+
362
+ rest_object = RestObject.new
363
+ rest_object.rally_rest = rally_rest
364
+ rest_object.type = :defect
365
+ rest_object.name = "name"
366
+ rest_object.description = "description"
367
+ rest_object.save!
368
+
369
+ rest_object.ref.should == "bla"
370
+ rest_object.name.should == "name"
371
+ rest_object.description.should == "description"
372
+ end
373
+
374
+ it "should not try to save if there is no rally_rest" do
375
+ rest_object = RestObject.new
376
+ lambda { rest_object.save! }.should raise_error(StandardError, /missing RallyRestAPI instance/)
377
+ end
378
+
379
+ it "should not try to save if there is no type" do
380
+ rally_rest = stub!("RallyRest")
381
+ rest_object = RestObject.new(rally_rest)
382
+ lambda { rest_object.save! }.should raise_error(StandardError, /missing object type/)
383
+ end
327
384
  end
@@ -1,8 +1,7 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
1
2
  require 'test/unit'
2
3
  require 'test/unit/testcase'
3
4
 
4
- require 'rubygems'
5
- require 'rally_rest_api'
6
5
 
7
6
  class QueryResultTestCase < Test::Unit::TestCase
8
7
 
@@ -1,9 +1,4 @@
1
- require 'test/unit'
2
- require 'test/unit/testcase'
3
-
4
- require 'rubygems'
5
- require 'rally_rest_api'
6
-
1
+ require File.dirname(__FILE__) + '/../test_helper'
7
2
  class RestApiTestCase < Test::Unit::TestCase
8
3
 
9
4
  # We need to override post_xml from RestBuilder, So redefine it here
@@ -1,8 +1,4 @@
1
-
2
- require "test/unit"
3
-
4
- require 'rubygems'
5
- require 'rally_rest_api'
1
+ require File.dirname(__FILE__) + '/../test_helper'
6
2
 
7
3
  class TestRestQuery < Test::Unit::TestCase
8
4
  # RestQuery.find(:feature).where { # default is and
@@ -1,7 +1,5 @@
1
- require 'spec'
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
2
  require 'ostruct'
3
- require 'logger'
4
- require 'rally_rest_api'
5
3
 
6
4
 
7
5
  describe "A Test Case type definition with 2 collection attribues, 1 object attributes, and 1 string attribute" do
@@ -15,11 +13,11 @@ describe "A Test Case type definition with 2 collection attribues, 1 object attr
15
13
  :type => "TypeDefinition") {
16
14
  @b.ElementName("TestCase")
17
15
  @b.Attributes {
18
- {"Notes" => {:type => "TEXT", :element_name => "Notes", :constrained => "false", :custom => "false"},
19
- "Test Case Result" => {:type => "COLLECTION", :element_name => "TestCaseResult", :constrained => "false", :custom => "false"},
16
+ {"Notes" => {:type => "TEXT", :element_name => "Notes", :constrained => "false", :custom => "false"},
17
+ "Test Case Result" => {:type => "COLLECTION", :element_name => "TestCaseResult", :constrained => "false", :custom => "false"},
20
18
  "Foo Bar" => {:type => "COLLECTION", :element_name => "FooBar", :constrained => "false", :custom => "false"},
21
19
  "Requirement" => {:type => "OBJECT", :element_name => "Requirement", :constrained => "false", :custom => "false"},
22
- "Constrained" => {:type => "STRING", :element_name => "Constrained", :constrained => "true", :custom => "false"},
20
+ "Constrained" => {:type => "STRING", :element_name => "Constrained", :constrained => "true", :custom => "false"},
23
21
  "Custom" => {:type => "STRING", :element_name => "Custom", :constrained => "false", :custom => "true"},
24
22
  "ConstainedCustom" => {:type => "STRING", :element_name => "ConstrainedCustom", :constrained => "true", :custom => "true"}
25
23
  }.each do |name, type|
@@ -0,0 +1,13 @@
1
+ dir = File.dirname(__FILE__)
2
+ app_path = File.expand_path("#{dir}/../lib")
3
+ $LOAD_PATH.unshift app_path unless $LOAD_PATH.include?(app_path)
4
+ require 'test/unit'
5
+ require 'rubygems'
6
+ require 'spec'
7
+ require 'net/http'
8
+ require 'rally_rest_api'
9
+
10
+ class RallyRestAPI
11
+ def user; end
12
+ end
13
+