jira-ruby 2.3.0 → 3.2.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.
- checksums.yaml +4 -4
- data/.github/ISSUE_TEMPLATE/bug_report.md +20 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
- data/.github/dependabot.yml +6 -0
- data/.github/workflows/CI.yml +30 -0
- data/.github/workflows/codeql.yml +96 -0
- data/.github/workflows/rubocop.yml +18 -0
- data/.gitignore +3 -1
- data/.rubocop.yml +123 -0
- data/.yardopts +4 -0
- data/Gemfile +11 -3
- data/Guardfile +2 -0
- data/README.md +94 -19
- data/Rakefile +3 -4
- data/jira-ruby.gemspec +12 -17
- data/lib/jira/atlassian/jwt.rb +76 -0
- data/lib/jira/base.rb +37 -36
- data/lib/jira/base_factory.rb +4 -1
- data/lib/jira/client.rb +132 -51
- data/lib/jira/has_many_proxy.rb +32 -28
- data/lib/jira/http_client.rb +80 -13
- data/lib/jira/http_error.rb +4 -0
- data/lib/jira/jwt_client.rb +19 -43
- data/lib/jira/oauth_client.rb +68 -3
- data/lib/jira/railtie.rb +2 -0
- data/lib/jira/request_client.rb +31 -2
- data/lib/jira/resource/agile.rb +7 -9
- data/lib/jira/resource/applinks.rb +5 -3
- data/lib/jira/resource/attachment.rb +144 -4
- data/lib/jira/resource/board.rb +5 -3
- data/lib/jira/resource/board_configuration.rb +2 -0
- data/lib/jira/resource/comment.rb +14 -0
- data/lib/jira/resource/component.rb +2 -0
- data/lib/jira/resource/createmeta.rb +7 -5
- data/lib/jira/resource/field.rb +13 -12
- data/lib/jira/resource/filter.rb +2 -0
- data/lib/jira/resource/issue.rb +148 -54
- data/lib/jira/resource/issue_picker_suggestions.rb +4 -1
- data/lib/jira/resource/issue_picker_suggestions_issue.rb +2 -0
- data/lib/jira/resource/issuelink.rb +6 -3
- data/lib/jira/resource/issuelinktype.rb +2 -0
- data/lib/jira/resource/issuetype.rb +2 -0
- data/lib/jira/resource/priority.rb +2 -0
- data/lib/jira/resource/project.rb +4 -2
- data/lib/jira/resource/properties.rb +56 -0
- data/lib/jira/resource/rapidview.rb +5 -3
- data/lib/jira/resource/remotelink.rb +2 -0
- data/lib/jira/resource/resolution.rb +2 -0
- data/lib/jira/resource/serverinfo.rb +2 -0
- data/lib/jira/resource/sprint.rb +14 -23
- data/lib/jira/resource/status.rb +7 -1
- data/lib/jira/resource/status_category.rb +10 -0
- data/lib/jira/resource/suggested_issue.rb +2 -0
- data/lib/jira/resource/transition.rb +2 -0
- data/lib/jira/resource/user.rb +3 -1
- data/lib/jira/resource/version.rb +2 -0
- data/lib/jira/resource/watcher.rb +3 -2
- data/lib/jira/resource/webhook.rb +9 -3
- data/lib/jira/resource/worklog.rb +15 -2
- data/lib/jira/version.rb +3 -1
- data/lib/jira-ruby.rb +6 -3
- data/lib/tasks/generate.rake +3 -1
- data/spec/data/files/jwt-signed-urls.json +317 -0
- data/spec/data/files/short.txt +1 -0
- data/spec/integration/attachment_spec.rb +3 -3
- data/spec/integration/comment_spec.rb +8 -8
- data/spec/integration/component_spec.rb +7 -7
- data/spec/integration/field_spec.rb +3 -3
- data/spec/integration/issue_spec.rb +21 -18
- data/spec/integration/issuelinktype_spec.rb +3 -3
- data/spec/integration/issuetype_spec.rb +3 -3
- data/spec/integration/priority_spec.rb +3 -3
- data/spec/integration/project_spec.rb +8 -8
- data/spec/integration/properties_spec.rb +45 -0
- data/spec/integration/rapidview_spec.rb +10 -10
- data/spec/integration/resolution_spec.rb +3 -3
- data/spec/integration/status_category_spec.rb +20 -0
- data/spec/integration/status_spec.rb +4 -8
- data/spec/integration/transition_spec.rb +5 -4
- data/spec/integration/user_spec.rb +34 -11
- data/spec/integration/version_spec.rb +7 -7
- data/spec/integration/watcher_spec.rb +21 -18
- data/spec/integration/webhook_spec.rb +35 -0
- data/spec/integration/worklog_spec.rb +8 -8
- data/spec/jira/atlassian/jwt_spec.rb +60 -0
- data/spec/jira/base_factory_spec.rb +13 -3
- data/spec/jira/base_spec.rb +135 -98
- data/spec/jira/client_spec.rb +72 -56
- data/spec/jira/has_many_proxy_spec.rb +3 -3
- data/spec/jira/http_client_spec.rb +94 -27
- data/spec/jira/http_error_spec.rb +2 -2
- data/spec/jira/oauth_client_spec.rb +14 -8
- data/spec/jira/request_client_spec.rb +4 -4
- data/spec/jira/resource/agile_spec.rb +32 -32
- data/spec/jira/resource/attachment_spec.rb +170 -57
- data/spec/jira/resource/board_spec.rb +24 -23
- data/spec/jira/resource/createmeta_spec.rb +48 -48
- data/spec/jira/resource/field_spec.rb +44 -27
- data/spec/jira/resource/filter_spec.rb +7 -6
- data/spec/jira/resource/issue_picker_suggestions_spec.rb +17 -17
- data/spec/jira/resource/issue_spec.rb +159 -93
- data/spec/jira/resource/jira_picker_suggestions_issue_spec.rb +3 -3
- data/spec/jira/resource/project_factory_spec.rb +3 -2
- data/spec/jira/resource/project_spec.rb +16 -16
- data/spec/jira/resource/sprint_spec.rb +88 -9
- data/spec/jira/resource/status_spec.rb +21 -0
- data/spec/jira/resource/user_factory_spec.rb +5 -5
- data/spec/jira/resource/worklog_spec.rb +4 -4
- data/spec/mock_responses/board/1_issues.json +2 -1
- data/spec/mock_responses/issue/10002/properties/foo.json +4 -0
- data/spec/mock_responses/issue/10002/properties/xyz.json +4 -0
- data/spec/mock_responses/issue/10002/properties/xyz.put.json +4 -0
- data/spec/mock_responses/issue/10002/properties.json +12 -0
- data/spec/mock_responses/issue.json +1 -0
- data/spec/mock_responses/rapidview/SAMPLEPROJECT.issues.full.json +2 -1
- data/spec/mock_responses/rapidview/SAMPLEPROJECT.issues.json +2 -1
- data/spec/mock_responses/sprint/1.json +13 -0
- data/spec/mock_responses/status/1.json +8 -1
- data/spec/mock_responses/status.json +40 -5
- data/spec/mock_responses/statuscategory/1.json +7 -0
- data/spec/mock_responses/statuscategory.json +30 -0
- data/spec/mock_responses/{user_username=admin.json → user_accountId=1234567890abcdef01234567.json} +2 -1
- data/spec/spec_helper.rb +1 -0
- data/spec/support/clients_helper.rb +5 -7
- data/spec/support/mock_client.rb +9 -0
- data/spec/support/mock_response.rb +8 -0
- data/spec/support/shared_examples/integration.rb +51 -58
- metadata +45 -257
- data/.travis.yml +0 -9
- data/example.rb +0 -232
- data/http-basic-example.rb +0 -113
- data/lib/jira/resource/sprint_report.rb +0 -8
- data/lib/jira/tasks.rb +0 -0
- data/spec/integration/webhook.rb +0 -25
- data/spec/jira/jwt_uri_builder_spec.rb +0 -59
- data/spec/mock_responses/jira/rest/webhooks/1.0/webhook.json +0 -11
- data/spec/mock_responses/webhook/webhook.json +0 -11
- /data/spec/mock_responses/{jira/rest/webhooks/1.0/webhook → webhook}/2.json +0 -0
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
2
|
|
|
3
3
|
describe JIRA::Resource::UserFactory do
|
|
4
|
+
subject { described_class.new(client) }
|
|
5
|
+
|
|
4
6
|
let(:client) do
|
|
5
|
-
instance_double(
|
|
7
|
+
instance_double(Client, options: { rest_base_path: '/jira/rest/api/2' })
|
|
6
8
|
end
|
|
7
9
|
|
|
8
|
-
subject { JIRA::Resource::UserFactory.new(client) }
|
|
9
|
-
|
|
10
10
|
describe '#myself' do
|
|
11
11
|
let(:response) do
|
|
12
12
|
instance_double(
|
|
13
|
-
|
|
13
|
+
Response, body: get_mock_response('user_accountId=1234567890abcdef01234567.json')
|
|
14
14
|
)
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
let(:user) { subject.myself }
|
|
18
18
|
|
|
19
|
-
before
|
|
19
|
+
before do
|
|
20
20
|
allow(client).to receive(:get).with(
|
|
21
21
|
'/jira/rest/api/2/myself'
|
|
22
22
|
).and_return(response)
|
|
@@ -5,10 +5,10 @@ describe JIRA::Resource::Worklog do
|
|
|
5
5
|
|
|
6
6
|
describe 'relationships' do
|
|
7
7
|
subject do
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
described_class.new(client, issue_id: '99999', attrs: {
|
|
9
|
+
'author' => { 'foo' => 'bar' },
|
|
10
|
+
'updateAuthor' => { 'foo' => 'bar' }
|
|
11
|
+
})
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
it 'has the correct relationships' do
|
|
@@ -101,6 +101,7 @@
|
|
|
101
101
|
},
|
|
102
102
|
"canManageSprints": true,
|
|
103
103
|
"maxIssuesExceeded": false,
|
|
104
|
+
"isLast": true,
|
|
104
105
|
"queryResultLimit": 2147483647,
|
|
105
106
|
"versionData": {
|
|
106
107
|
"versionsPerProject": {
|
|
@@ -108,4 +109,4 @@
|
|
|
108
109
|
},
|
|
109
110
|
"canCreateVersion": true
|
|
110
111
|
}
|
|
111
|
-
}
|
|
112
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": 1,
|
|
3
|
+
"self": "https://localhost:2990/jira/rest/agile/1.0/sprint/1",
|
|
4
|
+
"state": "closed",
|
|
5
|
+
"name": "SP Sprint 1",
|
|
6
|
+
"startDate": "2024-01-01T03:20:00.000Z",
|
|
7
|
+
"endDate": "2024-01-15T03:20:00.000Z",
|
|
8
|
+
"completeDate": "2024-01-16T03:48:00.000Z",
|
|
9
|
+
"createdDate": "2024-01-01T00:00:00.000Z",
|
|
10
|
+
"originBoardId": 1,
|
|
11
|
+
"goal": "",
|
|
12
|
+
"rapidview_id": 1
|
|
13
|
+
}
|
|
@@ -3,5 +3,12 @@
|
|
|
3
3
|
"description": "The issue is open and ready for the assignee to start work on it.",
|
|
4
4
|
"iconUrl": "http://localhost:2990/jira/images/icons/status_open.gif",
|
|
5
5
|
"name": "Open",
|
|
6
|
-
"id": "1"
|
|
6
|
+
"id": "1",
|
|
7
|
+
"statusCategory": {
|
|
8
|
+
"self": "http://localhost:2990/jira/rest/api/2/statuscategory/2",
|
|
9
|
+
"id": 2,
|
|
10
|
+
"key": "new",
|
|
11
|
+
"colorName": "blue-gray",
|
|
12
|
+
"name": "To Do"
|
|
13
|
+
}
|
|
7
14
|
}
|
|
@@ -4,34 +4,69 @@
|
|
|
4
4
|
"description": "The issue is open and ready for the assignee to start work on it.",
|
|
5
5
|
"iconUrl": "http://localhost:2990/jira/images/icons/status_open.gif",
|
|
6
6
|
"name": "Open",
|
|
7
|
-
"id": "1"
|
|
7
|
+
"id": "1",
|
|
8
|
+
"statusCategory": {
|
|
9
|
+
"self": "http://localhost:2990/jira/rest/api/2/statuscategory/2",
|
|
10
|
+
"id": 2,
|
|
11
|
+
"key": "new",
|
|
12
|
+
"colorName": "blue-gray",
|
|
13
|
+
"name": "To Do"
|
|
14
|
+
}
|
|
8
15
|
},
|
|
9
16
|
{
|
|
10
17
|
"self": "http://localhost:2990/jira/rest/api/2/status/3",
|
|
11
18
|
"description": "This issue is being actively worked on at the moment by the assignee.",
|
|
12
19
|
"iconUrl": "http://localhost:2990/jira/images/icons/status_inprogress.gif",
|
|
13
20
|
"name": "In Progress",
|
|
14
|
-
"id": "3"
|
|
21
|
+
"id": "3",
|
|
22
|
+
"statusCategory": {
|
|
23
|
+
"self": "http://localhost:2990/jira/rest/api/2/statuscategory/4",
|
|
24
|
+
"id": 4,
|
|
25
|
+
"key": "indeterminate",
|
|
26
|
+
"colorName": "yellow",
|
|
27
|
+
"name": "In Progress"
|
|
28
|
+
}
|
|
15
29
|
},
|
|
16
30
|
{
|
|
17
31
|
"self": "http://localhost:2990/jira/rest/api/2/status/4",
|
|
18
32
|
"description": "This issue was once resolved, but the resolution was deemed incorrect. From here issues are either marked assigned or resolved.",
|
|
19
33
|
"iconUrl": "http://localhost:2990/jira/images/icons/status_reopened.gif",
|
|
20
34
|
"name": "Reopened",
|
|
21
|
-
"id": "4"
|
|
35
|
+
"id": "4",
|
|
36
|
+
"statusCategory": {
|
|
37
|
+
"self": "http://localhost:2990/jira/rest/api/2/statuscategory/2",
|
|
38
|
+
"id": 2,
|
|
39
|
+
"key": "new",
|
|
40
|
+
"colorName": "blue-gray",
|
|
41
|
+
"name": "To Do"
|
|
42
|
+
}
|
|
22
43
|
},
|
|
23
44
|
{
|
|
24
45
|
"self": "http://localhost:2990/jira/rest/api/2/status/5",
|
|
25
46
|
"description": "A resolution has been taken, and it is awaiting verification by reporter. From here issues are either reopened, or are closed.",
|
|
26
47
|
"iconUrl": "http://localhost:2990/jira/images/icons/status_resolved.gif",
|
|
27
48
|
"name": "Resolved",
|
|
28
|
-
"id": "5"
|
|
49
|
+
"id": "5",
|
|
50
|
+
"statusCategory": {
|
|
51
|
+
"self": "http://localhost:2990/jira/rest/api/2/statuscategory/3",
|
|
52
|
+
"id": 3,
|
|
53
|
+
"key": "done",
|
|
54
|
+
"colorName": "green",
|
|
55
|
+
"name": "Done"
|
|
56
|
+
}
|
|
29
57
|
},
|
|
30
58
|
{
|
|
31
59
|
"self": "http://localhost:2990/jira/rest/api/2/status/6",
|
|
32
60
|
"description": "The issue is considered finished, the resolution is correct. Issues which are closed can be reopened.",
|
|
33
61
|
"iconUrl": "http://localhost:2990/jira/images/icons/status_closed.gif",
|
|
34
62
|
"name": "Closed",
|
|
35
|
-
"id": "6"
|
|
63
|
+
"id": "6",
|
|
64
|
+
"statusCategory": {
|
|
65
|
+
"self": "http://localhost:2990/jira/rest/api/2/statuscategory/3",
|
|
66
|
+
"id": 3,
|
|
67
|
+
"key": "done",
|
|
68
|
+
"colorName": "green",
|
|
69
|
+
"name": "Done"
|
|
70
|
+
}
|
|
36
71
|
}
|
|
37
72
|
]
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"self": "http://localhost:2990/jira/rest/api/2/statuscategory/1",
|
|
4
|
+
"id": 1,
|
|
5
|
+
"key": "undefined",
|
|
6
|
+
"colorName": "medium-gray",
|
|
7
|
+
"name": "No Category"
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"self": "http://localhost:2990/jira/rest/api/2/statuscategory/2",
|
|
11
|
+
"id": 2,
|
|
12
|
+
"key": "new",
|
|
13
|
+
"colorName": "blue-gray",
|
|
14
|
+
"name": "To Do"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"self": "http://localhost:2990/jira/rest/api/2/statuscategory/4",
|
|
18
|
+
"id": 4,
|
|
19
|
+
"key": "indeterminate",
|
|
20
|
+
"colorName": "yellow",
|
|
21
|
+
"name": "In Progress"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"self": "http://localhost:2990/jira/rest/api/2/statuscategory/3",
|
|
25
|
+
"id": 3,
|
|
26
|
+
"key": "done",
|
|
27
|
+
"colorName": "green",
|
|
28
|
+
"name": "Done"
|
|
29
|
+
}
|
|
30
|
+
]
|
data/spec/mock_responses/{user_username=admin.json → user_accountId=1234567890abcdef01234567.json}
RENAMED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"
|
|
2
|
+
"id": "1234567890abcdef01234567",
|
|
3
|
+
"self": "http://localhost:2990/jira/rest/api/2/user?accountId=1234567890abcdef01234567",
|
|
3
4
|
"name": "admin",
|
|
4
5
|
"emailAddress": "admin@example.com",
|
|
5
6
|
"avatarUrls": {
|
data/spec/spec_helper.rb
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
module ClientsHelper
|
|
2
|
-
def with_each_client
|
|
2
|
+
def with_each_client(opts = {}, &)
|
|
3
3
|
clients = {}
|
|
4
4
|
|
|
5
|
-
oauth_client = JIRA::Client.new(consumer_key: 'foo', consumer_secret: 'bar')
|
|
5
|
+
oauth_client = JIRA::Client.new({ consumer_key: 'foo', consumer_secret: 'bar' }.merge(opts))
|
|
6
6
|
oauth_client.set_access_token('abc', '123')
|
|
7
7
|
clients['http://localhost:2990'] = oauth_client
|
|
8
8
|
|
|
9
|
-
basic_client = JIRA::Client.new(username: 'foo', password: 'bar', auth_type: :basic, use_ssl: false)
|
|
10
|
-
clients['http://
|
|
9
|
+
basic_client = JIRA::Client.new({ username: 'foo', password: 'bar', auth_type: :basic, use_ssl: false }.merge(opts))
|
|
10
|
+
clients['http://localhost:2990'] = basic_client
|
|
11
11
|
|
|
12
|
-
clients.each
|
|
13
|
-
yield site_url, client
|
|
14
|
-
end
|
|
12
|
+
clients.each(&)
|
|
15
13
|
end
|
|
16
14
|
end
|
|
@@ -1,22 +1,20 @@
|
|
|
1
1
|
require 'cgi'
|
|
2
2
|
|
|
3
|
-
def
|
|
4
|
-
prefix =
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
file_path =
|
|
18
|
-
file_path = file_path + '.' + options[:suffix] if options[:suffix]
|
|
19
|
-
file_path = file_path + '.' + method.to_s unless method == :get
|
|
3
|
+
def build_url(options = {})
|
|
4
|
+
prefix = defined?(belongs_to) ? "#{belongs_to.path_component}/" : '/'
|
|
5
|
+
path = if options.key?(:key)
|
|
6
|
+
described_class.singular_path(client, options[:key], prefix)
|
|
7
|
+
else
|
|
8
|
+
described_class.collection_path(client, prefix)
|
|
9
|
+
end
|
|
10
|
+
site_url + path
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def get_mock_from_url(method, url, options = {})
|
|
14
|
+
# Remove site_url and rest api portion of the url
|
|
15
|
+
file_path = url.sub(site_url + client.options[:rest_base_path], '')
|
|
16
|
+
file_path = "#{file_path}.#{options[:suffix]}" if options[:suffix]
|
|
17
|
+
file_path = "#{file_path}.#{method}" unless method == :get
|
|
20
18
|
value_if_not_found = options.key?(:value_if_not_found) ? options[:value_if_not_found] : false
|
|
21
19
|
get_mock_response("#{file_path}.json", value_if_not_found)
|
|
22
20
|
end
|
|
@@ -33,7 +31,7 @@ end
|
|
|
33
31
|
|
|
34
32
|
def prefix
|
|
35
33
|
prefix = '/'
|
|
36
|
-
prefix = belongs_to.path_component
|
|
34
|
+
prefix = "#{belongs_to.path_component}/" if defined? belongs_to
|
|
37
35
|
prefix
|
|
38
36
|
end
|
|
39
37
|
|
|
@@ -47,24 +45,24 @@ end
|
|
|
47
45
|
|
|
48
46
|
shared_examples 'a resource' do
|
|
49
47
|
it 'gracefully handles non-json responses' do
|
|
50
|
-
if defined? target
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
48
|
+
subject = if defined? target
|
|
49
|
+
target
|
|
50
|
+
else
|
|
51
|
+
client.send(class_basename).build(described_class.key_attribute.to_s => '99999')
|
|
52
|
+
end
|
|
55
53
|
stub_request(:put, site_url + subject.url)
|
|
56
54
|
.to_return(status: 405, body: '<html><body>Some HTML</body></html>')
|
|
57
55
|
expect(subject.save('foo' => 'bar')).to be_falsey
|
|
58
|
-
expect
|
|
56
|
+
expect do
|
|
59
57
|
expect(subject.save!('foo' => 'bar')).to be_falsey
|
|
60
|
-
end
|
|
58
|
+
end.to raise_error(JIRA::HTTPError)
|
|
61
59
|
end
|
|
62
60
|
end
|
|
63
61
|
|
|
64
62
|
shared_examples 'a resource with a collection GET endpoint' do
|
|
65
|
-
it '
|
|
66
|
-
|
|
67
|
-
|
|
63
|
+
it 'gets the collection' do
|
|
64
|
+
req_url = build_url
|
|
65
|
+
stub_request(:get, req_url).to_return(status: 200, body: get_mock_from_url(:get, req_url))
|
|
68
66
|
collection = build_receiver.all
|
|
69
67
|
|
|
70
68
|
expect(collection.length).to eq(expected_collection_length)
|
|
@@ -73,14 +71,9 @@ shared_examples 'a resource with a collection GET endpoint' do
|
|
|
73
71
|
end
|
|
74
72
|
|
|
75
73
|
shared_examples 'a resource with JQL inputs and a collection GET endpoint' do
|
|
76
|
-
it '
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
site_url +
|
|
80
|
-
client.options[:rest_base_path] +
|
|
81
|
-
'/search?jql=' +
|
|
82
|
-
CGI.escape(jql_query_string)
|
|
83
|
-
).to_return(status: 200, body: get_mock_response('issue.json'))
|
|
74
|
+
it 'gets the collection' do
|
|
75
|
+
req_url = "#{site_url}#{client.options[:rest_base_path]}/search/jql?jql=#{CGI.escape(jql_query_string)}"
|
|
76
|
+
stub_request(:get, req_url).to_return(status: 200, body: get_mock_response('issue.json'))
|
|
84
77
|
|
|
85
78
|
collection = build_receiver.jql(jql_query_string)
|
|
86
79
|
|
|
@@ -93,8 +86,8 @@ shared_examples 'a resource with a singular GET endpoint' do
|
|
|
93
86
|
it 'GETs a single resource' do
|
|
94
87
|
# E.g., for JIRA::Resource::Project, we need to call
|
|
95
88
|
# client.Project.find()
|
|
96
|
-
|
|
97
|
-
|
|
89
|
+
req_url = build_url(key:)
|
|
90
|
+
stub_request(:get, req_url).to_return(status: 200, body: get_mock_from_url(:get, req_url))
|
|
98
91
|
subject = client.send(class_basename).find(key, options)
|
|
99
92
|
|
|
100
93
|
expect(subject).to have_attributes(expected_attributes)
|
|
@@ -103,8 +96,8 @@ shared_examples 'a resource with a singular GET endpoint' do
|
|
|
103
96
|
it 'builds and fetches a single resource' do
|
|
104
97
|
# E.g., for JIRA::Resource::Project, we need to call
|
|
105
98
|
# client.Project.build('key' => 'ABC123')
|
|
106
|
-
|
|
107
|
-
|
|
99
|
+
req_url = build_url(key:)
|
|
100
|
+
stub_request(:get, req_url).to_return(status: 200, body: get_mock_from_url(:get, req_url))
|
|
108
101
|
|
|
109
102
|
subject = build_receiver.build(described_class.key_attribute.to_s => key)
|
|
110
103
|
subject.fetch
|
|
@@ -113,11 +106,11 @@ shared_examples 'a resource with a singular GET endpoint' do
|
|
|
113
106
|
end
|
|
114
107
|
|
|
115
108
|
it 'handles a 404' do
|
|
116
|
-
stub_request(:get,
|
|
117
|
-
.to_return(status: 404, body:
|
|
118
|
-
expect
|
|
109
|
+
stub_request(:get, build_url(key: '99999'))
|
|
110
|
+
.to_return(status: 404, body: "{\"errorMessages\":[\"#{class_basename} Does Not Exist\"],\"errors\": {}}")
|
|
111
|
+
expect do
|
|
119
112
|
client.send(class_basename).find('99999', options)
|
|
120
|
-
end
|
|
113
|
+
end.to raise_exception(JIRA::HTTPError)
|
|
121
114
|
end
|
|
122
115
|
end
|
|
123
116
|
|
|
@@ -125,8 +118,8 @@ shared_examples 'a resource with a DELETE endpoint' do
|
|
|
125
118
|
it 'deletes a resource' do
|
|
126
119
|
# E.g., for JIRA::Resource::Project, we need to call
|
|
127
120
|
# client.Project.delete()
|
|
128
|
-
|
|
129
|
-
|
|
121
|
+
req_url = build_url(key:)
|
|
122
|
+
stub_request(:delete, req_url).to_return(status: 204, body: nil)
|
|
130
123
|
|
|
131
124
|
subject = build_receiver.build(described_class.key_attribute.to_s => key)
|
|
132
125
|
expect(subject.delete).to be_truthy
|
|
@@ -135,8 +128,8 @@ end
|
|
|
135
128
|
|
|
136
129
|
shared_examples 'a resource with a POST endpoint' do
|
|
137
130
|
it 'saves a new resource' do
|
|
138
|
-
|
|
139
|
-
|
|
131
|
+
req_url = build_url
|
|
132
|
+
stub_request(:post, req_url).to_return(status: 201, body: get_mock_from_url(:post, req_url))
|
|
140
133
|
subject = build_receiver.build
|
|
141
134
|
expect(subject.save(attributes_for_post)).to be_truthy
|
|
142
135
|
expected_attributes_from_post.each do |method_name, value|
|
|
@@ -147,10 +140,10 @@ end
|
|
|
147
140
|
|
|
148
141
|
shared_examples 'a resource with a PUT endpoint' do
|
|
149
142
|
it 'saves an existing component' do
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
stub_request(:put,
|
|
153
|
-
.to_return(status: 200, body:
|
|
143
|
+
req_url = build_url(key:)
|
|
144
|
+
stub_request(:get, req_url).to_return(status: 200, body: get_mock_from_url(:get, req_url))
|
|
145
|
+
stub_request(:put, req_url)
|
|
146
|
+
.to_return(status: 200, body: get_mock_from_url(:put, req_url, value_if_not_found: nil))
|
|
154
147
|
subject = build_receiver.build(described_class.key_attribute.to_s => key)
|
|
155
148
|
subject.fetch
|
|
156
149
|
expect(subject.save(attributes_for_put)).to be_truthy
|
|
@@ -162,16 +155,16 @@ end
|
|
|
162
155
|
|
|
163
156
|
shared_examples 'a resource with a PUT endpoint that rejects invalid fields' do
|
|
164
157
|
it 'fails to save with an invalid field' do
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
stub_request(:put,
|
|
168
|
-
.to_return(status: 400, body:
|
|
158
|
+
req_url = build_url(key:)
|
|
159
|
+
stub_request(:get, req_url).to_return(status: 200, body: get_mock_from_url(:get, req_url))
|
|
160
|
+
stub_request(:put, req_url)
|
|
161
|
+
.to_return(status: 400, body: get_mock_from_url(:put, req_url, suffix: 'invalid'))
|
|
169
162
|
subject = client.send(class_basename).build(described_class.key_attribute.to_s => key)
|
|
170
163
|
subject.fetch
|
|
171
164
|
|
|
172
165
|
expect(subject.save('fields' => { 'invalid' => 'field' })).to be_falsey
|
|
173
|
-
expect
|
|
166
|
+
expect do
|
|
174
167
|
subject.save!('fields' => { 'invalid' => 'field' })
|
|
175
|
-
end
|
|
168
|
+
end.to raise_error(JIRA::HTTPError)
|
|
176
169
|
end
|
|
177
170
|
end
|