ticket-replicator 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 (64) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/.rubocop.yml +20 -0
  4. data/CHANGELOG.md +5 -0
  5. data/CODE_OF_CONDUCT.md +132 -0
  6. data/Guardfile +158 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +136 -0
  9. data/Rakefile +23 -0
  10. data/bin/ticket-replicator +67 -0
  11. data/config/examples/ticket-replicator.mappings.yml +54 -0
  12. data/cucumber.yml +7 -0
  13. data/features/extract-sap-solution-manager-defect-tickets.feature +45 -0
  14. data/features/load_tickets_in_jira.feature +129 -0
  15. data/features/setup_ticket_replicator.feature +85 -0
  16. data/features/step_definitions/anonymized_sample.xlsx +0 -0
  17. data/features/step_definitions/anonymized_sample.xlsx:Zone.Identifier +3 -0
  18. data/features/step_definitions/execution_context_steps.rb +13 -0
  19. data/features/step_definitions/extract_defect_tickets_from_sap_solution_manager_steps.rb.rb +29 -0
  20. data/features/step_definitions/load_tickets_in_jira_steps.rb +47 -0
  21. data/features/step_definitions/transform_solution_manager_tickets_steps.rb +21 -0
  22. data/features/support/10.setup_cucumber.rb +10 -0
  23. data/features/support/env.rb +15 -0
  24. data/features/support/hooks.rb +13 -0
  25. data/features/support/manage_mock_sap_solution_manager.rb.DISABLED +12 -0
  26. data/features/support/mocks/mock_defect_ticket_server.rb.DISABLED +251 -0
  27. data/features/support/setup_rspec.rb +15 -0
  28. data/features/support/setup_simplecov.rb +5 -0
  29. data/features/transform-solution-manager-tickets-into-jira-loadable-tickets.feature +313 -0
  30. data/features/transform_and_load_extracted_ticket_queue.feature +121 -0
  31. data/lib/tasks/version.rake +55 -0
  32. data/lib/ticket/replicator/defect_export_automation.rb.DISABLED +128 -0
  33. data/lib/ticket/replicator/file_loader.rb +46 -0
  34. data/lib/ticket/replicator/file_replicator.rb +67 -0
  35. data/lib/ticket/replicator/file_transformer/for_csv.rb +22 -0
  36. data/lib/ticket/replicator/file_transformer/for_xlsx.rb +34 -0
  37. data/lib/ticket/replicator/file_transformer.rb +70 -0
  38. data/lib/ticket/replicator/jira_project.rb +65 -0
  39. data/lib/ticket/replicator/replicated_summary.rb +73 -0
  40. data/lib/ticket/replicator/row_loader.rb +109 -0
  41. data/lib/ticket/replicator/row_transformer.rb +126 -0
  42. data/lib/ticket/replicator/s_a_p_solution_manager_client.rb.DISABLED +169 -0
  43. data/lib/ticket/replicator/setup.rb +49 -0
  44. data/lib/ticket/replicator/ticket.rb +70 -0
  45. data/lib/ticket/replicator/ticket_status_transitioner.rb +45 -0
  46. data/lib/ticket/replicator/version.rb +7 -0
  47. data/lib/ticket/replicator.rb +90 -0
  48. data/sig/ticket/replicator.rbs +6 -0
  49. data/spec/spec_helper.rb +19 -0
  50. data/spec/ticket/replicator/file_loader_spec.rb +77 -0
  51. data/spec/ticket/replicator/file_replicator_spec.rb +153 -0
  52. data/spec/ticket/replicator/file_transformer/for_csv_spec.rb +52 -0
  53. data/spec/ticket/replicator/file_transformer/for_xlsx_spec.rb +52 -0
  54. data/spec/ticket/replicator/file_transformer_spec.rb +83 -0
  55. data/spec/ticket/replicator/jira_project_spec.rb +127 -0
  56. data/spec/ticket/replicator/replicated_summary_spec.rb +70 -0
  57. data/spec/ticket/replicator/row_loader_spec.rb +245 -0
  58. data/spec/ticket/replicator/row_transformer_spec.rb +234 -0
  59. data/spec/ticket/replicator/setup_spec.rb +80 -0
  60. data/spec/ticket/replicator/ticket_spec.rb +244 -0
  61. data/spec/ticket/replicator/ticket_status_transitioner_spec.rb +123 -0
  62. data/spec/ticket/replicator_spec.rb +137 -0
  63. data/transformed_file1 +1 -0
  64. metadata +235 -0
