jira-ruby 2.2.0 → 3.0.0.beta1

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 (117) 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 +28 -0
  6. data/.github/workflows/codeql.yml +100 -0
  7. data/.github/workflows/rubocop.yml +18 -0
  8. data/.rubocop.yml +188 -0
  9. data/Gemfile +11 -3
  10. data/Guardfile +2 -0
  11. data/README.md +121 -20
  12. data/Rakefile +4 -5
  13. data/jira-ruby.gemspec +11 -17
  14. data/lib/jira/base.rb +37 -28
  15. data/lib/jira/base_factory.rb +4 -1
  16. data/lib/jira/client.rb +65 -46
  17. data/lib/jira/has_many_proxy.rb +4 -2
  18. data/lib/jira/http_client.rb +18 -13
  19. data/lib/jira/http_error.rb +4 -0
  20. data/lib/jira/jwt_client.rb +18 -42
  21. data/lib/jira/oauth_client.rb +6 -3
  22. data/lib/jira/railtie.rb +2 -0
  23. data/lib/jira/request_client.rb +5 -1
  24. data/lib/jira/resource/agile.rb +7 -9
  25. data/lib/jira/resource/applinks.rb +5 -3
  26. data/lib/jira/resource/attachment.rb +43 -3
  27. data/lib/jira/resource/board.rb +5 -3
  28. data/lib/jira/resource/board_configuration.rb +2 -0
  29. data/lib/jira/resource/comment.rb +2 -0
  30. data/lib/jira/resource/component.rb +2 -0
  31. data/lib/jira/resource/createmeta.rb +3 -1
  32. data/lib/jira/resource/field.rb +9 -4
  33. data/lib/jira/resource/filter.rb +2 -0
  34. data/lib/jira/resource/issue.rb +35 -44
  35. data/lib/jira/resource/issue_picker_suggestions.rb +4 -1
  36. data/lib/jira/resource/issue_picker_suggestions_issue.rb +2 -0
  37. data/lib/jira/resource/issuelink.rb +2 -0
  38. data/lib/jira/resource/issuelinktype.rb +2 -0
  39. data/lib/jira/resource/issuetype.rb +2 -0
  40. data/lib/jira/resource/priority.rb +2 -0
  41. data/lib/jira/resource/project.rb +4 -2
  42. data/lib/jira/resource/rapidview.rb +5 -3
  43. data/lib/jira/resource/remotelink.rb +2 -0
  44. data/lib/jira/resource/resolution.rb +2 -0
  45. data/lib/jira/resource/serverinfo.rb +2 -0
  46. data/lib/jira/resource/sprint.rb +14 -23
  47. data/lib/jira/resource/status.rb +7 -1
  48. data/lib/jira/resource/status_category.rb +10 -0
  49. data/lib/jira/resource/suggested_issue.rb +2 -0
  50. data/lib/jira/resource/transition.rb +2 -0
  51. data/lib/jira/resource/user.rb +3 -1
  52. data/lib/jira/resource/version.rb +2 -0
  53. data/lib/jira/resource/watcher.rb +2 -1
  54. data/lib/jira/resource/webhook.rb +4 -2
  55. data/lib/jira/resource/worklog.rb +3 -2
  56. data/lib/jira/version.rb +3 -1
  57. data/lib/jira-ruby.rb +5 -3
  58. data/lib/tasks/generate.rake +4 -2
  59. data/spec/data/files/short.txt +1 -0
  60. data/spec/integration/attachment_spec.rb +3 -3
  61. data/spec/integration/comment_spec.rb +8 -8
  62. data/spec/integration/component_spec.rb +7 -7
  63. data/spec/integration/field_spec.rb +3 -3
  64. data/spec/integration/issue_spec.rb +20 -16
  65. data/spec/integration/issuelinktype_spec.rb +3 -3
  66. data/spec/integration/issuetype_spec.rb +3 -3
  67. data/spec/integration/priority_spec.rb +3 -3
  68. data/spec/integration/project_spec.rb +7 -7
  69. data/spec/integration/rapidview_spec.rb +9 -9
  70. data/spec/integration/resolution_spec.rb +3 -3
  71. data/spec/integration/status_category_spec.rb +20 -0
  72. data/spec/integration/status_spec.rb +4 -8
  73. data/spec/integration/transition_spec.rb +2 -2
  74. data/spec/integration/user_spec.rb +22 -8
  75. data/spec/integration/version_spec.rb +7 -7
  76. data/spec/integration/watcher_spec.rb +17 -18
  77. data/spec/integration/webhook.rb +5 -4
  78. data/spec/integration/worklog_spec.rb +8 -8
  79. data/spec/jira/base_factory_spec.rb +2 -1
  80. data/spec/jira/base_spec.rb +55 -41
  81. data/spec/jira/client_spec.rb +48 -34
  82. data/spec/jira/has_many_proxy_spec.rb +3 -3
  83. data/spec/jira/http_client_spec.rb +98 -26
  84. data/spec/jira/http_error_spec.rb +2 -2
  85. data/spec/jira/oauth_client_spec.rb +30 -8
  86. data/spec/jira/request_client_spec.rb +4 -4
  87. data/spec/jira/resource/agile_spec.rb +28 -28
  88. data/spec/jira/resource/attachment_spec.rb +142 -52
  89. data/spec/jira/resource/board_spec.rb +21 -20
  90. data/spec/jira/resource/createmeta_spec.rb +48 -48
  91. data/spec/jira/resource/field_spec.rb +30 -12
  92. data/spec/jira/resource/filter_spec.rb +4 -4
  93. data/spec/jira/resource/issue_picker_suggestions_spec.rb +18 -18
  94. data/spec/jira/resource/issue_spec.rb +44 -38
  95. data/spec/jira/resource/jira_picker_suggestions_issue_spec.rb +3 -3
  96. data/spec/jira/resource/project_factory_spec.rb +3 -2
  97. data/spec/jira/resource/project_spec.rb +16 -16
  98. data/spec/jira/resource/sprint_spec.rb +70 -3
  99. data/spec/jira/resource/status_spec.rb +21 -0
  100. data/spec/jira/resource/user_factory_spec.rb +4 -4
  101. data/spec/jira/resource/worklog_spec.rb +3 -3
  102. data/spec/mock_responses/sprint/1.json +13 -0
  103. data/spec/mock_responses/status/1.json +8 -1
  104. data/spec/mock_responses/status.json +40 -5
  105. data/spec/mock_responses/statuscategory/1.json +7 -0
  106. data/spec/mock_responses/statuscategory.json +30 -0
  107. data/spec/mock_responses/{user_username=admin.json → user_accountId=1234567890abcdef01234567.json} +2 -1
  108. data/spec/spec_helper.rb +1 -0
  109. data/spec/support/clients_helper.rb +3 -5
  110. data/spec/support/shared_examples/integration.rb +25 -28
  111. metadata +25 -257
  112. data/.travis.yml +0 -9
  113. data/example.rb +0 -232
  114. data/http-basic-example.rb +0 -113
  115. data/lib/jira/resource/sprint_report.rb +0 -8
  116. data/lib/jira/tasks.rb +0 -0
  117. data/spec/jira/jwt_uri_builder_spec.rb +0 -59
