alm-rest-api 0.0.2

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.
@@ -0,0 +1,22 @@
1
+ # Auto detect text files and perform LF normalization
2
+ * text=auto
3
+
4
+ # Custom for Visual Studio
5
+ *.cs diff=csharp
6
+ *.sln merge=union
7
+ *.csproj merge=union
8
+ *.vbproj merge=union
9
+ *.fsproj merge=union
10
+ *.dbproj merge=union
11
+
12
+ # Standard to msysgit
13
+ *.doc diff=astextplain
14
+ *.DOC diff=astextplain
15
+ *.docx diff=astextplain
16
+ *.DOCX diff=astextplain
17
+ *.dot diff=astextplain
18
+ *.DOT diff=astextplain
19
+ *.pdf diff=astextplain
20
+ *.PDF diff=astextplain
21
+ *.rtf diff=astextplain
22
+ *.RTF diff=astextplain
@@ -0,0 +1,163 @@
1
+ #################
2
+ ## Eclipse
3
+ #################
4
+
5
+ *.pydevproject
6
+ .project
7
+ .metadata
8
+ bin/
9
+ tmp/
10
+ *.tmp
11
+ *.bak
12
+ *.swp
13
+ *~.nib
14
+ local.properties
15
+ .classpath
16
+ .settings/
17
+ .loadpath
18
+
19
+ # External tool builders
20
+ .externalToolBuilders/
21
+
22
+ # Locally stored "Eclipse launch configurations"
23
+ *.launch
24
+
25
+ # CDT-specific
26
+ .cproject
27
+
28
+ # PDT-specific
29
+ .buildpath
30
+
31
+
32
+ #################
33
+ ## Visual Studio
34
+ #################
35
+
36
+ ## Ignore Visual Studio temporary files, build results, and
37
+ ## files generated by popular Visual Studio add-ons.
38
+
39
+ # User-specific files
40
+ *.suo
41
+ *.user
42
+ *.sln.docstates
43
+
44
+ # Build results
45
+ [Dd]ebug/
46
+ [Rr]elease/
47
+ *_i.c
48
+ *_p.c
49
+ *.ilk
50
+ *.meta
51
+ *.obj
52
+ *.pch
53
+ *.pdb
54
+ *.pgc
55
+ *.pgd
56
+ *.rsp
57
+ *.sbr
58
+ *.tlb
59
+ *.tli
60
+ *.tlh
61
+ *.tmp
62
+ *.vspscc
63
+ .builds
64
+ *.dotCover
65
+
66
+ ## TODO: If you have NuGet Package Restore enabled, uncomment this
67
+ #packages/
68
+
69
+ # Visual C++ cache files
70
+ ipch/
71
+ *.aps
72
+ *.ncb
73
+ *.opensdf
74
+ *.sdf
75
+
76
+ # Visual Studio profiler
77
+ *.psess
78
+ *.vsp
79
+
80
+ # ReSharper is a .NET coding add-in
81
+ _ReSharper*
82
+
83
+ # Installshield output folder
84
+ [Ee]xpress
85
+
86
+ # DocProject is a documentation generator add-in
87
+ DocProject/buildhelp/
88
+ DocProject/Help/*.HxT
89
+ DocProject/Help/*.HxC
90
+ DocProject/Help/*.hhc
91
+ DocProject/Help/*.hhk
92
+ DocProject/Help/*.hhp
93
+ DocProject/Help/Html2
94
+ DocProject/Help/html
95
+
96
+ # Click-Once directory
97
+ publish
98
+
99
+ # Others
100
+ [Bb]in
101
+ [Oo]bj
102
+ sql
103
+ TestResults
104
+ *.Cache
105
+ ClientBin
106
+ stylecop.*
107
+ ~$*
108
+ *.dbmdl
109
+ Generated_Code #added for RIA/Silverlight projects
110
+
111
+ # Backup & report files from converting an old project file to a newer
112
+ # Visual Studio version. Backup files are not needed, because we have git ;-)
113
+ _UpgradeReport_Files/
114
+ Backup*/
115
+ UpgradeLog*.XML
116
+
117
+
118
+
119
+ ############
120
+ ## Windows
121
+ ############
122
+
123
+ # Windows image file caches
124
+ Thumbs.db
125
+
126
+ # Folder config file
127
+ Desktop.ini
128
+
129
+
130
+ #############
131
+ ## Python
132
+ #############
133
+
134
+ *.py[co]
135
+
136
+ # Packages
137
+ *.egg
138
+ *.egg-info
139
+ dist
140
+ build
141
+ eggs
142
+ parts
143
+ bin
144
+ var
145
+ sdist
146
+ develop-eggs
147
+ .installed.cfg
148
+
149
+ # Installer logs
150
+ pip-log.txt
151
+
152
+ # Unit test / coverage reports
153
+ .coverage
154
+ .tox
155
+
156
+ #Translations
157
+ *.mo
158
+
159
+ #Mr Developer
160
+ .mr.developer.cfg
161
+
162
+ # Mac crap
163
+ .DS_Store
@@ -0,0 +1,8 @@
1
+ require 'rake/testtask'
2
+
3
+ Rake::TestTask.new do |t|
4
+ t.libs << 'test'
5
+ end
6
+
7
+ desc "Run tests"
8
+ task :default => :test
Binary file
@@ -0,0 +1,14 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'alm-rest-api'
3
+ s.version = '0.0.2'
4
+ s.date = '2012-12-14'
5
+ s.summary = "ALM!"
6
+ s.description = "ALM REST API Integration"
7
+ s.authors = ["Simon Zheng"]
8
+ s.email = 'xiaomengzheng@gmail.com'
9
+ s.require_paths = ["lib"]
10
+ s.files = `git ls-files`.split("\n")
11
+ #s.files = ["lib/alm-rest-api.rb"]
12
+ s.homepage =
13
+ 'http://rubygems.org/gems/alm-rest-api'
14
+ end
@@ -0,0 +1,154 @@
1
+ # alm-rest-api.rb
2
+
3
+ module ALM
4
+
5
+ # Logging in to our system is standard http login (basic authentication),
6
+ # where one must store the returned cookies for further use.
7
+ def self.login(loginUrl, username, password)
8
+ response = RestConnector.instance.httpBasicAuth(loginUrl, username, password)
9
+
10
+ return response.statusCode == '200'
11
+ end
12
+
13
+ def self.logout()
14
+ # note the get operation logs us out by setting authentication cookies to:
15
+ # LWSSO_COOKIE_KEY="" via server response header Set-Cookie
16
+ logoutUrl = RestConnector.instance.buildUrl("qcbin/authentication-point/logout")
17
+ response = RestConnector.instance.httpGet(logoutUrl, nil, nil)
18
+
19
+ return response.statusCode == '200'
20
+ end
21
+
22
+ def self.isAuthenticated()
23
+ isAuthenticateUrl = RestConnector.instance.buildUrl("qcbin/rest/is-authenticated")
24
+ response = RestConnector.instance.httpGet(isAuthenticateUrl, nil, nil)
25
+ responseCode = response.statusCode
26
+
27
+ # if already authenticated
28
+ # if not authenticated - get the address where to authenticate
29
+ # via WWW-Authenticate
30
+ if responseCode == "200"
31
+ ret = nil
32
+ elsif responseCode == "401"
33
+ authenticationHeader = response.responseHeaders["WWW-Authenticate"]
34
+ newUrl = authenticationHeader.split("=").at(1)
35
+ newUrl = newUrl.delete("\"")
36
+ newUrl = newUrl + "/authenticate"
37
+ ret = newUrl
38
+ end
39
+
40
+ return ret
41
+ end
42
+
43
+ # convenience method to do user login
44
+ def self.isLoggedIn(username, password)
45
+ authenticationPoint = isAuthenticated();
46
+ if (authenticationPoint != nil)
47
+ return login(authenticationPoint, username, password)
48
+ end
49
+ return true
50
+ end
51
+
52
+ # read all defects fields
53
+ def self.getDefectFields(required = false)
54
+ defectFieldsUrl = RestConnector.instance.buildEntityCollectionUrl("customization/entities/defect/field")
55
+ queryString = nil
56
+ if required
57
+ queryString = "required=true"
58
+ end
59
+ requestHeaders = Hash.new
60
+ requestHeaders["Accept"] = "application/xml"
61
+ response = RestConnector.instance.httpGet(defectFieldsUrl, queryString, requestHeaders)
62
+
63
+ defectFields = nil
64
+ if response.statusCode == '200'
65
+ defectFields = DefectFields::Fields.parse(response.toString())
66
+ end
67
+
68
+ return defectFields
69
+ end
70
+
71
+ # read pre-defined defects fields values
72
+ def self.getValueLists(defectFields = nil)
73
+ # ALM 11.0 the url is "customization/list"
74
+ valueListsUrl = RestConnector.instance.buildEntityCollectionUrl("customization/list")
75
+ queryString = nil
76
+ if defectFields
77
+ defectFields.fields.each do |field|
78
+ if field.list_id
79
+ if queryString == nil
80
+ queryString = "id=" + field.list_id.to_s
81
+ else
82
+ queryString = queryString + "," + field.list_id.to_s
83
+ end
84
+ end
85
+ end
86
+ end
87
+
88
+ requestHeaders = Hash.new
89
+ requestHeaders["Accept"] = "application/xml"
90
+ response = RestConnector.instance.httpGet(valueListsUrl, queryString, requestHeaders)
91
+
92
+ valueLists = nil
93
+ if response.statusCode == '200'
94
+ valueLists = ValueLists::Lists.parse(response.toString())
95
+ end
96
+
97
+ return valueLists
98
+ end
99
+
100
+ # create new defect
101
+ def self.createDefect(defect)
102
+ defectsUrl = RestConnector.instance.buildEntityCollectionUrl("defect")
103
+ requestHeaders = Hash.new
104
+ requestHeaders["Content-Type"] = "application/xml"
105
+ requestHeaders["Accept"] = "application/xml"
106
+
107
+ response = RestConnector.instance.httpPost(defectsUrl, defect.to_xml, requestHeaders)
108
+
109
+ defectId = nil
110
+ if response.statusCode == '201'
111
+ defectUrl = response.responseHeaders["Location"]
112
+ defectId = defectUrl.split('/').last
113
+ end
114
+
115
+ return defectId
116
+ end
117
+
118
+ # delete a defect
119
+ def self.deleteDefect(defectId)
120
+ defectUrl = RestConnector.instance.buildDefectUrl(defectId)
121
+ requestHeaders = Hash.new
122
+ requestHeaders["Accept"] = "application/xml"
123
+
124
+ response = RestConnector.instance.httpDelete(defectUrl, requestHeaders)
125
+
126
+ return response.statusCode == '200'
127
+ end
128
+
129
+ # attach a file
130
+ def self.attachWithMultipart(defectId, filePath)
131
+ attachmentUrl = RestConnector.instance.buildEntityCollectionUrl("attachment")
132
+ boundary = "AaB03x"
133
+ requestHeaders = Hash.new
134
+ requestHeaders["Content-Type"] = "multipart/form-data, boundary=#{boundary}"
135
+
136
+ #post_body = []
137
+ #post_body < < "--#{boundary}rn"
138
+ #post_body < < "Content-Disposition: form-data; name="datafile"; filename="#{File.basename(file)}"rn"
139
+ #post_body < < "Content-Type: text/plainrn"
140
+ #post_body < < "rn"
141
+ #post_body < < File.read(file)
142
+ #post_body < < "rn--#{boundary}--rn"
143
+
144
+ #Response response = RestConnector.instance.httpPost(attachmentUrl, post_body, requestHeaders)
145
+ end
146
+
147
+ end
148
+
149
+ require 'alm-rest-api/entity'
150
+ require 'alm-rest-api/defect-fields'
151
+ require 'alm-rest-api/value-lists'
152
+ require 'alm-rest-api/constants'
153
+ require 'alm-rest-api/response'
154
+ require 'alm-rest-api/rest-connector'
@@ -0,0 +1,12 @@
1
+ # These constants are used throughout the code to set the server to work with.
2
+ # To execute this code, change these settings to fit
3
+ # those of your server.
4
+ class ALM::Constants
5
+ HOST = "localhost"
6
+ PORT = "8080"
7
+ USERNAME = "sa"
8
+ PASSWORD = "C71a04t23"
9
+ DOMAIN = "DEFAULT"
10
+ PROJECT = "Simon"
11
+ VERSIONED = true
12
+ end
@@ -0,0 +1,33 @@
1
+ require 'happymapper'
2
+
3
+ module DefectFields
4
+
5
+ class Field
6
+ include HappyMapper
7
+
8
+ tag 'Field'
9
+ attribute :physical_name, String, :tag => 'PhysicalName'
10
+ attribute :name, String, :tag => 'Name'
11
+ attribute :label, String, :tag => 'Label'
12
+ element :active, Boolean, :tag => 'Active'
13
+ element :editable, Boolean, :tag => 'Editable'
14
+ element :size, Integer, :tag => 'Size'
15
+ element :filterable, Boolean, :tag => 'Filterable'
16
+ element :groupable, Boolean, :tag => 'Groupable'
17
+ element :history, Boolean, :tag => 'History'
18
+ element :list_id, Integer, :tag => 'List-Id'
19
+ element :type, String, :tag => 'Type'
20
+ element :supports_multivalue, Boolean, :tag => 'SupportsMultivalue'
21
+ element :required, Boolean, :tag => 'Required'
22
+ element :system, Boolean, :tag => 'System'
23
+ element :verify, Boolean, :tag => 'Verify'
24
+ element :virtual, Boolean, :tag => 'Virtual'
25
+ end
26
+
27
+ class Fields
28
+ include HappyMapper
29
+
30
+ tag 'Fields'
31
+ has_many :fields, Field
32
+ end
33
+ end
@@ -0,0 +1,30 @@
1
+ require 'happymapper'
2
+
3
+ class Field
4
+ include HappyMapper
5
+
6
+ tag 'Field'
7
+ attribute :name, String, :tag => 'Name'
8
+ element :value, String, :tag => 'Value'
9
+ end
10
+
11
+ class Fields
12
+ include HappyMapper
13
+
14
+ tag 'Fields'
15
+ has_many :fields, Field
16
+ end
17
+
18
+ class Entity
19
+ include HappyMapper
20
+
21
+ def initialize(type)
22
+ @type = type
23
+ @fields = Fields.new
24
+ @fields.fields = Array.new
25
+ end
26
+
27
+ tag 'Entity'
28
+ attribute :type, String, :tag => 'Type'
29
+ element :fields, Fields
30
+ end
@@ -0,0 +1,11 @@
1
+ class ALM::Response
2
+ attr_accessor :responseHeaders
3
+ attr_accessor :responseData
4
+ attr_accessor :failure
5
+ attr_accessor :statusCode
6
+
7
+ def toString()
8
+ return responseData
9
+ end
10
+
11
+ end
@@ -0,0 +1,147 @@
1
+ # rest-connector.rb
2
+
3
+ require 'net/http'
4
+ require 'uri'
5
+ require 'stringio'
6
+ require 'singleton'
7
+
8
+ class ALM::RestConnector
9
+ include Singleton
10
+
11
+ attr_accessor :cookies
12
+ attr_accessor :host
13
+ attr_accessor :port
14
+ attr_accessor :domain
15
+ attr_accessor :project
16
+
17
+ def init(cookies, host, port, domain, project)
18
+ @cookies = cookies
19
+ @host = host
20
+ @port = port
21
+ @domain = domain
22
+ @project = project
23
+ end
24
+
25
+ def buildEntityCollectionUrl(entityType)
26
+ return buildUrl('qcbin/rest/domains/' + domain + '/projects/' + project + '/' + entityType + 's')
27
+ end
28
+
29
+ def buildDefectUrl(defectId)
30
+ return buildUrl('qcbin/rest/domains/' + domain + '/projects/' + project + '/defects/' + defectId)
31
+ end
32
+
33
+ def buildUrl(path)
34
+ return "http://#{host}:#{port}/#{path}"
35
+ end
36
+
37
+ def httpPut(url, data, headers)
38
+ return doHttp('PUT', url, nil, data, headers, cookies)
39
+ end
40
+
41
+ def httpPost(url, data, headers)
42
+ return doHttp('POST', url, nil, data, headers, cookies)
43
+ end
44
+
45
+ def httpDelete(url, headers)
46
+ return doHttp('DELETE', url, nil, nil, headers, cookies)
47
+ end
48
+
49
+ def httpGet(url, queryString, headers)
50
+ return doHttp('GET', url, queryString, nil, headers, cookies)
51
+ end
52
+
53
+ def httpBasicAuth(url, username, password)
54
+ headers = {"username" => username, "password" => password}
55
+ return doHttp('AUTH', url, nil, nil, headers, cookies)
56
+ end
57
+
58
+ def getCookieString
59
+ s = StringIO.new
60
+ if (!cookies.empty?)
61
+ cookies.each{|key,value|
62
+ s << key << '=' << value << ';'
63
+ }
64
+ end
65
+
66
+ return s.string
67
+ end
68
+
69
+ private
70
+
71
+ def doHttp(type, url, queryString, data, headers, cookies)
72
+ if (queryString != nil && !queryString.empty?)
73
+ url.concat('?' + queryString)
74
+ end
75
+
76
+ uri = URI.parse(url)
77
+ http = Net::HTTP.new(uri.host, uri.port)
78
+
79
+ case type
80
+ when "POST"
81
+ request = Net::HTTP::Post.new(uri.request_uri)
82
+ when "GET"
83
+ request = Net::HTTP::Get.new(uri.request_uri)
84
+ when "PUT"
85
+ request = Net::HTTP::Put.new(uri.request_uri)
86
+ when "DELETE"
87
+ request = Net::HTTP::Delete.new(uri.request_uri)
88
+ when "AUTH"
89
+ request = Net::HTTP::Get.new(uri.request_uri)
90
+ request.basic_auth(headers["username"], headers["password"])
91
+ end
92
+
93
+ cookieString = getCookieString()
94
+ prepareHttpRequest(request, headers, data, cookieString)
95
+
96
+ response = http.request(request)
97
+
98
+ res = retrieveHtmlResponse(response)
99
+ updateCookies(res)
100
+
101
+ return res
102
+ end
103
+
104
+ def prepareHttpRequest(request, headers, data, cookieString)
105
+ contentType = nil
106
+ if (cookieString != nil && !cookieString.empty?)
107
+ request["Cookie"] = cookieString
108
+ end
109
+
110
+ if (headers != nil)
111
+ contentType = headers.delete("Content-Type")
112
+ headers.each{|key, value|
113
+ request[key] = value
114
+ }
115
+ end
116
+
117
+ if (data != nil)
118
+ if (contentType != nil)
119
+ request["Content-Type"] = contentType
120
+ request.body = data
121
+ end
122
+ end
123
+ end
124
+
125
+ def retrieveHtmlResponse(response)
126
+ res = ALM::Response.new
127
+ res.statusCode = response.code
128
+ res.responseHeaders = response
129
+ res.responseData = response.body
130
+
131
+ return res
132
+ end
133
+
134
+ def updateCookies(response)
135
+ newCookies = response.responseHeaders.get_fields('Set-Cookie')
136
+ if (newCookies != nil)
137
+ newCookies.each{|cookie|
138
+ c1 = cookie.split(';')[0]
139
+ c2 = c1.split('=')
140
+ key = c2[0]
141
+ value = c2[1]
142
+ cookies[key] = value
143
+ }
144
+ end
145
+ end
146
+
147
+ end
@@ -0,0 +1,43 @@
1
+ require 'happymapper'
2
+
3
+ module ValueLists
4
+
5
+ class Item
6
+ include HappyMapper
7
+
8
+ tag 'Item'
9
+ attribute :value, String, :tag => 'value'
10
+ end
11
+
12
+ class Items
13
+ include HappyMapper
14
+
15
+ tag 'Items'
16
+ has_many :items, Item
17
+ end
18
+
19
+ class List
20
+ include HappyMapper
21
+
22
+ tag 'List'
23
+ element :name, String, :tag => 'Name'
24
+ element :id, Integer, :tag => 'Id'
25
+ has_one :items, Items
26
+ end
27
+
28
+ class Lists
29
+ include HappyMapper
30
+
31
+ tag 'Lists'
32
+ has_many :lists, List
33
+ end
34
+
35
+ def self.getValuesById(id, valueLists)
36
+ valueLists.lists.each do |list|
37
+ if (list.id == id)
38
+ return list.items.items
39
+ end
40
+ end
41
+ end
42
+
43
+ end
@@ -0,0 +1,118 @@
1
+ require 'stringio'
2
+ require 'test/unit'
3
+ require 'alm-rest-api'
4
+
5
+ class TestALMRestAPI < Test::Unit::TestCase
6
+
7
+ def setup
8
+ ALM::RestConnector.instance.init(Hash.new,
9
+ ALM::Constants::HOST,
10
+ ALM::Constants::PORT,
11
+ ALM::Constants::DOMAIN,
12
+ ALM::Constants::PROJECT)
13
+ end
14
+
15
+ def test_AuthenticateLoginLogout
16
+ if false # change to true if you want run the test case
17
+ # Returns nil if authenticated. If not authenticated, returns
18
+ # a URL indicating where to login.
19
+ # We are not logged in, so call returns a URL
20
+ authenticationPoint = ALM.isAuthenticated()
21
+ assert_not_nil(authenticationPoint, "response from isAuthenticated means we're authenticated. that can't be.")
22
+
23
+ # now we login to previously returned URL.
24
+ loginResponse = ALM.login(authenticationPoint, ALM::Constants::USERNAME, ALM::Constants::PASSWORD)
25
+ assert(loginResponse, "failed to login.")
26
+ assert((ALM::RestConnector.instance.getCookieString.include? "LWSSO_COOKIE_KEY"), "login did not cause creation of Light Weight Single Sign On(LWSSO) cookie.")
27
+
28
+ # proof that we are indeed logged in
29
+ assert_nil(ALM.isAuthenticated(), "isAuthenticated returned not authenticated after login.")
30
+
31
+ # and now we logout
32
+ ALM.logout()
33
+
34
+ # And now we can see that we are indeed logged out
35
+ # because isAuthenticated once again returns a url, and not null.
36
+ assert_not_nil(ALM.isAuthenticated(), "isAuthenticated returned authenticated after logout.")
37
+ end
38
+ end
39
+
40
+ def test_GetDefectFields
41
+ if false # change to true if you want run the test case
42
+ loginResponse = ALM.isLoggedIn(ALM::Constants::USERNAME, ALM::Constants::PASSWORD)
43
+ assert(loginResponse, "failed to login.")
44
+
45
+ defectFields = ALM.getDefectFields(true)
46
+ valueLists = ALM.getValueLists(defectFields)
47
+ if defectFields
48
+ defectFields.fields.each do |field|
49
+ puts "Name = #{field.name}"
50
+ puts "Label = #{field.label}"
51
+ puts "Size = #{field.size}"
52
+ puts "Type = #{field.type}"
53
+ puts "Required = #{field.required}"
54
+ if (field.list_id && valueLists)
55
+ items = ValueLists.getValuesById(field.list_id, valueLists)
56
+ items.each do |item|
57
+ puts "Value = #{item.value}"
58
+ end
59
+ end
60
+ puts "--------------------------"
61
+ end
62
+
63
+ puts defectFields.to_xml
64
+ if valueLists
65
+ puts valueLists.to_xml
66
+ end
67
+ end
68
+
69
+ ALM.logout()
70
+ end
71
+ end
72
+
73
+ def test_CreateDeleteDefect
74
+ if true # change to true if you want run the test case
75
+ loginResponse = ALM.isLoggedIn(ALM::Constants::USERNAME, ALM::Constants::PASSWORD)
76
+ assert(loginResponse, "failed to login.")
77
+
78
+ defect = Entity.new("defect")
79
+
80
+ defectFields = ALM.getDefectFields(true)
81
+ valueLists = ALM.getValueLists(defectFields)
82
+ if defectFields
83
+ defectFields.fields.each do |field|
84
+ defectField = Field.new
85
+ defectField.name = field.name
86
+ type = field.type
87
+ case type
88
+ when "LookupList"
89
+ if valueLists
90
+ items = ValueLists.getValuesById(field.list_id, valueLists)
91
+ defectField.value = items.first.value
92
+ end
93
+ when "Date"
94
+ defectField.value = Time.now.strftime("%Y-%m-%d")
95
+ when "UsersList"
96
+ defectField.value = ALM::Constants::USERNAME
97
+ else
98
+ defectField.value = "0"
99
+ end
100
+ defect.fields.fields<<defectField
101
+ end
102
+
103
+ puts defect.to_xml
104
+
105
+ defectId = ALM.createDefect(defect)
106
+ assert_not_nil(defectId, "fail to create defect.")
107
+
108
+ if defectId
109
+ deleteResponse = ALM.deleteDefect(defectId)
110
+ assert(deleteResponse, "failed to delete defect.")
111
+ end
112
+ end
113
+
114
+ ALM.logout()
115
+ end
116
+ end
117
+
118
+ end
metadata ADDED
@@ -0,0 +1,77 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: alm-rest-api
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 2
10
+ version: 0.0.2
11
+ platform: ruby
12
+ authors:
13
+ - Simon Zheng
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2012-12-14 00:00:00 Z
19
+ dependencies: []
20
+
21
+ description: ALM REST API Integration
22
+ email: xiaomengzheng@gmail.com
23
+ executables: []
24
+
25
+ extensions: []
26
+
27
+ extra_rdoc_files: []
28
+
29
+ files:
30
+ - .gitattributes
31
+ - .gitignore
32
+ - Rakefile
33
+ - alm-rest-api-0.0.1.gem
34
+ - alm-rest-api.gemspec
35
+ - lib/alm-rest-api.rb
36
+ - lib/alm-rest-api/constants.rb
37
+ - lib/alm-rest-api/defect-fields.rb
38
+ - lib/alm-rest-api/entity.rb
39
+ - lib/alm-rest-api/response.rb
40
+ - lib/alm-rest-api/rest-connector.rb
41
+ - lib/alm-rest-api/value-lists.rb
42
+ - test/test_alm_rest_api.rb
43
+ homepage: http://rubygems.org/gems/alm-rest-api
44
+ licenses: []
45
+
46
+ post_install_message:
47
+ rdoc_options: []
48
+
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ hash: 3
57
+ segments:
58
+ - 0
59
+ version: "0"
60
+ required_rubygems_version: !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ hash: 3
66
+ segments:
67
+ - 0
68
+ version: "0"
69
+ requirements: []
70
+
71
+ rubyforge_project:
72
+ rubygems_version: 1.8.10
73
+ signing_key:
74
+ specification_version: 3
75
+ summary: ALM!
76
+ test_files: []
77
+