rally_rest_api 0.5.5
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.
- data/CHANGELOG.txt +4 -0
- data/History.txt +0 -0
- data/Manifest.txt +19 -0
- data/README.txt +111 -0
- data/Rakefile +51 -0
- data/lib/rally_rest_api.rb +1 -0
- data/lib/rally_rest_api/query.rb +170 -0
- data/lib/rally_rest_api/query_result.rb +73 -0
- data/lib/rally_rest_api/rally_rest.rb +100 -0
- data/lib/rally_rest_api/rest_builder.rb +179 -0
- data/lib/rally_rest_api/rest_object.rb +205 -0
- data/lib/rally_rest_api/typedef.rb +23 -0
- data/lib/rally_rest_api/version.rb +9 -0
- data/setup.rb +1585 -0
- data/test/tc_query_result.rb +41 -0
- data/test/tc_rest_api.rb +98 -0
- data/test/tc_rest_object.rb +146 -0
- data/test/tc_rest_query.rb +197 -0
- data/test/test_helper.rb +2 -0
- metadata +75 -0
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'test/unit/testcase'
|
3
|
+
|
4
|
+
require 'rally_rest_api/rally_rest'
|
5
|
+
|
6
|
+
class QueryResultTestCase < Test::Unit::TestCase
|
7
|
+
|
8
|
+
|
9
|
+
def setup
|
10
|
+
@api = RallyRestAPI.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def make_result(total, page_size, start_index)
|
14
|
+
xml = %Q(<QueryResult><TotalResultCount>#{total}</TotalResultCount><PageSize>#{page_size}</PageSize><StartIndex>#{start_index}</StartIndex><Results>)
|
15
|
+
page_size.times { |i| xml << %Q(<RefElement ref="http" refObjectName="name#{i}"/>) }
|
16
|
+
xml << %Q(</Results></QueryResult>)
|
17
|
+
xml
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_basic_numbers
|
21
|
+
result_xml = make_result(20, 20, 0)
|
22
|
+
result = QueryResult.new(nil, @api, result_xml)
|
23
|
+
assert_equal(20, result.total_result_count)
|
24
|
+
assert_equal(20, result.page_size)
|
25
|
+
assert_equal(0, result.start_index)
|
26
|
+
assert_equal(20, result.page_length)
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_more_pages_when_no_pages
|
30
|
+
query_result_xml = make_result(20, 20, 0)
|
31
|
+
result = QueryResult.new(nil, @api, query_result_xml)
|
32
|
+
assert(! result.more_pages?, "No more pages when total == page size")
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_more_pages_when_more_pages
|
36
|
+
query_result_xml = make_result(21, 20, 0)
|
37
|
+
result = QueryResult.new(nil, @api, query_result_xml)
|
38
|
+
assert(result.more_pages?, "Should have more pages when total != page size")
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
data/test/tc_rest_api.rb
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'test/unit/testcase'
|
3
|
+
|
4
|
+
require 'rally_rest_api/rally_rest'
|
5
|
+
|
6
|
+
class RestApiTestCase < Test::Unit::TestCase
|
7
|
+
|
8
|
+
# We need to override post_xml from RestBuilder, So redefine it here
|
9
|
+
# We want this post_xml to set the xml that was received onto the testcase
|
10
|
+
# So create an xml= on the test, and pass the test into the RallyRestAPI
|
11
|
+
module LocalBuilder
|
12
|
+
def test=(test)
|
13
|
+
@test = test
|
14
|
+
end
|
15
|
+
def post_xml(url, xml, username, password)
|
16
|
+
@test.xml = xml
|
17
|
+
"<CreateResult><Object/></CreateResult>"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def xml=(xml)
|
22
|
+
@xml = xml
|
23
|
+
end
|
24
|
+
|
25
|
+
def setup
|
26
|
+
super
|
27
|
+
@api = RallyRestAPI.new
|
28
|
+
class << @api
|
29
|
+
include LocalBuilder
|
30
|
+
end
|
31
|
+
@api.test = self
|
32
|
+
end
|
33
|
+
|
34
|
+
def preamble
|
35
|
+
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
36
|
+
end
|
37
|
+
|
38
|
+
# This covers:
|
39
|
+
# - Camel casing basic types and names
|
40
|
+
# - String values
|
41
|
+
def test_basic_create
|
42
|
+
xml = "#{preamble}<Feature><Name>name</Name></Feature>"
|
43
|
+
@api.feature(:name => "name")
|
44
|
+
assert_equal(xml, @xml)
|
45
|
+
end
|
46
|
+
|
47
|
+
# test that types and keys are camel cased (at least with one underscore)
|
48
|
+
def test_camel_case
|
49
|
+
xml = "#{preamble}<UseCase><NameName>name</NameName></UseCase>"
|
50
|
+
@api.use_case(:name_name => "name")
|
51
|
+
assert_equal(xml, @xml)
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_nil_value
|
55
|
+
xml = %Q(#{preamble}<UseCase><Name ref="null"/></UseCase>)
|
56
|
+
@api.use_case(:name => nil)
|
57
|
+
assert_equal(xml, @xml)
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_time_value
|
61
|
+
time = Time.now
|
62
|
+
xml = "#{preamble}<UseCase><Time>#{time.iso8601}</Time></UseCase>"
|
63
|
+
@api.use_case(:time => time)
|
64
|
+
assert_equal(xml, @xml)
|
65
|
+
end
|
66
|
+
|
67
|
+
# check passing one RestObject as the value
|
68
|
+
def test_rest_object_value
|
69
|
+
rest_object_xml = %Q(<Feature ref="url"><Name>name</Name></Feature>)
|
70
|
+
rest_object = RestObject.new(@api, rest_object_xml)
|
71
|
+
|
72
|
+
xml = %Q(#{preamble}<Feature><UseCase ref="url"/></Feature>)
|
73
|
+
@api.feature(:use_case => rest_object)
|
74
|
+
assert_equal(xml, @xml)
|
75
|
+
end
|
76
|
+
|
77
|
+
# Check for passing a single RestObject as the value to a collection node
|
78
|
+
def test_rest_object_array_value
|
79
|
+
rest_object_xml = %Q(<UseCase ref="url"><Name>name</Name></UseCase>)
|
80
|
+
uc1 = RestObject.new(@api, rest_object_xml)
|
81
|
+
|
82
|
+
xml = %Q(#{preamble}<Feature><Dependents><UseCase ref="url"/></Dependents></Feature>)
|
83
|
+
@api.feature(:dependents => uc1)
|
84
|
+
assert_equal(xml, @xml)
|
85
|
+
end
|
86
|
+
|
87
|
+
# Check for passing an array of RestObjects as the value
|
88
|
+
def test_rest_object_array_value_multiple_values
|
89
|
+
rest_object_xml = %Q(<UseCase ref="url"><Name>name</Name></UseCase>)
|
90
|
+
uc1 = RestObject.new(@api, rest_object_xml)
|
91
|
+
uc2 = RestObject.new(@api, rest_object_xml)
|
92
|
+
|
93
|
+
xml = %Q(#{preamble}<Feature><Dependents><UseCase ref="url"/><UseCase ref="url"/></Dependents></Feature>)
|
94
|
+
@api.feature(:dependents => [uc1, uc2])
|
95
|
+
assert_equal(xml, @xml)
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
|
2
|
+
require 'test/unit'
|
3
|
+
require 'test/unit/testcase'
|
4
|
+
|
5
|
+
require 'rally_rest_api/rally_rest'
|
6
|
+
|
7
|
+
# We need to override read_rest from RestBuilder, So redefine it here
|
8
|
+
# We need a way to inject the xml that will be read by a RestObject when
|
9
|
+
# it is converting itself from a ref.
|
10
|
+
# So change the RestBuilder, which RestObject includes, and add a test=
|
11
|
+
# so we can send in this instance of the test case
|
12
|
+
module MyRestBuilder
|
13
|
+
def read_rest(url, username, password)
|
14
|
+
@@test.url = url
|
15
|
+
@@test.read_xml
|
16
|
+
end
|
17
|
+
|
18
|
+
def MyRestBuilder.test=(test)
|
19
|
+
@@test = test
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
$GLOBAL_BINDING = binding
|
24
|
+
|
25
|
+
class RestObjectTestCase < Test::Unit::TestCase
|
26
|
+
def url=(url)
|
27
|
+
@url = url
|
28
|
+
end
|
29
|
+
|
30
|
+
def setup
|
31
|
+
super
|
32
|
+
@api = RallyRestAPI.new
|
33
|
+
|
34
|
+
s = <<-"EOF"
|
35
|
+
class Class
|
36
|
+
alias :old_new :new
|
37
|
+
def new(*args)
|
38
|
+
result = old_new(*args)
|
39
|
+
if result.kind_of?(RestObject)
|
40
|
+
class << result
|
41
|
+
include MyRestBuilder
|
42
|
+
end
|
43
|
+
end
|
44
|
+
return result
|
45
|
+
end
|
46
|
+
end
|
47
|
+
EOF
|
48
|
+
eval(s, $GLOBAL_BINDING)
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
def teardown
|
53
|
+
super
|
54
|
+
s = <<-"EOF"
|
55
|
+
class Class
|
56
|
+
alias :new :old_new
|
57
|
+
end
|
58
|
+
EOF
|
59
|
+
eval(s, $GLOBAL_BINDING)
|
60
|
+
end
|
61
|
+
|
62
|
+
def rest_object(xml)
|
63
|
+
o = RestObject.new(@api, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>#{xml}")
|
64
|
+
MyRestBuilder.test = self
|
65
|
+
o
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_basic_text_node
|
69
|
+
xml = %Q(<Object><TextNode>text</TextNode></Object>)
|
70
|
+
assert_equal("text", rest_object(xml).text_node)
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_nested_text_node
|
74
|
+
xml = %Q(<Object><Nested><TextNode>text</TextNode></Nested></Object>)
|
75
|
+
assert_equal("text", rest_object(xml).nested.text_node)
|
76
|
+
end
|
77
|
+
|
78
|
+
# make sure RestObject are being created
|
79
|
+
def test_ref_node
|
80
|
+
xml = %Q(<Object><Top><RefElement ref="http" refObjectName="name1"/></Top></Object>)
|
81
|
+
assert_equal(RestObject, rest_object(xml).top['name1'].class)
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_ref_node_reading
|
85
|
+
xml = %Q(<Object><Top><RefElement ref="http" refObjectName="name1"/></Top></Object>)
|
86
|
+
# This will be the xml returned from read_rest
|
87
|
+
class << self
|
88
|
+
def read_xml
|
89
|
+
%Q(<RefElement><Foo>foo</Foo></RefElement>)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
assert_equal("foo", rest_object(xml).top['name1'].foo)
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_ref_node_collection_reading
|
97
|
+
xml = %Q(<Object><Top><RefElements><RefElement ref="http1" refObjectName="name1"/><RefElement ref="http2" refObjectName="name2"/></RefElements></Top></Object>)
|
98
|
+
# This will be the xml returned from read_rest
|
99
|
+
class << self
|
100
|
+
def read_xml
|
101
|
+
%Q(<RefElement ref="http3" refObjectName="name1"><Name>name</Name><Description>Desc</Description></RefElement>)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
assert_equal(2, rest_object(xml).top.ref_elements.length)
|
106
|
+
ref_element = rest_object(xml).top.ref_elements["name1"]
|
107
|
+
|
108
|
+
assert_equal("http1", ref_element.ref)
|
109
|
+
assert_equal("Desc", ref_element.description) # Force a read
|
110
|
+
assert_equal("http3", ref_element.ref) # Post read
|
111
|
+
end
|
112
|
+
|
113
|
+
def test_ref_collection_with_dups_is_array
|
114
|
+
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>)
|
115
|
+
# This will be the xml returned from read_rest
|
116
|
+
class << self
|
117
|
+
def read_xml
|
118
|
+
%Q(<RefElement ref="http3" refObjectName="name1"><Name>name</Name><Description>Desc</Description></RefElement>)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
assert_equal(2, rest_object(xml).top.ref_elements.length)
|
123
|
+
assert_equal(Array, rest_object(xml).top.ref_elements["name2"].class)
|
124
|
+
assert_equal(3, rest_object(xml).top.ref_elements["name2"].length)
|
125
|
+
end
|
126
|
+
|
127
|
+
def test_named_collection_reading
|
128
|
+
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>)
|
129
|
+
|
130
|
+
assert_equal(2, rest_object(xml).top.named_elements.length)
|
131
|
+
named_element1 = rest_object(xml).top.named_elements["name1"]
|
132
|
+
assert_equal("name1", named_element1.name)
|
133
|
+
|
134
|
+
named_element2 = rest_object(xml).top.named_elements["name2"]
|
135
|
+
assert_equal("name2", named_element2.name)
|
136
|
+
end
|
137
|
+
|
138
|
+
def test_unnamed_collection_reading
|
139
|
+
xml = %Q(<Object><Top><NamedElements><NamedElement ref="http1"><Name>name1</Name></NamedElement><NamedElement ref="http2"><Name>name2</Name></NamedElement></NamedElements></Top></Object>)
|
140
|
+
|
141
|
+
assert_equal(2, rest_object(xml).top.named_elements.length)
|
142
|
+
assert_equal("name1", rest_object(xml).top.named_elements[0].name)
|
143
|
+
assert_equal("name2", rest_object(xml).top.named_elements[1].name)
|
144
|
+
end
|
145
|
+
|
146
|
+
end
|
@@ -0,0 +1,197 @@
|
|
1
|
+
|
2
|
+
require "test/unit"
|
3
|
+
require 'rally_rest_api/query'
|
4
|
+
|
5
|
+
class TestRestQuery < Test::Unit::TestCase
|
6
|
+
# RestQuery.find(:feature).where { # default is and
|
7
|
+
# equal :name, "name"
|
8
|
+
# or {
|
9
|
+
# equal :name, "name"
|
10
|
+
# equal :card.task.name, "task name"
|
11
|
+
# less_than :plan_estimate, "10"
|
12
|
+
# }
|
13
|
+
# }
|
14
|
+
def test_single_statement
|
15
|
+
assert_equal("(Name = name)", RestQuery.query { equal :name, "name"} )
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_name_with_spaces
|
19
|
+
assert_equal("(Name = \"name name\")", RestQuery.query { equal :name, "name name"} )
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_attribute_camelized
|
23
|
+
assert_equal("(IterationName != iteration)",
|
24
|
+
RestQuery.query { not_equal :iteration_name, "iteration"}
|
25
|
+
)
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_attribute_path_camelized
|
29
|
+
assert_equal("(Card.IterationName contains iteration)",
|
30
|
+
RestQuery.query{ contains :'card.iteration_name', "iteration"}
|
31
|
+
)
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_multiple_and_statements
|
35
|
+
assert_equal("((Name = name) and (Description > description))",
|
36
|
+
RestQuery.query do
|
37
|
+
equal :name, "name"
|
38
|
+
greater_than :description, "description"
|
39
|
+
end
|
40
|
+
)
|
41
|
+
|
42
|
+
assert_equal("(((Name = name) and (Description = description)) and (Notes <= notes))",
|
43
|
+
RestQuery.query do
|
44
|
+
equal :name, "name"
|
45
|
+
equal :description, "description"
|
46
|
+
lte :notes, "notes"
|
47
|
+
end
|
48
|
+
)
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_multiple_or_statements
|
52
|
+
assert_equal("((Name = name) or (Description >= description))",
|
53
|
+
RestQuery.query do
|
54
|
+
_or_ do
|
55
|
+
equal :name, "name"
|
56
|
+
gte :description, "description"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
)
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_multiple_ands_with_or
|
63
|
+
assert_equal("(((Name = name) and (Description >= description)) or (Notes = notes))",
|
64
|
+
RestQuery.query do
|
65
|
+
_or_ do
|
66
|
+
_and_ do
|
67
|
+
equal :name, "name"
|
68
|
+
greater_than_equal :description, "description"
|
69
|
+
end
|
70
|
+
equal :notes, "notes"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
)
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_multiple_ors_with_and
|
77
|
+
assert_equal("(((Name = name) or (Description = description)) and (Notes = notes))",
|
78
|
+
RestQuery.query do
|
79
|
+
_or_ do
|
80
|
+
equal :name, "name"
|
81
|
+
equal :description, "description"
|
82
|
+
end
|
83
|
+
equal :notes, "notes"
|
84
|
+
end
|
85
|
+
)
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_multiple_ors_with_multiple_ands
|
89
|
+
assert_equal("(((Name = name) or (Description = description)) and ((Notes = notes) and (StartDate = start)))",
|
90
|
+
RestQuery.query do
|
91
|
+
_or_ do
|
92
|
+
equal :name, "name"
|
93
|
+
equal :description, "description"
|
94
|
+
end
|
95
|
+
_and_ do
|
96
|
+
equal :notes, "notes"
|
97
|
+
equal :start_date, "start"
|
98
|
+
end
|
99
|
+
end
|
100
|
+
)
|
101
|
+
end
|
102
|
+
|
103
|
+
def test_three_ors_with_three_ands
|
104
|
+
assert_equal("((((Name = name1) or (Description = description1)) or (Other = other1)) and (((Notes = notes2) and (StartDate = start2)) and (Other = other2)))",
|
105
|
+
RestQuery.query {
|
106
|
+
_and_ {
|
107
|
+
_or_ {
|
108
|
+
equal :name, "name1"
|
109
|
+
equal :description, "description1"
|
110
|
+
equal :other, "other1"
|
111
|
+
}
|
112
|
+
_and_ {
|
113
|
+
equal :notes, "notes2"
|
114
|
+
equal :start_date, "start2"
|
115
|
+
equal :other, "other2"
|
116
|
+
}
|
117
|
+
}
|
118
|
+
}
|
119
|
+
)
|
120
|
+
end
|
121
|
+
|
122
|
+
def test_anded_ors
|
123
|
+
assert_equal("(((Name = name1) or (Name = name2)) and ((Name = name3) or (Name = name4)))",
|
124
|
+
RestQuery.query do
|
125
|
+
_or_ do
|
126
|
+
equal :name, "name1"
|
127
|
+
equal :name, "name2"
|
128
|
+
end
|
129
|
+
_or_ do
|
130
|
+
equal :name, "name3"
|
131
|
+
equal :name, "name4"
|
132
|
+
end
|
133
|
+
end
|
134
|
+
)
|
135
|
+
end
|
136
|
+
|
137
|
+
def test_new_with_type_no_args
|
138
|
+
query_string = RestQuery.new(:artifact) { equal :name, "name"}.to_q
|
139
|
+
assert_equal("query=(Name = name)", URI.unescape(query_string) )
|
140
|
+
end
|
141
|
+
|
142
|
+
def test_new_with_type_and_args
|
143
|
+
query_string = RestQuery.new(:artifact,
|
144
|
+
:pagesize => 10,
|
145
|
+
:start => 1) { equal :name, "name"}.to_q
|
146
|
+
|
147
|
+
# The parameters sometimes appear in a different order
|
148
|
+
unescaped_qs = URI.unescape(query_string)
|
149
|
+
assert(unescaped_qs =~ /&start=1/)
|
150
|
+
assert(unescaped_qs =~ /&pagesize=10/)
|
151
|
+
assert(unescaped_qs =~ /query=\(Name = name\)/)
|
152
|
+
# assert_equal("query=(Name = name)&pagesize=10&start=1", URI.unescape(query_string) )
|
153
|
+
end
|
154
|
+
|
155
|
+
def test_new_with_one_order_arg
|
156
|
+
query_string = RestQuery.new(:artifact,
|
157
|
+
:order => :package) { equal :name, "name"}.to_q
|
158
|
+
assert_equal("query=(Name = name)&order=Package", URI.unescape(query_string) )
|
159
|
+
end
|
160
|
+
|
161
|
+
def test_new_with_multiple_order_arg
|
162
|
+
query_string = RestQuery.new(:artifact,
|
163
|
+
:order => [:package, :owner]) { equal :name, "name"}.to_q
|
164
|
+
assert_equal("query=(Name = name)&order=Package, Owner", URI.unescape(query_string) )
|
165
|
+
end
|
166
|
+
|
167
|
+
def test_new_with_multiple_order_arg_desc
|
168
|
+
query_string = RestQuery.new(:artifact,
|
169
|
+
:order => [:package, :owner, :desc]) { equal :name, "name"}.to_q
|
170
|
+
assert_equal("query=(Name = name)&order=Package, Owner desc", URI.unescape(query_string) )
|
171
|
+
end
|
172
|
+
|
173
|
+
def test_next_page
|
174
|
+
q = RestQuery.new(:artifact,
|
175
|
+
:pagesize => 10,
|
176
|
+
:start => 1) { equal :name, "name"}
|
177
|
+
query_string = q.to_q
|
178
|
+
|
179
|
+
# The parameters sometimes appear in a different order
|
180
|
+
unescaped_qs = URI.unescape(query_string)
|
181
|
+
assert(unescaped_qs =~ /&start=1/)
|
182
|
+
assert(unescaped_qs =~ /&pagesize=10/)
|
183
|
+
assert(unescaped_qs =~ /query=\(Name = name\)/)
|
184
|
+
# assert_equal("query=(Name = name)&pagesize=10&start=1", URI.unescape(query_string) )
|
185
|
+
query_string = q.next_page(:pagesize => 20,
|
186
|
+
:start => 20).to_q
|
187
|
+
|
188
|
+
# The parameters sometimes appear in a different order
|
189
|
+
unescaped_qs = URI.unescape(query_string)
|
190
|
+
assert(unescaped_qs =~ /&start=20/)
|
191
|
+
assert(unescaped_qs =~ /&pagesize=20/)
|
192
|
+
assert(unescaped_qs =~ /query=\(Name = name\)/)
|
193
|
+
# assert_equal("query=(Name = name)&pagesize=20&start=20", URI.unescape(query_string) )
|
194
|
+
end
|
195
|
+
|
196
|
+
|
197
|
+
end
|