@@ -10,15 +10,33 @@ describe JIRA::Resource::Field do
10
10
  allow(client).to receive(:cache).and_return(cache)
11
11
  # info about all fields on the client
12
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 } })
13
+ described_class.new(client,
14
+ attrs: { 'id' => 'customfield_10666', 'name' => 'Priority', 'custom' => true, 'orderable' => true, 'navigable' => true,
15
+ 'searchable' => true, 'clauseNames' => ['cf[10666]', 'Priority'], 'schema' => { 'type' => 'string', 'custom' => 'com.atlassian.jira.plugin.system.customfieldtypes:select', 'customId' => 10_666 } }),
16
+ described_class.new(client,
17
+ attrs: { 'id' => 'issuekey', 'name' => 'Key', 'custom' => false, 'orderable' => false,
18
+ 'navigable' => true, 'searchable' => false, 'clauseNames' => %w[id issue issuekey key] }),
19
+ described_class.new(client,
20
+ attrs: { 'id' => 'priority', 'name' => 'Priority', 'custom' => false, 'orderable' => true,
21
+ 'navigable' => true, 'searchable' => true, 'clauseNames' => ['priority'], 'schema' => { 'type' => 'priority', 'system' => 'priority' } }),
22
+ described_class.new(client,
23
+ attrs: { 'id' => 'summary', 'name' => 'Summary', 'custom' => false, 'orderable' => true,
24
+ 'navigable' => true, 'searchable' => true, 'clauseNames' => ['summary'], 'schema' => { 'type' => 'string', 'system' => 'summary' } }),
25
+ described_class.new(client,
26
+ attrs: { 'id' => 'issuetype', 'name' => 'Issue Type', 'custom' => false, 'orderable' => true,
27
+ 'navigable' => true, 'searchable' => true, 'clauseNames' => %w[issuetype type], 'schema' => { 'type' => 'issuetype', 'system' => 'issuetype' } }),
28
+ described_class.new(client,
29
+ attrs: { 'id' => 'customfield_10111', 'name' => 'SingleWord', 'custom' => true, 'orderable' => true,
30
+ 'navigable' => true, 'searchable' => true, 'clauseNames' => ['cf[10111]', 'SingleWord'], 'schema' => { 'type' => 'string', 'custom' => 'com.atlassian.jira.plugin.system.customfieldtypes:select', 'customId' => 10_111 } }),
31
+ described_class.new(client,
32
+ attrs: { 'id' => 'customfield_10222', 'name' => 'Multi Word', 'custom' => true, 'orderable' => true,
33
+ 'navigable' => true, 'searchable' => true, 'clauseNames' => ['cf[10222]', 'Multi Word'], 'schema' => { 'type' => 'string', 'custom' => 'com.atlassian.jira.plugin.system.customfieldtypes:select', 'customId' => 10_222 } }),
34
+ described_class.new(client,
35
+ attrs: { 'id' => 'customfield_10333', 'name' => 'Why/N@t', 'custom' => true, 'orderable' => true,
36
+ '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
+ described_class.new(client,
38
+ attrs: { 'id' => 'customfield_10444', 'name' => 'SingleWord', 'custom' => true, 'orderable' => true,
39
+ 'navigable' => true, 'searchable' => true, 'clauseNames' => ['cf[10444]', 'SingleWord'], 'schema' => { 'type' => 'string', 'custom' => 'com.atlassian.jira.plugin.system.customfieldtypes:select', 'customId' => 10_444 } })
22
40
  ])
