jira-ruby 2.3.0 → 3.0.0.beta2

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 (122) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE/bug_report.md +20 -0
  3. data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  4. data/.github/dependabot.yml +6 -0
  5. data/.github/workflows/CI.yml +29 -0
  6. data/.github/workflows/codeql.yml +96 -0
  7. data/.github/workflows/rubocop.yml +18 -0
  8. data/.gitignore +3 -1
  9. data/.rubocop.yml +120 -0
  10. data/.yardopts +4 -0
  11. data/Gemfile +11 -3
  12. data/Guardfile +2 -0
  13. data/README.md +94 -18
  14. data/Rakefile +3 -4
  15. data/jira-ruby.gemspec +11 -17
  16. data/lib/jira/base.rb +37 -36
  17. data/lib/jira/base_factory.rb +4 -1
  18. data/lib/jira/client.rb +123 -50
  19. data/lib/jira/has_many_proxy.rb +32 -28
  20. data/lib/jira/http_client.rb +80 -13
  21. data/lib/jira/http_error.rb +4 -0
  22. data/lib/jira/jwt_client.rb +18 -42
  23. data/lib/jira/oauth_client.rb +68 -3
  24. data/lib/jira/railtie.rb +2 -0
  25. data/lib/jira/request_client.rb +31 -2
  26. data/lib/jira/resource/agile.rb +7 -9
  27. data/lib/jira/resource/applinks.rb +5 -3
  28. data/lib/jira/resource/attachment.rb +128 -3
  29. data/lib/jira/resource/board.rb +5 -3
  30. data/lib/jira/resource/board_configuration.rb +2 -0
  31. data/lib/jira/resource/comment.rb +2 -0
  32. data/lib/jira/resource/component.rb +2 -0
  33. data/lib/jira/resource/createmeta.rb +3 -1
  34. data/lib/jira/resource/field.rb +13 -12
  35. data/lib/jira/resource/filter.rb +2 -0
  36. data/lib/jira/resource/issue.rb +95 -44
  37. data/lib/jira/resource/issue_picker_suggestions.rb +4 -1
  38. data/lib/jira/resource/issue_picker_suggestions_issue.rb +2 -0
  39. data/lib/jira/resource/issuelink.rb +6 -3
  40. data/lib/jira/resource/issuelinktype.rb +2 -0
  41. data/lib/jira/resource/issuetype.rb +2 -0
  42. data/lib/jira/resource/priority.rb +2 -0
  43. data/lib/jira/resource/project.rb +4 -2
  44. data/lib/jira/resource/rapidview.rb +5 -3
  45. data/lib/jira/resource/remotelink.rb +2 -0
  46. data/lib/jira/resource/resolution.rb +2 -0
  47. data/lib/jira/resource/serverinfo.rb +2 -0
  48. data/lib/jira/resource/sprint.rb +14 -23
  49. data/lib/jira/resource/status.rb +7 -1
  50. data/lib/jira/resource/status_category.rb +10 -0
  51. data/lib/jira/resource/suggested_issue.rb +2 -0
  52. data/lib/jira/resource/transition.rb +2 -0
  53. data/lib/jira/resource/user.rb +3 -1
  54. data/lib/jira/resource/version.rb +2 -0
  55. data/lib/jira/resource/watcher.rb +3 -2
  56. data/lib/jira/resource/webhook.rb +9 -3
  57. data/lib/jira/resource/worklog.rb +3 -2
  58. data/lib/jira/version.rb +3 -1
  59. data/lib/jira-ruby.rb +5 -3
  60. data/lib/tasks/generate.rake +3 -1
  61. data/spec/data/files/short.txt +1 -0
  62. data/spec/integration/attachment_spec.rb +3 -3
  63. data/spec/integration/comment_spec.rb +8 -8
  64. data/spec/integration/component_spec.rb +7 -7
  65. data/spec/integration/field_spec.rb +3 -3
  66. data/spec/integration/issue_spec.rb +20 -16
  67. data/spec/integration/issuelinktype_spec.rb +3 -3
  68. data/spec/integration/issuetype_spec.rb +3 -3
  69. data/spec/integration/priority_spec.rb +3 -3
  70. data/spec/integration/project_spec.rb +8 -8
  71. data/spec/integration/rapidview_spec.rb +10 -10
  72. data/spec/integration/resolution_spec.rb +3 -3
  73. data/spec/integration/status_category_spec.rb +20 -0
  74. data/spec/integration/status_spec.rb +4 -8
  75. data/spec/integration/transition_spec.rb +2 -2
  76. data/spec/integration/user_spec.rb +34 -11
  77. data/spec/integration/version_spec.rb +7 -7
  78. data/spec/integration/watcher_spec.rb +21 -18
  79. data/spec/integration/webhook_spec.rb +33 -0
  80. data/spec/integration/worklog_spec.rb +8 -8
  81. data/spec/jira/base_factory_spec.rb +13 -3
  82. data/spec/jira/base_spec.rb +135 -98
  83. data/spec/jira/client_spec.rb +63 -47
  84. data/spec/jira/has_many_proxy_spec.rb +3 -3
  85. data/spec/jira/http_client_spec.rb +94 -27
  86. data/spec/jira/http_error_spec.rb +2 -2
  87. data/spec/jira/oauth_client_spec.rb +14 -8
  88. data/spec/jira/request_client_spec.rb +4 -4
  89. data/spec/jira/resource/agile_spec.rb +30 -30
  90. data/spec/jira/resource/attachment_spec.rb +170 -57
  91. data/spec/jira/resource/board_spec.rb +24 -23
  92. data/spec/jira/resource/createmeta_spec.rb +48 -48
  93. data/spec/jira/resource/field_spec.rb +44 -27
  94. data/spec/jira/resource/filter_spec.rb +4 -4
  95. data/spec/jira/resource/issue_picker_suggestions_spec.rb +17 -17
  96. data/spec/jira/resource/issue_spec.rb +49 -43
  97. data/spec/jira/resource/jira_picker_suggestions_issue_spec.rb +3 -3
  98. data/spec/jira/resource/project_factory_spec.rb +3 -2
  99. data/spec/jira/resource/project_spec.rb +14 -14
  100. data/spec/jira/resource/sprint_spec.rb +88 -9
  101. data/spec/jira/resource/status_spec.rb +21 -0
  102. data/spec/jira/resource/user_factory_spec.rb +5 -5
  103. data/spec/jira/resource/worklog_spec.rb +4 -4
  104. data/spec/mock_responses/sprint/1.json +13 -0
  105. data/spec/mock_responses/status/1.json +8 -1
  106. data/spec/mock_responses/status.json +40 -5
  107. data/spec/mock_responses/statuscategory/1.json +7 -0
  108. data/spec/mock_responses/statuscategory.json +30 -0
  109. data/spec/mock_responses/{user_username=admin.json → user_accountId=1234567890abcdef01234567.json} +2 -1
  110. data/spec/spec_helper.rb +1 -0
  111. data/spec/support/clients_helper.rb +3 -5
  112. data/spec/support/mock_client.rb +9 -0
  113. data/spec/support/mock_response.rb +8 -0
  114. data/spec/support/shared_examples/integration.rb +25 -28
  115. metadata +27 -260
  116. data/.travis.yml +0 -9
  117. data/example.rb +0 -232
  118. data/http-basic-example.rb +0 -113
  119. data/lib/jira/resource/sprint_report.rb +0 -8
  120. data/lib/jira/tasks.rb +0 -0
  121. data/spec/integration/webhook.rb +0 -25
  122. data/spec/jira/jwt_uri_builder_spec.rb +0 -59
