leantesting 1.0.0

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.
Files changed (71) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +9 -0
  3. data/LICENSE +10 -0
  4. data/README.md +348 -0
  5. data/Rakefile +9 -0
  6. data/leantesting.gemspec +20 -0
  7. data/lib/BaseClass/APIRequest.rb +195 -0
  8. data/lib/BaseClass/Entity.rb +33 -0
  9. data/lib/BaseClass/EntityHandler.rb +183 -0
  10. data/lib/BaseClass/EntityList.rb +188 -0
  11. data/lib/Entity/Bug/Bug.rb +11 -0
  12. data/lib/Entity/Bug/BugAttachment.rb +7 -0
  13. data/lib/Entity/Bug/BugComment.rb +7 -0
  14. data/lib/Entity/Platform/PlatformBrowser.rb +10 -0
  15. data/lib/Entity/Platform/PlatformBrowserVersion.rb +7 -0
  16. data/lib/Entity/Platform/PlatformDevice.rb +7 -0
  17. data/lib/Entity/Platform/PlatformOS.rb +10 -0
  18. data/lib/Entity/Platform/PlatformOSVersion.rb +7 -0
  19. data/lib/Entity/Platform/PlatformType.rb +10 -0
  20. data/lib/Entity/Project/Project.rb +27 -0
  21. data/lib/Entity/Project/ProjectBugScheme.rb +7 -0
  22. data/lib/Entity/Project/ProjectSection.rb +7 -0
  23. data/lib/Entity/Project/ProjectUser.rb +7 -0
  24. data/lib/Entity/Project/ProjectVersion.rb +7 -0
  25. data/lib/Entity/User/UserOrganization.rb +7 -0
  26. data/lib/Exception/BaseException/SDKException.rb +19 -0
  27. data/lib/Exception/SDKBadJSONResponseException.rb +15 -0
  28. data/lib/Exception/SDKDuplicateRequestException.rb +19 -0
  29. data/lib/Exception/SDKErrorResponseException.rb +13 -0
  30. data/lib/Exception/SDKIncompleteRequestException.rb +19 -0
  31. data/lib/Exception/SDKInvalidArgException.rb +15 -0
  32. data/lib/Exception/SDKMissingArgException.rb +15 -0
  33. data/lib/Exception/SDKUnexpectedResponseException.rb +15 -0
  34. data/lib/Exception/SDKUnsupportedRequestException.rb +19 -0
  35. data/lib/Handler/Attachment/AttachmentsHandler.rb +17 -0
  36. data/lib/Handler/Auth/OAuth2Handler.rb +118 -0
  37. data/lib/Handler/Bug/BugAttachmentsHandler.rb +51 -0
  38. data/lib/Handler/Bug/BugCommentsHandler.rb +20 -0
  39. data/lib/Handler/Bug/BugsHandler.rb +57 -0
  40. data/lib/Handler/Platform/PlatformBrowserVersionsHandler.rb +20 -0
  41. data/lib/Handler/Platform/PlatformBrowsersHandler.rb +23 -0
  42. data/lib/Handler/Platform/PlatformDevicesHandler.rb +10 -0
  43. data/lib/Handler/Platform/PlatformHandler.rb +22 -0
  44. data/lib/Handler/Platform/PlatformOSHandler.rb +23 -0
  45. data/lib/Handler/Platform/PlatformOSVersionsHandler.rb +20 -0
  46. data/lib/Handler/Platform/PlatformTypeDevicesHandler.rb +20 -0
  47. data/lib/Handler/Platform/PlatformTypesHandler.rb +21 -0
  48. data/lib/Handler/Project/ProjectBugReproducibilitySchemeHandler.rb +20 -0
  49. data/lib/Handler/Project/ProjectBugSeveritySchemeHandler.rb +20 -0
  50. data/lib/Handler/Project/ProjectBugStatusSchemeHandler.rb +20 -0
  51. data/lib/Handler/Project/ProjectBugTypeSchemeHandler.rb +20 -0
  52. data/lib/Handler/Project/ProjectBugsHandler.rb +67 -0
  53. data/lib/Handler/Project/ProjectSectionsHandler.rb +39 -0
  54. data/lib/Handler/Project/ProjectUsersHandler.rb +20 -0
  55. data/lib/Handler/Project/ProjectVersionsHandler.rb +39 -0
  56. data/lib/Handler/Project/ProjectsHandler.rb +46 -0
  57. data/lib/Handler/User/UserHandler.rb +14 -0
  58. data/lib/Handler/User/UserOrganizationsHandler.rb +14 -0
  59. data/lib/leantesting.rb +65 -0
  60. data/lib/loader.rb +18 -0
  61. data/tests/APIRequestTest.rb +152 -0
  62. data/tests/BaseClassesTest.rb +96 -0
  63. data/tests/ClientTest.rb +52 -0
  64. data/tests/EntitiesTest.rb +97 -0
  65. data/tests/EntityListTest.rb +51 -0
  66. data/tests/ExceptionsTest.rb +70 -0
  67. data/tests/HandlersRequestsTest.rb +215 -0
  68. data/tests/MockRequestsTest.rb +556 -0
  69. data/tests/OAuth2HandlerTest.rb +75 -0
  70. data/tests/res/upload_sample.jpg +0 -0
  71. metadata +169 -0