23
41
  client
24
42
  end
@@ -26,14 +44,14 @@ describe JIRA::Resource::Field do
26
44
  describe 'field_mappings' do
27
45
  shared_context 'mapped or not' do
28
46
  subject do
29
- JIRA::Resource::Field.new(client, attrs: {
30
- 'priority' => 1,
47
+ described_class.new(client, attrs: {
48
+ 'priority' => 1,
31
49
  'customfield_10111' => 'data_in_custom_field',
32
50
  'customfield_10222' => 'multi word custom name',
33
51
  'customfield_10333' => 'complex custom name',
34
52
  'customfield_10444' => 'duplicated custom name',
35
53
  'customfield_10666' => 'duplicate of a system name'
36
- })
54
+ })
37
55
  end
38
56
 
39
57
  it 'can find a standard field by id' do
@@ -48,9 +48,9 @@ describe JIRA::Resource::Filter do
48
48
  response
49
49
  end
50
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)
51
+ allow(client).to receive(:get).with("#{collection_path}/42").and_return(filter_response)
52
+ allow(described_class).to receive(:collection_path).and_return(collection_path)
53
+ described_class.find(client, 42)
54
54
  end
55
55
  let(:jql_issue) do
56
56
  {
@@ -90,7 +90,7 @@ describe JIRA::Resource::Filter do
90
90
  .and_return(issue_jql_response)
91
91
  issues = filter.issues
92
92
  expect(issues).to be_an(Array)
93
- expect(issues.size).to eql(1)
93
+ expect(issues.size).to be(1)
94
94
  expected_issue = client.Issue.build(JSON.parse(jql_issue.to_json))
95
95
  expect(issues.first.attrs).to eql(expected_issue.attrs)
96
96
  end
@@ -3,15 +3,15 @@ require 'spec_helper'
3
3
  describe JIRA::Resource::IssuePickerSuggestions do
4
4
  let(:client) do
5
5
  double('client', options: {
6
- rest_base_path: '/jira/rest/api/2'
7
- })
6
+ rest_base_path: '/jira/rest/api/2'
7
+ })
8
8
  end
9
9
 
10
10
  describe 'relationships' do
11
11
  subject do
12
- JIRA::Resource::IssuePickerSuggestions.new(client, attrs: {
13
- 'sections' => [{ 'id' => 'hs'}, { 'id' => 'cs' }]
14
- })
12
+ described_class.new(client, attrs: {
13
+ 'sections' => [{ 'id' => 'hs' }, { 'id' => 'cs' }]
14
+ })
15
15
  end
16
16
 
17
17
  it 'has the correct relationships' do
