rally_rest_api 0.6.2 → 0.6.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -72,4 +72,10 @@ class QueryResult < RestObject
72
72
  return false if start_index == 0
73
73
  (self.start_index + self.page_length) -1 < self.total_result_count
74
74
  end
75
+
76
+ protected
77
+ def parse_collections_as_hash?
78
+ false
79
+ end
80
+
75
81
  end
@@ -3,7 +3,6 @@ require 'uri'
3
3
  require 'rexml/document'
4
4
  require 'ostruct'
5
5
 
6
-
7
6
  #
8
7
  # RallyRestAPI - A Ruby-ized interface to Rally's REST webservice API
9
8
  #
@@ -11,6 +10,7 @@ class RallyRestAPI
11
10
  include RestBuilder
12
11
 
13
12
  attr_reader :username, :password, :base_url, :raise_on_warning, :logger
13
+ attr_accessor :parse_collections_as_hash
14
14
 
15
15
  ALLOWED_TYPES = %w[subscription workspace project iteration release defect defect_suite test_case
16
16
  feature supplemental_requirement use_case story actor card
@@ -35,6 +35,7 @@ class RallyRestAPI
35
35
  @base_url = options[:base_url]
36
36
  @raise_on_warning = options[:raise_on_warning]
37
37
  @logger = options[:logger]
38
+ @parse_collections_as_hash = options[:parse_collections_as_hash] || false
38
39
  end
39
40
 
40
41
  # return an instance of User, for the currently logged in user.
@@ -95,6 +96,17 @@ class RallyRestAPI
95
96
  QueryResult.new(query, self, xml)
96
97
  end
97
98
 
99
+ # Should rest_objects parse into hashes
100
+ def parse_collections_as_hash?
101
+ @parse_collections_as_hash
102
+ end
103
+
104
+ protected
105
+ def debug(message)
106
+ @logger.debug(message) if @logger
107
+ end
108
+
98
109
  end
99
110
 
100
111
 
112
+
@@ -18,7 +18,7 @@ module RestBuilder # :nodoc:
18
18
  # then call create on the REST api
19
19
  def create_rest(artifact_type, args, username, password)
20
20
  type = camel_case_word(artifact_type)
21
- puts "RestBuilder#create_rest artifact_type = #{type}" if DEBUG
21
+ debug "RestBuilder#create_rest artifact_type = #{type}"
22
22
  b = create_builder
23
23
  xml = b.__send__(type, &builder_block(args))
24
24
 
@@ -37,7 +37,7 @@ module RestBuilder # :nodoc:
37
37
  # }
38
38
  # then call create on the REST api
39
39
  def update_rest(artifact_type, url, args, username, password)
40
- puts "RestBuilder#update_rest url = #{url}" if DEBUG
40
+ debug "RestBuilder#update_rest url = #{url}"
41
41
  b = create_builder
42
42
  # and pass that to the builder
43
43
  xml = b.__send__(artifact_type, :ref => url, &builder_block(args))
@@ -45,21 +45,21 @@ module RestBuilder # :nodoc:
45
45
  end
46
46
 
47
47
  def read_rest(ref_url, username, password)
48
- puts "RestBuilder#read_rest ref_url = #{ref_url} username = #{ username } pass = #{ password }" if DEBUG
48
+ debug "RestBuilder#read_rest ref_url = #{ref_url} username = #{ username } pass = #{ password }"
49
49
  url = URI.parse(ref_url)
50
50
  req = Net::HTTP::Get.new(url.path + (url.query ? "?" + url.query : ""))
51
51
  send_request(url, req, username, password)
52
52
  end
53
53
 
54
54
  def delete_rest(ref_url, username, password)
55
- puts "RestBuilder#delete_rest ref_url = #{ref_url} username = #{ username } pass = #{ password }" if DEBUG
55
+ debug "RestBuilder#delete_rest ref_url = #{ref_url} username = #{ username } pass = #{ password }"
56
56
  url = URI.parse(ref_url)
57
57
  req = Net::HTTP::Delete.new(url.path)
58
58
  send_request(url, req, username, password)
59
59
  end
60
60
 
61
61
  def post_xml(url, xml, username, password)
62
- puts "RestBuilder#post_xml xml = #{xml} as user #{ self.username } pass = #{ self.password }" if DEBUG
62
+ debug "RestBuilder#post_xml xml = #{xml} as user #{ self.username } pass = #{ self.password }"
63
63
  url = URI.parse(url)
64
64
  req = Net::HTTP::Post.new(url.path)
65
65
  req.body = xml
@@ -67,13 +67,13 @@ module RestBuilder # :nodoc:
67
67
  end
68
68
 
69
69
  def send_request(url, req, username, password)
70
- puts "RestBuilder#send_request req = #{req.inspect}" if DEBUG
70
+ debug "RestBuilder#send_request req = #{req.inspect}"
71
71
  req.basic_auth username, password
72
72
  req.content_type = 'text/xml'
73
73
  http = Net::HTTP.new(url.host, url.port)
74
74
  http.use_ssl = true if url.scheme == "https"
75
75
  body = http.start { |http| http.request(req) }.body
76
- puts "RestBuilder#send_request result = #{body}" if DEBUG
76
+ debug "RestBuilder#send_request result = #{body}"
77
77
  check_for_errors(body)
78
78
  body
79
79
  end
@@ -1,3 +1,4 @@
1
+ require 'logger'
1
2
  require File.dirname(__FILE__) + '/rest_builder'
2
3
 
3
4
  # == An interface to a Rally resource
@@ -19,8 +20,6 @@ require File.dirname(__FILE__) + '/rest_builder'
19
20
  class RestObject
20
21
  include RestBuilder
21
22
 
22
- DEBUG = false
23
-
24
23
  attr_reader :username, :password, :rally_rest
25
24
  alias :builder :rally_rest
26
25
 
@@ -36,17 +35,16 @@ class RestObject
36
35
  end
37
36
  end
38
37
 
39
-
40
38
  private
41
39
  def parse(node)
42
- puts "parse self = #{self.object_id} node = #{ node.to_s }" if DEBUG
40
+ debug "parse self = #{self.object_id} node = #{ node.to_s }"
43
41
 
44
42
  if !node.has_elements?
45
43
  if ref?(node)
46
- puts "Returning RestObject for #{ node.to_s}" if DEBUG
44
+ debug "Returning RestObject for #{ node.to_s}"
47
45
  return RestObject.new(@rally_rest, node.to_s)
48
46
  else
49
- puts "Returning text #{ node.text }" if DEBUG
47
+ debug "Returning text #{ node.text }"
50
48
  return node.text
51
49
  end
52
50
  end
@@ -63,16 +61,16 @@ class RestObject
63
61
  #Add all the element's children to the hash.
64
62
  node.each_element do |e|
65
63
  name = underscore(e.name).to_sym
66
- puts "Looking at name = #{ name }" if DEBUG
64
+ debug "Looking at name = #{ name }"
67
65
  case elements[name]
68
66
  # We've not seen this element before
69
67
  when NilClass
70
- puts "NilClass name = #{ name }" if DEBUG
68
+ debug "NilClass name = #{ name }"
71
69
  # if we have a collection of things with refObjectName attributes, collect them into a hash
72
- # with the refObjectName as the key
73
- if named_collection?(e)
74
- puts "Named collection #{ name }" if DEBUG
75
- elements[name] = {} # We might want to decorate {} here to handle scoping
70
+ # with the refObjectName as the key, unless we're told not to make hashs out of collections.
71
+ if named_collection?(e) && parse_collections_as_hash?
72
+ debug "Named collection #{ name }"
73
+ elements[name] = {}
76
74
  e.elements.each do |child|
77
75
  ref_name = child.attributes["refObjectName"]
78
76
  if elements[name][ref_name]
@@ -82,21 +80,21 @@ class RestObject
82
80
  elements[name][ref_name] = parse(child)
83
81
  end
84
82
  end
85
- elsif unnamed_collection?(e)
86
- puts "UnNamed collection #{ name }" if DEBUG
83
+ elsif collection?(e)
84
+ debug "Collection #{ name }"
87
85
  elements[name] = []
88
86
  e.elements.each do |child|
89
87
  elements[name] << parse(child)
90
88
  end
91
89
  else # a fully dressed object, without a name
92
- puts "Fully Dressed object, without a name #{ name }" if DEBUG
90
+ debug "Fully Dressed object, without a name #{ name }"
93
91
  elements[name] = parse(e)
94
92
  end
95
93
 
96
94
  #Non-unique child elements become arrays: We've already
97
95
  #created the array: just add the element.
98
96
  when Array
99
- puts "Array name = #{ name }" if DEBUG
97
+ debug "Array name = #{ name }"
100
98
  elements[name] << parse(e)
101
99
 
102
100
  #We haven't created the array yet: do so,
@@ -105,7 +103,7 @@ class RestObject
105
103
  # when Hash
106
104
  # raise "Don't know how to deail with a named collection we've already seen! element = #{e}"
107
105
  else
108
- puts "creating and wrapping #{elements[name]}with an array name = #{ name }" if DEBUG
106
+ debug "creating and wrapping #{elements[name]}with an array name = #{ name }"
109
107
  elements[name] = [elements[name]]
110
108
  elements[name] << parse(e)
111
109
  end
@@ -207,11 +205,15 @@ class RestObject
207
205
 
208
206
  protected
209
207
  def named_collection?(element) # :nodoc:
210
- element.elements.find_all { |e| e.attributes['ref'] && e.attributes['refObjectName'] }.length > 0
208
+ collection?(element) && element.elements.find_all { |e| e.attributes['ref'] && e.attributes['refObjectName'] }.length > 0
211
209
  end
212
210
 
213
211
  def unnamed_collection?(element) # :nodoc:
214
- element.elements.find_all { |e| e.attributes['ref'] && e.attributes['refObjectName'] == nil }.length > 0
212
+ collection?(element) && element.elements.find_all { |e| e.attributes['ref'] && e.attributes['refObjectName'] == nil }.length > 0
213
+ end
214
+
215
+ def collection?(element) # :nodoc:
216
+ !element.has_attributes? && element.has_elements? && element.elements.find_all { |e| e.attributes['ref'] }.length == element.elements.size
215
217
  end
216
218
 
217
219
  def ref?(element) # :nodoc:
@@ -220,4 +222,12 @@ class RestObject
220
222
  !element.attributes["ref"].nil?
221
223
  end
222
224
 
225
+ def parse_collections_as_hash? # :nodoc:
226
+ self.rally_rest.parse_collections_as_hash?
227
+ end
228
+
229
+ def debug(message)
230
+ # @rally_rest.logger.debug(message) if @rally_rest.logger
231
+ end
232
+
223
233
  end
@@ -15,19 +15,10 @@ class TypeDefinition < RestObject # :nodoc:
15
15
  end
16
16
 
17
17
  def self.get_type_definition(workspace, type)
18
- mangle_type_definitions(workspace.type_definitions)
19
- typedef = workspace.type_definitions[type]
18
+ typedef = workspace.type_definitions.find { |td| td.element_name == type }
20
19
  TypeDefinition.new(typedef.rally_rest, typedef.body)
21
20
  end
22
21
 
23
- # This is a hack
24
- # Strip spaces from the name, and put the values back in to the hash
25
- def self.mangle_type_definitions(type_definitions)
26
- type_definitions.each do |key, value|
27
- type_definitions[key.gsub(" ", "")] = value if key.include? " "
28
- end
29
- end
30
-
31
22
  def self.make_key(workspace, type)
32
23
  # Parent typedefs don't have a workspace, so key them appropriately
33
24
  ref = workspace.ref rescue ""
@@ -101,5 +92,10 @@ class TypeDefinition < RestObject # :nodoc:
101
92
  end
102
93
  typedef
103
94
  end
95
+
96
+ protected
97
+ def parse_collections_as_hash?
98
+ true
99
+ end
104
100
 
105
101
  end
@@ -2,7 +2,7 @@ module RallyRestVersion #:nodoc:
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
4
  MINOR = 6
5
- TINY = 2
5
+ TINY = 3
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
@@ -2,6 +2,7 @@ require 'rubygems'
2
2
  require 'spec'
3
3
  require 'builder'
4
4
  require 'ostruct'
5
+ require 'logger'
5
6
  require 'rally_rest_api'
6
7
 
7
8
 
@@ -28,7 +29,7 @@ context "An attribute definition for a custom dropdown" do
28
29
  }