@@ -9,127 +9,127 @@ describe JIRA::Resource::Agile do
9
9
  let(:response) { double }
10
10
 
11
11
  describe '#all' do
12
- it 'should query url without parameters' do
12
+ it 'queries url without parameters' do
13
13
  expect(client).to receive(:get).with('/jira/rest/agile/1.0/board').and_return(response)
14
14
  expect(response).to receive(:body).and_return(get_mock_response('board/1.json'))
15
15
 
16
- JIRA::Resource::Agile.all(client)
16
+ described_class.all(client)
17
17
  end
18
18
  end
19
19
 
20
20
  describe '#get_backlog_issues' do
21
- it 'should query the url without parameters' do
21
+ it 'queries the url without parameters' do
22
22
  expect(client).to receive(:get).with('/jira/rest/agile/1.0/board/1/backlog?maxResults=100').and_return(response)
23
23
  expect(response).to receive(:body).and_return(get_mock_response('board/1.json'))
24
24
 
25
- JIRA::Resource::Agile.get_backlog_issues(client, 1)
25
+ described_class.get_backlog_issues(client, 1)
26
26
  end
27
27
  end
28
28
 
29
29
  describe '#get_board_issues' do
30
- it 'should query correct url without parameters' do
30
+ it 'queries correct url without parameters' do
31
31
  expect(client).to receive(:get).with('/jira/rest/agile/1.0/board/1/issue?').and_return(response)