@@ -30,50 +30,50 @@ describe JIRA::Resource::IssuePickerSuggestions do
30
30
  allow(issue_picker_suggestions).to receive(:build)
31
31
  end
32
32
 
33
- it 'should autocomplete issues' do
33
+ it 'autocompletes issues' do
34
34
  allow(response).to receive(:body).and_return('{"sections":[{"id": "cs"}]}')
35
35
  expect(client).to receive(:get).with('/jira/rest/api/2/issue/picker?query=query')
36
36
  .and_return(response)
37
37
 
38
38
  expect(client).to receive(:IssuePickerSuggestions).and_return(issue_picker_suggestions)
39
- expect(issue_picker_suggestions).to receive(:build).with('sections' => [{ 'id' => 'cs' }])
39
+ expect(issue_picker_suggestions).to receive(:build).with({ 'sections' => [{ 'id' => 'cs' }] })
40
40
 
41
- JIRA::Resource::IssuePickerSuggestions.all(client, 'query')
41
+ described_class.all(client, 'query')
42
42
  end
43
43
 
44
- it 'should autocomplete issues with current jql' do
44
+ it 'autocompletes issues with current jql' do
45
45
  expect(client).to receive(:get).with('/jira/rest/api/2/issue/picker?query=query&currentJQL=project+%3D+PR')
46
46
  .and_return(response)
47
47
 
48
- JIRA::Resource::IssuePickerSuggestions.all(client, 'query', current_jql: 'project = PR')
48
+ described_class.all(client, 'query', current_jql: 'project = PR')
49
49
  end
50
50
 
51
- it 'should autocomplete issues with current issue jey' do
51
+ it 'autocompletes issues with current issue jey' do
52
52
  expect(client).to receive(:get).with('/jira/rest/api/2/issue/picker?query=query&currentIssueKey=PR-42')
53
53
  .and_return(response)
54
54
 
55
- JIRA::Resource::IssuePickerSuggestions.all(client, 'query', current_issue_key: 'PR-42')
55
+ described_class.all(client, 'query', current_issue_key: 'PR-42')
56
56
  end
57
57
 
58
- it 'should autocomplete issues with current project id' do
58
+ it 'autocompletes issues with current project id' do
59
59
  expect(client).to receive(:get).with('/jira/rest/api/2/issue/picker?query=query&currentProjectId=PR')
60
60
  .and_return(response)
61
61
 
62
- JIRA::Resource::IssuePickerSuggestions.all(client, 'query', current_project_id: 'PR')
62
+ described_class.all(client, 'query', current_project_id: 'PR')
63
63
  end
64
64
 
65
- it 'should autocomplete issues with show sub tasks' do
65
+ it 'autocompletes issues with show sub tasks' do
66
66
  expect(client).to receive(:get).with('/jira/rest/api/2/issue/picker?query=query&showSubTasks=true')
67
67
  .and_return(response)
68
68
 
69
- JIRA::Resource::IssuePickerSuggestions.all(client, 'query', show_sub_tasks: true)
69
+ described_class.all(client, 'query', show_sub_tasks: true)
70
70
  end
71
71
 
72
- it 'should autocomplete issues with show sub tasks parent' do
72
+ it 'autocompletes issues with show sub tasks parent' do
73
73
  expect(client).to receive(:get).with('/jira/rest/api/2/issue/picker?query=query&showSubTaskParent=true')
74
74
  .and_return(response)
75
75
 
76
- JIRA::Resource::IssuePickerSuggestions.all(client, 'query', show_sub_task_parent: true)
76
+ described_class.all(client, 'query', show_sub_task_parent: true)
77
77
  end
78
78
  end
79
79
  end
@@ -13,19 +13,21 @@ describe JIRA::Resource::Issue do
13
13
 
14
14
  describe '#respond_to?' do
15
15
  describe 'when decorated by SimpleDelegator' do
16
- before(:each) do
16
+ before do
17
17
  response = double
18
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')
19
+ allow(described_class).to receive(:collection_path).and_return('/jira/rest/api/2/issue')
20
20
  allow(client).to receive(:get).with('/jira/rest/api/2/issue/101')
21
21
  .and_return(response)
22
22
 
23
- issue = JIRA::Resource::Issue.find(client, 101)
23
+ issue = described_class.find(client, 101)
24
24
  @decorated = JIRAResourceDelegation.new(issue)
25
25
  end
26
+
26
27
  it 'responds to key' do
27
28
  expect(@decorated.respond_to?(:key)).to eq(true)
28
29
  end