29
30
  }
30
31
  }
31
- fake_rally_rest = OpenStruct.new(:username => "", :password => "")
32
+ fake_rally_rest = OpenStruct.new(:username => "", :password => "", :logger => nil)
32
33
  @attrdef = AttributeDefinition.new(fake_rally_rest, RestObject.new(fake_rally_rest, xml).elements)
33
34
  end
34
35
 
@@ -51,4 +52,9 @@ context "An attribute definition for a custom dropdown" do
51
52
  specify "allowed_values should match" do
52
53
  @attrdef.allowed_values.should == [nil, "Actor"]
53
54
  end
55
+
56
+ specify "should have 'AttributeDefinition' as the type" do
57
+ @attrdef.type.should == "AttributeDefinition"
58
+ end
59
+
54
60
  end
@@ -10,6 +10,8 @@ context "A QueryResult" do
10
10
  @api = mock("RallyRestAPI")
11
11
  @api.stub! :username
12
12
  @api.stub! :password
13
+ @api.stub!(:logger).and_return(nil)
14
+ @api.stub!(:parse_collections_as_hash?).and_return true
13
15
  end
14
16
 
15
17
  def make_result(total, page_size, start_index)
@@ -66,6 +68,17 @@ context "A QueryResult" do
66
68
  start.should_be 0