32
32
  expect(response).to receive(:body).and_return(get_mock_response('board/1_issues.json'))
33
33
 
34
34
  expect(client).to receive(:get).with('/jira/rest/api/2/search?jql=id+IN%2810546%2C+10547%2C+10556%2C+10557%2C+10558%2C+10559%2C+10600%2C+10601%2C+10604%29').and_return(response)
35
35
  expect(response).to receive(:body).and_return(get_mock_response('board/1_issues.json'))
36
36
 
37
- issues = JIRA::Resource::Agile.get_board_issues(client, 1)
37
+ issues = described_class.get_board_issues(client, 1)
38
38
  expect(issues).to be_an(Array)
39
- expect(issues.size).to eql(9)
39
+ expect(issues.size).to be(9)
40
40
 
41
41
  issues.each do |issue|
42
42
  expect(issue.class).to eq(JIRA::Resource::Issue)
43
- expect(issue.expanded?).to be_falsey
43
+ expect(issue).not_to be_expanded
44
44
  end
45
45
  end
46
46
 
47
- it 'should query correct url with parameters' do
47
+ it 'queries correct url with parameters' do
48
48
  expect(client).to receive(:get).with('/jira/rest/agile/1.0/board/1/issue?startAt=50').and_return(response)
49
49
  expect(response).to receive(:body).and_return(get_mock_response('board/1_issues.json'))
50
50
 
51
51
  expect(client).to receive(:get).with('/jira/rest/api/2/search?jql=id+IN%2810546%2C+10547%2C+10556%2C+10557%2C+10558%2C+10559%2C+10600%2C+10601%2C+10604%29').and_return(response)
52
52
  expect(response).to receive(:body).and_return(get_mock_response('board/1_issues.json'))
53
53
 
54
- issues = JIRA::Resource::Agile.get_board_issues(client, 1, startAt: 50)
54
+ issues = described_class.get_board_issues(client, 1, startAt: 50)
55
55
  expect(issues).to be_an(Array)
56
- expect(issues.size).to eql(9)
56
+ expect(issues.size).to be(9)
57
57
 
58
58
  issues.each do |issue|
59
59
  expect(issue.class).to eq(JIRA::Resource::Issue)
60
- expect(issue.expanded?).to be_falsey
60
+ expect(issue).not_to be_expanded
61
61
  end
62
62
  end
63
63
  end
64
64
 
65
65
  describe '#get_sprints' do
66
- it 'should query correct url without parameters' do
66
+ it 'queries correct url without parameters' do
67
67
  expect(client).to receive(:get).with('/jira/rest/agile/1.0/board/1/sprint?maxResults=100').and_return(response)
68
68
  expect(response).to receive(:body).and_return(get_mock_response('board/1.json'))
69
69
 
70
- JIRA::Resource::Agile.get_sprints(client, 1)
70
+ described_class.get_sprints(client, 1)
71
71
  end