30
+
29
31
  it 'does not raise an error' do
30
32
  expect do
31
33
  @issue.respond_to?(:project)
@@ -34,7 +36,7 @@ describe JIRA::Resource::Issue do
34
36
  end
35
37
  end
36
38
 
37
- it 'should find all issues' do
39
+ it 'finds all issues' do
38
40
  response = double
39
41
  empty_response = double
40
42
  issue = double
@@ -47,28 +49,28 @@ describe JIRA::Resource::Issue do
47
49
  .and_return(empty_response)
48
50
 
49
51
  expect(client).to receive(:Issue).and_return(issue)
50
- expect(issue).to receive(:build).with('id' => '1', 'summary' => 'Bugs Everywhere')
52
+ expect(issue).to receive(:build).with({ 'id' => '1', 'summary' => 'Bugs Everywhere' })
51
53
 
52
- issues = JIRA::Resource::Issue.all(client)
54
+ issues = described_class.all(client)
53
55
  end
54
56
 
55
- it 'should find an issue by key or id' do
57
+ it 'finds an issue by key or id' do
56
58
  response = double
57
59
 
58
60
  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')
61
+ allow(described_class).to receive(:collection_path).and_return('/jira/rest/api/2/issue')
60
62
  expect(client).to receive(:get).with('/jira/rest/api/2/issue/foo')
61
63
  .and_return(response)
62
64
  expect(client).to receive(:get).with('/jira/rest/api/2/issue/101')
63
65
  .and_return(response)
64
66
 
65
- issue_from_id = JIRA::Resource::Issue.find(client, 101)
66
- issue_from_key = JIRA::Resource::Issue.find(client, 'foo')
67
+ issue_from_id = described_class.find(client, 101)
68
+ issue_from_key = described_class.find(client, 'foo')
67
69
 
68
70
  expect(issue_from_id.attrs).to eq(issue_from_key.attrs)
69
71
  end
70
72
 
71
- it 'should search an issue with a jql query string' do
73
+ it 'searches an issue with a jql query string' do
72
74
  response = double
73
75
  issue = double
74
76
 
@@ -78,10 +80,10 @@ describe JIRA::Resource::Issue do
78
80
  expect(client).to receive(:Issue).and_return(issue)
79
81
  expect(issue).to receive(:build).with(%w[key foo]).and_return('')
80
82
 
81
- expect(JIRA::Resource::Issue.jql(client, 'foo bar')).to eq([''])
83
+ expect(described_class.jql(client, 'foo bar')).to eq([''])
82
84
  end
83
85
 
84
- it 'should search an issue with a jql query string and fields' do
86
+ it 'searches an issue with a jql query string and fields' do
85
87
  response = double
86
88
  issue = double
87
89
 
@@ -92,10 +94,10 @@ describe JIRA::Resource::Issue do
92
94
  expect(client).to receive(:Issue).and_return(issue)
93
95
  expect(issue).to receive(:build).with(%w[key foo]).and_return('')
94
96
 
95
- expect(JIRA::Resource::Issue.jql(client, 'foo bar', fields: %w[foo bar])).to eq([''])
97
+ expect(described_class.jql(client, 'foo bar', fields: %w[foo bar])).to eq([''])
96
98
  end
97
99
 
98
- it 'should search an issue with a jql query string, start at, and maxResults' do
100
+ it 'searches an issue with a jql query string, start at, and maxResults' do
99
101
  response = double
100
102
  issue = double
101
103
 
@@ -106,10 +108,10 @@ describe JIRA::Resource::Issue do
106
108
  expect(client).to receive(:Issue).and_return(issue)
107
109
  expect(issue).to receive(:build).with(%w[key foo]).and_return('')
108
110
 
109
- expect(JIRA::Resource::Issue.jql(client, 'foo bar', start_at: 1, max_results: 3)).to eq([''])
111
+ expect(described_class.jql(client, 'foo bar', start_at: 1, max_results: 3)).to eq([''])
110
112
  end
111
113
 
112
- it 'should search an issue with a jql query string and maxResults equals zero and should return the count of tickets' do
114
+ it 'searches an issue with a jql query string and maxResults equals zero and should return the count of tickets' do
113
115
  response = double
114
116
  issue = double
115
117
 
@@ -118,10 +120,10 @@ describe JIRA::Resource::Issue do
118
120
  .with('/jira/rest/api/2/search?jql=foo+bar&maxResults=0')
119
121
  .and_return(response)
120
122
 