67
69
  end
68
70
 
71
+ specify "a page of results should match the page size" do
72
+ make_result(20, 20, 1).results.length.should_be 20
73
+ end
74
+
75
+ specify "results should be in the same order as returned" do
76
+ result = make_result(20, 20, 1)
77
+ result.results.length.should_be 20
78
+ result.results[0].name.should == "name0"
79
+ result.results[19].name.should == "name19"
80
+ end
81
+
69
82
  end
70
83
 
71
84
  context "A QueryResult with 2 pages" do
@@ -1,6 +1,6 @@
1
- require 'rubygems'
2
1
  require 'spec'
3
2
  require 'ostruct'
3
+ require 'logger'
4
4
  require 'rally_rest_api'
5
5
 
6
6
 
@@ -33,7 +33,7 @@ context "A Test Case type definition with 2 collection attribues, 1 object attri
33
33
  end
34
34
  }
35
35
  }
36
- @typedef = TypeDefinition.new(OpenStruct.new(:username => "", :password => ""), xml)
36
+ @typedef = TypeDefinition.new(OpenStruct.new(:username => "", :password => "", :logger => nil), xml)
37
37
  end
38
38
 
39
39
  specify "all attribute keys are symbols" do
@@ -69,8 +69,8 @@ context "A Test Case type definition with 2 collection attribues, 1 object attri
69
69
  end
