jira-ruby 2.1.3

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 (154) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +13 -0
  3. data/.travis.yml +9 -0
  4. data/Gemfile +14 -0
  5. data/Guardfile +14 -0
  6. data/LICENSE +19 -0
  7. data/README.md +427 -0
  8. data/Rakefile +31 -0
  9. data/example.rb +224 -0
  10. data/http-basic-example.rb +113 -0
  11. data/jira-ruby.gemspec +35 -0
  12. data/lib/jira-ruby.rb +49 -0
  13. data/lib/jira/base.rb +525 -0
  14. data/lib/jira/base_factory.rb +46 -0
  15. data/lib/jira/client.rb +308 -0
  16. data/lib/jira/has_many_proxy.rb +42 -0
  17. data/lib/jira/http_client.rb +112 -0
  18. data/lib/jira/http_error.rb +14 -0
  19. data/lib/jira/jwt_client.rb +67 -0
  20. data/lib/jira/oauth_client.rb +114 -0
  21. data/lib/jira/railtie.rb +10 -0
  22. data/lib/jira/request_client.rb +31 -0
  23. data/lib/jira/resource/agile.rb +79 -0
  24. data/lib/jira/resource/applinks.rb +39 -0
  25. data/lib/jira/resource/attachment.rb +50 -0
  26. data/lib/jira/resource/board.rb +91 -0
  27. data/lib/jira/resource/board_configuration.rb +9 -0
  28. data/lib/jira/resource/comment.rb +12 -0
  29. data/lib/jira/resource/component.rb +8 -0
  30. data/lib/jira/resource/createmeta.rb +44 -0
  31. data/lib/jira/resource/field.rb +83 -0
  32. data/lib/jira/resource/filter.rb +15 -0
  33. data/lib/jira/resource/issue.rb +141 -0
  34. data/lib/jira/resource/issuelink.rb +20 -0
  35. data/lib/jira/resource/issuelinktype.rb +14 -0
  36. data/lib/jira/resource/issuetype.rb +8 -0
  37. data/lib/jira/resource/priority.rb +8 -0
  38. data/lib/jira/resource/project.rb +41 -0
  39. data/lib/jira/resource/rapidview.rb +67 -0
  40. data/lib/jira/resource/remotelink.rb +26 -0
  41. data/lib/jira/resource/resolution.rb +8 -0
  42. data/lib/jira/resource/serverinfo.rb +18 -0
  43. data/lib/jira/resource/sprint.rb +105 -0
  44. data/lib/jira/resource/sprint_report.rb +8 -0
  45. data/lib/jira/resource/status.rb +8 -0
  46. data/lib/jira/resource/transition.rb +29 -0
  47. data/lib/jira/resource/user.rb +30 -0
  48. data/lib/jira/resource/version.rb +8 -0
  49. data/lib/jira/resource/watcher.rb +35 -0
  50. data/lib/jira/resource/webhook.rb +37 -0
  51. data/lib/jira/resource/worklog.rb +14 -0
  52. data/lib/jira/tasks.rb +0 -0
  53. data/lib/jira/version.rb +3 -0
  54. data/lib/tasks/generate.rake +18 -0
  55. data/spec/integration/attachment_spec.rb +32 -0
  56. data/spec/integration/comment_spec.rb +52 -0
  57. data/spec/integration/component_spec.rb +39 -0
  58. data/spec/integration/field_spec.rb +32 -0
  59. data/spec/integration/issue_spec.rb +93 -0
  60. data/spec/integration/issuelinktype_spec.rb +26 -0
  61. data/spec/integration/issuetype_spec.rb +24 -0
  62. data/spec/integration/priority_spec.rb +24 -0
  63. data/spec/integration/project_spec.rb +49 -0
  64. data/spec/integration/rapidview_spec.rb +74 -0
  65. data/spec/integration/resolution_spec.rb +26 -0
  66. data/spec/integration/status_spec.rb +24 -0
  67. data/spec/integration/transition_spec.rb +49 -0
  68. data/spec/integration/user_spec.rb +41 -0
  69. data/spec/integration/version_spec.rb +39 -0
  70. data/spec/integration/watcher_spec.rb +62 -0
  71. data/spec/integration/webhook.rb +25 -0
  72. data/spec/integration/worklog_spec.rb +51 -0
  73. data/spec/jira/base_factory_spec.rb +45 -0
  74. data/spec/jira/base_spec.rb +598 -0
  75. data/spec/jira/client_spec.rb +291 -0
  76. data/spec/jira/has_many_proxy_spec.rb +46 -0
  77. data/spec/jira/http_client_spec.rb +328 -0
  78. data/spec/jira/http_error_spec.rb +24 -0
  79. data/spec/jira/jwt_uri_builder_spec.rb +59 -0
  80. data/spec/jira/oauth_client_spec.rb +162 -0
  81. data/spec/jira/request_client_spec.rb +41 -0
  82. data/spec/jira/resource/agile_spec.rb +135 -0
  83. data/spec/jira/resource/attachment_spec.rb +138 -0
  84. data/spec/jira/resource/board_spec.rb +224 -0
  85. data/spec/jira/resource/createmeta_spec.rb +258 -0
  86. data/spec/jira/resource/field_spec.rb +85 -0
  87. data/spec/jira/resource/filter_spec.rb +97 -0
  88. data/spec/jira/resource/issue_spec.rb +227 -0
  89. data/spec/jira/resource/issuelink_spec.rb +14 -0
  90. data/spec/jira/resource/project_factory_spec.rb +11 -0
  91. data/spec/jira/resource/project_spec.rb +123 -0
  92. data/spec/jira/resource/sprint_spec.rb +90 -0
  93. data/spec/jira/resource/user_factory_spec.rb +31 -0
  94. data/spec/jira/resource/worklog_spec.rb +22 -0
  95. data/spec/mock_responses/board/1.json +33 -0
  96. data/spec/mock_responses/board/1_issues.json +62 -0
  97. data/spec/mock_responses/component.post.json +28 -0
  98. data/spec/mock_responses/component/10000.invalid.put.json +5 -0
  99. data/spec/mock_responses/component/10000.json +39 -0
  100. data/spec/mock_responses/component/10000.put.json +39 -0
  101. data/spec/mock_responses/empty_issues.json +8 -0
  102. data/spec/mock_responses/field.json +32 -0
  103. data/spec/mock_responses/field/1.json +15 -0
  104. data/spec/mock_responses/issue.json +1108 -0
  105. data/spec/mock_responses/issue.post.json +5 -0
  106. data/spec/mock_responses/issue/10002.invalid.put.json +6 -0
  107. data/spec/mock_responses/issue/10002.json +126 -0
  108. data/spec/mock_responses/issue/10002.put.missing_field_update.json +6 -0
  109. data/spec/mock_responses/issue/10002/attachments/10000.json +20 -0
  110. data/spec/mock_responses/issue/10002/comment.json +65 -0
  111. data/spec/mock_responses/issue/10002/comment.post.json +29 -0
  112. data/spec/mock_responses/issue/10002/comment/10000.json +29 -0
  113. data/spec/mock_responses/issue/10002/comment/10000.put.json +29 -0
  114. data/spec/mock_responses/issue/10002/transitions.json +49 -0
  115. data/spec/mock_responses/issue/10002/transitions.post.json +1 -0
  116. data/spec/mock_responses/issue/10002/watchers.json +13 -0
  117. data/spec/mock_responses/issue/10002/worklog.json +98 -0
  118. data/spec/mock_responses/issue/10002/worklog.post.json +30 -0
  119. data/spec/mock_responses/issue/10002/worklog/10000.json +31 -0
  120. data/spec/mock_responses/issue/10002/worklog/10000.put.json +30 -0
  121. data/spec/mock_responses/issueLinkType.json +25 -0
  122. data/spec/mock_responses/issueLinkType/10000.json +7 -0
  123. data/spec/mock_responses/issuetype.json +42 -0
  124. data/spec/mock_responses/issuetype/5.json +8 -0
  125. data/spec/mock_responses/jira/rest/webhooks/1.0/webhook.json +11 -0
  126. data/spec/mock_responses/jira/rest/webhooks/1.0/webhook/2.json +11 -0
  127. data/spec/mock_responses/priority.json +42 -0
  128. data/spec/mock_responses/priority/1.json +8 -0
  129. data/spec/mock_responses/project.json +12 -0
  130. data/spec/mock_responses/project/SAMPLEPROJECT.issues.json +1108 -0
  131. data/spec/mock_responses/project/SAMPLEPROJECT.json +84 -0
  132. data/spec/mock_responses/rapidview.json +10 -0
  133. data/spec/mock_responses/rapidview/SAMPLEPROJECT.issues.full.json +276 -0
  134. data/spec/mock_responses/rapidview/SAMPLEPROJECT.issues.json +111 -0
  135. data/spec/mock_responses/rapidview/SAMPLEPROJECT.json +6 -0
  136. data/spec/mock_responses/resolution.json +15 -0
  137. data/spec/mock_responses/resolution/1.json +7 -0
  138. data/spec/mock_responses/sprint/1_issues.json +125 -0
  139. data/spec/mock_responses/status.json +37 -0
  140. data/spec/mock_responses/status/1.json +7 -0
  141. data/spec/mock_responses/user_username=admin.json +17 -0
  142. data/spec/mock_responses/version.post.json +7 -0
  143. data/spec/mock_responses/version/10000.invalid.put.json +5 -0
  144. data/spec/mock_responses/version/10000.json +11 -0
  145. data/spec/mock_responses/version/10000.put.json +7 -0
  146. data/spec/mock_responses/webhook.json +11 -0
  147. data/spec/mock_responses/webhook/webhook.json +11 -0
  148. data/spec/spec_helper.rb +21 -0
  149. data/spec/support/clients_helper.rb +16 -0
  150. data/spec/support/matchers/have_attributes.rb +11 -0
  151. data/spec/support/matchers/have_many.rb +9 -0
  152. data/spec/support/matchers/have_one.rb +5 -0
  153. data/spec/support/shared_examples/integration.rb +177 -0
  154. metadata +491 -0