121
- expect(JIRA::Resource::Issue.jql(client, 'foo bar', max_results: 0)).to eq(1)
123
+ expect(described_class.jql(client, 'foo bar', max_results: 0)).to eq(1)
122
124
  end
123
125
 
124
- it 'should search an issue with a jql query string and string expand' do
126
+ it 'searches an issue with a jql query string and string expand' do
125
127
  response = double
126
128
  issue = double
127
129
 
@@ -132,10 +134,10 @@ describe JIRA::Resource::Issue do
132
134
  expect(client).to receive(:Issue).and_return(issue)
133
135
  expect(issue).to receive(:build).with(%w[key foo]).and_return('')
134
136
 
135
- expect(JIRA::Resource::Issue.jql(client, 'foo bar', expand: 'transitions')).to eq([''])
137
+ expect(described_class.jql(client, 'foo bar', expand: 'transitions')).to eq([''])
136
138
  end
137
139
 
138
- it 'should search an issue with a jql query string and array expand' do
140
+ it 'searches an issue with a jql query string and array expand' do
139
141
  response = double
140
142
  issue = double
141
143
 
@@ -146,11 +148,11 @@ describe JIRA::Resource::Issue do
146
148
  expect(client).to receive(:Issue).and_return(issue)
147
149
  expect(issue).to receive(:build).with(%w[key foo]).and_return('')
148
150
 
149
- expect(JIRA::Resource::Issue.jql(client, 'foo bar', expand: %w[transitions])).to eq([''])
151
+ expect(described_class.jql(client, 'foo bar', expand: %w[transitions])).to eq([''])
150
152
  end
151
153
 
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
+ it 'returns meta data available for editing an issue' do
155
+ subject = described_class.new(client, attrs: { 'fields' => { 'key' => 'TST=123' } })
154
156
  response = double
155
157
 
156
158
  allow(response).to receive(:body).and_return(
@@ -164,29 +166,30 @@ describe JIRA::Resource::Issue do
164
166
  end
165
167
 
166
168
  it 'provides direct accessors to the fields' do
167
- subject = JIRA::Resource::Issue.new(client, attrs: { 'fields' => { 'foo' => 'bar' } })
169
+ subject = described_class.new(client, attrs: { 'fields' => { 'foo' => 'bar' } })
168
170
  expect(subject).to respond_to(:foo)
169
171
  expect(subject.foo).to eq('bar')
170
172
  end
171
173
 
172
174
  describe 'relationships' do
173
175
  subject do
174
- JIRA::Resource::Issue.new(client, attrs: {
175
- 'id' => '123',
176
+ described_class.new(client, attrs: {
177
+ 'id' => '123',
176
178
  'fields' => {
177
179
  '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' }] }
180
+ 'assignee' => { 'foo' => 'bar' },
181
+ 'project' => { 'foo' => 'bar' },
182
+ 'priority' => { 'foo' => 'bar' },
183
+ 'issuetype' => { 'foo' => 'bar' },
184
+ 'status' => { 'foo' => 'bar' },
185
+ 'resolution' => { 'foo' => 'bar' },
186
+ 'components' => [{ 'foo' => 'bar' }, { 'baz' => 'flum' }],
187
+ 'versions' => [{ 'foo' => 'bar' }, { 'baz' => 'flum' }],
188
+ 'comment' => { 'comments' => [{ 'foo' => 'bar' }, { 'baz' => 'flum' }] },
189
+ 'attachment' => [{ 'foo' => 'bar' }, { 'baz' => 'flum' }],
190
+ 'worklog' => { 'worklogs' => [{ 'foo' => 'bar' }, { 'baz' => 'flum' }] }
188
191
  }
189
- })
192
+ })
190
193
  end
191
194
 
192
195
  it 'has the correct relationships' do
@@ -208,6 +211,9 @@ describe JIRA::Resource::Issue do
208
211
  expect(subject).to have_one(:status, JIRA::Resource::Status)
209
212
  expect(subject.status.foo).to eq('bar')
210
213
 
214
+ expect(subject).to have_one(:resolution, JIRA::Resource::Resolution)
215
+ expect(subject.resolution.foo).to eq('bar')
216
+
211
217
  expect(subject).to have_many(:components, JIRA::Resource::Component)
212
218
  expect(subject.components.length).to eq(2)
213
219
 
@@ -5,9 +5,9 @@ describe JIRA::Resource::IssuePickerSuggestionsIssue do
5
5
 
6
6
  describe 'relationships' do
