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.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +291 -0
- data/CHANGELOG.md +5 -0
- data/CODE_OF_CONDUCT.md +132 -0
- data/Guardfile +105 -0
- data/LICENSE.txt +21 -0
- data/README.md +159 -0
- data/Rakefile +20 -0
- data/bin/jira-auto-tool +57 -0
- data/bin/jira-auto-tool.bat +2 -0
- data/bin/setup +8 -0
- data/bin/setup-dev-win.bat +3 -0
- data/cucumber.yml +7 -0
- data/features/align_sprint_time_in_dates.feature +33 -0
- data/features/assign_tickets_to_team_sprints.feature +73 -0
- data/features/cache_boards.feature +24 -0
- data/features/control_http_request_rate_limit.feature +17 -0
- data/features/create_sprints_using_existing_ones_as_reference.feature +79 -0
- data/features/list_boards.feature +12 -0
- data/features/list_project_fields.feature +89 -0
- data/features/list_sprint_prefixes.feature +77 -0
- data/features/quarterly_add_sprints_using_existing_ones_as_a_reference.feature +71 -0
- data/features/quarterly_create_sprints_until_specific_date.feature +75 -0
- data/features/quarterly_rename_sprints.feature +179 -0
- data/features/rename_sprints.feature +203 -0
- data/features/self_documented_command_line.feature +15 -0
- data/features/sprint_filtering.feature +111 -0
- data/features/step_definitions/execution_context_steps.rb +33 -0
- data/features/step_definitions/jira_board_steps.rb +102 -0
- data/features/step_definitions/jira_ticket_steps.rb +63 -0
- data/features/support/10.setup_cucumber.rb +10 -0
- data/features/support/env.rb +25 -0
- data/features/support/hooks.rb +25 -0
- data/features/support/setup_rspec.rb +14 -0
- data/features/support/setup_simplecov.rb +5 -0
- data/features/update_sprint_end_date_and_shift_following_ones.feature +52 -0
- data/lib/jira/auto/tool/board/cache.rb +67 -0
- data/lib/jira/auto/tool/board/unavailable_board.rb +36 -0
- data/lib/jira/auto/tool/board.rb +105 -0
- data/lib/jira/auto/tool/board_controller/options.rb +32 -0
- data/lib/jira/auto/tool/board_controller.rb +88 -0
- data/lib/jira/auto/tool/common_options.rb +37 -0
- data/lib/jira/auto/tool/config/options.rb +19 -0
- data/lib/jira/auto/tool/config.rb +64 -0
- data/lib/jira/auto/tool/fetch_custom_field_options.rb +47 -0
- data/lib/jira/auto/tool/field.rb +59 -0
- data/lib/jira/auto/tool/field_controller.rb +50 -0
- data/lib/jira/auto/tool/field_option.rb +35 -0
- data/lib/jira/auto/tool/get_createmeta_for_project.rb +24 -0
- data/lib/jira/auto/tool/helpers/environment_based_value.rb +96 -0
- data/lib/jira/auto/tool/helpers/option_parser.rb +16 -0
- data/lib/jira/auto/tool/helpers/overridable_time.rb +18 -0
- data/lib/jira/auto/tool/helpers/pagination.rb +50 -0
- data/lib/jira/auto/tool/jira_http_options.rb +20 -0
- data/lib/jira/auto/tool/next_sprint_creator.rb +60 -0
- data/lib/jira/auto/tool/performer/options.rb +76 -0
- data/lib/jira/auto/tool/performer/planning_increment_sprint_creator.rb +42 -0
- data/lib/jira/auto/tool/performer/prefix_sprint_updater.rb +42 -0
- data/lib/jira/auto/tool/performer/quarterly_sprint_renamer/next_name_generator.rb +60 -0
- data/lib/jira/auto/tool/performer/quarterly_sprint_renamer.rb +19 -0
- data/lib/jira/auto/tool/performer/sprint_end_date_updater.rb +55 -0
- data/lib/jira/auto/tool/performer/sprint_renamer/keep_same_name_generator.rb +19 -0
- data/lib/jira/auto/tool/performer/sprint_renamer/next_name_generator.rb +47 -0
- data/lib/jira/auto/tool/performer/sprint_renamer.rb +55 -0
- data/lib/jira/auto/tool/performer/sprint_time_in_dates_aligner.rb +52 -0
- data/lib/jira/auto/tool/project/options.rb +22 -0
- data/lib/jira/auto/tool/project/ticket_fields.rb +70 -0
- data/lib/jira/auto/tool/project.rb +40 -0
- data/lib/jira/auto/tool/rate_limited_jira_client.rb +50 -0
- data/lib/jira/auto/tool/request_builder/field_context_fetcher.rb +78 -0
- data/lib/jira/auto/tool/request_builder/field_option_fetcher.rb +54 -0
- data/lib/jira/auto/tool/request_builder/get.rb +29 -0
- data/lib/jira/auto/tool/request_builder/sprint_creator.rb +112 -0
- data/lib/jira/auto/tool/request_builder/sprint_state_updater.rb +60 -0
- data/lib/jira/auto/tool/request_builder.rb +89 -0
- data/lib/jira/auto/tool/setup_logging.rb +35 -0
- data/lib/jira/auto/tool/sprint/name.rb +105 -0
- data/lib/jira/auto/tool/sprint/prefix.rb +66 -0
- data/lib/jira/auto/tool/sprint.rb +183 -0
- data/lib/jira/auto/tool/sprint_controller/options.rb +61 -0
- data/lib/jira/auto/tool/sprint_controller.rb +152 -0
- data/lib/jira/auto/tool/sprint_state_controller.rb +58 -0
- data/lib/jira/auto/tool/team.rb +23 -0
- data/lib/jira/auto/tool/team_sprint_prefix_mapper/options.rb +27 -0
- data/lib/jira/auto/tool/team_sprint_prefix_mapper.rb +62 -0
- data/lib/jira/auto/tool/team_sprint_ticket_dispatcher.rb +76 -0
- data/lib/jira/auto/tool/ticket.rb +110 -0
- data/lib/jira/auto/tool/until_date.rb +68 -0
- data/lib/jira/auto/tool/version.rb +9 -0
- data/lib/jira/auto/tool.rb +216 -0
- data/sig/jira/sprint/tool.rbs +8 -0
- data/spec/jira/auto/tool/board/cache_spec.rb +179 -0
- data/spec/jira/auto/tool/board/unavailable_board_spec.rb +34 -0
- data/spec/jira/auto/tool/board_controller/options_spec.rb +52 -0
- data/spec/jira/auto/tool/board_controller_spec.rb +154 -0
- data/spec/jira/auto/tool/board_spec.rb +163 -0
- data/spec/jira/auto/tool/common_options_spec.rb +49 -0
- data/spec/jira/auto/tool/config_spec.rb +108 -0
- data/spec/jira/auto/tool/field_controller_spec.rb +121 -0
- data/spec/jira/auto/tool/field_option_spec.rb +42 -0
- data/spec/jira/auto/tool/field_spec.rb +99 -0
- data/spec/jira/auto/tool/helpers/environment_based_value_spec.rb +21 -0
- data/spec/jira/auto/tool/helpers/option_parser_spec.rb +21 -0
- data/spec/jira/auto/tool/helpers/overridable_time_spec.rb +43 -0
- data/spec/jira/auto/tool/helpers/pagination_spec.rb +72 -0
- data/spec/jira/auto/tool/jira_http_options_spec.rb +32 -0
- data/spec/jira/auto/tool/next_sprint_creator_spec.rb +85 -0
- data/spec/jira/auto/tool/performer/option_spec.rb +55 -0
- data/spec/jira/auto/tool/performer/planning_increment_sprint_creator_spec.rb +62 -0
- data/spec/jira/auto/tool/performer/prefix_sprint_updater_spec.rb +35 -0
- data/spec/jira/auto/tool/performer/quarterly_sprint_renamer/next_name_generator_spec.rb +175 -0
- data/spec/jira/auto/tool/performer/quarterly_sprint_renamer_spec.rb +239 -0
- data/spec/jira/auto/tool/performer/sprint_end_date_updater_spec.rb +90 -0
- data/spec/jira/auto/tool/performer/sprint_renamer/keep_same_name_generator_spec.rb +12 -0
- data/spec/jira/auto/tool/performer/sprint_renamer/next_name_generator_spec.rb +129 -0
- data/spec/jira/auto/tool/performer/sprint_renamer_spec.rb +240 -0
- data/spec/jira/auto/tool/performer/sprint_time_in_dates_aligner_spec.rb +132 -0
- data/spec/jira/auto/tool/project/ticket_fields_spec.rb +390 -0
- data/spec/jira/auto/tool/project_spec.rb +31 -0
- data/spec/jira/auto/tool/rate_limited_jira_client_spec.rb +82 -0
- data/spec/jira/auto/tool/request_builder/field_context_fetcher_spec.rb +54 -0
- data/spec/jira/auto/tool/request_builder/field_option_fetcher_spec.rb +64 -0
- data/spec/jira/auto/tool/request_builder/get_spec.rb +40 -0
- data/spec/jira/auto/tool/request_builder/sprint_creator_spec.rb +179 -0
- data/spec/jira/auto/tool/request_builder/sprint_state_updater_spec.rb +31 -0
- data/spec/jira/auto/tool/request_builder_spec.rb +73 -0
- data/spec/jira/auto/tool/sprint/name_spec.rb +101 -0
- data/spec/jira/auto/tool/sprint/prefix_spec.rb +207 -0
- data/spec/jira/auto/tool/sprint_controller_spec.rb +406 -0
- data/spec/jira/auto/tool/sprint_spec.rb +309 -0
- data/spec/jira/auto/tool/team_spec.rb +21 -0
- data/spec/jira/auto/tool/team_sprint_prefix_mapper_spec.rb +97 -0
- data/spec/jira/auto/tool/team_sprint_ticket_dispatcher_spec.rb +232 -0
- data/spec/jira/auto/tool/ticket_spec.rb +116 -0
- data/spec/jira/auto/tool/until_date_spec.rb +80 -0
- data/spec/jira/auto/tool_spec.rb +458 -0
- data/spec/spec_helper.rb +42 -0
- metadata +368 -0
@@ -0,0 +1,175 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rspec"
|
4
|
+
|
5
|
+
require "jira/auto/tool/performer/quarterly_sprint_renamer/next_name_generator"
|
6
|
+
|
7
|
+
RSpec.describe Jira::Auto::Tool::Performer::QuarterlySprintRenamer::NextNameGenerator do
|
8
|
+
def parsed_name(sprint_name)
|
9
|
+
Jira::Auto::Tool::Sprint::Name.parse(sprint_name)
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "#new_name_of_sprint_next_to_first_renamed_sprint" do
|
13
|
+
subject(:new_name) { next_name_generator.new_name_of_sprint_next_to_first_renamed_sprint }
|
14
|
+
|
15
|
+
let(:next_name_generator) do
|
16
|
+
described_class.new(original_name_of_first_renamed_sprint, name_of_first_renamed_sprint)
|
17
|
+
end
|
18
|
+
|
19
|
+
context "when pulling sprint into previous planning interval" do
|
20
|
+
let(:original_name_of_first_renamed_sprint) { "prefix_23.2.1" }
|
21
|
+
let(:name_of_first_renamed_sprint) { "prefix_23.1.6" }
|
22
|
+
|
23
|
+
it("returns the original sprint name") { expect(new_name).to eq(parsed_name("prefix_23.2.1")) }
|
24
|
+
end
|
25
|
+
|
26
|
+
context "when renaming inside planning interval" do
|
27
|
+
let(:original_name_of_first_renamed_sprint) { "prefix_23.2.1" }
|
28
|
+
let(:name_of_first_renamed_sprint) { "prefix_23.2.4" }
|
29
|
+
|
30
|
+
it { expect(new_name).to eq(parsed_name("prefix_23.2.5")) }
|
31
|
+
end
|
32
|
+
|
33
|
+
context "when pushing sprint into next planning interval" do
|
34
|
+
let(:original_name_of_first_renamed_sprint) { "prefix_23.1.5" }
|
35
|
+
let(:name_of_first_renamed_sprint) { "prefix_23.2.2" }
|
36
|
+
|
37
|
+
it("returns the original sprint parsed name") { expect(new_name).to eq(parsed_name("prefix_23.2.3")) }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "#pulling_sprint_into_previous_planning_interval?" do
|
42
|
+
let(:next_name_generator) do
|
43
|
+
described_class.new(original_name_of_first_renamed_sprint, name_of_first_renamed_sprint)
|
44
|
+
end
|
45
|
+
|
46
|
+
context "when sprint goes to the preceding planning interval" do
|
47
|
+
let(:original_name_of_first_renamed_sprint) { "prefix_26.1.1" }
|
48
|
+
let(:name_of_first_renamed_sprint) { "prefix_25.2.1" }
|
49
|
+
|
50
|
+
it { expect(next_name_generator).to be_pulling_sprint_into_previous_planning_interval }
|
51
|
+
end
|
52
|
+
|
53
|
+
context "when sprint is renamed backward inside the current planning interval" do
|
54
|
+
let(:original_name_of_first_renamed_sprint) { "prefix_26.1.4" }
|
55
|
+
let(:name_of_first_renamed_sprint) { "prefix_26.1.1" }
|
56
|
+
|
57
|
+
it { expect(next_name_generator).not_to be_pulling_sprint_into_previous_planning_interval }
|
58
|
+
end
|
59
|
+
|
60
|
+
context "when sprint is renamed forward inside the current planning interval" do
|
61
|
+
let(:original_name_of_first_renamed_sprint) { "prefix_26.1.1" }
|
62
|
+
let(:name_of_first_renamed_sprint) { "prefix_26.1.4" }
|
63
|
+
|
64
|
+
it { expect(next_name_generator).not_to be_pulling_sprint_into_previous_planning_interval }
|
65
|
+
end
|
66
|
+
|
67
|
+
context "when sprint goes to the following planning interval" do
|
68
|
+
let(:original_name_of_first_renamed_sprint) { "prefix_25.1.5" }
|
69
|
+
let(:name_of_first_renamed_sprint) { "prefix_25.2.1" }
|
70
|
+
|
71
|
+
it { expect(next_name_generator).not_to be_pulling_sprint_into_previous_planning_interval }
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe "#next_name_in_planning_interval" do
|
76
|
+
let(:name_generator) { described_class.new(original_name_of_first_renamed_sprint, name_of_first_renamed_sprint) }
|
77
|
+
let(:next_names) { 4.times.collect { name_generator.next_name_in_planning_interval } }
|
78
|
+
|
79
|
+
context "when pulling to the previous planning interval" do
|
80
|
+
let(:original_name_of_first_renamed_sprint) { "prefix_25.2.1" }
|
81
|
+
let(:name_of_first_renamed_sprint) { "prefix_25.1.8" }
|
82
|
+
|
83
|
+
it "generates a new name consecutive to the previous one in the planning interval" do
|
84
|
+
expect(next_names).to eq(%w[prefix_25.2.1 prefix_25.2.2 prefix_25.2.3 prefix_25.2.4])
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
context "when renaming in the same planning interval" do
|
89
|
+
let(:original_name_of_first_renamed_sprint) { "prefix_25.1.5" }
|
90
|
+
let(:name_of_first_renamed_sprint) { "prefix_25.1.20" }
|
91
|
+
|
92
|
+
it "generates a new name consecutive to the previous one in the planning interval" do
|
93
|
+
expect(next_names).to eq(%w[prefix_25.1.21 prefix_25.1.22 prefix_25.1.23 prefix_25.1.24])
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
context "when pushing to the next planning interval" do
|
98
|
+
let(:original_name_of_first_renamed_sprint) { "prefix_25.1.5" }
|
99
|
+
let(:name_of_first_renamed_sprint) { "prefix_25.2.1" }
|
100
|
+
|
101
|
+
it "generates a new name consecutive to the previous one in the planning interval" do
|
102
|
+
expect(next_names).to eq(%w[prefix_25.2.2 prefix_25.2.3 prefix_25.2.4 prefix_25.2.5])
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe "#name_for" do
|
108
|
+
let(:name_generator) { described_class.new(original_name_of_first_renamed_sprint, name_of_first_renamed_sprint) }
|
109
|
+
let(:original_name_of_first_renamed_sprint) { "prefix_25.2.1" }
|
110
|
+
let(:name_of_first_renamed_sprint) { "prefix_25.1.8" }
|
111
|
+
|
112
|
+
context "when sprint name inside the planning interval" do
|
113
|
+
before do
|
114
|
+
allow(name_generator).to receive_messages(next_name_in_planning_interval: "next_name_in_planning_interval")
|
115
|
+
end
|
116
|
+
|
117
|
+
it { expect(name_generator.name_for("prefix_25.2.2")).to eq("next_name_in_planning_interval") }
|
118
|
+
end
|
119
|
+
|
120
|
+
context "when sprint name outside planning interval from first sprint to rename" do
|
121
|
+
let(:original_name_of_first_renamed_sprint) { "prefix_25.1.5" }
|
122
|
+
let(:name_of_first_renamed_sprint) { "prefix_25.1.20" }
|
123
|
+
|
124
|
+
it "the name stays unchanged" do
|
125
|
+
expect(name_generator.name_for("prefix_25.3.2")).to eq("prefix_25.3.2")
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
describe "#outside_planning_interval_of_sprint_next_to_first_renamed_sprint?" do
|
131
|
+
let(:name_generator) { described_class.new(original_name, new_name) }
|
132
|
+
|
133
|
+
def outside?(sprint_name)
|
134
|
+
name_generator.outside_planning_interval_of_sprint_next_to_first_renamed_sprint?(sprint_name)
|
135
|
+
end
|
136
|
+
|
137
|
+
context "when pulling sprint into previous planning interval" do
|
138
|
+
let(:original_name) { "prefix_25.2.1" }
|
139
|
+
let(:new_name) { "prefix_25.1.6" }
|
140
|
+
|
141
|
+
it { expect(outside?("prefix_25.1.3")).to be_truthy }
|
142
|
+
it { expect(outside?("prefix_25.2.1")).not_to be_truthy }
|
143
|
+
it { expect(outside?("prefix_25.2.3")).not_to be_truthy }
|
144
|
+
it { expect(outside?("prefix_25.3.1")).to be_truthy }
|
145
|
+
it { expect(outside?("prefix_25.3.2")).to be_truthy }
|
146
|
+
it { expect(outside?("prefix_25.4.2")).to be_truthy }
|
147
|
+
it { expect(outside?("prefix_26.1.1")).to be_truthy }
|
148
|
+
end
|
149
|
+
|
150
|
+
context "when sprint renamed inside planning interval" do
|
151
|
+
let(:original_name) { "prefix_25.2.5" }
|
152
|
+
let(:new_name) { "prefix_25.2.16" }
|
153
|
+
|
154
|
+
it { expect(outside?("prefix_25.1.5")).to be_truthy }
|
155
|
+
it { expect(outside?("prefix_25.2.1")).to be_falsy }
|
156
|
+
it { expect(outside?("prefix_25.2.20")).to be_falsy }
|
157
|
+
it { expect(outside?("prefix_25.3.2")).to be_truthy }
|
158
|
+
it { expect(outside?("prefix_25.4.2")).to be_truthy }
|
159
|
+
it { expect(outside?("prefix_26.1.1")).to be_truthy }
|
160
|
+
end
|
161
|
+
|
162
|
+
context "when pushing sprint into next planning interval" do
|
163
|
+
let(:original_name) { "prefix_25.1.5" }
|
164
|
+
let(:new_name) { "prefix_25.2.1" }
|
165
|
+
|
166
|
+
it { expect(outside?("prefix_25.1.5")).to be_truthy }
|
167
|
+
it { expect(outside?("prefix_25.2.1")).to be_falsy }
|
168
|
+
it { expect(outside?("prefix_25.2.3")).to be_falsy }
|
169
|
+
it { expect(outside?("prefix_25.3.1")).to be_truthy }
|
170
|
+
it { expect(outside?("prefix_25.3.2")).to be_truthy }
|
171
|
+
it { expect(outside?("prefix_25.4.2")).to be_truthy }
|
172
|
+
it { expect(outside?("prefix_26.1.1")).to be_truthy }
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
@@ -0,0 +1,239 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rspec"
|
4
|
+
require "jira/auto/tool/performer/quarterly_sprint_renamer"
|
5
|
+
|
6
|
+
RSpec.describe Jira::Auto::Tool::Performer::QuarterlySprintRenamer do
|
7
|
+
let(:sprint_renamer) { described_class.new(tool, from_string, to_string) }
|
8
|
+
let(:tool) { instance_double(Jira::Auto::Tool) }
|
9
|
+
let(:from_string) { "25.1.5" }
|
10
|
+
let(:to_string) { "25.2.1" }
|
11
|
+
|
12
|
+
describe "#from_string_regex" do
|
13
|
+
it { expect(sprint_renamer.from_string_regex).to eq(/25\.1\.5/) }
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "#to_string" do
|
17
|
+
it { expect(sprint_renamer.to_string).to eq("25.2.1") }
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "#acton_sprints_for_sprint_prefix" do
|
21
|
+
def create_sprint(name)
|
22
|
+
instance_double(Jira::Auto::Tool::Sprint, name: name, rename_to: nil)
|
23
|
+
end
|
24
|
+
|
25
|
+
let(:one_sprint) { create_sprint("a sprint name") }
|
26
|
+
let(:another_sprint) { create_sprint("another sprint name") }
|
27
|
+
|
28
|
+
let(:sprints) { [one_sprint, another_sprint] }
|
29
|
+
|
30
|
+
let(:prefix) { instance_double(Jira::Auto::Tool::Sprint::Prefix, name: "Food_Delivery", sprints: sprints) }
|
31
|
+
|
32
|
+
before do
|
33
|
+
allow(sprint_renamer).to receive_messages(calculate_sprint_new_names: ["a new name", "another new name"])
|
34
|
+
end
|
35
|
+
|
36
|
+
it "renames each sprint" do
|
37
|
+
sprint_renamer.act_on_sprints_for_sprint_prefix(prefix)
|
38
|
+
|
39
|
+
expect(sprints).to all have_received(:rename_to)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "#calculate_sprint_new_names" do
|
44
|
+
let(:sprint_names) do
|
45
|
+
%w[
|
46
|
+
Food_Delivery_25.1.2
|
47
|
+
Food_Delivery_25.1.3
|
48
|
+
Food_Delivery_25.1.4
|
49
|
+
Food_Delivery_25.1.5
|
50
|
+
Food_Delivery_25.2.1
|
51
|
+
Food_Delivery_25.2.2
|
52
|
+
Food_Delivery_25.2.3
|
53
|
+
Food_Delivery_25.2.4
|
54
|
+
Food_Delivery_25.2.5
|
55
|
+
]
|
56
|
+
end
|
57
|
+
|
58
|
+
context "when pulling a sprint into the previous planning interval" do
|
59
|
+
let(:from_string) { "25.2.1" }
|
60
|
+
let(:to_string) { "25.1.6" }
|
61
|
+
|
62
|
+
let(:expected_new_sprint_names) do
|
63
|
+
%w[
|
64
|
+
Food_Delivery_25.1.2
|
65
|
+
Food_Delivery_25.1.3
|
66
|
+
Food_Delivery_25.1.4
|
67
|
+
Food_Delivery_25.1.5
|
68
|
+
Food_Delivery_25.1.6
|
69
|
+
Food_Delivery_25.2.1
|
70
|
+
Food_Delivery_25.2.2
|
71
|
+
Food_Delivery_25.2.3
|
72
|
+
Food_Delivery_25.2.4
|
73
|
+
]
|
74
|
+
end
|
75
|
+
|
76
|
+
it { expect(sprint_renamer.calculate_sprint_new_names(sprint_names)).to eq(expected_new_sprint_names) }
|
77
|
+
end
|
78
|
+
|
79
|
+
context "when renaming sprint forward inside planning interval" do
|
80
|
+
let(:from_string) { "25.2.1" }
|
81
|
+
let(:to_string) { "25.2.10" }
|
82
|
+
|
83
|
+
let(:expected_new_sprint_names) do
|
84
|
+
%w[
|
85
|
+
Food_Delivery_25.1.2
|
86
|
+
Food_Delivery_25.1.3
|
87
|
+
Food_Delivery_25.1.4
|
88
|
+
Food_Delivery_25.1.5
|
89
|
+
Food_Delivery_25.2.10
|
90
|
+
Food_Delivery_25.2.11
|
91
|
+
Food_Delivery_25.2.12
|
92
|
+
Food_Delivery_25.2.13
|
93
|
+
Food_Delivery_25.2.14
|
94
|
+
]
|
95
|
+
end
|
96
|
+
|
97
|
+
it do
|
98
|
+
expect(sprint_renamer.calculate_sprint_new_names(["Food_Delivery_25.1.5"]))
|
99
|
+
.to eq(["Food_Delivery_25.1.5"])
|
100
|
+
end
|
101
|
+
|
102
|
+
it { expect(sprint_renamer.calculate_sprint_new_names(sprint_names)).to eq(expected_new_sprint_names) }
|
103
|
+
end
|
104
|
+
|
105
|
+
context "when renaming sprint backward inside planning interval" do
|
106
|
+
let(:from_string) { "25.2.10" }
|
107
|
+
let(:to_string) { "25.2.1" }
|
108
|
+
|
109
|
+
let(:sprint_names) do
|
110
|
+
%w[
|
111
|
+
Food_Delivery_25.1.2
|
112
|
+
Food_Delivery_25.1.3
|
113
|
+
Food_Delivery_25.1.4
|
114
|
+
Food_Delivery_25.1.5
|
115
|
+
Food_Delivery_25.2.10
|
116
|
+
Food_Delivery_25.2.11
|
117
|
+
Food_Delivery_25.2.12
|
118
|
+
Food_Delivery_25.2.13
|
119
|
+
Food_Delivery_25.2.14
|
120
|
+
]
|
121
|
+
end
|
122
|
+
|
123
|
+
let(:expected_new_sprint_names) do
|
124
|
+
%w[
|
125
|
+
Food_Delivery_25.1.2
|
126
|
+
Food_Delivery_25.1.3
|
127
|
+
Food_Delivery_25.1.4
|
128
|
+
Food_Delivery_25.1.5
|
129
|
+
Food_Delivery_25.2.1
|
130
|
+
Food_Delivery_25.2.2
|
131
|
+
Food_Delivery_25.2.3
|
132
|
+
Food_Delivery_25.2.4
|
133
|
+
Food_Delivery_25.2.5
|
134
|
+
]
|
135
|
+
end
|
136
|
+
|
137
|
+
it do
|
138
|
+
expect(sprint_renamer.calculate_sprint_new_names(["Food_Delivery_25.1.5"]))
|
139
|
+
.to eq(["Food_Delivery_25.1.5"])
|
140
|
+
end
|
141
|
+
|
142
|
+
it { expect(sprint_renamer.calculate_sprint_new_names(sprint_names)).to eq(expected_new_sprint_names) }
|
143
|
+
end
|
144
|
+
|
145
|
+
context "when pushing a sprint to the next planning interval" do
|
146
|
+
let(:expected_new_sprint_names) do
|
147
|
+
%w[
|
148
|
+
Food_Delivery_25.1.2
|
149
|
+
Food_Delivery_25.1.3
|
150
|
+
Food_Delivery_25.1.4
|
151
|
+
Food_Delivery_25.2.1
|
152
|
+
Food_Delivery_25.2.2
|
153
|
+
Food_Delivery_25.2.3
|
154
|
+
Food_Delivery_25.2.4
|
155
|
+
Food_Delivery_25.2.5
|
156
|
+
Food_Delivery_25.2.6
|
157
|
+
]
|
158
|
+
end
|
159
|
+
|
160
|
+
it { expect(sprint_renamer.calculate_sprint_new_names(["Food_Delivery_25.1.5"])).to eq(["Food_Delivery_25.2.1"]) }
|
161
|
+
|
162
|
+
it { expect(sprint_renamer.calculate_sprint_new_names(sprint_names)).to eq(expected_new_sprint_names) }
|
163
|
+
end
|
164
|
+
|
165
|
+
context "when sprints exist beyond the immediate planning interval of the sprint" do
|
166
|
+
let(:from_string) { "25.2.1" }
|
167
|
+
let(:to_string) { "25.1.6" }
|
168
|
+
|
169
|
+
let(:sprint_names) do
|
170
|
+
%w[
|
171
|
+
Food_Delivery_25.1.5
|
172
|
+
Food_Delivery_25.2.1
|
173
|
+
Food_Delivery_25.2.2
|
174
|
+
Food_Delivery_25.3.1
|
175
|
+
Food_Delivery_25.3.2
|
176
|
+
Food_Delivery_25.3.3
|
177
|
+
]
|
178
|
+
end
|
179
|
+
|
180
|
+
let(:expected_new_sprint_names) do
|
181
|
+
%w[
|
182
|
+
Food_Delivery_25.1.5
|
183
|
+
Food_Delivery_25.1.6
|
184
|
+
Food_Delivery_25.2.1
|
185
|
+
Food_Delivery_25.3.1
|
186
|
+
Food_Delivery_25.3.2
|
187
|
+
Food_Delivery_25.3.3
|
188
|
+
]
|
189
|
+
end
|
190
|
+
|
191
|
+
it "does not rename those sprints" do
|
192
|
+
expect(sprint_renamer.calculate_sprint_new_names(sprint_names)).to eq(expected_new_sprint_names)
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
context "when multiple sprints are matching the first sprint to rename" do
|
197
|
+
let(:from_string) { "25.2.1" }
|
198
|
+
let(:to_string) { "25.1.6" }
|
199
|
+
|
200
|
+
let(:sprint_names) do
|
201
|
+
%w[
|
202
|
+
Food_Delivery_25.1.5
|
203
|
+
Food_Delivery_25.2.1
|
204
|
+
Food_Delivery_25.2.1
|
205
|
+
Food_Delivery_25.2.1
|
206
|
+
Food_Delivery_25.2.1
|
207
|
+
]
|
208
|
+
end
|
209
|
+
|
210
|
+
let(:expected_new_sprint_names) do
|
211
|
+
%w[
|
212
|
+
Food_Delivery_25.1.5
|
213
|
+
Food_Delivery_25.1.6
|
214
|
+
Food_Delivery_25.2.1
|
215
|
+
Food_Delivery_25.2.2
|
216
|
+
Food_Delivery_25.2.3
|
217
|
+
]
|
218
|
+
end
|
219
|
+
|
220
|
+
it "does rename those sprints in sequence" do
|
221
|
+
expect(sprint_renamer.calculate_sprint_new_names(sprint_names)).to eq(expected_new_sprint_names)
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
describe "#first_sprint_to_act_on?" do
|
227
|
+
let(:sprint_renamer) { described_class.new(nil, "25.1.5", "25.2.1") }
|
228
|
+
|
229
|
+
def first_to_rename?(sprint_name)
|
230
|
+
sprint_renamer.first_sprint_to_act_on?(sprint_name)
|
231
|
+
end
|
232
|
+
|
233
|
+
it { expect(first_to_rename?("prefix_25.1.4")).not_to be_truthy }
|
234
|
+
it { expect(first_to_rename?("prefix_25.1.5")).to be_truthy }
|
235
|
+
it { expect(first_to_rename?("prefix_24.1.5")).not_to be_truthy }
|
236
|
+
it { expect(first_to_rename?("prefix_25.2.1")).not_to be_truthy }
|
237
|
+
it { expect(first_to_rename?("prefix_26.1.6")).not_to be_truthy }
|
238
|
+
end
|
239
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rspec"
|
4
|
+
|
5
|
+
require "jira/auto/tool/performer/sprint_end_date_updater"
|
6
|
+
|
7
|
+
module Jira
|
8
|
+
module Auto
|
9
|
+
class Tool
|
10
|
+
class Performer
|
11
|
+
class SprintEndDateUpdater
|
12
|
+
RSpec.describe SprintEndDateUpdater do
|
13
|
+
let(:updater) { described_class.new(tool, "25.2.2", new_end_date_string) }
|
14
|
+
let(:tool) { instance_double(Tool) }
|
15
|
+
let(:new_end_date_string) { "2025-02-14 15:38" }
|
16
|
+
let(:new_end_date) { get_date(new_end_date_string) }
|
17
|
+
|
18
|
+
def get_date(date_string)
|
19
|
+
Time.parse(date_string)
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "#update_sprint_end_date" do
|
23
|
+
let(:sprint) { instance_double(Sprint, :end_date= => nil, :save => nil, :length_in_days => 10) }
|
24
|
+
|
25
|
+
it do
|
26
|
+
updater.update_sprint_end_date(sprint)
|
27
|
+
|
28
|
+
expect(sprint).to have_received(:end_date=).with(new_end_date)
|
29
|
+
expect(sprint).to have_received(:save)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "#shift_sprint_to_new_start_date" do
|
34
|
+
let(:sprint) { instance_double(Sprint, length_in_days: 10, save: nil) }
|
35
|
+
|
36
|
+
let(:new_start_date) { get_date("2025-03-21 15:38") }
|
37
|
+
|
38
|
+
it "keeps the the sprint length unchanged" do
|
39
|
+
allow(sprint).to receive(:start_date=).with(new_start_date)
|
40
|
+
allow(sprint).to receive(:end_date=).with(get_date("2025-03-31 15:38"))
|
41
|
+
|
42
|
+
updater.shift_sprint_to_new_start_date(sprint, new_start_date)
|
43
|
+
|
44
|
+
expect(sprint).to have_received(:save)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# rubocop:disable RSpec/MultipleMemoizedHelpers
|
49
|
+
describe "#act_on_sprints_for_sprint_prefix" do
|
50
|
+
def get_sprint(name, attributes)
|
51
|
+
instance_double(Sprint, name: name, to_s: name, **attributes)
|
52
|
+
end
|
53
|
+
|
54
|
+
let(:a_sprint_that_should_not_change) { get_sprint "Food_Delivery_25.2.1", end_date: nil }
|
55
|
+
|
56
|
+
let(:a_that_should_get_a_new_end_date) do
|
57
|
+
get_sprint "Food_Delivery_25.2.2", end_date: get_date("2025-03-21 15:38")
|
58
|
+
end
|
59
|
+
|
60
|
+
let(:a_sprint_that_should_get_shifted_with_a_new_start_date) do
|
61
|
+
get_sprint "Food_Delivery_25.2.3", end_date: get_date("2025-03-31 15:38")
|
62
|
+
end
|
63
|
+
|
64
|
+
let(:sprints) do
|
65
|
+
[a_sprint_that_should_not_change,
|
66
|
+
a_that_should_get_a_new_end_date,
|
67
|
+
a_sprint_that_should_get_shifted_with_a_new_start_date]
|
68
|
+
end
|
69
|
+
|
70
|
+
let(:sprint_prefix) { instance_double(Sprint::Prefix, sprints: sprints) }
|
71
|
+
|
72
|
+
it "the prefix sprints as per expectations" do
|
73
|
+
expect(updater).to receive(:do_nothing).with(a_sprint_that_should_not_change, nil)
|
74
|
+
expect(updater).to receive(:update_sprint_end_date).with(a_that_should_get_a_new_end_date)
|
75
|
+
|
76
|
+
expect(updater).to receive(:shift_sprint_to_new_start_date).with(
|
77
|
+
a_sprint_that_should_get_shifted_with_a_new_start_date,
|
78
|
+
get_date("2025-03-21 15:38")
|
79
|
+
)
|
80
|
+
|
81
|
+
updater.act_on_sprints_for_sprint_prefix(sprint_prefix)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
# rubocop:enable RSpec/MultipleMemoizedHelpers
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rspec"
|
4
|
+
|
5
|
+
require "jira/auto/tool/performer/sprint_renamer/keep_same_name_generator"
|
6
|
+
|
7
|
+
RSpec.describe Jira::Auto::Tool::Performer::SprintRenamer::KeepSameNameGenerator do
|
8
|
+
let(:keep_same_name_generator) { described_class.new }
|
9
|
+
let(:sprint_name) { "random sprint name #{rand}" }
|
10
|
+
|
11
|
+
it { expect(keep_same_name_generator.name_for(sprint_name)).to eq(sprint_name) }
|
12
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rspec"
|
4
|
+
|
5
|
+
require "jira/auto/tool/performer/sprint_renamer/next_name_generator"
|
6
|
+
|
7
|
+
RSpec.describe Jira::Auto::Tool::Performer::SprintRenamer::NextNameGenerator do
|
8
|
+
def parsed_name(sprint_name)
|
9
|
+
Jira::Auto::Tool::Sprint::Name.parse(sprint_name)
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "#new_name_of_sprint_next_to_first_renamed_sprint" do
|
13
|
+
subject(:new_name) { next_name_generator.new_name_of_sprint_next_to_first_renamed_sprint }
|
14
|
+
|
15
|
+
let(:next_name_generator) do
|
16
|
+
described_class.new(original_name_of_first_renamed_sprint, name_of_first_renamed_sprint)
|
17
|
+
end
|
18
|
+
|
19
|
+
context "when pulling sprint into previous planning interval" do
|
20
|
+
let(:original_name_of_first_renamed_sprint) { "prefix_23.2.1" }
|
21
|
+
let(:name_of_first_renamed_sprint) { "prefix_23.1.6" }
|
22
|
+
|
23
|
+
it("returns the original sprint name") { expect(new_name).to eq(parsed_name("prefix_23.1.7")) }
|
24
|
+
end
|
25
|
+
|
26
|
+
context "when renaming inside planning interval" do
|
27
|
+
let(:original_name_of_first_renamed_sprint) { "prefix_23.2.1" }
|
28
|
+
let(:name_of_first_renamed_sprint) { "prefix_23.2.4" }
|
29
|
+
|
30
|
+
it { expect(new_name).to eq(parsed_name("prefix_23.2.5")) }
|
31
|
+
end
|
32
|
+
|
33
|
+
context "when pushing sprint into next planning interval" do
|
34
|
+
let(:original_name_of_first_renamed_sprint) { "prefix_23.1.5" }
|
35
|
+
let(:name_of_first_renamed_sprint) { "prefix_23.2.2" }
|
36
|
+
|
37
|
+
it("returns the original sprint parsed name") { expect(new_name).to eq(parsed_name("prefix_23.2.3")) }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "#pulling_sprint_into_previous_planning_interval?" do
|
42
|
+
let(:next_name_generator) do
|
43
|
+
described_class.new(original_name_of_first_renamed_sprint, name_of_first_renamed_sprint)
|
44
|
+
end
|
45
|
+
|
46
|
+
context "when sprint goes to the preceding planning interval" do
|
47
|
+
let(:original_name_of_first_renamed_sprint) { "prefix_26.1.1" }
|
48
|
+
let(:name_of_first_renamed_sprint) { "prefix_25.2.1" }
|
49
|
+
|
50
|
+
it { expect(next_name_generator).to be_pulling_sprint_into_previous_planning_interval }
|
51
|
+
end
|
52
|
+
|
53
|
+
context "when sprint is renamed backward inside the current preceding planning interval" do
|
54
|
+
let(:original_name_of_first_renamed_sprint) { "prefix_26.1.4" }
|
55
|
+
let(:name_of_first_renamed_sprint) { "prefix_26.1.1" }
|
56
|
+
|
57
|
+
it { expect(next_name_generator).not_to be_pulling_sprint_into_previous_planning_interval }
|
58
|
+
end
|
59
|
+
|
60
|
+
context "when sprint is renamed forward inside the current planning interval" do
|
61
|
+
let(:original_name_of_first_renamed_sprint) { "prefix_26.1.1" }
|
62
|
+
let(:name_of_first_renamed_sprint) { "prefix_26.1.4" }
|
63
|
+
|
64
|
+
it { expect(next_name_generator).not_to be_pulling_sprint_into_previous_planning_interval }
|
65
|
+
end
|
66
|
+
|
67
|
+
context "when sprint goes to the following planning interval" do
|
68
|
+
let(:original_name_of_first_renamed_sprint) { "prefix_25.1.5" }
|
69
|
+
let(:name_of_first_renamed_sprint) { "prefix_25.2.1" }
|
70
|
+
|
71
|
+
it { expect(next_name_generator).not_to be_pulling_sprint_into_previous_planning_interval }
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe "#next_name_in_planning_interval" do
|
76
|
+
let(:name_generator) { described_class.new(original_name_of_first_renamed_sprint, name_of_first_renamed_sprint) }
|
77
|
+
let(:next_names) { 4.times.collect { name_generator.next_name_in_planning_interval } }
|
78
|
+
|
79
|
+
context "when pulling to the previous planning interval" do
|
80
|
+
let(:original_name_of_first_renamed_sprint) { "prefix_25.2.1" }
|
81
|
+
let(:name_of_first_renamed_sprint) { "prefix_25.1.8" }
|
82
|
+
|
83
|
+
it "generates a new name consecutive to the previous one in the planning interval" do
|
84
|
+
expect(next_names).to eq(%w[prefix_25.1.9 prefix_25.1.10 prefix_25.1.11 prefix_25.1.12])
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
context "when renaming in the same planning interval" do
|
89
|
+
let(:original_name_of_first_renamed_sprint) { "prefix_25.1.5" }
|
90
|
+
let(:name_of_first_renamed_sprint) { "prefix_25.1.20" }
|
91
|
+
|
92
|
+
it "generates a new name consecutive to the previous one in the planning interval" do
|
93
|
+
expect(next_names).to eq(%w[prefix_25.1.21 prefix_25.1.22 prefix_25.1.23 prefix_25.1.24])
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
context "when pushing to the next planning interval" do
|
98
|
+
let(:original_name_of_first_renamed_sprint) { "prefix_25.1.5" }
|
99
|
+
let(:name_of_first_renamed_sprint) { "prefix_25.2.1" }
|
100
|
+
|
101
|
+
it "generates a new name consecutive to the previous one in the planning interval" do
|
102
|
+
expect(next_names).to eq(%w[prefix_25.2.2 prefix_25.2.3 prefix_25.2.4 prefix_25.2.5])
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe "#name_for" do
|
108
|
+
let(:name_generator) { described_class.new(original_name_of_first_renamed_sprint, name_of_first_renamed_sprint) }
|
109
|
+
let(:original_name_of_first_renamed_sprint) { "prefix_25.2.1" }
|
110
|
+
let(:name_of_first_renamed_sprint) { "prefix_25.1.8" }
|
111
|
+
|
112
|
+
context "when sprint name inside the planning interval" do
|
113
|
+
before do
|
114
|
+
allow(name_generator).to receive_messages(next_name_in_planning_interval: "next_name_in_planning_interval")
|
115
|
+
end
|
116
|
+
|
117
|
+
it { expect(name_generator.name_for("prefix_25.2.2")).to eq("next_name_in_planning_interval") }
|
118
|
+
end
|
119
|
+
|
120
|
+
context "when sprint name outside planning interval" do
|
121
|
+
let(:original_name_of_first_renamed_sprint) { "prefix_25.1.5" }
|
122
|
+
let(:name_of_first_renamed_sprint) { "prefix_25.2.20" }
|
123
|
+
|
124
|
+
it "generates a new name consecutive to the previous one in the planning interval" do
|
125
|
+
expect(name_generator.name_for("prefix_25.3.2")).to eq("prefix_25.2.21")
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|