jira-ruby 2.1.3

Sign up to get free protection for your applications and to get access to all the features.
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