7
7
  subject do
8
- JIRA::Resource::IssuePickerSuggestionsIssue.new(client, attrs: {
9
- 'issues' => [{ 'id' => '1'}, { 'id' => '2' }]
10
- })
8
+ described_class.new(client, attrs: {
9
+ 'issues' => [{ 'id' => '1' }, { 'id' => '2' }]
10
+ })
11
11
  end
12
12
 
13
13
  it 'has the correct relationships' do
@@ -1,11 +1,12 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe JIRA::Resource::ProjectFactory do
4
+ subject { described_class.new(client) }
5
+
4
6
  let(:client) { double }
5
- subject { JIRA::Resource::ProjectFactory.new(client) }
6
7
 
7
8
  it 'initializes correctly' do
8
- expect(subject.class).to eq(JIRA::Resource::ProjectFactory)
9
+ expect(subject.class).to eq(described_class)
9
10
  expect(subject.client).to eq(client)
10
11
  end
11
12
  end
@@ -9,11 +9,11 @@ describe JIRA::Resource::Project do
9
9
 
10
10
  describe 'relationships' do
11
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
- })
12
+ described_class.new(client, attrs: {
13
+ 'lead' => { 'foo' => 'bar' },
14
+ 'issueTypes' => [{ 'foo' => 'bar' }, { 'baz' => 'flum' }],
15
+ 'versions' => [{ 'foo' => 'bar' }, { 'baz' => 'flum' }]
16
+ })
17
17
  end
18
18
 
19
19
  it 'has the correct relationships' do
@@ -30,13 +30,13 @@ describe JIRA::Resource::Project do
30
30
 
31
31
  describe 'issues' do
32
32
  subject do
33
- JIRA::Resource::Project.new(client, attrs: {
34
- 'key' => 'test'
35
- })
33
+ described_class.new(client, attrs: {
34
+ 'key' => 'test'
35
+ })
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"}}]}' # rubocop:disable Layout/LineLength
40
40
  response = double('response',
41
41
  body: response_body)
42
42
  issue_factory = double('issue factory')
@@ -52,7 +52,7 @@ 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":{}}]}' # rubocop:disable Layout/LineLength
56
56
  response = double('response',
57
57
  body: response_body)
58
58
  issue_factory = double('issue factory')
@@ -69,12 +69,12 @@ describe JIRA::Resource::Project do
69
69
  end
70
70
 
71
71
  describe 'users' do
72
- let(:project) { JIRA::Resource::Project.new(client, attrs: { 'key' => project_key }) }
72
+ let(:project) { described_class.new(client, attrs: { 'key' => project_key }) }
73
73
  let(:project_key) { SecureRandom.hex }
74
74
  let(:response) { double('response', body: '[{}]') }
75
75
 
76
76
  context 'pagination' do
77
- before(:each) do
77
+ before do
78
78
  user_factory = double('user factory')
79
79
  expect(client).to receive(:User).and_return(user_factory)
80
80
  expect(user_factory).to receive(:build).with(any_args)
@@ -95,7 +95,7 @@ describe JIRA::Resource::Project do
95
95
  .with("/jira/rest/api/2/user/assignable/search?project=#{project_key}&startAt=#{start_at}")
96
96
  .and_return(response)
97
97
 
98
- project.users(start_at: start_at)
98
+ project.users(start_at:)
99
99
  end
100
100
 
101
101
  it 'accepts max_results option' do
@@ -105,7 +105,7 @@ describe JIRA::Resource::Project do
105
105
  .with("/jira/rest/api/2/user/assignable/search?project=#{project_key}&maxResults=#{max_results}")
106
106
  .and_return(response)
107
107
 
108
- project.users(max_results: max_results)
108
+ project.users(max_results:)
109
109
  end
110
110
 
111
111
  it 'accepts start_at and max_results options' do
@@ -113,10 +113,10 @@ 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}") # rubocop:disable Layout/LineLength
117
117
  .and_return(response)
118
118
 
119
- project.users(start_at: start_at, max_results: max_results)
119
+ project.users(start_at:, max_results:)
120
120
  end
121
121
  end
122
122
  end
@@ -2,19 +2,32 @@ require 'spec_helper'
2
2
 
3
3
  describe JIRA::Resource::Sprint do
4
4
  let(:client) do
5
- client = double(options: { site: 'https://foo.bar.com', context_path: '/jira' })
5
+ client = double(options: { rest_base_path: '/jira/rest/api/2', context_path: '/jira' })
6
6
  allow(client).to receive(:Sprint).and_return(JIRA::Resource::SprintFactory.new(client))