72
72
 
73
- it 'should query correct url with parameters' do
73
+ it 'queries correct url with parameters' do
74
74
  expect(client).to receive(:get).with('/jira/rest/agile/1.0/board/1/sprint?startAt=50&maxResults=100').and_return(response)
75
75
  expect(response).to receive(:body).and_return(get_mock_response('board/1.json'))
76
76
 
77
- JIRA::Resource::Agile.get_sprints(client, 1, startAt: 50)
77
+ described_class.get_sprints(client, 1, startAt: 50)
78
78
  end
79
79
 
80
- it 'should work with pagination starting at 0' do
80
+ it 'works with pagination starting at 0' do
81
81
  expect(client).to receive(:get).with('/jira/rest/agile/1.0/board/1/sprint?maxResults=1&startAt=0').and_return(response)
82
82
  expect(response).to receive(:body).and_return(get_mock_response('board/1.json'))
83
83
 
84
- JIRA::Resource::Agile.get_sprints(client, 1, maxResults: 1, startAt: 0)
84
+ described_class.get_sprints(client, 1, maxResults: 1, startAt: 0)
85
85
  end
86
86
 
87
- it 'should work with pagination not starting at 0' do
87
+ it 'works with pagination not starting at 0' do
88
88
  expect(client).to receive(:get).with('/jira/rest/agile/1.0/board/1/sprint?maxResults=1&startAt=1').and_return(response)
89
89
  expect(response).to receive(:body).and_return(get_mock_response('board/1.json'))
90
90
 
91
- JIRA::Resource::Agile.get_sprints(client, 1, maxResults: 1, startAt: 1)
91
+ described_class.get_sprints(client, 1, maxResults: 1, startAt: 1)
92
92
  end
93
93
  end
94
94
 
95
95
  describe '#get_sprint_issues' do
96
- it 'should query correct url without parameters' do
96
+ it 'queries correct url without parameters' do
97
97
  expect(client).to receive(:get).with('/jira/rest/agile/1.0/sprint/1/issue?maxResults=100').and_return(response)
98
98
  expect(response).to receive(:body).and_return(get_mock_response('sprint/1_issues.json'))
99
99
 
100
- JIRA::Resource::Agile.get_sprint_issues(client, 1)
100
+ described_class.get_sprint_issues(client, 1)
101
101
  end
102
102
 
103
- it 'should query correct url with parameters' do
103
+ it 'queries correct url with parameters' do
104
104
  expect(client).to receive(:get).with('/jira/rest/agile/1.0/sprint/1/issue?startAt=50&maxResults=100').and_return(response)
105
105
  expect(response).to receive(:body).and_return(get_mock_response('sprint/1_issues.json'))
106
106
 
107
- JIRA::Resource::Agile.get_sprint_issues(client, 1, startAt: 50)
107
+ described_class.get_sprint_issues(client, 1, startAt: 50)
108
108
  end
109
109
  end
110
110
 
111
111
  describe '#get_projects_full' do
112
- it 'should query correct url without parameters' do
112
+ it 'queries correct url without parameters' do
113
113
  expect(client).to receive(:get).with('/jira/rest/agile/1.0/board/1/project/full').and_return(response)
114
114
  expect(response).to receive(:body).and_return(get_mock_response('board/1.json'))
115
115
 
116
- JIRA::Resource::Agile.get_projects_full(client, 1)
116
+ described_class.get_projects_full(client, 1)
117
117
  end
118
118
  end
119
119
 
120
120
  describe '#get_projects' do
121
- it 'should query correct url without parameters' do
121
+ it 'queries correct url without parameters' do
122
122
  expect(client).to receive(:get).with('/jira/rest/agile/1.0/board/1/project?maxResults=100').and_return(response)
123
123
  expect(response).to receive(:body).and_return(get_mock_response('board/1.json'))
124
124
 
125
- JIRA::Resource::Agile.get_projects(client, 1)
125
+ described_class.get_projects(client, 1)
126
126
  end
127
127
 