@@ -0,0 +1,85 @@
1
+ require 'spec_helper'
2
+
3
+ describe JIRA::Resource::Field do
4
+ let(:cache) { OpenStruct.new }
5
+
6
+ let(:client) do
7
+ client = double(options: { rest_base_path: '/jira/rest/api/2' })
8
+ field = JIRA::Resource::FieldFactory.new(client)
9
+ allow(client).to receive(:Field).and_return(field)
10
+ allow(client).to receive(:cache).and_return(cache)
11
+ # info about all fields on the client
12
+ allow(client.Field).to receive(:all).and_return([
13
+ JIRA::Resource::Field.new(client, attrs: { 'id' => 'customfield_10666', 'name' => 'Priority', 'custom' => true, 'orderable' => true, 'navigable' => true, 'searchable' => true, 'clauseNames' => ['cf[10666]', 'Priority'], 'schema' => { 'type' => 'string', 'custom' => 'com.atlassian.jira.plugin.system.customfieldtypes:select', 'customId' => 10_666 } }),
14
+ JIRA::Resource::Field.new(client, attrs: { 'id' => 'issuekey', 'name' => 'Key', 'custom' => false, 'orderable' => false, 'navigable' => true, 'searchable' => false, 'clauseNames' => %w[id issue issuekey key] }),
15
+ JIRA::Resource::Field.new(client, attrs: { 'id' => 'priority', 'name' => 'Priority', 'custom' => false, 'orderable' => true, 'navigable' => true, 'searchable' => true, 'clauseNames' => ['priority'], 'schema' => { 'type' => 'priority', 'system' => 'priority' } }),
16
+ JIRA::Resource::Field.new(client, attrs: { 'id' => 'summary', 'name' => 'Summary', 'custom' => false, 'orderable' => true, 'navigable' => true, 'searchable' => true, 'clauseNames' => ['summary'], 'schema' => { 'type' => 'string', 'system' => 'summary' } }),
17
+ JIRA::Resource::Field.new(client, attrs: { 'id' => 'issuetype', 'name' => 'Issue Type', 'custom' => false, 'orderable' => true, 'navigable' => true, 'searchable' => true, 'clauseNames' => %w[issuetype type], 'schema' => { 'type' => 'issuetype', 'system' => 'issuetype' } }),
18
+ JIRA::Resource::Field.new(client, attrs: { 'id' => 'customfield_10111', 'name' => 'SingleWord', 'custom' => true, 'orderable' => true, 'navigable' => true, 'searchable' => true, 'clauseNames' => ['cf[10111]', 'SingleWord'], 'schema' => { 'type' => 'string', 'custom' => 'com.atlassian.jira.plugin.system.customfieldtypes:select', 'customId' => 10_111 } }),
19
+ JIRA::Resource::Field.new(client, attrs: { 'id' => 'customfield_10222', 'name' => 'Multi Word', 'custom' => true, 'orderable' => true, 'navigable' => true, 'searchable' => true, 'clauseNames' => ['cf[10222]', 'Multi Word'], 'schema' => { 'type' => 'string', 'custom' => 'com.atlassian.jira.plugin.system.customfieldtypes:select', 'customId' => 10_222 } }),
20
+ JIRA::Resource::Field.new(client, attrs: { 'id' => 'customfield_10333', 'name' => 'Why/N@t', 'custom' => true, 'orderable' => true, 'navigable' => true, 'searchable' => true, 'clauseNames' => ['cf[10333]', 'Why/N@t'], 'schema' => { 'type' => 'string', 'custom' => 'com.atlassian.jira.plugin.system.customfieldtypes:select', 'customId' => 10_333 } }),
21
+ JIRA::Resource::Field.new(client, attrs: { 'id' => 'customfield_10444', 'name' => 'SingleWord', 'custom' => true, 'orderable' => true, 'navigable' => true, 'searchable' => true, 'clauseNames' => ['cf[10444]', 'SingleWord'], 'schema' => { 'type' => 'string', 'custom' => 'com.atlassian.jira.plugin.system.customfieldtypes:select', 'customId' => 10_444 } })
22
+ ])
23
+ client
24
+ end
25
+
26
+ describe 'field_mappings' do
27
+ shared_context 'mapped or not' do
28
+ subject do
29
+ JIRA::Resource::Field.new(client, attrs: {
30
+ 'priority' => 1,
31
+ 'customfield_10111' => 'data_in_custom_field',
32
+ 'customfield_10222' => 'multi word custom name',
33
+ 'customfield_10333' => 'complex custom name',
34
+ 'customfield_10444' => 'duplicated custom name',
35
+ 'customfield_10666' => 'duplicate of a system name'
36
+ })
37
+ end
38
+
39
+ it 'can find a standard field by id' do
40
+ expect(subject.priority).to eq(1)
41
+ end
42
+
43
+ it 'can find a custom field by customfield_##### name' do
44
+ expect(subject.customfield_10111).to eq('data_in_custom_field')
45
+ end
46
+
47
+ it 'is not confused by common attribute keys' do
48
+ expect { subject.name }.to raise_error(NoMethodError)
49
+ expect { subject.custom }.to raise_error(NoMethodError)
50
+ expect(subject.id).to eq(nil) # picks up ID from the parent -
51
+ end
52
+ end
53
+
54
+ context 'before fields are mapped' do
55
+ include_context 'mapped or not'
56
+
57
+ it 'can find a standard field by id' do
58
+ expect(subject.priority).to eq(1)
59
+ end
60
+
61
+ it 'cannot find a standard field by name before mapping' do
62
+ expect { subject.Priority }.to raise_error(NoMethodError)
63
+ end
64
+
65
+ it 'can find a custom field by customfield_##### name' do
66
+ expect(subject.customfield_10111).to eq('data_in_custom_field')
67
+ end
68
+
69
+ it 'is not confused by common attribute keys and raises error' do
70
+ expect { subject.name }.to raise_error(NoMethodError)
71
+ expect { subject.custom }.to raise_error(NoMethodError)
72
+ expect(subject.id).to eq(nil) # picks up ID from the parent -
73
+ end
74
+ end
75
+
76
+ context 'after fields are mapped' do
77
+ include_context 'mapped or not'
78
+
79
+ it 'warns of duplicate fields' do
80
+ expect { client.Field.map_fields }.to output(/renaming as Priority_10666/).to_stderr
81
+ expect { client.Field.map_fields }.to output(/renaming as SingleWord_10444/).to_stderr
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,97 @@
1
+ require 'spec_helper'
2
+
3
+ describe JIRA::Resource::Filter do
4
+ let(:client) do
5
+ client = double
6
+ allow(client).to receive(:Issue).and_return(JIRA::Resource::IssueFactory.new(self))
7
+ client
8
+ end
9
+ let(:collection_path) { '/rest/api/2/filter' }
10
+ let(:jira_user) do
11
+ {
12
+ self: 'https://localhost/rest/api/2/user?username=ljharb',
13
+ name: 'ljharb',
14
+ avatarUrls: {
15
+ '16x16' => 'https://localhost/secure/useravatar?size=small&ownerId=ljharb&avatarId=1',
16
+ '48x48' => 'https://localhost/secure/useravatar?ownerId=ljharb&avatarId=1'
17
+ },
18
+ displayName: 'Jordan Harband',
19
+ active: true
20
+ }
21
+ end
22
+ let(:filter_attrs) do
23
+ {
24
+ self: "https://localhost#{collection_path}/42",
25
+ id: 42,
26
+ name: 'Resolved Tickets',
27
+ description: '',
28
+ owner: jira_user,
29
+ jql: '"Git Repository" ~ jira-ruby AND status = Resolved',
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',
32
+ favourite: false,
33
+ sharePermissions: [
34
+ {
35
+ id: 123,
36
+ type: 'global'
37
+ }
38
+ ],
39
+ subscriptions: {
40
+ size: 0,
41
+ items: []
42
+ }
43
+ }
44
+ end
45
+ let(:filter_response) do
46
+ response = double
47
+ allow(response).to receive(:body).and_return(filter_attrs.to_json)
48
+ response
49
+ end
50
+ let(:filter) do
51
+ expect(client).to receive(:get).with("#{collection_path}/42").and_return(filter_response)
52
+ allow(JIRA::Resource::Filter).to receive(:collection_path).and_return(collection_path)
53
+ JIRA::Resource::Filter.find(client, 42)
54
+ end
55
+ let(:jql_issue) do
56
+ {
57
+ id: '663147',
58
+ self: 'https://localhost/rest/api/2/issue/663147',
59
+ key: 'JIRARUBY-2386',
60
+ fields: {
61
+ reporter: jira_user,
62
+ created: '2013-12-11T23:28:02.000+0000',
63
+ assignee: jira_user
64
+ }
65
+ }
66
+ end
67
+ let(:jql_attrs) do
68
+ {
69
+ startAt: 0,
70
+ maxResults: 50,
71
+ total: 2,
72
+ issues: [jql_issue]
73
+ }
74
+ end
75
+ let(:issue_jql_response) do
76
+ response = double
77
+ allow(response).to receive(:body).and_return(jql_attrs.to_json)
78
+ response
79
+ end
80
+
81
+ it 'can be found by ID' do
82
+ expect(JSON.parse(filter.attrs.to_json)).to eql(JSON.parse(filter_attrs.to_json))
83
+ end
84
+
85
+ it 'returns issues' do
86
+ expect(filter).to be_present
87
+ allow(client).to receive(:options).and_return(rest_base_path: 'localhost')
88
+ expect(client).to receive(:get)
89
+ .with("localhost/search?jql=#{CGI.escape(filter.jql)}")
90
+ .and_return(issue_jql_response)
91
+ issues = filter.issues
92
+ expect(issues).to be_an(Array)
93
+ expect(issues.size).to eql(1)
94
+ expected_issue = client.Issue.build(JSON.parse(jql_issue.to_json))
95
+ expect(issues.first.attrs).to eql(expected_issue.attrs)
96
+ end
97
+ end
@@ -0,0 +1,227 @@
1
+ require 'spec_helper'
2
+
3
+ describe JIRA::Resource::Issue do
4
+ class JIRAResourceDelegation < SimpleDelegator # :nodoc:
5
+ end
6
+
7
+ let(:client) do
8
+ client = double(options: { rest_base_path: '/jira/rest/api/2' })
9
+ allow(client).to receive(:Field).and_return(JIRA::Resource::FieldFactory.new(client))
10
+ allow(client).to receive(:cache).and_return(OpenStruct.new)
11
+ client
12
+ end
13
+
14
+ describe '#respond_to?' do
15
+ describe 'when decorated by SimpleDelegator' do
16
+ before(:each) do
17
+ response = double
18
+ allow(response).to receive(:body).and_return('{"key":"foo","id":"101"}')
19
+ allow(JIRA::Resource::Issue).to receive(:collection_path).and_return('/jira/rest/api/2/issue')
20
+ allow(client).to receive(:get).with('/jira/rest/api/2/issue/101')
21
+ .and_return(response)
22
+
23
+ issue = JIRA::Resource::Issue.find(client, 101)
24
+ @decorated = JIRAResourceDelegation.new(issue)
25
+ end
26
+ it 'responds to key' do
27
+ expect(@decorated.respond_to?(:key)).to eq(true)
28
+ end
29
+ it 'does not raise an error' do
30
+ expect do
31
+ @issue.respond_to?(:project)
32
+ end.not_to raise_error
33
+ end
34
+ end
35
+ end
36
+
37
+ it 'should find all issues' do
38
+ response = double
39
+ empty_response = double
40
+ issue = double
41
+
42
+ allow(response).to receive(:body).and_return('{"issues":[{"id":"1","summary":"Bugs Everywhere"}]}')
43
+ expect(client).to receive(:get).with('/jira/rest/api/2/search?expand=transitions.fields&maxResults=1000&startAt=0')
44
+ .and_return(response)
45
+ allow(empty_response).to receive(:body).and_return('{"issues":[]}')
46
+ expect(client).to receive(:get).with('/jira/rest/api/2/search?expand=transitions.fields&maxResults=1000&startAt=1')
47
+ .and_return(empty_response)
48
+
49
+ expect(client).to receive(:Issue).and_return(issue)
50
+ expect(issue).to receive(:build).with('id' => '1', 'summary' => 'Bugs Everywhere')
51
+
52
+ issues = JIRA::Resource::Issue.all(client)
53
+ end
54
+
55
+ it 'should find an issue by key or id' do
56
+ response = double
57
+
58
+ allow(response).to receive(:body).and_return('{"key":"foo","id":"101"}')
59
+ allow(JIRA::Resource::Issue).to receive(:collection_path).and_return('/jira/rest/api/2/issue')
60
+ expect(client).to receive(:get).with('/jira/rest/api/2/issue/foo')
61
+ .and_return(response)
62
+ expect(client).to receive(:get).with('/jira/rest/api/2/issue/101')
63
+ .and_return(response)
64
+
65
+ issue_from_id = JIRA::Resource::Issue.find(client, 101)
66
+ issue_from_key = JIRA::Resource::Issue.find(client, 'foo')
67
+
68
+ expect(issue_from_id.attrs).to eq(issue_from_key.attrs)
69
+ end
70
+
71
+ it 'should search an issue with a jql query string' do
72
+ response = double
73
+ issue = double
74
+
75
+ allow(response).to receive(:body).and_return('{"issues": {"key":"foo"}}')
76
+ expect(client).to receive(:get).with('/jira/rest/api/2/search?jql=foo+bar')
77
+ .and_return(response)
78
+ expect(client).to receive(:Issue).and_return(issue)
79
+ expect(issue).to receive(:build).with(%w[key foo]).and_return('')
80
+
81
+ expect(JIRA::Resource::Issue.jql(client, 'foo bar')).to eq([''])
82
+ end
83
+
84
+ it 'should search an issue with a jql query string and fields' do
85
+ response = double
86
+ issue = double
87
+
88
+ allow(response).to receive(:body).and_return('{"issues": {"key":"foo"}}')
89
+ expect(client).to receive(:get)
90
+ .with('/jira/rest/api/2/search?jql=foo+bar&fields=foo,bar')
91
+ .and_return(response)
92
+ expect(client).to receive(:Issue).and_return(issue)
93
+ expect(issue).to receive(:build).with(%w[key foo]).and_return('')
94
+
95
+ expect(JIRA::Resource::Issue.jql(client, 'foo bar', fields: %w[foo bar])).to eq([''])
96
+ end
97
+
98
+ it 'should search an issue with a jql query string, start at, and maxResults' do
99
+ response = double
100
+ issue = double
101
+
102
+ allow(response).to receive(:body).and_return('{"issues": {"key":"foo"}}')
103
+ expect(client).to receive(:get)
104
+ .with('/jira/rest/api/2/search?jql=foo+bar&startAt=1&maxResults=3')
105
+ .and_return(response)
106
+ expect(client).to receive(:Issue).and_return(issue)
107
+ expect(issue).to receive(:build).with(%w[key foo]).and_return('')
108
+
109
+ expect(JIRA::Resource::Issue.jql(client, 'foo bar', start_at: 1, max_results: 3)).to eq([''])
110
+ end
111
+
112
+ it 'should search an issue with a jql query string and maxResults equals zero and should return the count of tickets' do
113
+ response = double
114
+ issue = double
115
+
116
+ allow(response).to receive(:body).and_return('{"total": 1, "issues": []}')
117
+ expect(client).to receive(:get)
118
+ .with('/jira/rest/api/2/search?jql=foo+bar&maxResults=0')
119
+ .and_return(response)
120
+
121
+ expect(JIRA::Resource::Issue.jql(client, 'foo bar', max_results: 0)).to eq(1)
122
+ end
123
+
124
+ it 'should search an issue with a jql query string and string expand' do
125
+ response = double
126
+ issue = double
127
+
128
+ allow(response).to receive(:body).and_return('{"issues": {"key":"foo"}}')
129
+ expect(client).to receive(:get)
130
+ .with('/jira/rest/api/2/search?jql=foo+bar&expand=transitions')
131
+ .and_return(response)
132
+ expect(client).to receive(:Issue).and_return(issue)
133
+ expect(issue).to receive(:build).with(%w[key foo]).and_return('')
134
+
135
+ expect(JIRA::Resource::Issue.jql(client, 'foo bar', expand: 'transitions')).to eq([''])
136
+ end
137
+
138
+ it 'should search an issue with a jql query string and array expand' do
139
+ response = double
140
+ issue = double
141
+
142
+ allow(response).to receive(:body).and_return('{"issues": {"key":"foo"}}')
143
+ expect(client).to receive(:get)
144
+ .with('/jira/rest/api/2/search?jql=foo+bar&expand=transitions')
145
+ .and_return(response)
146
+ expect(client).to receive(:Issue).and_return(issue)
147
+ expect(issue).to receive(:build).with(%w[key foo]).and_return('')
148
+
149
+ expect(JIRA::Resource::Issue.jql(client, 'foo bar', expand: %w[transitions])).to eq([''])
150
+ end
151
+
152
+ it 'should return meta data available for editing an issue' do
153
+ subject = JIRA::Resource::Issue.new(client, attrs: { 'fields' => { 'key' => 'TST=123' } })
154
+ response = double
155
+
156
+ allow(response).to receive(:body).and_return(
157
+ '{"fields":{"summary":{"required":true,"name":"Summary","operations":["set"]}}}'
158
+ )
159
+ expect(client).to receive(:get)
160
+ .with('/jira/rest/api/2/issue/TST=123/editmeta')
161
+ .and_return(response)
162
+
163
+ expect(subject.editmeta).to eq('summary' => { 'required' => true, 'name' => 'Summary', 'operations' => ['set'] })
164
+ end
165
+
166
+ it 'provides direct accessors to the fields' do
167
+ subject = JIRA::Resource::Issue.new(client, attrs: { 'fields' => { 'foo' => 'bar' } })
168
+ expect(subject).to respond_to(:foo)
169
+ expect(subject.foo).to eq('bar')
170
+ end
171
+
172
+ describe 'relationships' do
173
+ subject do
174
+ JIRA::Resource::Issue.new(client, attrs: {
175
+ 'id' => '123',
176
+ 'fields' => {
177
+ 'reporter' => { 'foo' => 'bar' },
178
+ 'assignee' => { 'foo' => 'bar' },
179
+ 'project' => { 'foo' => 'bar' },
180
+ 'priority' => { 'foo' => 'bar' },
181
+ 'issuetype' => { 'foo' => 'bar' },
182
+ 'status' => { 'foo' => 'bar' },
183
+ 'components' => [{ 'foo' => 'bar' }, { 'baz' => 'flum' }],
184
+ 'versions' => [{ 'foo' => 'bar' }, { 'baz' => 'flum' }],
185
+ 'comment' => { 'comments' => [{ 'foo' => 'bar' }, { 'baz' => 'flum' }] },
186
+ 'attachment' => [{ 'foo' => 'bar' }, { 'baz' => 'flum' }],
187
+ 'worklog' => { 'worklogs' => [{ 'foo' => 'bar' }, { 'baz' => 'flum' }] }
188
+ }
189
+ })
190
+ end
191
+
192
+ it 'has the correct relationships' do
193
+ expect(subject).to have_one(:reporter, JIRA::Resource::User)
194
+ expect(subject.reporter.foo).to eq('bar')
195
+
196
+ expect(subject).to have_one(:assignee, JIRA::Resource::User)
197
+ expect(subject.assignee.foo).to eq('bar')
198
+
199
+ expect(subject).to have_one(:project, JIRA::Resource::Project)
200
+ expect(subject.project.foo).to eq('bar')
201
+
202
+ expect(subject).to have_one(:issuetype, JIRA::Resource::Issuetype)
203
+ expect(subject.issuetype.foo).to eq('bar')
204
+
205
+ expect(subject).to have_one(:priority, JIRA::Resource::Priority)
206
+ expect(subject.priority.foo).to eq('bar')
207
+
208
+ expect(subject).to have_one(:status, JIRA::Resource::Status)
209
+ expect(subject.status.foo).to eq('bar')
210
+
211
+ expect(subject).to have_many(:components, JIRA::Resource::Component)
212
+ expect(subject.components.length).to eq(2)
213
+
214
+ expect(subject).to have_many(:comments, JIRA::Resource::Comment)
215
+ expect(subject.comments.length).to eq(2)
216
+
217
+ expect(subject).to have_many(:attachments, JIRA::Resource::Attachment)
218
+ expect(subject.attachments.length).to eq(2)
219
+
220
+ expect(subject).to have_many(:versions, JIRA::Resource::Version)
221
+ expect(subject.attachments.length).to eq(2)
222
+
223
+ expect(subject).to have_many(:worklogs, JIRA::Resource::Worklog)
224
+ expect(subject.worklogs.length).to eq(2)
225
+ end
226
+ end
227
+ end
@@ -0,0 +1,14 @@
1
+ # require 'spec_helper'
2
+ #
3
+ # describe JIRA::Resource::Issuelink do
4
+ # let(:client) { double() }
5
+ #
6
+ # describe "links" do
7
+ # subject {
8
+ # JIRA::Resource::Issuelink.new(client, :attrs => {
9
+ #
10
+ # }
11
+ # )
12
+ # }
13
+ # end
14
+ # end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe JIRA::Resource::ProjectFactory do
4
+ let(:client) { double }
5
+ subject { JIRA::Resource::ProjectFactory.new(client) }
6
+
7
+ it 'initializes correctly' do
8
+ expect(subject.class).to eq(JIRA::Resource::ProjectFactory)
9
+ expect(subject.client).to eq(client)
10
+ end
11
+ end
@@ -0,0 +1,123 @@
1
+ require 'spec_helper'
2
+
3
+ describe JIRA::Resource::Project do
4
+ let(:client) do
5
+ double('client', options: {
6
+ rest_base_path: '/jira/rest/api/2'
7
+ })
8
+ end
9
+
10
+ describe 'relationships' do
11
+ subject do
12
+ JIRA::Resource::Project.new(client, attrs: {
13
+ 'lead' => { 'foo' => 'bar' },
14
+ 'issueTypes' => [{ 'foo' => 'bar' }, { 'baz' => 'flum' }],
15
+ 'versions' => [{ 'foo' => 'bar' }, { 'baz' => 'flum' }]
16
+ })
17
+ end
18
+
19
+ it 'has the correct relationships' do
20
+ expect(subject).to have_one(:lead, JIRA::Resource::User)
21
+ expect(subject.lead.foo).to eq('bar')
22
+
23
+ expect(subject).to have_many(:issuetypes, JIRA::Resource::Issuetype)
24
+ expect(subject.issuetypes.length).to eq(2)
25
+
26
+ expect(subject).to have_many(:versions, JIRA::Resource::Version)
27
+ expect(subject.versions.length).to eq(2)
28
+ end
29
+ end
30
+
31
+ describe 'issues' do
32
+ subject do
33
+ JIRA::Resource::Project.new(client, attrs: {
34
+ 'key' => 'test'
35
+ })
36
+ end
37
+
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"}}]}'
40
+ response = double('response',
41
+ body: response_body)
42
+ issue_factory = double('issue factory')
43
+
44
+ expect(client).to receive(:get)
45
+ .with('/jira/rest/api/2/search?jql=project%3D%22test%22')
46
+ .and_return(response)
47
+ expect(client).to receive(:Issue).and_return(issue_factory)
48
+ expect(issue_factory).to receive(:build)
49
+ .with(JSON.parse(response_body)['issues'][0])
50
+ subject.issues
51
+ end
52
+
53
+ context 'with changelog' do
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":{}}]}'
56
+ response = double('response',
57
+ body: response_body)
58
+ issue_factory = double('issue factory')
59
+
60
+ expect(client).to receive(:get)
61
+ .with('/jira/rest/api/2/search?jql=project%3D%22test%22&expand=changelog&startAt=1&maxResults=100')
62
+ .and_return(response)
63
+ expect(client).to receive(:Issue).and_return(issue_factory)
64
+ expect(issue_factory).to receive(:build)
65
+ .with(JSON.parse(response_body)['issues'][0])
66
+ subject.issues(expand: 'changelog', startAt: 1, maxResults: 100)
67
+ end
68
+ end
69
+ end
70
+
71
+ describe 'users' do
72
+ let(:project) { JIRA::Resource::Project.new(client, attrs: { 'key' => project_key }) }
73
+ let(:project_key) { SecureRandom.hex }
74
+ let(:response) { double('response', body: '[{}]') }
75
+
76
+ context 'pagination' do
77
+ before(:each) do
78
+ user_factory = double('user factory')
79
+ expect(client).to receive(:User).and_return(user_factory)
80
+ expect(user_factory).to receive(:build).with(any_args)
81
+ end
82
+
83
+ it 'doesn\'t use pagination parameters by default' do
84
+ expect(client).to receive(:get)
85
+ .with("/jira/rest/api/2/user/assignable/search?project=#{project_key}")
86
+ .and_return(response)
87
+
88
+ project.users
89
+ end
90
+
91
+ it 'accepts start_at option' do
92
+ start_at = rand(1000)
93
+
94
+ expect(client).to receive(:get)
95
+ .with("/jira/rest/api/2/user/assignable/search?project=#{project_key}&startAt=#{start_at}")
96
+ .and_return(response)
97
+
98
+ project.users(start_at: start_at)
99
+ end
100
+
101
+ it 'accepts max_results option' do
102
+ max_results = rand(1000)
103
+
104
+ expect(client).to receive(:get)
105
+ .with("/jira/rest/api/2/user/assignable/search?project=#{project_key}&maxResults=#{max_results}")
106
+ .and_return(response)
107
+
108
+ project.users(max_results: max_results)
109
+ end
110
+
111
+ it 'accepts start_at and max_results options' do
112
+ start_at = rand(1000)
113
+ max_results = rand(1000)
114
+
115
+ expect(client).to receive(:get)
116
+ .with("/jira/rest/api/2/user/assignable/search?project=#{project_key}&startAt=#{start_at}&maxResults=#{max_results}")
117
+ .and_return(response)
118
+
119
+ project.users(start_at: start_at, max_results: max_results)
120
+ end
121
+ end
122
+ end
123
+ end