@@ -0,0 +1,7 @@
1
+ class PlatformDevice < Entity
2
+
3
+ def initialize(origin, data)
4
+ super
5
+ end
6
+
7
+ end
@@ -0,0 +1,10 @@
1
+ class PlatformOS < Entity
2
+ attr_reader :versions
3
+
4
+ def initialize(origin, data)
5
+ super
6
+
7
+ @versions = PlatformOSVersionsHandler.new(origin, data['id'])
8
+ end
9
+
10
+ end
@@ -0,0 +1,7 @@
1
+ class PlatformOSVersion < Entity
2
+
3
+ def initialize(origin, data)
4
+ super
5
+ end
6
+
7
+ end
@@ -0,0 +1,10 @@
1
+ class PlatformType < Entity
2
+ attr_reader :devices
3
+
4
+ def initialize(origin, data)
5
+ super
6
+
7
+ @devices = PlatformTypeDevicesHandler.new(origin, data['id'])
8
+ end
9
+
10
+ end
@@ -0,0 +1,27 @@
1
+ class Project < Entity
2
+ attr_reader \
3
+ :sections,
4
+ :versions,
5
+ :users,
6
+ :bugTypeScheme,
7
+ :bugStatusScheme,
8
+ :bugSeverityScheme,
9
+ :bugReproducibilityScheme,
10
+ :bugs
11
+
12
+ def initialize(origin, data)
13
+ super
14
+
15
+ @sections = ProjectSectionsHandler.new(origin, data['id'])
16
+ @versions = ProjectVersionsHandler.new(origin, data['id'])
17
+ @users = ProjectUsersHandler.new(origin, data['id'])
18
+
19
+ @bugTypeScheme = ProjectBugTypeSchemeHandler.new(origin, data['id'])
20
+ @bugStatusScheme = ProjectBugStatusSchemeHandler.new(origin, data['id'])
21
+ @bugSeverityScheme = ProjectBugSeveritySchemeHandler.new(origin, data['id'])
22
+ @bugReproducibilityScheme = ProjectBugReproducibilitySchemeHandler.new(origin, data['id'])
23
+
24
+ @bugs = ProjectBugsHandler.new(origin, data['id'])
25
+ end
26
+
27
+ end
@@ -0,0 +1,7 @@
1
+ class ProjectBugScheme < Entity
2
+
3
+ def initialize(origin, data)
4
+ super
5
+ end
6
+
7
+ end
@@ -0,0 +1,7 @@
1
+ class ProjectSection < Entity
2
+
3
+ def initialize(origin, data)
4
+ super
5
+ end
6
+
7
+ end
@@ -0,0 +1,7 @@
1
+ class ProjectUser < Entity
2
+
3
+ def initialize(origin, data)
4
+ super
5
+ end
6
+
7
+ end
@@ -0,0 +1,7 @@
1
+ class ProjectVersion < Entity
2
+
3
+ def initialize(origin, data)
4
+ super
5
+ end
6
+
7
+ end
@@ -0,0 +1,7 @@
1
+ class UserOrganization < Entity
2
+
3
+ def initialize(origin, data)
4
+ super
5
+ end
6
+
7
+ end
@@ -0,0 +1,19 @@
1
+ class SDKException < Exception
2
+
3
+ def initialize(message = nil)
4
+ super
5
+
6
+ if !message
7
+ message = 'Unknown SDK Error'
8
+ else
9
+ message = 'SDK Error: ' + message
10
+ end
11
+
12
+ @message = message
13
+ end
14
+
15
+ def message
16
+ @message
17
+ end
18
+
19
+ end
@@ -0,0 +1,15 @@
1
+ class SDKBadJSONResponseException < SDKException
2
+
3
+ def initialize(message = nil)
4
+ @baseMessage = 'JSON remote response is inconsistent or invalid'
5
+
6
+ if !message
7
+ message = @baseMessage
8
+ else
9
+ message = @baseMessage + ' - ' + message
10
+ end
11
+
12
+ super
13
+ end
14
+
15
+ end
@@ -0,0 +1,19 @@
1
+ class SDKDuplicateRequestException < SDKException
2
+
3
+ def initialize(message = nil)
4
+ @baseMessage = 'Duplicate request data'
5
+
6
+ if message.is_a? Array
7
+ message = message.map{ |el| '`' + el + '`' }.join(', ')
8
+ end
9
+
10
+ if !message
11
+ message = @baseMessage
12
+ else
13
+ message = @baseMessage + ' - multiple ' + message
14
+ end
15
+
16
+ super
17
+ end
18
+
19
+ end
@@ -0,0 +1,13 @@
1
+ class SDKErrorResponseException < SDKException
2
+
3
+ def initialize(message = nil)
4
+ if !message
5
+ message = 'Unknown remote error'
6
+ else
7
+ message = 'Got error response: ' + message
8
+ end
9
+
10
+ super
11
+ end
12
+
13
+ end
@@ -0,0 +1,19 @@
1
+ class SDKIncompleteRequestException < SDKException
2
+
3
+ def initialize(message = nil)
4
+ @baseMessage = 'Incomplete request data'
5
+
6
+ if message.is_a? Array
7
+ message = message.map{ |el| '`' + el + '`' }.join(', ')
8
+ end
9
+
10
+ if !message
11
+ message = @baseMessage
12
+ else
13
+ message = @baseMessage + ' - missing required ' + message
14
+ end
15
+
16
+ super
17
+ end
18
+
19
+ end
@@ -0,0 +1,15 @@
1
+ class SDKInvalidArgException < SDKException
2
+
3
+ def initialize(message = nil)
4
+ @baseMessage = 'Invalid argument'
5
+
6
+ if !message
7
+ message = @baseMessage
8
+ else
9
+ message = @baseMessage + ': ' + message
10
+ end
11
+
12
+ super
13
+ end
14
+
15
+ end
@@ -0,0 +1,15 @@
1
+ class SDKMissingArgException < SDKException
2
+
3
+ def initialize(message = nil)
4
+ @baseMessage = 'Missing argument'
5
+
6
+ if !message
7
+ message = @baseMessage
8
+ else
9
+ message = @baseMessage + ' `' + message + '`'
10
+ end
11
+
12
+ super
13
+ end
14
+
15
+ end
@@ -0,0 +1,15 @@
1
+ class SDKUnexpectedResponseException < SDKException
2
+
3
+ def initialize(message = nil)
4
+ @baseMessage = 'Got unexpected remote response'
5
+
6
+ if !message
7
+ message = @baseMessage
8
+ else
9
+ message = @baseMessage + ' - ' + message
10
+ end
11
+
12
+ super
13
+ end
14
+
15
+ end
@@ -0,0 +1,19 @@
1
+ class SDKUnsupportedRequestException < SDKException
2
+
3
+ def initialize(message = nil)
4
+ @baseMessage = 'Unsupported request data'
5
+
6
+ if message.is_a? Array
7
+ message = message.map{ |el| '`' + el + '`' }.join(', ')
8
+ end
9
+
10
+ if !message
11
+ message = @baseMessage
12
+ else
13
+ message = @baseMessage + ' - invalid ' + message
14
+ end
15
+
16
+ super
17
+ end
18
+
19
+ end
@@ -0,0 +1,17 @@
1
+ class AttachmentsHandler < EntityHandler
2
+
3
+ def find(id)
4
+ super
5
+
6
+ req = APIRequest.new(@origin, '/v1/attachments/' + id.to_s(), 'GET')
7
+ BugAttachment.new(@origin, req.exec)
8
+ end
9
+
10
+ def delete(id)
11
+ super
12
+
13
+ req = APIRequest.new(@origin, '/v1/attachments/' + id.to_s(), 'DELETE')
14
+ req.exec
15
+ end
16
+
17
+ end
@@ -0,0 +1,118 @@
1
+ #
2
+ # Handler to manage general authentication routines
3
+ #
4
+ # leantesting.com/en/api-docs#oauth-flow
5
+ #
6
+ class OAuth2Handler
7
+
8
+ #
9
+ # Constructs an OAuth2Handler instance
10
+ #
11
+ # Arguments:
12
+ # origin Client -- Originating client reference
13
+ #
14
+ def initialize(origin)
15
+ @origin = origin
16
+ end
17
+
18
+ #
19
+ # Function that generates link for user to follow in order to request authorization code
20
+ #
21
+ # Arguments:
22
+ # clientID String -- client ID given at application registration
23
+ # redirectURI String -- URL to be redirected to after authorization
24
+ # scope String -- (optional) comma-separated list of requested scopes (default: 'read')
25
+ # state String -- (optional) random string for MITM attack prevention
26
+ #
27
+ # Exceptions:
28
+ # SDKInvalidArgException if provided clientID param is not a string
29
+ # SDKInvalidArgException if provided redirectURI param is not a string
30
+ # SDKInvalidArgException if provided scope param is not a string
31
+ # SDKInvalidArgException if provided state param is not a string
32
+ #
33
+ # Returns:
34
+ # String -- returns URL to follow for authorization code request
35
+ #
36
+ def generateAuthLink(clientID, redirectURI, scope = 'read', state = nil)
37
+ if !clientID.is_a? String
38
+ raise SDKInvalidArgException, '`clientID` must be a string'
39
+ elsif !redirectURI.is_a? String
40
+ raise SDKInvalidArgException, '`redirectURI` must be a string'
41
+ elsif !scope.is_a? String
42
+ raise SDKInvalidArgException, '`scope` must be a string'
43
+ elsif state && !state.is_a?(String)
44
+ raise SDKInvalidArgException, '`state` must be a string'
45
+ end
46
+
47
+ baseURL = 'https://leantesting.com/login/oauth/authorize'
48
+
49
+ params = {
50
+ 'client_id' => clientID,
51
+ 'redirect_uri' => redirectURI,
52
+ 'scope' => scope
53
+ }
54
+
55
+ if state
56
+ params['state'] = state
57
+ end
58
+
59
+ baseURL += '?' + Curl::postalize(params)
60
+ baseURL
61
+ end
62
+
63
+ #
64
+ # Generates an access token string from the provided authorization code
65
+ #
66
+ # Arguments:
67
+ # clientID String -- client ID given at application registration
68
+ # clientSecret String -- client secret given at application registration
69
+ # grantType String -- oauth specific grant_type value (i.e.: authorization_code)
70
+ # code String -- authorization code obtained from the generated auth link
71
+ # redirectURI String -- URL to be redirected to after authorization
72
+
73
+ # Exceptions:
74
+ # SDKInvalidArgException if provided clientID param is not a string
75
+ # SDKInvalidArgException if provided clientSecret param is not a string
76
+ # SDKInvalidArgException if provided grantType param is not a string
77
+ # SDKInvalidArgException if provided code param is not a string
78
+ # SDKInvalidArgException if provided redirectURI param is not a string
79
+ #
80
+ # Returns:
81
+ # String -- returns obtained access token string
82
+ #
83
+ def exchangeAuthCode(clientID, clientSecret, grantType, code, redirectURI)
84
+ if !clientID.is_a? String
85
+ raise SDKInvalidArgException, '`clientID` must be a string'
86
+ elsif !clientSecret.is_a? String
87
+ raise SDKInvalidArgException, '`clientSecret` must be a string'
88
+ elsif !grantType.is_a? String
89
+ raise SDKInvalidArgException, '`grantType` must be a string'
90
+ elsif !code.is_a? String
91
+ raise SDKInvalidArgException, '`code` must be a string'
92
+ elsif !redirectURI.is_a? String
93
+ raise SDKInvalidArgException, '`redirectURI` must be a string'
94
+ end
95
+
96
+ params = {
97
+ 'grant_type' => grantType,
98
+ 'client_id' => clientID,
99
+ 'client_secret' => clientSecret,
100
+ 'redirect_uri' => redirectURI,
101
+ 'code' => code
102
+ }
103
+
104
+ req = APIRequest.new(
105
+ @origin,
106
+ '/login/oauth/access_token',
107
+ 'POST',
108
+ {
109
+ 'base_uri' => 'https://leantesting.com',
110
+ 'params' => params
111
+ }
112
+ )
113
+
114
+ resp = req.exec
115
+ resp['access_token']
116
+ end
117
+
118
+ end
@@ -0,0 +1,51 @@
1
+ class BugAttachmentsHandler < EntityHandler
2
+
3
+ def initialize(origin, bugID)
4
+ super(origin)
5
+
6
+ @bugID = bugID
7
+ end
8
+
9
+ #
10
+ # Uploads given file as an attachment for specified bug.
11
+ #
12
+ # Arguments:
13
+ # filepath String -- an absolute path of the file to be uploaded
14
+ # example: /home/path/to/file.txt (Linux), C:\\Users\\Documents\\file.txt (Windows)
15
+ #
16
+ # Exceptions:
17
+ # SDKInvalidArgException if filepath is not a string
18
+ #
19
+ # Returns:
20
+ # BugAttachment -- the newly uploaded attachment
21
+ #
22
+ def upload(filepath)
23
+ if !filepath.is_a? String
24
+ raise SDKInvalidArgException, '`filepath` must be of type string'
25
+ end
26
+
27
+ req = APIRequest.new(
28
+ @origin,
29
+ '/v1/bugs/' + @bugID.to_s() + '/attachments',
30
+ 'POST',
31
+ {
32
+ 'form_data' => true,
33
+ 'file_path' => filepath
34
+ }
35
+ )
36
+
37
+ BugAttachment.new(@origin, req.exec)
38
+ end
39
+
40
+ def all(filters = nil)
41
+ if !filters
42
+ filters = {}
43
+ end
44
+
45
+ super
46
+
47
+ request = APIRequest.new(@origin, '/v1/bugs/' + @bugID.to_s() + '/attachments', 'GET')
48
+ EntityList.new(@origin, request, BugAttachment, filters)
49
+ end
50
+
51
+ end