rally_rest_api 0.5.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|