jira-auto-tool 0.1.1

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 (139) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/.rubocop.yml +291 -0
  4. data/CHANGELOG.md +5 -0
  5. data/CODE_OF_CONDUCT.md +132 -0
  6. data/Guardfile +105 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +159 -0
  9. data/Rakefile +20 -0
  10. data/bin/jira-auto-tool +57 -0
  11. data/bin/jira-auto-tool.bat +2 -0
  12. data/bin/setup +8 -0
  13. data/bin/setup-dev-win.bat +3 -0
  14. data/cucumber.yml +7 -0
  15. data/features/align_sprint_time_in_dates.feature +33 -0
  16. data/features/assign_tickets_to_team_sprints.feature +73 -0
  17. data/features/cache_boards.feature +24 -0
  18. data/features/control_http_request_rate_limit.feature +17 -0
  19. data/features/create_sprints_using_existing_ones_as_reference.feature +79 -0
  20. data/features/list_boards.feature +12 -0
  21. data/features/list_project_fields.feature +89 -0
  22. data/features/list_sprint_prefixes.feature +77 -0
  23. data/features/quarterly_add_sprints_using_existing_ones_as_a_reference.feature +71 -0
  24. data/features/quarterly_create_sprints_until_specific_date.feature +75 -0
  25. data/features/quarterly_rename_sprints.feature +179 -0
  26. data/features/rename_sprints.feature +203 -0
  27. data/features/self_documented_command_line.feature +15 -0
  28. data/features/sprint_filtering.feature +111 -0
  29. data/features/step_definitions/execution_context_steps.rb +33 -0
  30. data/features/step_definitions/jira_board_steps.rb +102 -0
  31. data/features/step_definitions/jira_ticket_steps.rb +63 -0
  32. data/features/support/10.setup_cucumber.rb +10 -0
  33. data/features/support/env.rb +25 -0
  34. data/features/support/hooks.rb +25 -0
  35. data/features/support/setup_rspec.rb +14 -0
  36. data/features/support/setup_simplecov.rb +5 -0
  37. data/features/update_sprint_end_date_and_shift_following_ones.feature +52 -0
  38. data/lib/jira/auto/tool/board/cache.rb +67 -0
  39. data/lib/jira/auto/tool/board/unavailable_board.rb +36 -0
  40. data/lib/jira/auto/tool/board.rb +105 -0
  41. data/lib/jira/auto/tool/board_controller/options.rb +32 -0
  42. data/lib/jira/auto/tool/board_controller.rb +88 -0
  43. data/lib/jira/auto/tool/common_options.rb +37 -0
  44. data/lib/jira/auto/tool/config/options.rb +19 -0
  45. data/lib/jira/auto/tool/config.rb +64 -0
  46. data/lib/jira/auto/tool/fetch_custom_field_options.rb +47 -0
  47. data/lib/jira/auto/tool/field.rb +59 -0
  48. data/lib/jira/auto/tool/field_controller.rb +50 -0
  49. data/lib/jira/auto/tool/field_option.rb +35 -0
  50. data/lib/jira/auto/tool/get_createmeta_for_project.rb +24 -0
  51. data/lib/jira/auto/tool/helpers/environment_based_value.rb +96 -0
  52. data/lib/jira/auto/tool/helpers/option_parser.rb +16 -0
  53. data/lib/jira/auto/tool/helpers/overridable_time.rb +18 -0
  54. data/lib/jira/auto/tool/helpers/pagination.rb +50 -0
  55. data/lib/jira/auto/tool/jira_http_options.rb +20 -0
  56. data/lib/jira/auto/tool/next_sprint_creator.rb +60 -0
  57. data/lib/jira/auto/tool/performer/options.rb +76 -0
  58. data/lib/jira/auto/tool/performer/planning_increment_sprint_creator.rb +42 -0
  59. data/lib/jira/auto/tool/performer/prefix_sprint_updater.rb +42 -0
  60. data/lib/jira/auto/tool/performer/quarterly_sprint_renamer/next_name_generator.rb +60 -0
  61. data/lib/jira/auto/tool/performer/quarterly_sprint_renamer.rb +19 -0
  62. data/lib/jira/auto/tool/performer/sprint_end_date_updater.rb +55 -0
  63. data/lib/jira/auto/tool/performer/sprint_renamer/keep_same_name_generator.rb +19 -0
  64. data/lib/jira/auto/tool/performer/sprint_renamer/next_name_generator.rb +47 -0
  65. data/lib/jira/auto/tool/performer/sprint_renamer.rb +55 -0
  66. data/lib/jira/auto/tool/performer/sprint_time_in_dates_aligner.rb +52 -0
  67. data/lib/jira/auto/tool/project/options.rb +22 -0
  68. data/lib/jira/auto/tool/project/ticket_fields.rb +70 -0
  69. data/lib/jira/auto/tool/project.rb +40 -0
  70. data/lib/jira/auto/tool/rate_limited_jira_client.rb +50 -0
  71. data/lib/jira/auto/tool/request_builder/field_context_fetcher.rb +78 -0
  72. data/lib/jira/auto/tool/request_builder/field_option_fetcher.rb +54 -0
  73. data/lib/jira/auto/tool/request_builder/get.rb +29 -0
  74. data/lib/jira/auto/tool/request_builder/sprint_creator.rb +112 -0
  75. data/lib/jira/auto/tool/request_builder/sprint_state_updater.rb +60 -0
  76. data/lib/jira/auto/tool/request_builder.rb +89 -0
  77. data/lib/jira/auto/tool/setup_logging.rb +35 -0
  78. data/lib/jira/auto/tool/sprint/name.rb +105 -0
  79. data/lib/jira/auto/tool/sprint/prefix.rb +66 -0
  80. data/lib/jira/auto/tool/sprint.rb +183 -0
  81. data/lib/jira/auto/tool/sprint_controller/options.rb +61 -0
  82. data/lib/jira/auto/tool/sprint_controller.rb +152 -0
  83. data/lib/jira/auto/tool/sprint_state_controller.rb +58 -0
  84. data/lib/jira/auto/tool/team.rb +23 -0
  85. data/lib/jira/auto/tool/team_sprint_prefix_mapper/options.rb +27 -0
  86. data/lib/jira/auto/tool/team_sprint_prefix_mapper.rb +62 -0
  87. data/lib/jira/auto/tool/team_sprint_ticket_dispatcher.rb +76 -0
  88. data/lib/jira/auto/tool/ticket.rb +110 -0
  89. data/lib/jira/auto/tool/until_date.rb +68 -0
  90. data/lib/jira/auto/tool/version.rb +9 -0
  91. data/lib/jira/auto/tool.rb +216 -0
  92. data/sig/jira/sprint/tool.rbs +8 -0
  93. data/spec/jira/auto/tool/board/cache_spec.rb +179 -0
  94. data/spec/jira/auto/tool/board/unavailable_board_spec.rb +34 -0
  95. data/spec/jira/auto/tool/board_controller/options_spec.rb +52 -0
  96. data/spec/jira/auto/tool/board_controller_spec.rb +154 -0
  97. data/spec/jira/auto/tool/board_spec.rb +163 -0
  98. data/spec/jira/auto/tool/common_options_spec.rb +49 -0
  99. data/spec/jira/auto/tool/config_spec.rb +108 -0
  100. data/spec/jira/auto/tool/field_controller_spec.rb +121 -0
  101. data/spec/jira/auto/tool/field_option_spec.rb +42 -0
  102. data/spec/jira/auto/tool/field_spec.rb +99 -0
  103. data/spec/jira/auto/tool/helpers/environment_based_value_spec.rb +21 -0
  104. data/spec/jira/auto/tool/helpers/option_parser_spec.rb +21 -0
  105. data/spec/jira/auto/tool/helpers/overridable_time_spec.rb +43 -0
  106. data/spec/jira/auto/tool/helpers/pagination_spec.rb +72 -0
  107. data/spec/jira/auto/tool/jira_http_options_spec.rb +32 -0
  108. data/spec/jira/auto/tool/next_sprint_creator_spec.rb +85 -0
  109. data/spec/jira/auto/tool/performer/option_spec.rb +55 -0
  110. data/spec/jira/auto/tool/performer/planning_increment_sprint_creator_spec.rb +62 -0
  111. data/spec/jira/auto/tool/performer/prefix_sprint_updater_spec.rb +35 -0
  112. data/spec/jira/auto/tool/performer/quarterly_sprint_renamer/next_name_generator_spec.rb +175 -0
  113. data/spec/jira/auto/tool/performer/quarterly_sprint_renamer_spec.rb +239 -0
  114. data/spec/jira/auto/tool/performer/sprint_end_date_updater_spec.rb +90 -0
  115. data/spec/jira/auto/tool/performer/sprint_renamer/keep_same_name_generator_spec.rb +12 -0
  116. data/spec/jira/auto/tool/performer/sprint_renamer/next_name_generator_spec.rb +129 -0
  117. data/spec/jira/auto/tool/performer/sprint_renamer_spec.rb +240 -0
  118. data/spec/jira/auto/tool/performer/sprint_time_in_dates_aligner_spec.rb +132 -0
  119. data/spec/jira/auto/tool/project/ticket_fields_spec.rb +390 -0
  120. data/spec/jira/auto/tool/project_spec.rb +31 -0
  121. data/spec/jira/auto/tool/rate_limited_jira_client_spec.rb +82 -0
  122. data/spec/jira/auto/tool/request_builder/field_context_fetcher_spec.rb +54 -0
  123. data/spec/jira/auto/tool/request_builder/field_option_fetcher_spec.rb +64 -0
  124. data/spec/jira/auto/tool/request_builder/get_spec.rb +40 -0
  125. data/spec/jira/auto/tool/request_builder/sprint_creator_spec.rb +179 -0
  126. data/spec/jira/auto/tool/request_builder/sprint_state_updater_spec.rb +31 -0
  127. data/spec/jira/auto/tool/request_builder_spec.rb +73 -0
  128. data/spec/jira/auto/tool/sprint/name_spec.rb +101 -0
  129. data/spec/jira/auto/tool/sprint/prefix_spec.rb +207 -0
  130. data/spec/jira/auto/tool/sprint_controller_spec.rb +406 -0
  131. data/spec/jira/auto/tool/sprint_spec.rb +309 -0
  132. data/spec/jira/auto/tool/team_spec.rb +21 -0
  133. data/spec/jira/auto/tool/team_sprint_prefix_mapper_spec.rb +97 -0
  134. data/spec/jira/auto/tool/team_sprint_ticket_dispatcher_spec.rb +232 -0
  135. data/spec/jira/auto/tool/ticket_spec.rb +116 -0
  136. data/spec/jira/auto/tool/until_date_spec.rb +80 -0
  137. data/spec/jira/auto/tool_spec.rb +458 -0
  138. data/spec/spec_helper.rb +42 -0
  139. metadata +368 -0