7
7
  client
8
8
  end
9
9
  let(:sprint) { described_class.new(client) }
10
- let(:agile_sprint_path) { "#{sprint.client.options[:context_path]}/rest/agile/1.0/sprint/#{sprint.id}" }
10
+ let(:agile_sprint_path) { "/jira/rest/agile/1.0/sprint/#{sprint.id}" }
11
+ let(:response) { double }
12
+
13
+ describe 'get_sprint_details' do
14
+ let(:sprint) { described_class.find(client, '1') }
15
+
16
+ it 'check each of the date attributes' do
17
+ allow(client).to receive(:get).and_return(double(body: get_mock_response('sprint/1.json')))
18
+
19
+ expect(sprint.start_date).to eq Date.parse('2024-01-01T03:20:00.000Z')
20
+ expect(sprint.end_date).to eq Date.parse('2024-01-15T03:20:00.000Z')
21
+ expect(sprint.complete_date).to eq Date.parse('2024-01-16T03:48:00.000Z')
22
+ end
23
+ end
11
24
 
12
25
  describe '::find' do
13
26
  let(:response) { double('Response', body: '{"some_detail":"some detail"}') }
14
27
 
15
28
  it 'fetches the sprint from JIRA' do
16
29
  expect(client).to receive(:get).with('/jira/rest/agile/1.0/sprint/111').and_return(response)
17
- expect(JIRA::Resource::Sprint.find(client, '111')).to be_a(JIRA::Resource::Sprint)
30
+ expect(described_class.find(client, '111')).to be_a(described_class)
18
31
  end
19
32
  end
20
33
 
@@ -86,5 +99,59 @@ describe JIRA::Resource::Sprint do
86
99
  end
87
100
  end
88
101
  end
102
+
103
+ context 'an issue exists' do
104
+ let(:issue_id) { 1001 }
105
+ let(:post_issue_path) do
106
+ described_class.agile_path(client, sprint.id)
107
+ '/jira/rest/agile/1.0/sprint//issue'
108
+ end
109
+ let(:issue) do
110
+ issue = double
111
+ allow(issue).to receive(:id).and_return(issue_id)
112
+ issue
113
+ end
114
+ let(:post_issue_input) do
115
+ { issues: [issue.id] }
116
+ end
117
+
118
+ describe '#add_issu' do
119
+ context 'when an issue is passed' do
120
+ it 'posts with the issue id' do
121
+ expect(client).to receive(:post).with(post_issue_path, post_issue_input.to_json)
122
+
123
+ sprint.add_issue(issue)
124
+ end
125
+ end
126
+ end
127
+ end
128
+
129
+ context 'multiple issues exists' do
130
+ let(:issue_ids) { [1001, 1012] }
131
+ let(:post_issue_path) do
132
+ described_class.agile_path(client, sprint.id)
133
+ '/jira/rest/agile/1.0/sprint//issue'
134
+ end
135
+ let(:issues) do
136
+ issue_ids.map do |issue_id|
137
+ issue = double
138
+ allow(issue).to receive(:id).and_return(issue_id)
139
+ issue
140
+ end
141
+ end
142
+ let(:post_issue_input) do
143
+ { issues: issue_ids }
144
+ end
145
+
146
+ describe '#add_issues' do
147
+ context 'when an issue is passed' do
148
+ it 'posts with the issue id' do
149
+ expect(client).to receive(:post).with(post_issue_path, post_issue_input.to_json)
150
+
151
+ sprint.add_issues(issues)
152
+ end
153
+ end
154
+ end
155
+ end
89
156
  end
90
157
  end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe JIRA::Resource::Status do
4
+ let(:client) do
5
+ client = double(options: { rest_base_path: '/jira/rest/api/2' })
6
+ allow(client).to receive(:Field).and_return(JIRA::Resource::FieldFactory.new(client))
7
+ allow(client).to receive(:cache).and_return(OpenStruct.new)
8
+ client
9
+ end
10
+
11
+ describe '#status_category' do
12
+ subject do
13
+ described_class.new(client, attrs: JSON.parse(File.read('spec/mock_responses/status/1.json')))
14
+ end
15
+
16
+ it 'has a status_category relationship' do
17
+ expect(subject).to have_one(:status_category, JIRA::Resource::StatusCategory)
18
+ expect(subject.status_category.name).to eq('To Do')
19
+ end
20
+ end
21
+ end