70
70
 
71
71
  specify "should have 1 custom_constrained_attributes" do
72
- @typedef.custom_constrained_attributes.size.should == 1
73
- @typedef.custom_dropdown_attributes.size.should == 1
72
+ @typedef.custom_constrained_attributes.size.should_be 1
73
+ @typedef.custom_dropdown_attributes.size.should_be 1
74
74
  end
75
75
 
76
76
  specify "#attributes should return instances of AttributeDefinitions" do
@@ -48,20 +48,20 @@ class RestApiTestCase < Test::Unit::TestCase
48
48
  # test that types and keys are camel cased (at least with one underscore)
49
49
  def test_camel_case
50
50
  xml = "#{preamble}<UseCase><NameName>name</NameName></UseCase>"
51
- @api.use_case(:name_name => "name")
51
+ @api.create(:use_case, :name_name => "name")
52
52
  assert_equal(xml, @xml)
53
53
  end
54
54
 
55
55
  def test_nil_value
56
56
  xml = %Q(#{preamble}<UseCase><Name ref="null"/></UseCase>)
57
- @api.use_case(:name => nil)
57
+ @api.create(:use_case, :name => nil)
58
58
  assert_equal(xml, @xml)
59
59
  end
60
60
 
61
61
  def test_time_value
62
62
  time = Time.now
63
63
  xml = "#{preamble}<UseCase><Time>#{time.iso8601}</Time></UseCase>"
64
- @api.use_case(:time => time)
64
+ @api.create(:use_case, :time => time)
65
65
  assert_equal(xml, @xml)
66
66
  end
67
67
 
@@ -71,7 +71,7 @@ class RestApiTestCase < Test::Unit::TestCase
71
71
  rest_object = RestObject.new(@api, rest_object_xml)
72
72
 
73
73
  xml = %Q(#{preamble}<Feature><UseCase ref="url"/></Feature>)
74
- @api.feature(:use_case => rest_object)
74
+ @api.create(:feature, :use_case => rest_object)
75
75
  assert_equal(xml, @xml)
76
76
  end
77
77
 
@@ -81,7 +81,7 @@ class RestApiTestCase < Test::Unit::TestCase
81
81
  uc1 = RestObject.new(@api, rest_object_xml)
82
82
 
83
83
  xml = %Q(#{preamble}<Feature><Dependents><UseCase ref="url"/></Dependents></Feature>)
84
- @api.feature(:dependents => uc1)
84
+ @api.create(:feature, :dependents => uc1)
85
85
  assert_equal(xml, @xml)
86
86
  end
87
87
 
@@ -92,7 +92,7 @@ class RestApiTestCase < Test::Unit::TestCase
92
92
  uc2 = RestObject.new(@api, rest_object_xml)
93
93
 
94
94
  xml = %Q(#{preamble}<Feature><Dependents><UseCase ref="url"/><UseCase ref="url"/></Dependents></Feature>)
95
- @api.feature(:dependents => [uc1, uc2])
95
+ @api.create(:feature, :dependents => [uc1, uc2])
96
96
  assert_equal(xml, @xml)
97
97
  end
98
98
 
@@ -1,6 +1,7 @@
1
1
 
2
2
  require 'test/unit'
3
3
  require 'test/unit/testcase'
4
+ require 'logger'
4
5
 
5
6
  require 'rubygems'
6
7
  require 'rally_rest_api'
@@ -68,13 +69,13 @@ class RestObjectTestCase < Test::Unit::TestCase
68
69
  end
69
70
 
70
71
  def test_equal_same_instance
71
- xml = %Q(<Object><TextNode>text</TextNode></Object>)
72
+ xml = %Q(<Object ref="http"><TextNode>text</TextNode></Object>)
72
73
  r1 = r2 = rest_object(xml)
73
74
  assert(r1 == r2)
74
75
  end
75
76
 
76
77
  def test_equal_with_nil
77
- xml = %Q(<Object><TextNode>text</TextNode></Object>)
78
+ xml = %Q(<Object ref="http"><TextNode>text</TextNode></Object>)
78
79
  r1 = rest_object(xml)
79
80
  assert(r1 != nil)
80
81
  end
@@ -87,23 +88,23 @@ class RestObjectTestCase < Test::Unit::TestCase
87
88
 
88
89
 
89
90
  def test_basic_text_node
90
- xml = %Q(<Object><TextNode>text</TextNode></Object>)
91
+ xml = %Q(<Object ref="bla"><TextNode>text</TextNode></Object>)
91
92
  assert_equal("text", rest_object(xml).text_node)
92
93
  end
93
94
 
94
95
  def test_nested_text_node
95
- xml = %Q(<Object><Nested><TextNode>text</TextNode></Nested></Object>)
96
+ xml = %Q(<Object ref="bla"><Nested ref="bla/nested"><TextNode>text</TextNode></Nested></Object>)
96
97
  assert_equal("text", rest_object(xml).nested.text_node)
97
98
  end
98
99
 
99
100
  # make sure RestObject are being created
100
101
  def test_ref_node
101
- xml = %Q(<Object><Top><RefElement ref="http" refObjectName="name1"/></Top></Object>)
102
- assert_equal(RestObject, rest_object(xml).top['name1'].class)
102
+ xml = %Q(<Object ref="http"><RefElement ref="http" refObjectName="name1"/></Object>)
103
+ assert_equal(RestObject, rest_object(xml).class)
103
104
  end
104
105
 
105
106
  def test_ref_node_reading
106
- xml = %Q(<Object><Top><RefElement ref="http" refObjectName="name1"/></Top></Object>)
107
+ xml = %Q(<Object ref="bla"><Top ref="blabla"><RefElement ref="http" refObjectName="name1"/></Top></Object>)
107
108
  # This will be the xml returned from read_rest
108
109
  class << self
109
110
  def read_xml
@@ -111,11 +112,11 @@ class RestObjectTestCase < Test::Unit::TestCase
111
112
  end
112
113
  end
113
114
 
114
- assert_equal("foo", rest_object(xml).top['name1'].foo)
115
+ assert_equal("foo", rest_object(xml).top.ref_element.foo)
115
116
  end
116
117
 
117
118
  def test_ref_node_collection_reading
118
- xml = %Q(<Object><Top><RefElements><RefElement ref="http1" refObjectName="name1"/><RefElement ref="http2" refObjectName="name2"/></RefElements></Top></Object>)
119
+ xml = %Q(<Object ref="bla"><Top ref="bla"><RefElements><RefElement ref="http1" refObjectName="name1"/><RefElement ref="http2" refObjectName="name2"/></RefElements></Top></Object>)
119
120
  # This will be the xml returned from read_rest
120
121
  class << self
121
122
  def read_xml
@@ -124,7 +125,7 @@ class RestObjectTestCase < Test::Unit::TestCase
124
125
  end
125
126
 
126
127
  assert_equal(2, rest_object(xml).top.ref_elements.length)
127
- ref_element = rest_object(xml).top.ref_elements["name1"]
128
+ ref_element = rest_object(xml).top.ref_elements[0]
128
129
 
129
130
  assert_equal("http1", ref_element.ref)
130
131
  assert_equal("Desc", ref_element.description) # Force a read
@@ -132,7 +133,7 @@ class RestObjectTestCase < Test::Unit::TestCase
132
133
  end
133
134
 
134
135
  def test_ref_collection_with_dups_is_array
135
- xml = %Q(<Object><Top><RefElements><RefElement ref="http1" refObjectName="name1"/><RefElement ref="http2" refObjectName="name2"/><RefElement ref="http3" refObjectName="name2"/><RefElement ref="http3" refObjectName="name2"/></RefElements></Top></Object>)
136
+ xml = %Q(<Object ref="bla"><Top ref="bla"><RefElements><RefElement ref="http1" refObjectName="name1"/><RefElement ref="http2" refObjectName="name2"/><RefElement ref="http3" refObjectName="name2"/><RefElement ref="http3" refObjectName="name2"/></RefElements></Top></Object>)
136
137
  # This will be the xml returned from read_rest
137
138
  class << self
138
139
  def read_xml
@@ -140,24 +141,22 @@ class RestObjectTestCase < Test::Unit::TestCase
140
141
  end
141
142
  end
142
143
 
143
- assert_equal(2, rest_object(xml).top.ref_elements.length)
144
- assert_equal(Array, rest_object(xml).top.ref_elements["name2"].class)
145
- assert_equal(3, rest_object(xml).top.ref_elements["name2"].length)
144
+ assert_equal(4, rest_object(xml).top.ref_elements.length)
146
145
  end
147
146
 
148
147
  def test_named_collection_reading
149
- xml = %Q(<Object><Top><NamedElements><NamedElement ref="http1" refObjectName="name1"><Name>name1</Name></NamedElement><NamedElement ref="http2" refObjectName="name2"><Name>name2</Name></NamedElement></NamedElements></Top></Object>)
148
+ xml = %Q(<Object ref="bla"><Top ref="bla"><NamedElements><NamedElement ref="http1" refObjectName="name1"><Name>name1</Name></NamedElement><NamedElement ref="http2" refObjectName="name2"><Name>name2</Name></NamedElement></NamedElements></Top></Object>)
150
149
 
151
150
  assert_equal(2, rest_object(xml).top.named_elements.length)
152
- named_element1 = rest_object(xml).top.named_elements["name1"]
151
+ named_element1 = rest_object(xml).top.named_elements[0]
153
152
  assert_equal("name1", named_element1.name)
154
153
 
155
- named_element2 = rest_object(xml).top.named_elements["name2"]
154
+ named_element2 = rest_object(xml).top.named_elements[1]
156
155
  assert_equal("name2", named_element2.name)
157
156
  end
158
157
 
159
158
  def test_unnamed_collection_reading
160
- xml = %Q(<Object><Top><NamedElements><NamedElement ref="http1"><Name>name1</Name></NamedElement><NamedElement ref="http2"><Name>name2</Name></NamedElement></NamedElements></Top></Object>)
159
+ xml = %Q(<Object ref="bla"><Top ref="bla"><NamedElements><NamedElement ref="http1"><Name>name1</Name></NamedElement><NamedElement ref="http2"><Name>name2</Name></NamedElement></NamedElements></Top></Object>)
161
160
 
162
161
  assert_equal(2, rest_object(xml).top.named_elements.length)
163
162
  assert_equal("name1", rest_object(xml).top.named_elements[0].name)
@@ -20,6 +20,10 @@ class TestRestQuery < Test::Unit::TestCase
20
20
  def test_name_with_spaces
21
21
  assert_equal("(Name = \"name name\")", RestQuery.query { equal :name, "name name"} )
22
22
  end
23
+
24
+ def test_null_parameter
25
+ assert_equal("(Name = null)", RestQuery.query { equal :name, nil} )
26
+ end
23
27
 
24
28
  def test_attribute_camelized
25
29
  assert_equal("(IterationName != iteration)",
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.0
3
3
  specification_version: 1
4
4
  name: rally_rest_api
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.6.2
7
- date: 2006-12-18 00:00:00 -07:00
6
+ version: 0.6.3
7
+ date: 2007-01-03 00:00:00 -07:00
8
8
  summary: A ruby-ized interface to Rally's REST webservices API
9
9
  require_paths:
10
10
  - lib