128
- it 'should query correct url with parameters' do
128
+ it 'queries correct url with parameters' do
129
129
  expect(client).to receive(:get).with('/jira/rest/agile/1.0/board/1/project?startAt=50&maxResults=100').and_return(response)
130
130
  expect(response).to receive(:body).and_return(get_mock_response('board/1.json'))
131
131
 
132
- JIRA::Resource::Agile.get_projects(client, 1, startAt: 50)
132
+ described_class.get_projects(client, 1, startAt: 50)
133
133
  end
134
134
  end
135
135
  end
@@ -2,13 +2,15 @@ require 'spec_helper'
2
2
 
3
3
  describe JIRA::Resource::Attachment do
4
4
  subject(:attachment) do
5
- JIRA::Resource::Attachment.new(
6
- client,
7
- issue: JIRA::Resource::Issue.new(client),
8
- attrs: { 'author' => { 'foo' => 'bar' } }
5
+ described_class.new(
6
+ client,
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',
@@ -35,22 +37,26 @@ describe JIRA::Resource::Attachment do
35
37
  end
36
38
 
37
39
  describe '.meta' do
38
- subject { JIRA::Resource::Attachment.meta(client) }
40
+ subject { described_class.meta(client) }
39
41
 
40
42
  let(:response) do
41
43
  double(
42
- 'response',
43
- body: '{"enabled":true,"uploadLimit":10485760}'
44
+ 'response',
45
+ body: '{"enabled":true,"uploadLimit":10485760}'
44
46
  )
45
47
  end
46
48
 
47
- it 'returns meta information about attachment upload' do
48
- expect(client).to receive(:get).with('/jira/rest/api/2/attachment/meta').and_return(response)
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)
52
+
53
+ result = subject
49
54
 
50
- subject
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,79 +65,186 @@ describe JIRA::Resource::Attachment do
59
65
  end
60
66
  end
61
67
 
62
- describe '#save' do
63
- subject { attachment.save('file' => path_to_file) }
64
- let(:path_to_file) { './spec/mock_responses/issue.json' }
65
- let(:response) do
66
- double(
67
- body: [
68
- {
69
- "id": 10_001,
70
- "self": 'http://www.example.com/jira/rest/api/2.0/attachments/10000',
71
- "filename": 'picture.jpg',
72
- "created": '2017-07-19T12:23:06.572+0000',
73
- "size": 23_123,
74
- "mimeType": 'image/jpeg'
75
- }
76
- ].to_json
68
+ context 'when there is an attachment on an issue' do
69
+ subject(:attachment) do
70
+ described_class.new(
71
+ client,
72
+ issue: JIRA::Resource::Issue.new(client),
73
+ attrs: { 'author' => { 'foo' => 'bar' }, 'content' => attachment_url }
77
74
  )
78
75
  end
79
- let(:issue) { JIRA::Resource::Issue.new(client) }
76
+
77
+ let(:attachment_url) { 'https://localhost:2990/secure/attachment/32323/myfile.txt' }
78
+ let(:client) do
79
+ JIRA::Client.new(username: 'username', password: 'password', auth_type: :basic, use_ssl: false)
80
+ end
81
+ let(:attachment_file_contents) { 'file contents' }
82
+ let(:issue_id) { 3232 }
83
+ let(:issue) { JIRA::Resource::Issue.new(client, attrs: { 'id' => issue_id }) }
80
84
 
81
85
  before do
82
- allow(client).to receive(:post_multipart).and_return(response)
86
+ stub_request(:get, attachment_url).to_return(body: attachment_file_contents)
83
87
  end
84
88
 
85
- it 'successfully update the attachment' do
86
- subject
89
+ describe '.download_file' do
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
87
93
 
88
- expect(attachment.filename).to eq 'picture.jpg'
89
- expect(attachment.mimeType).to eq 'image/jpeg'
90
- expect(attachment.size).to eq 23_123
94
+ attachment.download_file do |file|
95
+ expect(file.read).to eq(attachment_file_contents)
96
+ end
97
+ end
98
+ end
91
99
  end
92
- end
93
100
 
94
- describe '#save!' do
95
- subject { attachment.save!('file' => path_to_file) }
101
+ describe '.download_contents' do
102
+ it 'downloads the file contents as a string' do
103
+ expect(URI).to receive(:parse).with(attachment_url).and_call_original
104
+
105
+ expect(attachment.download_contents).to eq(attachment_file_contents)
106
+ end
107
+ end
108
+ end
96
109
 
97
- let(:path_to_file) { './spec/mock_responses/issue.json' }
110
+ context 'when there is a local file' do
111
+ let(:file_name) { 'short.txt' }
112
+ let(:file_size) { 11 }
113
+ let(:file_mime_type) { 'text/plain' }
114
+ let(:path_to_file) { "./spec/data/files/#{file_name}" }
98
115
  let(:response) do
99
116
  double(
100
117
  body: [
101
118
  {
102
- "id": 10_001,
103
- "self": 'http://www.example.com/jira/rest/api/2.0/attachments/10000',
104
- "filename": 'picture.jpg',
105
- "created": '2017-07-19T12:23:06.572+0000',
106
- "size": 23_123,
107
- "mimeType": 'image/jpeg'
119
+ id: 10_001,
120
+ self: 'http://www.example.com/jira/rest/api/2.0/attachments/10000',
121
+ filename: file_name,
122
+ created: '2017-07-19T12:23:06.572+0000',
123
+ size: file_size,
124
+ mimeType: file_mime_type
108
125
  }
109
126
  ].to_json
110
127
  )
111
128
  end
112
- let(:issue) { JIRA::Resource::Issue.new(client) }
129
+ let(:issue) { JIRA::Resource::Issue.new(client, attrs: { 'id' => issue_id }) }
113
130
 
114
- before do
115
- allow(client).to receive(:post_multipart).and_return(response)
116
- end
131
+ describe '#save' do
132
+ subject { attachment.save('file' => path_to_file) }
133
+
134
+ before do
135
+ allow(client).to receive(:post_multipart).and_return(response)
136
+ end
117
137
 
118
- it 'successfully update the attachment' do
119
- subject
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
+
141
+ subject
142
+
143
+ expect(attachment.filename).to eq file_name
144
+ expect(attachment.mimeType).to eq file_mime_type
145
+ expect(attachment.size).to eq file_size
146
+ end
147
+
148
+ context 'when using custom client headers' do
149
+ subject(:bearer_attachment) do
150
+ described_class.new(
151
+ bearer_client,
152
+ issue: JIRA::Resource::Issue.new(bearer_client),
153
+ attrs: { 'author' => { 'foo' => 'bar' } }
154
+ )
155
+ end
120
156
 
121
- expect(attachment.filename).to eq 'picture.jpg'
122
- expect(attachment.mimeType).to eq 'image/jpeg'
123
- expect(attachment.size).to eq 23_123
157
+ let(:default_headers_given) do
158
+ {
159
+ 'authorization' => 'Bearer 83CF8B609DE60036A8277BD0E96135751BBC07EB234256D4B65B893360651BF2'
160
+ }
161
+ end
162
+ let(:bearer_client) do
163
+ JIRA::Client.new(username: 'username', password: 'password', auth_type: :basic, use_ssl: false,
164
+ default_headers: default_headers_given)
165
+ end
166
+ let(:merged_headers) do
167
+ {
168
+ 'Accept' => 'application/json',
169
+ 'X-Atlassian-Token' => 'nocheck'
170
+ }.merge(default_headers_given)
171
+ end
172
+
173
+ it 'passes the custom headers' do
174
+ expect(bearer_client.request_client).to receive(:request_multipart)
175
+ .with(anything, anything, merged_headers)
176
+ .and_return(response)
177
+
178
+ bearer_attachment.save('file' => path_to_file)
179
+ end
180
+ end
124
181
  end
125
182
 
126
- context 'when passing in a symbol as file key' do
127
- subject { attachment.save!(file: path_to_file) }
183
+ describe '#save!' do
184
+ subject { attachment.save!('file' => path_to_file) }
185
+
186
+ before do
187
+ allow(client).to receive(:post_multipart).and_return(response)
188
+ end
128
189
 
129
190
  it 'successfully update the attachment' do
130
191
  subject
131
192
 
132
- expect(attachment.filename).to eq 'picture.jpg'
133
- expect(attachment.mimeType).to eq 'image/jpeg'
134
- expect(attachment.size).to eq 23_123
193
+ expect(attachment.filename).to eq file_name
194
+ expect(attachment.mimeType).to eq file_mime_type
195
+ expect(attachment.size).to eq file_size
196
+ end
197
+
198
+ context 'when passing in a symbol as file key' do
199
+ subject { attachment.save!(file: path_to_file) }
200
+
201
+ it 'successfully update the attachment' do
202
+ subject
203
+
204
+ expect(attachment.filename).to eq file_name
205
+ expect(attachment.mimeType).to eq file_mime_type
206
+ expect(attachment.size).to eq file_size
207
+ end
208
+ end
209
+
210
+ context 'when using custom client headers' do
211
+ subject(:bearer_attachment) do
212
+ described_class.new(
213
+ bearer_client,
214
+ issue: JIRA::Resource::Issue.new(bearer_client),
215
+ attrs: { 'author' => { 'foo' => 'bar' } }
216
+ )
217
+ end
218
+
219
+ let(:default_headers_given) { { 'authorization' => 'Bearer 83CF8B609DE60036A8277BD0E96135751BBC07EB234256D4B65B893360651BF2' } }
220
+ let(:bearer_client) do
221
+ JIRA::Client.new(username: 'username', password: 'password', auth_type: :basic, use_ssl: false,
222
+ default_headers: default_headers_given)
223
+ end
224
+ let(:merged_headers) do
225
+ {
226
+ 'Accept' => 'application/json',
227
+ 'X-Atlassian-Token' => 'nocheck'
228
+ }.merge(default_headers_given)
229
+ end
230
+
231
+ it 'passes the custom headers' do
232
+ expect(bearer_client.request_client).to receive(:request_multipart)
233
+ .with(anything, anything, merged_headers)
234
+ .and_return(response)
235
+
236
+ bearer_attachment.save!('file' => path_to_file)
237
+ end
238
+ end
239
+ end
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
135
248
  end
136
249
  end
137
250
  end
@@ -21,16 +21,16 @@ describe JIRA::Resource::Board do
21
21
  \"type\": \"scrum\"
22
22
  }"
23
23
  allow(response).to receive(:body).and_return(api_json_board)
24
- expect(client).to receive(:get).with('/rest/agile/1.0/board/84')
25
- .and_return(response)
24
+ allow(client).to receive(:get).with('/rest/agile/1.0/board/84')
25
+ .and_return(response)
26
26
 
27
- expect(client).to receive(:Board).and_return(JIRA::Resource::BoardFactory.new(client))
28
- JIRA::Resource::Board.find(client, '84')
27
+ allow(client).to receive(:Board).and_return(JIRA::Resource::BoardFactory.new(client))
28
+ described_class.find(client, '84')
29
29
  end
30
30
 
31
- it 'should find all boards' do
31
+ it 'finds all boards' do
32
32
  response = double
33
- api_json = <<eos
33
+ api_json = <<EOS
34
34
  {
35
35
  "maxResults": 50,
36
36
  "startAt": 0,
@@ -48,24 +48,24 @@ describe JIRA::Resource::Board do
48
48
  }
49
49
  ]