@@ -0,0 +1,99 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rspec"
4
+ require "jira/auto/tool/field"
5
+
6
+ module Jira
7
+ module Auto
8
+ class Tool
9
+ RSpec.describe Jira::Auto::Tool::Field do
10
+ let(:field) { described_class.new(jira_client, jira_field) }
11
+
12
+ let(:jira_client) { jira_resource_double(JIRA::Client) }
13
+
14
+ let(:jira_field) do
15
+ jira_resource_double(
16
+ JIRA::Resource::Field,
17
+ name: "Field Name",
18
+ schema: { "type" => "string" },
19
+ id: "customfield_12345"
20
+ )
21
+ end
22
+
23
+ describe "#initialize" do
24
+ it "assigns jira_client" do
25
+ expect(field.jira_client).to eq(jira_client)
26
+ end
27
+
28
+ it "assigns jira_field" do
29
+ expect(field.jira_field).to eq(jira_field)
30
+ end
31
+ end
32
+
33
+ describe "#name" do
34
+ it "returns the field name" do
35
+ expect(field.name).to eq("Field Name")
36
+ end
37
+ end
38
+
39
+ describe "#type" do
40
+ it "returns the field type" do
41
+ expect(field.type).to eq("string")
42
+ end
43
+ end
44
+
45
+ describe "#id" do
46
+ it "returns the field id" do
47
+ expect(field.id).to eq("customfield_12345")
48
+ end
49
+ end
50
+
51
+ # TODO
52
+ describe "#values" do
53
+ let(:field_options) { [instance_double(FieldOption)] }
54
+
55
+ it "fetches the field values" do
56
+ allow(RequestBuilder::FieldOptionFetcher)
57
+ .to receive(:fetch_field_options).with(field).and_return(field_options)
58
+
59
+ expect(field.values).not_to be_empty
60
+ end
61
+ end
62
+
63
+ describe "#field_context" do
64
+ let(:logger) { instance_double(Logger) }
65
+
66
+ before do
67
+ allow(field)
68
+ .to receive_messages(field_contexts: %i[first_context second_context third_context],
69
+ log: logger)
70
+ end
71
+
72
+ it "returns the first context associated to a field and warns about multiple contexts" do
73
+ expect(logger).to receive(:warn)
74
+
75
+ expect(field.field_context).to eq(:first_context)
76
+ end
77
+ end
78
+
79
+ describe "#field_contexts" do
80
+ before do
81
+ allow(RequestBuilder::FieldContextFetcher)
82
+ .to receive_messages(fetch_field_contexts: %i[first_context second_context third_context])
83
+ end
84
+
85
+ it { expect(field.field_contexts).to eq(%i[first_context second_context third_context]) }
86
+ end
87
+
88
+ # TODO: - implement and maybe create a shared example to simplfy and reuse
89
+ describe "#<=>" do
90
+ def build_field(name, type, id)
91
+ # descr
92
+ end
93
+
94
+ it { expect(true).to be_truthy }
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rspec"
4
+
5
+ module Jira
6
+ module Auto
7
+ class Tool
8
+ module Helpers
9
+ module EnvironmentBasedValue
10
+ RSpec.describe "EnvironmentBasedValue" do
11
+ context "when condition" do
12
+ it "succeeds" do
13
+ expect(true).to be_truthy # TODO
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rspec"
4
+
5
+ require "jira/auto/tool/helpers/option_parser"
6
+
7
+ RSpec.describe OptionParser do
8
+ let(:option_parser) { described_class.new([]) }
9
+
10
+ describe ".section_header" do
11
+ it do
12
+ expect(option_parser).to receive(:on).with(<<~EOSB)
13
+
14
+ a section name:
15
+ ---------------
16
+ EOSB
17
+
18
+ option_parser.section_header("a section name")
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "jira/auto/tool/helpers/overridable_time"
4
+
5
+ module Jira
6
+ module Auto
7
+ class Tool
8
+ module Helpers
9
+ class OverridableTime
10
+ RSpec.describe OverridableTime do
11
+ describe ".now" do
12
+ let(:time_from_now) { Time.new(2025, 1, 1, 16, 32, 0, "UTC") }
13
+
14
+ it "returns the current date time" do
15
+ allow(Time).to receive_messages(now: time_from_now)
16
+
17
+ expect(described_class.now).to eq(time_from_now)
18
+ end
19
+
20
+ context "when the current date time is overridden" do
21
+ before do
22
+ @previous_date_override = ENV.fetch("JAT_CURRENT_DATE_TIME", nil)
23
+ end
24
+
25
+ after do
26
+ ENV["JAT_CURRENT_DATE_TIME"] = @previous_date_override
27
+ end
28
+
29
+ let(:overridden_date_time_string) { "2024-04-16 16:32 UTC" }
30
+
31
+ it "can be overridden using the JAT_CURRENT_DATE_TIME environment variable (e.g., for testing)" do
32
+ ENV["JAT_CURRENT_DATE_TIME"] = overridden_date_time_string
33
+
34
+ expect(described_class.now).to eq(Time.parse(overridden_date_time_string))
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "jira/auto/tool/helpers/pagination"
4
+
5
+ class PaginatedObjectFetcher
6
+ def fetch_objects(pagination_options) end
7
+ end
8
+
9
+ RSpec.describe Jira::Auto::Tool::Helpers::Pagination do
10
+ describe ".fetch_all_object_pages" do
11
+ let(:object) { PaginatedObjectFetcher.new }
12
+
13
+ shared_examples "paginated request" do |parameter_naming_convention|
14
+ describe "#build_pagination_options" do
15
+ it "respects the parameter naming convention" do
16
+ expect(described_class.build_pagination_options(parameter_naming_convention, 50, 0))
17
+ .to eq(expected_build_pagination_options)
18
+ end
19
+ end
20
+
21
+ let(:object_pages_to_return) do
22
+ [
23
+ %w[object_1 object_2],
24
+ %w[object_3 object_4],
25
+ %w[object_5],
26
+ %w[]
27
+ ]
28
+ end
29
+
30
+ it "deals with JIRA::Resource pagination" do
31
+ expected_multi_page_options.zip(object_pages_to_return).each do
32
+ |expected_pagination_options, object_page_to_return|
33
+
34
+ allow(object).to receive(:fetch_objects).with(expected_pagination_options).and_return(object_page_to_return)
35
+ end
36
+
37
+ expect(described_class.fetch_all_object_pages(parameter_naming_convention) do |pagination_options|
38
+ object.fetch_objects(pagination_options)
39
+ end)
40
+ .to eq(%w[object_1 object_2 object_3 object_4 object_5])
41
+ end
42
+ end
43
+
44
+ context "when :snake_case parameter naming convention used" do
45
+ let(:page_keyset) { %i[start_at max_results] }
46
+ let(:expected_build_pagination_options) { { max_results: 50, start_at: 0 } }
47
+
48
+ let(:expected_multi_page_options) do
49
+ [{ max_results: 50, start_at: 0 },
50
+ { max_results: 50, start_at: 50 },
51
+ { max_results: 50, start_at: 100 },
52
+ { max_results: 50, start_at: 150 }]
53
+ end
54
+
55
+ it_behaves_like "paginated request", :snake_case
56
+ end
57
+
58
+ context "when :camelCase parameter naming convention used" do
59
+ let(:page_keyset) { %i[startAt maxResults] }
60
+ let(:expected_build_pagination_options) { { maxResults: 50, startAt: 0 } }
61
+
62
+ let(:expected_multi_page_options) do
63
+ [{ maxResults: 50, startAt: 0 },
64
+ { maxResults: 50, startAt: 50 },
65
+ { maxResults: 50, startAt: 100 },
66
+ { maxResults: 50, startAt: 150 }]
67
+ end
68
+
69
+ it_behaves_like "paginated request", :camelCase
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rspec"
4
+ require "jira/auto/tool/jira_http_options"
5
+
6
+ module Jira
7
+ module Auto
8
+ class Tool
9
+ module JiraHttpOptions
10
+ RSpec.describe JiraHttpOptions do
11
+ describe ".add" do
12
+ let(:tool) { instance_double(Tool) }
13
+ let(:parser) { OptionParser.new }
14
+
15
+ before { described_class.add(tool, parser) }
16
+
17
+ # TODO: define proper tests
18
+ def expect_option_use_to_be_valid(option_use_with_args)
19
+ expect do
20
+ parser.parse([option_use_with_args])
21
+ end.not_to raise_error
22
+ end
23
+
24
+ it { expect_option_use_to_be_valid(["--jira-http-debug"]) }
25
+ it { expect_option_use_to_be_valid(["--jira-http-debug=false"]) }
26
+ it { expect_option_use_to_be_valid(["--no-jira-http-debug"]) }
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "jira/auto/tool/next_sprint_creator"
4
+
5
+ module Jira
6
+ module Auto
7
+ class Tool
8
+ RSpec.describe NextSprintCreator do
9
+ let(:tool) { instance_double(Tool) }
10
+ let(:last_sprint_name) { "ART_Team_24.4.5" }
11
+ let(:last_sprint_index_in_quarter) { 5 }
12
+ let(:last_sprint_start) { "2024-12-27 13:00:00 UTC" }
13
+ let(:last_sprint_end) { "2024-12-31 13:00:00 UTC" }
14
+
15
+ def last_sprint
16
+ instance_double(Sprint, tool: tool,
17
+ name: last_sprint_name,
18
+ start_date: Time.parse(last_sprint_start),
19
+ end_date: Time.parse(last_sprint_end),
20
+ name_prefix: "ART_Team",
21
+ length_in_days: 4,
22
+ index_in_quarter: last_sprint_index_in_quarter,
23
+ state: "closed",
24
+ origin_board_id: 512)
25
+ end
26
+
27
+ def next_sprint_creator_instance
28
+ described_class.new(last_sprint)
29
+ end
30
+
31
+ describe ".create_sprint_following" do
32
+ RSpec.shared_examples "a next sprint creator" do |expected|
33
+ it "requests the sprint creation with the expected attributes" do
34
+ allow(RequestBuilder::SprintCreator).to receive(:create_sprint)
35
+
36
+ described_class.create_sprint_following(last_sprint)
37
+
38
+ expect(RequestBuilder::SprintCreator)
39
+ .to have_received(:create_sprint)
40
+ .with(tool, 512,
41
+ { name: expected[:next_sprint_name],
42
+ start_date: Time.parse(expected[:next_sprint_start]).utc.to_s,
43
+ length_in_days: 4 })
44
+ end
45
+ end
46
+
47
+ context "when next sprint is in the same quarter" do
48
+ it_behaves_like "a next sprint creator", { next_sprint_name: "ART_Team_24.4.6",
49
+ next_sprint_start: "2024-12-31 13:00:00 UTC" }
50
+ end
51
+
52
+ context "when next sprint is in the coming year" do
53
+ let(:last_sprint_start) { "2024-12-31 13:00:00 UTC" }
54
+ let(:last_sprint_end) { "2025-01-03 13:00:00 UTC" }
55
+
56
+ it_behaves_like "a next sprint creator",
57
+ { next_sprint_name: "ART_Team_25.1.1", next_sprint_start: "2025-01-03 13:00:00 UTC" }
58
+ end
59
+
60
+ context "when the current sprint starts locally at midnight and UTC is not yet in the new year" do
61
+ let(:last_sprint_name) { "ART_Team_25.1.1" }
62
+ let(:last_sprint_start) { "2025-01-01 00:00:00 +01:00" }
63
+ let(:last_sprint_end) { "2025-01-03 00:00:00 +01:00" }
64
+ let(:last_sprint_index_in_quarter) { 1 }
65
+
66
+ it_behaves_like "a next sprint creator",
67
+ { next_sprint_name: "ART_Team_25.1.2", next_sprint_start: "2025-01-03 00:00:00 +01:00" }
68
+ end
69
+ end
70
+
71
+ describe "#same_quarter?" do
72
+ it { expect(next_sprint_creator_instance.same_quarter?).to be true }
73
+ end
74
+
75
+ describe "#next_sprint_start_date" do
76
+ it { expect(next_sprint_creator_instance.next_sprint_start_date).to eq(Time.parse("2024-12-31 13:00 UTC")) }
77
+ end
78
+
79
+ describe "#next_sprint_length_in_days" do
80
+ it { expect(next_sprint_creator_instance.next_sprint_length_in_days).to eq(4) }
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rspec"
4
+ require "active_support"
5
+ require "active_support/core_ext/string/inflections"
6
+ require "jira/auto/tool/performer/options"
7
+
8
+ module Jira
9
+ module Auto
10
+ class Tool
11
+ class Performer
12
+ module Options
13
+ RSpec.describe Options do
14
+ describe ".add" do
15
+ let(:tool) { instance_double(Tool) }
16
+ let(:parser) { OptionParser.new }
17
+
18
+ shared_examples "a performer" do |option_use_with_args, performer_class, *expected_args|
19
+ let(:performer_instance) { instance_double(performer_class, run: nil) }
20
+
21
+ before do
22
+ allow(performer_class).to receive_messages(new: performer_instance)
23
+ end
24
+
25
+ it "adds a parser option to process #{option_use_with_args}" do
26
+ expect do
27
+ described_class.add(tool, parser)
28
+ parser.parse([option_use_with_args])
29
+ end.not_to raise_error
30
+
31
+ expect(performer_class).to have_received(:new).with(tool, *expected_args)
32
+ expect(performer_instance).to have_received(:run)
33
+ end
34
+ end
35
+
36
+ it_behaves_like "a performer", "--sprint-add=25.3.1,4",
37
+ PlanningIncrementSprintCreator, "25.3.1", 4
38
+
39
+ it_behaves_like "a performer", "--sprint-align-time-in-dates=12:00 UTC",
40
+ SprintTimeInDatesAligner, Time.parse("12:00 UTC")
41
+
42
+ ["--quarterly-sprint-rename", "--qsr"].each do |option|
43
+ it_behaves_like "a performer", "#{option}=old_name,new_name",
44
+ QuarterlySprintRenamer, "old_name", "new_name"
45
+ end
46
+
47
+ it_behaves_like "a performer", "--sprint-update-end-date=regex,new_end_date",
48
+ SprintEndDateUpdater, "regex", "new_end_date"
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rspec"
4
+
5
+ require "jira/auto/tool/performer/planning_increment_sprint_creator"
6
+
7
+ module Jira
8
+ module Auto
9
+ class Tool
10
+ class Performer
11
+ class PlanningIncrementSprintCreator
12
+ RSpec.describe PlanningIncrementSprintCreator do
13
+ let(:updater) { described_class.new(tool, "25.3.1", 4) }
14
+ let(:tool) { instance_double(Tool) }
15
+
16
+ def get_date(date_string)
17
+ Time.parse(date_string)
18
+ end
19
+
20
+ describe "#create_sprint_for" do
21
+ let(:last_sprint) do
22
+ instance_double(Sprint, origin_board_id: 64,
23
+ end_date: get_date("2025-02-16 15:06"), length_in_days: 4)
24
+ end
25
+
26
+ it "creates a sprint" do
27
+ expect(RequestBuilder::SprintCreator).to receive(:create_sprint).with(
28
+ tool, 64, name: "Food_Restaurant_25.3.1",
29
+ start_date: get_date("2025-02-16 15:06"), length_in_days: 4
30
+ )
31
+
32
+ updater.create_sprint_for(last_sprint, "Food_Restaurant_25.3.1")
33
+ end
34
+ end
35
+
36
+ describe "#act_on_sprints_for_sprint_prefix" do
37
+ def get_sprint(name, attributes)
38
+ instance_double(Sprint, name: name, to_s: name, **attributes)
39
+ end
40
+
41
+ let(:last_sprint) { get_sprint "Food_Delivery_25.2.1", end_date: "2025-02-16 12:45", length_in_days: 10 }
42
+
43
+ let(:sprint_prefix) { instance_double(Sprint::Prefix, name: "Food_Delivery", last_sprint: last_sprint) }
44
+
45
+ # rubocop:disable RSpec/MultipleExpectations
46
+ it "creates the expected number of sprints with the expected names" do
47
+ expect(updater).to receive(:create_sprint_for).ordered.with(last_sprint, "Food_Delivery_25.3.1")
48
+ expect(updater).to receive(:create_sprint_for).ordered.with(nil, "Food_Delivery_25.3.2")
49
+ expect(updater).to receive(:create_sprint_for).ordered.with(nil, "Food_Delivery_25.3.3")
50
+ expect(updater).to receive(:create_sprint_for).ordered.with(nil, "Food_Delivery_25.3.4")
51
+ expect(sprint_prefix).to receive(:<<).exactly(4).times
52
+
53
+ updater.act_on_sprints_for_sprint_prefix(sprint_prefix)
54
+ end
55
+ # rubocop:enable RSpec/MultipleExpectations
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "jira/auto/tool/performer/prefix_sprint_updater"
4
+
5
+ module Jira
6
+ module Auto
7
+ class Tool
8
+ class Performer
9
+ class PrefixSprintUpdater
10
+ RSpec.describe PrefixSprintUpdater do
11
+ let(:tool) { instance_double(Tool, unclosed_sprint_prefixes: sprint_prefixes) }
12
+ let(:updater) { described_class.new(tool) }
13
+
14
+ let(:sprint_prefixes) { %i[one_sprint_prefix another_sprint_prefix] }
15
+
16
+ describe "#sprint_prefixes" do
17
+ it { expect(updater.sprint_prefixes).to eq(sprint_prefixes) }
18
+ end
19
+
20
+ describe "#run" do
21
+ it "act on the sprints for each sprint prefix" do
22
+ allow(updater).to receive_messages(sprint_prefixes: sprint_prefixes,
23
+ act_on_sprints_for_sprint_prefix: nil)
24
+
25
+ updater.run
26
+
27
+ expect(updater).to have_received(:act_on_sprints_for_sprint_prefix).exactly(2).times
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end