@@ -0,0 +1,245 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "ticket/replicator/row_loader"
4
+
5
+ module Ticket
6
+ # rubocop:disable Metrics/ClassLength
7
+ class Replicator
8
+ RSpec.describe RowLoader do
9
+ let(:loader) { described_class.send(:new, jira_project, :a_row) }
10
+
11
+ let(:jira_project) { instance_double(JiraProject, project_key: "PROJKEY", ticket_type_name: "Bug") }
12
+
13
+ describe ".run_on" do
14
+ it do
15
+ expect(described_class).to receive(:new).with(jira_project, :a_row).and_return(loader)
16
+ expect(loader).to receive(:run)
17
+
18
+ described_class.run_on(jira_project, :a_row)
19
+ end
20
+ end
21
+
22
+ describe ".fields_to_load" do
23
+ it { expect(described_class.fields_to_load).to eq(%i[id status resolution priority team summary]) }
24
+ end
25
+
26
+ describe "#run" do
27
+ it do
28
+ expect(loader).to receive(:save_ticket)
29
+ expect(loader).to receive(:transition_ticket_to_the_expected_status)
30
+
31
+ loader.run
32
+ end
33
+ end
34
+
35
+ describe "#jira_ticket" do
36
+ before { expect(loader).to receive(:ticket_previously_replicated?).and_return(previously_replicated?) }
37
+
38
+ context "when the ticket has yet to be replicated" do
39
+ let(:previously_replicated?) { false }
40
+
41
+ it do
42
+ expect(loader).to receive(:create_ticket)
43
+
44
+ loader.ticket
45
+ end
46
+ end
47
+
48
+ context "when the ticket was already replicated" do
49
+ let(:previously_replicated?) { true }
50
+
51
+ it do
52
+ expect(loader).to receive(:fetch_ticket)
53
+
54
+ loader.ticket
55
+ end
56
+ end
57
+ end
58
+
59
+ describe "#fetch_ticket" do
60
+ let(:loader) { described_class.send(:new, jira_project, { id: "123" }) }
61
+
62
+ let(:replicated_tickets) { { "123" => :a_ticket, "456" => :another_ticket } }
63
+
64
+ it do
65
+ expect(jira_project).to receive(:replicated_tickets).and_return(replicated_tickets)
66
+
67
+ expect(loader.fetch_ticket).to be(:a_ticket)
68
+ end
69
+ end
70
+
71
+ describe "#create_ticket" do
72
+ let(:loader) { described_class.send(:new, jira_project, {}) }
73
+ let(:jira_auto_tool) { instance_double(Jira::Auto::Tool, jira_client: jira_client) }
74
+ let(:jira_client) { instance_double(JIRA::Client, Issue: issue_accessor) }
75
+ let(:issue_accessor) { double("jira_client.Issue") }
76
+
77
+ let(:jira_ticket) { instance_double(JIRA::Resource::Issue) }
78
+
79
+ let(:jira_project) do
80
+ instance_double(JiraProject, jira_client: jira_client, jira_auto_tool: jira_auto_tool)
81
+ end
82
+
83
+ it do
84
+ expect(issue_accessor).to receive(:build).and_return(jira_ticket)
85
+ expect(Ticket).to receive(:new).with(jira_auto_tool, jira_ticket).and_return(:ticket)
86
+
87
+ expect(loader.create_ticket).to eq(:ticket)
88
+ end
89
+ end
90
+
91
+ describe "#save_ticket" do
92
+ let(:loader) { described_class.send(:new, jira_project, row) }
93
+
94
+ let(:row) do
95
+ { id: "123", priority: "Low", resolution: "", status: "Open", summary: "PREFIX | summary", team: "A Team" }
96
+ end
97
+
98
+ let(:ticket) { instance_double(Ticket, jira_ticket: jira_ticket) }
99
+
100
+ let(:jira_ticket) { double(JIRA::Resource::Issue) }
101
+
102
+ before do
103
+ allow(loader).to receive_messages(ticket: ticket,
104
+ :ticket_fields_need_to_be_updated? => ticket_fields_need_to_be_updated?)
105
+ end
106
+
107
+ context "when the previously replicated needs to be updated " do
108
+ let(:ticket_fields_need_to_be_updated?) { true }
109
+
110
+ it do
111
+ expect(jira_ticket).to receive(:save!).with({
112
+ fields: {
113
+ project: { key: "PROJKEY" },
114
+ issuetype: { name: "Bug" },
115
+ # resolution: { name: "" },
116
+ priority: { name: "Low" },
117
+ # team: { name: "A Team" },
118
+ summary: "PREFIX | summary"
119
+ }
120
+ })
121
+
122
+ expect(jira_ticket).to receive(:fetch)
123
+
124
+ loader.save_ticket
125
+ end
126
+ end
127
+
128
+ context "when the previously replicated ticket is already up to date" do
129
+ let(:ticket_fields_need_to_be_updated?) { false }
130
+
131
+ it do
132
+ expect(jira_ticket).not_to receive(:save!)
133
+ expect(jira_ticket).not_to receive(:fetch)
134
+
135
+ loader.save_ticket
136
+ end
137
+ end
138
+ end
139
+
140
+ describe "#ticket_fields_need_to_be_updated?" do
141
+ before do
142
+ allow(loader).to receive_messages(ticket_previously_replicated?: ticket_previously_replicated?,
143
+ ticket_fields_changed?: ticket_fields_changed?)
144
+ end
145
+
146
+ context "when has yet to be replicated" do
147
+ let(:ticket_previously_replicated?) { false }
148
+ let(:ticket_fields_changed?) { false }
149
+
150
+ it { expect(loader.ticket_fields_need_to_be_updated?).to be_truthy }
151
+ end
152
+
153
+ context "when the fields changed since last replication" do
154
+ let(:ticket_previously_replicated?) { true }
155
+ let(:ticket_fields_changed?) { true }
156
+
157
+ it { expect(loader.ticket_fields_need_to_be_updated?).to be_truthy }
158
+ end
159
+
160
+ context "when the fields did not change since last replication" do
161
+ let(:ticket_previously_replicated?) { true }
162
+ let(:ticket_fields_changed?) { false }
163
+
164
+ it { expect(loader.ticket_fields_need_to_be_updated?).to be_falsey }
165
+ end
166
+ end
167
+
168
+ describe "#ticket_fields_changed?" do
169
+ let(:row) do
170
+ { id: "123", priority: "Low", resolution: "", status: "Open", summary: "PREFIX | summary", team: "A Team" }
171
+ end
172
+
173
+ let(:loader) { described_class.send(:new, jira_project, row) }
174
+ let(:jira_ticket) { double(JIRA::Resource::Issue, summary: current_summary, priority: current_priority) }
175
+
176
+ before do
177
+ expect(loader).to receive(:ticket).at_least(:once).and_return(jira_ticket)
178
+ end
179
+
180
+ context "when both summary and priority changed" do
181
+ let(:current_summary) { "PREFIX | different summary" }
182
+ let(:current_priority) { "High" }
183
+
184
+ it { expect(loader.ticket_fields_changed?).to be_truthy }
185
+ end
186
+
187
+ context "when only summary changed" do
188
+ let(:current_summary) { "PREFIX | different summary" }
189
+ let(:current_priority) { "Low" }
190
+
191
+ it { expect(loader.ticket_fields_changed?).to be_truthy }
192
+ end
193
+
194
+ context "when only priority changed" do
195
+ let(:current_summary) { "PREFIX | summary" }
196
+ let(:current_priority) { "High" }
197
+
198
+ it { expect(loader.ticket_fields_changed?).to be_truthy }
199
+ end
200
+
201
+ context "when neither summary nor priority changed" do
202
+ let(:current_summary) { "PREFIX | summary" }
203
+ let(:current_priority) { "Low" }
204
+
205
+ it { expect(loader.ticket_fields_changed?).to be_falsey }
206
+ end
207
+ end
208
+
209
+ describe "#ticket_previously_replicated?" do
210
+ let(:loader) { described_class.send(:new, jira_project, row) }
211
+ let(:replicated_tickets) { { "123" => "a_ticket" } }
212
+
213
+ before { expect(jira_project).to receive(:replicated_tickets).and_return(replicated_tickets) }
214
+
215
+ context "when previously replicated" do
216
+ let(:row) { { id: "123" } }
217
+
218
+ it { expect(loader.ticket_previously_replicated?).to be_truthy }
219
+ end
220
+
221
+ context "when previously replicated" do
222
+ let(:row) { { id: "456" } }
223
+
224
+ it { expect(loader.ticket_previously_replicated?).to be_falsey }
225
+ end
226
+ end
227
+
228
+ describe "#transition_ticket_to_the_expected_status" do
229
+ let(:loader) { described_class.send(:new, jira_project, row) }
230
+ let(:row) { { id: "123", status: "Testing" } }
231
+
232
+ let(:ticket) { double(Ticket) }
233
+
234
+ it do
235
+ expect(loader).to receive(:ticket).at_least(:once).and_return(ticket)
236
+ expect(ticket).to receive(:transition_to).with("Testing")
237
+
238
+ loader.transition_ticket_to_the_expected_status
239
+ end
240
+ end
241
+ end
242
+ end
243
+
244
+ # rubocop:enable Metrics/ClassLength
245
+ end
@@ -0,0 +1,234 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "ticket/replicator/row_transformer"
4
+
5
+ RSpec.describe Ticket::Replicator::RowTransformer do
6
+ let(:transformer) { described_class.send(:new, extracted_row) }
7
+
8
+ describe ".run_on" do
9
+ let(:extracted_row) { :a_row_to_transform }
10
+
11
+ it "transforms the given file" do
12
+ expect(described_class).to receive(:new).with(:a_row_to_transform).and_return(transformer)
13
+
14
+ expect(transformer).to receive(:run)
15
+
16
+ described_class.run_on(:a_row_to_transform)
17
+ end
18
+ end
19
+
20
+ describe "#run" do
21
+ let(:extracted_row) do
22
+ {
23
+ id: "123",
24
+ status: "Open",
25
+ priority: "4 - Low",
26
+ team: "Source Team",
27
+ summary: "summary"
28
+ }
29
+ end
30
+
31
+ it "transforms a row" do
32
+ allow(transformer).to receive(:transformed_id).and_return("123")
33
+ allow(transformer).to receive(:transformed_status).and_return("Open")
34
+ allow(transformer).to receive(:transformed_resolution).and_return("")
35
+ allow(transformer).to receive(:transformed_priority).and_return("Low")
36
+ allow(transformer).to receive(:transformed_team).and_return("Transformed Team")
37
+ allow(transformer).to receive(:transformed_summary).and_return("transformed summary (123)")
38
+
39
+ expect(transformer.run)
40
+ .to eq(["123", "Open", "", "Low", "Transformed Team", "transformed summary (123)"])
41
+ end
42
+ end
43
+
44
+ describe "#mappings" do
45
+ let(:mappings_yaml) do
46
+ <<~YAML
47
+ field_mapping:
48
+ id: Defect
49
+ summary: Defect (2)
50
+ status_mapping:
51
+ defaults_to: keep_original_value
52
+ Open: Open
53
+ Closed: Closed
54
+ resolution_mapping:
55
+ Closed: Done
56
+ Rejected: Won't Fix
57
+ team_mapping:
58
+ Source Team: Transformed Team
59
+ Front End: Web Team
60
+ priority_mapping:
61
+ 1 - Critical: Critical
62
+ 2 - High: High
63
+ 3 - Medium: Medium
64
+ 4 - Low: Low
65
+ YAML
66
+ end
67
+
68
+ let(:extracted_row) { {} }
69
+
70
+ let(:file_io) { instance_double(IO) }
71
+
72
+ it "loads the mappings from the mappings.yml file" do
73
+ expect(IO).to receive(:open).with("config/ticket-replicator.mappings.yml", "r:bom|utf-8").and_yield(mappings_yaml)
74
+
75
+ expect(transformer.mappings)
76
+ .to eq(
77
+ "field_mapping" => { "id" => "Defect", "summary" => "Defect (2)" },
78
+ "status_mapping" => { "defaults_to" => "keep_original_value", "Open" => "Open", "Closed" => "Closed" },
79
+ "resolution_mapping" => { "Closed" => "Done", "Rejected" => "Won't Fix" },
80
+ "team_mapping" => { "Source Team" => "Transformed Team", "Front End" => "Web Team" },
81
+ "priority_mapping" =>
82
+ { "1 - Critical" => "Critical", "2 - High" => "High", "3 - Medium" => "Medium", "4 - Low" => "Low" }
83
+ )
84
+ end
85
+ end
86
+
87
+ describe "using mappings" do
88
+ before { allow(transformer).to receive_messages(mappings: mappings) }
89
+
90
+ describe "#remapped_field_extracted_row" do
91
+ let(:mappings) do
92
+ {
93
+ "field_mapping" => {
94
+ "id" => "Defect", "priority" => "Defect Priority", "resolution" => "Defect (2)",
95
+ "status" => "Defect status", "summary" => "Defect (2)", "team" => "Defect Team (2)"
96
+ }
97
+ }
98
+ end
99
+
100
+ let(:extracted_row) do
101
+ {
102
+ "defect (2)" => "a summary", "defect priority" => "High", "defect status" => "Open",
103
+ "defect team (2)" => "system team", "defect" => "123"
104
+ }
105
+ end
106
+
107
+ it do
108
+ expect(transformer.remapped_field_extracted_row)
109
+ .to eq({ "id" => "123", "priority" => "High", "resolution" => "a summary",
110
+ "status" => "Open", "summary" => "a summary", "team" => "system team" })
111
+ end
112
+ end
113
+
114
+ # rubocop:disable Metrics/BlockLength
115
+ context "when remapped field extracted row used" do
116
+ let(:extracted_row) { { :extracted_row => "should not be used in this context but the remapped version" } }
117
+
118
+ before { allow(transformer).to receive_messages(remapped_field_extracted_row: remapped_field_extracted_row) }
119
+
120
+ describe "#transformed_id" do
121
+ let(:remapped_field_extracted_row) { { "id" => "123" } }
122
+ let(:mappings) { {} }
123
+
124
+ it "returns the ID" do
125
+ expect(transformer.transformed_id).to eq("123")
126
+ end
127
+ end
128
+
129
+ describe "#transformed_summary" do
130
+ let(:remapped_field_extracted_row) { { "id" => "426", "summary" => "a summary" } }
131
+ let(:mappings) { {} }
132
+
133
+ before do
134
+ allow(Ticket::Replicator::ReplicatedSummary)
135
+ .to receive(:build).with("426", "a summary").and_return("replicated_summary")
136
+ end
137
+
138
+ it "returns the summary" do
139
+ expect(transformer.transformed_summary).to eq("replicated_summary")
140
+ end
141
+ end
142
+
143
+ shared_examples "an unmapped value handler" do |field_name, source_field|
144
+ source_field ||= field_name
145
+
146
+ let(:remapped_field_extracted_row) { { source_field.to_s => an_original_value } }
147
+
148
+ let(:an_original_value) { "any #{field_name} #{rand}" }
149
+
150
+ let(:transformed_value) { transformer.send("transformed_#{field_name}") }
151
+
152
+ context "when defaulting to original value" do
153
+ let(:mappings) { { "#{field_name}_mapping" => { "defaults_to" => "keep_original_value" } } }
154
+
155
+ it { expect(transformed_value).to eq(an_original_value) }
156
+ end
157
+
158
+ context "when the status is unexpected" do
159
+ let(:mappings) do
160
+ { "#{field_name}_mapping" => { "extracted value" => "transformed value" } }
161
+ end
162
+
163
+ it do
164
+ expect { transformed_value }
165
+ .to raise_error(RuntimeError,
166
+ "No mapping found for #{field_name.inspect} = #{an_original_value.inspect} " \
167
+ "in #{mappings["#{field_name}_mapping"].inspect}")
168
+ end
169
+ end
170
+ end
171
+
172
+ describe "#transformed_status" do
173
+ let(:mappings) do
174
+ { "status_mapping" => { "Open" => "Open", "Closed" => "Closed" } }
175
+ end
176
+
177
+ let(:remapped_field_extracted_row) { { "status" => "Open" } }
178
+
179
+ it "returns the status" do
180
+ expect(transformer.transformed_status).to eq("Open")
181
+ end
182
+
183
+ it_behaves_like "an unmapped value handler", :status
184
+ end
185
+
186
+ describe "#transformed_resolution" do
187
+ let(:mappings) { { "resolution_mapping" => { "Closed" => "Done", "Rejected" => "Won't Fix" } } }
188
+
189
+ context "when the status is Closed" do
190
+ let(:remapped_field_extracted_row) { { "status" => "Closed" } }
191
+
192
+ it "returns the resolution" do
193
+ expect(transformer.transformed_resolution).to eq("Done")
194
+ end
195
+ end
196
+
197
+ context "when the status is Rejected" do
198
+ let(:remapped_field_extracted_row) { { "status" => "Rejected" } }
199
+
200
+ it "returns the resolution" do
201
+ expect(transformer.transformed_resolution).to eq("Won't Fix")
202
+ end
203
+ end
204
+
205
+ it_behaves_like "an unmapped value handler", :resolution, :status
206
+ end
207
+
208
+ describe "#transformed_team" do
209
+ let(:mappings) { { "team_mapping" => { "Source Team" => "Transformed Team", "Front End" => "Web Team" } } }
210
+
211
+ let(:remapped_field_extracted_row) { { "team" => "Source Team" } }
212
+
213
+ it "returns the team" do
214
+ expect(transformer.transformed_team).to eq("Transformed Team")
215
+ end
216
+
217
+ it_behaves_like "an unmapped value handler", :team
218
+ end
219
+
220
+ describe "#transformed_priority" do
221
+ let(:mappings) { { "priority_mapping" => { "1 - Critical" => "Critical", "2 - High" => "High" } } }
222
+
223
+ let(:remapped_field_extracted_row) { { "priority" => "1 - Critical" } }
224
+
225
+ it "returns the priority" do
226
+ expect(transformer.transformed_priority).to eq("Critical")
227
+ end
228
+
229
+ it_behaves_like "an unmapped value handler", :priority
230
+ end
231
+ end
232
+ # rubocop:enable Metrics/BlockLength
233
+ end
234
+ end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "ticket/replicator/setup"
4
+
5
+ module Ticket
6
+ class Replicator
7
+ class Setup
8
+ RSpec.describe Setup do
9
+ let(:setup) { described_class.new(replicator) }
10
+ let(:replicator) { instance_double(Replicator) }
11
+ let(:logger) { instance_double(Logger, info: nil, error: nil) }
12
+
13
+ before { allow(setup).to receive_messages(log: logger) }
14
+
15
+ describe "#run" do
16
+ it do
17
+ expect(setup).to receive(:create_queue)
18
+ expect(setup).to receive(:create_initial_configuration)
19
+
20
+ setup.run
21
+ end
22
+ end
23
+
24
+ describe "#create_queue" do
25
+ it do
26
+ expect(replicator).to receive(:extracted_folder).and_return("queue/10.extracted")
27
+
28
+ expect(logger).to receive(:info).with(%(Created folder "queue/10.extracted"))
29
+
30
+ setup.send(:create_queue)
31
+ end
32
+ end
33
+
34
+ describe "#create_initial_configuration" do
35
+ let(:expected_config_path) { "config/ticket-replicator.mappings.yml" }
36
+
37
+ before { allow(File).to receive(:exist?).with(expected_config_path).and_return(config_exists) }
38
+
39
+ context "when the config file does not exist" do
40
+ let(:config_exists) { false }
41
+
42
+ it do
43
+ allow(setup).to receive_messages(example_config_file_path: "path/to/example_config.yml")
44
+
45
+ expect(FileUtils).to receive(:mkdir_p).with("config")
46
+
47
+ expect(FileUtils).to receive(:cp).with("path/to/example_config.yml", expected_config_path)
48
+
49
+ expect(logger).to receive(:info) do |&block|
50
+ expect(block.call).to eq("Created file #{expected_config_path.inspect}")
51
+ end
52
+
53
+ setup.send(:create_initial_configuration)
54
+ end
55
+ end
56
+
57
+ context "when the config file already exists" do
58
+ let(:config_exists) { true }
59
+
60
+ it "does not overwrite it" do
61
+ expect(FileUtils).not_to receive(:cp)
62
+
63
+ expect { setup.send(:create_initial_configuration) }
64
+ .to raise_error(SetupError, "Not overwriting existing config file #{expected_config_path.inspect}")
65
+ end
66
+ end
67
+ end
68
+
69
+ describe "#example_config_file_path" do
70
+ it do
71
+ allow(replicator).to receive_messages(home_dir: "REPLICATOR_HOME")
72
+
73
+ expect(setup.send(:example_config_file_path))
74
+ .to eq("REPLICATOR_HOME/config/examples/ticket-replicator.mappings.yml")
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end