50
50
  }
51
- eos
51
+ EOS
52
52
  allow(response).to receive(:body).and_return(api_json)
53
53
  expect(client).to receive(:get).with('/rest/agile/1.0/board')
54
54
  .and_return(response)
55
55
  expect(client).to receive(:Board).twice.and_return(JIRA::Resource::BoardFactory.new(client))
56
- boards = JIRA::Resource::Board.all(client)
56
+ boards = described_class.all(client)
57
57
  expect(boards.count).to eq(2)
58
58
  end
59
59
 
60
- it 'should find one board by id' do
61
- expect(board).to be_a(JIRA::Resource::Board)
60
+ it 'finds one board by id' do
61
+ expect(board).to be_a(described_class)
62
62
  end
63
63
 
64
64
  describe '#issues' do
65
- it 'should find all issues' do
65
+ it 'finds all issues' do
66
66
  issues_response = double
67
67
 
68
- api_json_issues = <<eos
68
+ api_json_issues = <<EOS
69
69
  {
70
70
  "expand": "names,schema",
71
71
  "startAt": 0,
@@ -85,7 +85,7 @@ eos
85
85
  }
86
86
  ]
87
87
  }
88
- eos
88
+ EOS
89
89
 
90
90
  allow(issues_response).to receive(:body).and_return(api_json_issues)
