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,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
|