jira-ruby 3.0.0.beta1 → 3.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.
- checksums.yaml +4 -4
- data/.github/workflows/CI.yml +1 -0
- data/.github/workflows/codeql.yml +0 -4
- data/.gitignore +3 -1
- data/.rubocop.yml +5 -70
- data/.yardopts +4 -0
- data/lib/jira/base.rb +5 -13
- data/lib/jira/client.rb +59 -4
- data/lib/jira/has_many_proxy.rb +30 -28
- data/lib/jira/http_client.rb +64 -1
- data/lib/jira/oauth_client.rb +62 -0
- data/lib/jira/request_client.rb +26 -1
- data/lib/jira/resource/attachment.rb +88 -3
- data/lib/jira/resource/field.rb +4 -8
- data/lib/jira/resource/issue.rb +80 -11
- data/lib/jira/resource/issue_picker_suggestions.rb +1 -1
- data/lib/jira/resource/issuelink.rb +4 -3
- data/lib/jira/resource/project.rb +1 -1
- data/lib/jira/resource/sprint.rb +2 -2
- data/lib/jira/resource/watcher.rb +1 -1
- data/lib/jira/resource/webhook.rb +5 -1
- data/lib/jira/version.rb +1 -1
- data/lib/tasks/generate.rake +1 -1
- data/spec/integration/issue_spec.rb +2 -2
- data/spec/integration/project_spec.rb +2 -2
- data/spec/integration/rapidview_spec.rb +3 -3
- data/spec/integration/user_spec.rb +12 -3
- data/spec/integration/watcher_spec.rb +6 -2
- data/spec/integration/{webhook.rb → webhook_spec.rb} +8 -1
- data/spec/jira/base_factory_spec.rb +11 -2
- data/spec/jira/base_spec.rb +80 -57
- data/spec/jira/client_spec.rb +29 -27
- data/spec/jira/http_client_spec.rb +2 -2
- data/spec/jira/oauth_client_spec.rb +8 -4
- data/spec/jira/resource/agile_spec.rb +4 -4
- data/spec/jira/resource/attachment_spec.rb +36 -13
- data/spec/jira/resource/board_spec.rb +5 -5
- data/spec/jira/resource/field_spec.rb +23 -24
- data/spec/jira/resource/filter_spec.rb +3 -2
- data/spec/jira/resource/issue_spec.rb +103 -81
- data/spec/jira/resource/project_spec.rb +8 -8
- data/spec/jira/resource/sprint_spec.rb +23 -11
- data/spec/jira/resource/status_spec.rb +1 -1
- data/spec/jira/resource/user_factory_spec.rb +2 -2
- data/spec/jira/resource/worklog_spec.rb +1 -1
- data/spec/mock_responses/board/1_issues.json +2 -1
- 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/support/clients_helper.rb +2 -2
- data/spec/support/mock_client.rb +9 -0
- data/spec/support/mock_response.rb +8 -0
- data/spec/support/shared_examples/integration.rb +1 -1
- metadata +9 -10
@@ -4,11 +4,13 @@ describe JIRA::Resource::Attachment do
|
|
4
4
|
subject(:attachment) do
|
5
5
|
described_class.new(
|
6
6
|
client,
|
7
|
-
issue: JIRA::Resource::Issue.new(client),
|
8
|
-
attrs: { 'author' => { 'foo' => 'bar' } }
|
7
|
+
issue: JIRA::Resource::Issue.new(client, attrs: { 'id' => issue_id }),
|
8
|
+
attrs: { 'author' => { 'foo' => 'bar' }, 'id' => attachment_id }
|
9
9
|
)
|
10
10
|
end
|
11
11
|
|
12
|
+
let(:issue_id) { 27_676 }
|
13
|
+
let(:attachment_id) { 30_076 }
|
12
14
|
let(:client) do
|
13
15
|
double(
|
14
16
|
'client',
|
@@ -44,13 +46,17 @@ describe JIRA::Resource::Attachment do
|
|
44
46
|
)
|
45
47
|
end
|
46
48
|
|
47
|
-
|
48
|
-
|
49
|
+
context 'when returning meta information' do
|
50
|
+
it 'returns meta information about attachment upload' do
|
51
|
+
expect(client).to receive(:get).with('/jira/rest/api/2/attachment/meta').and_return(response)
|
49
52
|
|
50
|
-
|
53
|
+
result = subject
|
54
|
+
|
55
|
+
expect(result).to be_a(Hash)
|
56
|
+
end
|
51
57
|
end
|
52
58
|
|
53
|
-
context 'the factory delegates correctly' do
|
59
|
+
context 'when the factory delegates correctly' do
|
54
60
|
subject { JIRA::Resource::AttachmentFactory.new(client) }
|
55
61
|
|
56
62
|
it 'delegates #meta to to target class' do
|
@@ -59,7 +65,7 @@ describe JIRA::Resource::Attachment do
|
|
59
65
|
end
|
60
66
|
end
|
61
67
|
|
62
|
-
context 'there is an attachment on an issue' do
|
68
|
+
context 'when there is an attachment on an issue' do
|
63
69
|
subject(:attachment) do
|
64
70
|
described_class.new(
|
65
71
|
client,
|
@@ -68,22 +74,26 @@ describe JIRA::Resource::Attachment do
|
|
68
74
|
)
|
69
75
|
end
|
70
76
|
|
77
|
+
let(:attachment_url) { 'https://localhost:2990/secure/attachment/32323/myfile.txt' }
|
71
78
|
let(:client) do
|
72
79
|
JIRA::Client.new(username: 'username', password: 'password', auth_type: :basic, use_ssl: false)
|
73
80
|
end
|
74
81
|
let(:attachment_file_contents) { 'file contents' }
|
75
|
-
let(:
|
82
|
+
let(:issue_id) { 3232 }
|
83
|
+
let(:issue) { JIRA::Resource::Issue.new(client, attrs: { 'id' => issue_id }) }
|
76
84
|
|
77
85
|
before do
|
78
86
|
stub_request(:get, attachment_url).to_return(body: attachment_file_contents)
|
79
87
|
end
|
80
88
|
|
81
89
|
describe '.download_file' do
|
82
|
-
|
83
|
-
|
90
|
+
context 'when passing file object to block' do
|
91
|
+
it 'passes file object to block' do
|
92
|
+
expect(URI).to receive(:parse).with(attachment_url).and_call_original
|
84
93
|
|
85
|
-
|
86
|
-
|
94
|
+
attachment.download_file do |file|
|
95
|
+
expect(file.read).to eq(attachment_file_contents)
|
96
|
+
end
|
87
97
|
end
|
88
98
|
end
|
89
99
|
end
|
@@ -91,6 +101,7 @@ describe JIRA::Resource::Attachment do
|
|
91
101
|
describe '.download_contents' do
|
92
102
|
it 'downloads the file contents as a string' do
|
93
103
|
expect(URI).to receive(:parse).with(attachment_url).and_call_original
|
104
|
+
|
94
105
|
expect(attachment.download_contents).to eq(attachment_file_contents)
|
95
106
|
end
|
96
107
|
end
|
@@ -115,7 +126,7 @@ describe JIRA::Resource::Attachment do
|
|
115
126
|
].to_json
|
116
127
|
)
|
117
128
|
end
|
118
|
-
let(:issue) { JIRA::Resource::Issue.new(client) }
|
129
|
+
let(:issue) { JIRA::Resource::Issue.new(client, attrs: { 'id' => issue_id }) }
|
119
130
|
|
120
131
|
describe '#save' do
|
121
132
|
subject { attachment.save('file' => path_to_file) }
|
@@ -125,6 +136,8 @@ describe JIRA::Resource::Attachment do
|
|
125
136
|
end
|
126
137
|
|
127
138
|
it 'successfully update the attachment' do
|
139
|
+
expect(client).to receive(:post_multipart).and_return(response).with("/jira/rest/api/2/issue/#{issue.id}/attachments/#{attachment.id}", anything, anything)
|
140
|
+
|
128
141
|
subject
|
129
142
|
|
130
143
|
expect(attachment.filename).to eq file_name
|
@@ -225,4 +238,14 @@ describe JIRA::Resource::Attachment do
|
|
225
238
|
end
|
226
239
|
end
|
227
240
|
end
|
241
|
+
|
242
|
+
context 'when an attachment is on an issue' do
|
243
|
+
describe '#delete' do
|
244
|
+
it 'removes the attachment' do
|
245
|
+
expect(client).to receive(:delete).with("/jira/rest/api/2/issue/#{issue_id}/attachments/#{attachment_id}")
|
246
|
+
|
247
|
+
attachment.delete
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|
228
251
|
end
|
@@ -107,7 +107,7 @@ EOS
|
|
107
107
|
|
108
108
|
context 'when there are multiple pages of results' do
|
109
109
|
let(:result_1) do
|
110
|
-
|
110
|
+
double(body: {
|
111
111
|
'startAt' => 0,
|
112
112
|
'maxResults' => 1,
|
113
113
|
'total' => 2,
|
@@ -115,7 +115,7 @@ EOS
|
|
115
115
|
}.to_json)
|
116
116
|
end
|
117
117
|
let(:result_2) do
|
118
|
-
|
118
|
+
double(body: {
|
119
119
|
'startAt' => 1,
|
120
120
|
'maxResults' => 1,
|
121
121
|
'total' => 2,
|
@@ -132,7 +132,7 @@ EOS
|
|
132
132
|
|
133
133
|
context 'when there is only one page of results' do
|
134
134
|
let(:result_1) do
|
135
|
-
|
135
|
+
double(body: {
|
136
136
|
'startAt' => 0,
|
137
137
|
'maxResults' => 2,
|
138
138
|
'total' => 2,
|
@@ -166,7 +166,7 @@ EOS
|
|
166
166
|
}
|
167
167
|
]
|
168
168
|
}
|
169
|
-
EOS
|
169
|
+
EOS
|
170
170
|
allow(response).to receive(:body).and_return(api_json)
|
171
171
|
allow(board).to receive(:id).and_return(84)
|
172
172
|
expect(client).to receive(:get).with('/rest/agile/1.0/board/84/sprint?').and_return(response)
|
@@ -215,7 +215,7 @@ EOS
|
|
215
215
|
"rankCustomFieldId":10011
|
216
216
|
}
|
217
217
|
}
|
218
|
-
EOS
|
218
|
+
EOS
|
219
219
|
allow(response).to receive(:body).and_return(api_json)
|
220
220
|
allow(board).to receive(:id).and_return(84)
|
221
221
|
expect(client).to receive(:get).with('/rest/agile/1.0/board/84/configuration').and_return(response)
|
@@ -1,56 +1,55 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe JIRA::Resource::Field do
|
4
|
-
let(:cache) { OpenStruct.new }
|
5
|
-
|
6
4
|
let(:client) do
|
7
5
|
client = double(options: { rest_base_path: '/jira/rest/api/2' })
|
8
6
|
field = JIRA::Resource::FieldFactory.new(client)
|
9
7
|
allow(client).to receive(:Field).and_return(field)
|
10
|
-
allow(client).to receive(:
|
8
|
+
allow(client).to receive(:field_map_cache).and_return(nil)
|
9
|
+
allow(client).to receive(:field_map_cache=)
|
11
10
|
# info about all fields on the client
|
12
11
|
allow(client.Field).to receive(:all).and_return([
|
13
12
|
described_class.new(client,
|
14
13
|
attrs: { 'id' => 'customfield_10666', 'name' => 'Priority', 'custom' => true, 'orderable' => true, 'navigable' => true,
|
15
|
-
|
14
|
+
'searchable' => true, 'clauseNames' => ['cf[10666]', 'Priority'], 'schema' => { 'type' => 'string', 'custom' => 'com.atlassian.jira.plugin.system.customfieldtypes:select', 'customId' => 10_666 } }),
|
16
15
|
described_class.new(client,
|
17
16
|
attrs: { 'id' => 'issuekey', 'name' => 'Key', 'custom' => false, 'orderable' => false,
|
18
|
-
|
17
|
+
'navigable' => true, 'searchable' => false, 'clauseNames' => %w[id issue issuekey key] }),
|
19
18
|
described_class.new(client,
|
20
19
|
attrs: { 'id' => 'priority', 'name' => 'Priority', 'custom' => false, 'orderable' => true,
|
21
|
-
|
20
|
+
'navigable' => true, 'searchable' => true, 'clauseNames' => ['priority'], 'schema' => { 'type' => 'priority', 'system' => 'priority' } }),
|
22
21
|
described_class.new(client,
|
23
22
|
attrs: { 'id' => 'summary', 'name' => 'Summary', 'custom' => false, 'orderable' => true,
|
24
|
-
|
23
|
+
'navigable' => true, 'searchable' => true, 'clauseNames' => ['summary'], 'schema' => { 'type' => 'string', 'system' => 'summary' } }),
|
25
24
|
described_class.new(client,
|
26
25
|
attrs: { 'id' => 'issuetype', 'name' => 'Issue Type', 'custom' => false, 'orderable' => true,
|
27
|
-
|
26
|
+
'navigable' => true, 'searchable' => true, 'clauseNames' => %w[issuetype type], 'schema' => { 'type' => 'issuetype', 'system' => 'issuetype' } }),
|
28
27
|
described_class.new(client,
|
29
28
|
attrs: { 'id' => 'customfield_10111', 'name' => 'SingleWord', 'custom' => true, 'orderable' => true,
|
30
|
-
|
29
|
+
'navigable' => true, 'searchable' => true, 'clauseNames' => ['cf[10111]', 'SingleWord'], 'schema' => { 'type' => 'string', 'custom' => 'com.atlassian.jira.plugin.system.customfieldtypes:select', 'customId' => 10_111 } }),
|
31
30
|
described_class.new(client,
|
32
31
|
attrs: { 'id' => 'customfield_10222', 'name' => 'Multi Word', 'custom' => true, 'orderable' => true,
|
33
|
-
|
32
|
+
'navigable' => true, 'searchable' => true, 'clauseNames' => ['cf[10222]', 'Multi Word'], 'schema' => { 'type' => 'string', 'custom' => 'com.atlassian.jira.plugin.system.customfieldtypes:select', 'customId' => 10_222 } }),
|
34
33
|
described_class.new(client,
|
35
34
|
attrs: { 'id' => 'customfield_10333', 'name' => 'Why/N@t', 'custom' => true, 'orderable' => true,
|
36
|
-
|
35
|
+
'navigable' => true, 'searchable' => true, 'clauseNames' => ['cf[10333]', 'Why/N@t'], 'schema' => { 'type' => 'string', 'custom' => 'com.atlassian.jira.plugin.system.customfieldtypes:select', 'customId' => 10_333 } }),
|
37
36
|
described_class.new(client,
|
38
37
|
attrs: { 'id' => 'customfield_10444', 'name' => 'SingleWord', 'custom' => true, 'orderable' => true,
|
39
|
-
|
38
|
+
'navigable' => true, 'searchable' => true, 'clauseNames' => ['cf[10444]', 'SingleWord'], 'schema' => { 'type' => 'string', 'custom' => 'com.atlassian.jira.plugin.system.customfieldtypes:select', 'customId' => 10_444 } })
|
40
39
|
])
|
41
40
|
client
|
42
41
|
end
|
43
42
|
|
44
43
|
describe 'field_mappings' do
|
45
|
-
shared_context '
|
44
|
+
shared_context 'with or without mapping' do
|
46
45
|
subject do
|
47
46
|
described_class.new(client, attrs: {
|
48
47
|
'priority' => 1,
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
48
|
+
'customfield_10111' => 'data_in_custom_field',
|
49
|
+
'customfield_10222' => 'multi word custom name',
|
50
|
+
'customfield_10333' => 'complex custom name',
|
51
|
+
'customfield_10444' => 'duplicated custom name',
|
52
|
+
'customfield_10666' => 'duplicate of a system name'
|
54
53
|
})
|
55
54
|
end
|
56
55
|
|
@@ -65,12 +64,12 @@ describe JIRA::Resource::Field do
|
|
65
64
|
it 'is not confused by common attribute keys' do
|
66
65
|
expect { subject.name }.to raise_error(NoMethodError)
|
67
66
|
expect { subject.custom }.to raise_error(NoMethodError)
|
68
|
-
expect(subject.id).to
|
67
|
+
expect(subject.id).to be_nil # picks up ID from the parent -
|
69
68
|
end
|
70
69
|
end
|
71
70
|
|
72
|
-
context '
|
73
|
-
include_context '
|
71
|
+
context 'when fields are not yet mapped' do
|
72
|
+
include_context 'with or without mapping'
|
74
73
|
|
75
74
|
it 'can find a standard field by id' do
|
76
75
|
expect(subject.priority).to eq(1)
|
@@ -87,12 +86,12 @@ describe JIRA::Resource::Field do
|
|
87
86
|
it 'is not confused by common attribute keys and raises error' do
|
88
87
|
expect { subject.name }.to raise_error(NoMethodError)
|
89
88
|
expect { subject.custom }.to raise_error(NoMethodError)
|
90
|
-
expect(subject.id).to
|
89
|
+
expect(subject.id).to be_nil # picks up ID from the parent -
|
91
90
|
end
|
92
91
|
end
|
93
92
|
|
94
|
-
context '
|
95
|
-
include_context '
|
93
|
+
context 'when fields have been mapped' do
|
94
|
+
include_context 'with or without mapping'
|
96
95
|
|
97
96
|
it 'warns of duplicate fields' do
|
98
97
|
expect { client.Field.map_fields }.to output(/renaming as Priority_10666/).to_stderr
|
@@ -28,7 +28,7 @@ describe JIRA::Resource::Filter do
|
|
28
28
|
owner: jira_user,
|
29
29
|
jql: '"Git Repository" ~ jira-ruby AND status = Resolved',
|
30
30
|
viewUrl: 'https://localhost/secure/IssueNavigator.jspa?mode=hide&requestId=42',
|
31
|
-
searchUrl: 'https://localhost/rest/api/2/search?jql=%22Git+Repository%22+~+jira-ruby+AND+status+%3D+Resolved',
|
31
|
+
searchUrl: 'https://localhost/rest/api/2/search/jql?jql=%22Git+Repository%22+~+jira-ruby+AND+status+%3D+Resolved',
|
32
32
|
favourite: false,
|
33
33
|
sharePermissions: [
|
34
34
|
{
|
@@ -69,6 +69,7 @@ describe JIRA::Resource::Filter do
|
|
69
69
|
startAt: 0,
|
70
70
|
maxResults: 50,
|
71
71
|
total: 2,
|
72
|
+
isLast: true,
|
72
73
|
issues: [jql_issue]
|
73
74
|
}
|
74
75
|
end
|
@@ -86,7 +87,7 @@ describe JIRA::Resource::Filter do
|
|
86
87
|
expect(filter).to be_present
|
87
88
|
allow(client).to receive(:options).and_return(rest_base_path: 'localhost')
|
88
89
|
expect(client).to receive(:get)
|
89
|
-
.with("localhost/search?jql=#{CGI.escape(filter.jql)}")
|
90
|
+
.with("localhost/search/jql?jql=#{CGI.escape(filter.jql)}")
|
90
91
|
.and_return(issue_jql_response)
|
91
92
|
issues = filter.issues
|
92
93
|
expect(issues).to be_an(Array)
|
@@ -7,7 +7,7 @@ describe JIRA::Resource::Issue do
|
|
7
7
|
let(:client) do
|
8
8
|
client = double(options: { rest_base_path: '/jira/rest/api/2' })
|
9
9
|
allow(client).to receive(:Field).and_return(JIRA::Resource::FieldFactory.new(client))
|
10
|
-
allow(client).to receive(:
|
10
|
+
allow(client).to receive(:field_map_cache).and_return(nil)
|
11
11
|
client
|
12
12
|
end
|
13
13
|
|
@@ -25,7 +25,7 @@ describe JIRA::Resource::Issue do
|
|
25
25
|
end
|
26
26
|
|
27
27
|
it 'responds to key' do
|
28
|
-
expect(@decorated.respond_to?(:key)).to
|
28
|
+
expect(@decorated.respond_to?(:key)).to be(true)
|
29
29
|
end
|
30
30
|
|
31
31
|
it 'does not raise an error' do
|
@@ -42,16 +42,16 @@ describe JIRA::Resource::Issue do
|
|
42
42
|
issue = double
|
43
43
|
|
44
44
|
allow(response).to receive(:body).and_return('{"issues":[{"id":"1","summary":"Bugs Everywhere"}]}')
|
45
|
-
expect(client).to receive(:get).with('/jira/rest/api/2/search?expand=transitions.fields&maxResults=1000&startAt=0')
|
45
|
+
expect(client).to receive(:get).with('/jira/rest/api/2/search/jql?expand=transitions.fields&maxResults=1000&startAt=0')
|
46
46
|
.and_return(response)
|
47
47
|
allow(empty_response).to receive(:body).and_return('{"issues":[]}')
|
48
|
-
expect(client).to receive(:get).with('/jira/rest/api/2/search?expand=transitions.fields&maxResults=1000&startAt=1')
|
48
|
+
expect(client).to receive(:get).with('/jira/rest/api/2/search/jql?expand=transitions.fields&maxResults=1000&startAt=1')
|
49
49
|
.and_return(empty_response)
|
50
50
|
|
51
51
|
expect(client).to receive(:Issue).and_return(issue)
|
52
52
|
expect(issue).to receive(:build).with({ 'id' => '1', 'summary' => 'Bugs Everywhere' })
|
53
53
|
|
54
|
-
|
54
|
+
described_class.all(client)
|
55
55
|
end
|
56
56
|
|
57
57
|
it 'finds an issue by key or id' do
|
@@ -70,85 +70,107 @@ describe JIRA::Resource::Issue do
|
|
70
70
|
expect(issue_from_id.attrs).to eq(issue_from_key.attrs)
|
71
71
|
end
|
72
72
|
|
73
|
-
|
74
|
-
|
75
|
-
issue = double
|
73
|
+
describe '.jql' do
|
74
|
+
subject { described_class.jql(client, 'foo bar', args) }
|
76
75
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
expect(issue).to receive(:build).with(%w[key foo]).and_return('')
|
76
|
+
let(:args) { {} }
|
77
|
+
let(:issue) { double }
|
78
|
+
let(:response) { double }
|
79
|
+
let(:response_string) { '{"issues": {"key":"foo"}, "isLast": true}' }
|
82
80
|
|
83
|
-
|
84
|
-
|
81
|
+
before do
|
82
|
+
allow(response).to receive(:body).and_return(response_string)
|
83
|
+
allow(client).to receive(:Issue).and_return(issue)
|
84
|
+
allow(issue).to receive(:build).with(%w[key foo]).and_return('')
|
85
|
+
end
|
85
86
|
|
86
|
-
|
87
|
-
|
88
|
-
|
87
|
+
it 'searches an issue with a jql query string' do
|
88
|
+
expect(client).to receive(:get).with('/jira/rest/api/2/search/jql?jql=foo+bar')
|
89
|
+
.and_return(response)
|
90
|
+
expect(described_class.jql(client, 'foo bar')).to eq([''])
|
91
|
+
end
|
89
92
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
expect(client).to receive(:Issue).and_return(issue)
|
95
|
-
expect(issue).to receive(:build).with(%w[key foo]).and_return('')
|
93
|
+
it 'passes thorugh the reconcileIssues parameter' do
|
94
|
+
expect(client).to receive(:get)
|
95
|
+
.with('/jira/rest/api/2/search/jql?jql=foo+bar&reconcileIssues=true')
|
96
|
+
.and_return(response)
|
96
97
|
|
97
|
-
|
98
|
-
|
98
|
+
expect(described_class.jql(client, 'foo bar', reconcile_issues: true)).to eq([''])
|
99
|
+
end
|
99
100
|
|
100
|
-
|
101
|
-
|
102
|
-
|
101
|
+
it 'searches an issue with a jql query string and fields' do
|
102
|
+
expect(client).to receive(:get)
|
103
|
+
.with('/jira/rest/api/2/search/jql?jql=foo+bar&fields=foo,bar')
|
104
|
+
.and_return(response)
|
103
105
|
|
104
|
-
|
105
|
-
|
106
|
-
.with('/jira/rest/api/2/search?jql=foo+bar&startAt=1&maxResults=3')
|
107
|
-
.and_return(response)
|
108
|
-
expect(client).to receive(:Issue).and_return(issue)
|
109
|
-
expect(issue).to receive(:build).with(%w[key foo]).and_return('')
|
106
|
+
expect(described_class.jql(client, 'foo bar', fields: %w[foo bar])).to eq([''])
|
107
|
+
end
|
110
108
|
|
111
|
-
|
112
|
-
|
109
|
+
context 'when maxResults is provided' do
|
110
|
+
let(:args) { { max_results: } }
|
113
111
|
|
114
|
-
|
115
|
-
|
116
|
-
issue = double
|
112
|
+
context 'with non-zero' do
|
113
|
+
let(:max_results) { 3 }
|
117
114
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
115
|
+
it 'searches an issue with a jql query string and maxResults' do
|
116
|
+
expect(client).to receive(:get)
|
117
|
+
.with('/jira/rest/api/2/search/jql?jql=foo+bar&maxResults=3')
|
118
|
+
.and_return(response)
|
122
119
|
|
123
|
-
|
124
|
-
|
120
|
+
expect(subject).to eq([''])
|
121
|
+
end
|
122
|
+
end
|
125
123
|
|
126
|
-
|
127
|
-
|
128
|
-
|
124
|
+
context 'with zero' do
|
125
|
+
let(:response_string) { '{"total": 1, "issues": []}' }
|
126
|
+
let(:max_results) { 0 }
|
129
127
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
expect(client).to receive(:Issue).and_return(issue)
|
135
|
-
expect(issue).to receive(:build).with(%w[key foo]).and_return('')
|
128
|
+
it 'searches an issue with a jql query string and should return the count of tickets' do
|
129
|
+
expect(client).to receive(:get)
|
130
|
+
.with('/jira/rest/api/2/search/jql?jql=foo+bar&maxResults=0')
|
131
|
+
.and_return(response)
|
136
132
|
|
137
|
-
|
138
|
-
|
133
|
+
expect(subject).to eq(1)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
139
137
|
|
140
|
-
|
141
|
-
|
142
|
-
|
138
|
+
it 'searches an issue with a jql query string and string expand' do
|
139
|
+
expect(client).to receive(:get)
|
140
|
+
.with('/jira/rest/api/2/search/jql?jql=foo+bar&expand=transitions')
|
141
|
+
.and_return(response)
|
143
142
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
143
|
+
expect(described_class.jql(client, 'foo bar', expand: 'transitions')).to eq([''])
|
144
|
+
end
|
145
|
+
|
146
|
+
it 'searches an issue with a jql query string and array expand' do
|
147
|
+
expect(client).to receive(:get)
|
148
|
+
.with('/jira/rest/api/2/search/jql?jql=foo+bar&expand=transitions')
|
149
|
+
.and_return(response)
|
150
|
+
|
151
|
+
expect(described_class.jql(client, 'foo bar', expand: %w[transitions])).to eq([''])
|
152
|
+
end
|
153
|
+
|
154
|
+
context 'when pagination is required' do
|
155
|
+
let(:response_string) { '{"issues": [{"key":"foo"}], "isLast": false, "nextPageToken": "abc"}' }
|
156
|
+
let(:second_response_string) { '{"issues": [{"key":"bar"}], "isLast": true}' }
|
150
157
|
|
151
|
-
|
158
|
+
before do
|
159
|
+
allow(issue).to receive(:build).with({ 'key' => 'foo' }).and_return('1')
|
160
|
+
allow(issue).to receive(:build).with({ 'key' => 'bar' }).and_return('2')
|
161
|
+
end
|
162
|
+
|
163
|
+
it 'makes multiple requests' do
|
164
|
+
expect(client).to receive(:get)
|
165
|
+
.with('/jira/rest/api/2/search/jql?jql=foo+bar')
|
166
|
+
.and_return(response)
|
167
|
+
expect(client).to receive(:get)
|
168
|
+
.with('/jira/rest/api/2/search/jql?jql=foo+bar&nextPageToken=abc')
|
169
|
+
.and_return(double(body: second_response_string))
|
170
|
+
|
171
|
+
expect(subject).to eq(%w[1 2])
|
172
|
+
end
|
173
|
+
end
|
152
174
|
end
|
153
175
|
|
154
176
|
it 'returns meta data available for editing an issue' do
|
@@ -175,20 +197,20 @@ describe JIRA::Resource::Issue do
|
|
175
197
|
subject do
|
176
198
|
described_class.new(client, attrs: {
|
177
199
|
'id' => '123',
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
200
|
+
'fields' => {
|
201
|
+
'reporter' => { 'foo' => 'bar' },
|
202
|
+
'assignee' => { 'foo' => 'bar' },
|
203
|
+
'project' => { 'foo' => 'bar' },
|
204
|
+
'priority' => { 'foo' => 'bar' },
|
205
|
+
'issuetype' => { 'foo' => 'bar' },
|
206
|
+
'status' => { 'foo' => 'bar' },
|
207
|
+
'resolution' => { 'foo' => 'bar' },
|
208
|
+
'components' => [{ 'foo' => 'bar' }, { 'baz' => 'flum' }],
|
209
|
+
'versions' => [{ 'foo' => 'bar' }, { 'baz' => 'flum' }],
|
210
|
+
'comment' => { 'comments' => [{ 'foo' => 'bar' }, { 'baz' => 'flum' }] },
|
211
|
+
'attachment' => [{ 'foo' => 'bar' }, { 'baz' => 'flum' }],
|
212
|
+
'worklog' => { 'worklogs' => [{ 'foo' => 'bar' }, { 'baz' => 'flum' }] }
|
213
|
+
}
|
192
214
|
})
|
193
215
|
end
|
194
216
|
|
@@ -11,8 +11,8 @@ describe JIRA::Resource::Project do
|
|
11
11
|
subject do
|
12
12
|
described_class.new(client, attrs: {
|
13
13
|
'lead' => { 'foo' => 'bar' },
|
14
|
-
|
15
|
-
|
14
|
+
'issueTypes' => [{ 'foo' => 'bar' }, { 'baz' => 'flum' }],
|
15
|
+
'versions' => [{ 'foo' => 'bar' }, { 'baz' => 'flum' }]
|
16
16
|
})
|
17
17
|
end
|
18
18
|
|
@@ -36,13 +36,13 @@ describe JIRA::Resource::Project do
|
|
36
36
|
end
|
37
37
|
|
38
38
|
it 'returns issues' do
|
39
|
-
response_body = '{"expand":"schema,names","startAt":0,"maxResults":1,"total":1,"issues":[{"expand":"editmeta,renderedFields,transitions,changelog,operations","id":"53062","self":"/rest/api/2/issue/53062","key":"test key","fields":{"summary":"test summary"}}]}'
|
39
|
+
response_body = '{"expand":"schema,names","startAt":0,"maxResults":1,"total":1,"issues":[{"expand":"editmeta,renderedFields,transitions,changelog,operations","id":"53062","self":"/rest/api/2/issue/53062","key":"test key","fields":{"summary":"test summary"}}]}'
|
40
40
|
response = double('response',
|
41
41
|
body: response_body)
|
42
42
|
issue_factory = double('issue factory')
|
43
43
|
|
44
44
|
expect(client).to receive(:get)
|
45
|
-
.with('/jira/rest/api/2/search?jql=project%3D%22test%22')
|
45
|
+
.with('/jira/rest/api/2/search/jql?jql=project%3D%22test%22')
|
46
46
|
.and_return(response)
|
47
47
|
expect(client).to receive(:Issue).and_return(issue_factory)
|
48
48
|
expect(issue_factory).to receive(:build)
|
@@ -52,13 +52,13 @@ describe JIRA::Resource::Project do
|
|
52
52
|
|
53
53
|
context 'with changelog' do
|
54
54
|
it 'returns issues' do
|
55
|
-
response_body = '{"expand":"schema,names","startAt":0,"maxResults":1,"total":1,"issues":[{"expand":"editmeta,renderedFields,transitions,changelog,operations","id":"53062","self":"/rest/api/2/issue/53062","key":"test key","fields":{"summary":"test summary"},"changelog":{}}]}'
|
55
|
+
response_body = '{"expand":"schema,names","startAt":0,"maxResults":1,"total":1,"issues":[{"expand":"editmeta,renderedFields,transitions,changelog,operations","id":"53062","self":"/rest/api/2/issue/53062","key":"test key","fields":{"summary":"test summary"},"changelog":{}}]}'
|
56
56
|
response = double('response',
|
57
57
|
body: response_body)
|
58
58
|
issue_factory = double('issue factory')
|
59
59
|
|
60
60
|
expect(client).to receive(:get)
|
61
|
-
.with('/jira/rest/api/2/search?jql=project%3D%22test%22&expand=changelog&startAt=1&maxResults=100')
|
61
|
+
.with('/jira/rest/api/2/search/jql?jql=project%3D%22test%22&expand=changelog&startAt=1&maxResults=100')
|
62
62
|
.and_return(response)
|
63
63
|
expect(client).to receive(:Issue).and_return(issue_factory)
|
64
64
|
expect(issue_factory).to receive(:build)
|
@@ -73,7 +73,7 @@ describe JIRA::Resource::Project do
|
|
73
73
|
let(:project_key) { SecureRandom.hex }
|
74
74
|
let(:response) { double('response', body: '[{}]') }
|
75
75
|
|
76
|
-
context 'pagination' do
|
76
|
+
context 'with pagination' do
|
77
77
|
before do
|
78
78
|
user_factory = double('user factory')
|
79
79
|
expect(client).to receive(:User).and_return(user_factory)
|
@@ -113,7 +113,7 @@ describe JIRA::Resource::Project do
|
|
113
113
|
max_results = rand(1000)
|
114
114
|
|
115
115
|
expect(client).to receive(:get)
|
116
|
-
.with("/jira/rest/api/2/user/assignable/search?project=#{project_key}&startAt=#{start_at}&maxResults=#{max_results}")
|
116
|
+
.with("/jira/rest/api/2/user/assignable/search?project=#{project_key}&startAt=#{start_at}&maxResults=#{max_results}")
|
117
117
|
.and_return(response)
|
118
118
|
|
119
119
|
project.users(start_at:, max_results:)
|