91
91
  allow(board).to receive(:id).and_return(84)
@@ -98,6 +98,7 @@ eos
98
98
 
99
99
  describe 'pagination' do
100
100
  subject { described_class.new(client) }
101
+
101
102
  let(:client) { JIRA::Client.new }
102
103
 
103
104
  before do
@@ -106,7 +107,7 @@ eos
106
107
 
107
108
  context 'when there are multiple pages of results' do
108
109
  let(:result_1) do
109
- OpenStruct.new(body: {
110
+ double(body: {
110
111
  'startAt' => 0,
111
112
  'maxResults' => 1,
112
113
  'total' => 2,
@@ -114,7 +115,7 @@ eos
114
115
  }.to_json)
115
116
  end
116
117
  let(:result_2) do
117
- OpenStruct.new(body: {
118
+ double(body: {
118
119
  'startAt' => 1,
119
120
  'maxResults' => 1,
120
121
  'total' => 2,
@@ -131,7 +132,7 @@ eos
131
132
 
132
133
  context 'when there is only one page of results' do
133
134
  let(:result_1) do
134
- OpenStruct.new(body: {
135
+ double(body: {
135
136
  'startAt' => 0,
136
137
  'maxResults' => 2,
137
138
  'total' => 2,
@@ -147,10 +148,10 @@ eos
147
148
  end
148
149
  end
149
150
 
150
- it 'should get all sprints for a board' do
151
+ it 'gets all sprints for a board' do
151
152
  response = double
152
153
 
153
- api_json = <<-eos
154
+ api_json = <<-EOS
154
155
  {
155
156
  "values": [
156
157
  {
@@ -165,7 +166,7 @@ eos
165
166
  }
166
167
  ]
167
168
  }
168
- eos
169
+ EOS
169
170
  allow(response).to receive(:body).and_return(api_json)
170
171
  allow(board).to receive(:id).and_return(84)
171
172
  expect(client).to receive(:get).with('/rest/agile/1.0/board/84/sprint?').and_return(response)
@@ -173,10 +174,10 @@ eos
173
174
  expect(board.sprints.size).to be(2)
174
175
  end
175
176
 
176
- it 'should get board configuration for a board' do
177
+ it 'gets board configuration for a board' do
177
178
  response = double
178
179
 
179
- api_json = <<-eos
180
+ api_json = <<-EOS
180
181
  {
181
182
  "id":1,
182
183
  "name":"My Board",
@@ -214,11 +215,11 @@ eos
214
215
  "rankCustomFieldId":10011
215
216
  }
216
217
  }
217
- eos
218
+ EOS
218
219
  allow(response).to receive(:body).and_return(api_json)
219
220
  allow(board).to receive(:id).and_return(84)
220
221
  expect(client).to receive(:get).with('/rest/agile/1.0/board/84/configuration').and_return(response)
221
222
  expect(client).to receive(:BoardConfiguration).and_return(JIRA::Resource::BoardConfigurationFactory.new(client))
222
- expect(board.configuration).not_to be(nil)
223
+ expect(board.configuration).not_to be_nil
223
224
  end
224
225
  end