csvops 0.4.0.alpha → 0.6.0.alpha

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 (120) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +60 -12
  3. data/docs/architecture.md +208 -21
  4. data/docs/release-v0.5.0-alpha.md +89 -0
  5. data/docs/release-v0.6.0-alpha.md +84 -0
  6. data/lib/csvtool/application/use_cases/run_cross_csv_dedupe.rb +17 -14
  7. data/lib/csvtool/application/use_cases/run_csv_parity.rb +70 -0
  8. data/lib/csvtool/application/use_cases/run_extraction.rb +63 -88
  9. data/lib/csvtool/application/use_cases/run_row_extraction.rb +45 -73
  10. data/lib/csvtool/application/use_cases/run_row_randomization.rb +56 -73
  11. data/lib/csvtool/cli.rb +11 -7
  12. data/lib/csvtool/domain/csv_parity_session/parity_options.rb +22 -0
  13. data/lib/csvtool/domain/csv_parity_session/parity_session.rb +20 -0
  14. data/lib/csvtool/domain/csv_parity_session/source_pair.rb +19 -0
  15. data/lib/csvtool/infrastructure/csv/csv_parity_comparator.rb +71 -0
  16. data/lib/csvtool/infrastructure/output/csv_cross_csv_dedupe_file_writer.rb +23 -0
  17. data/lib/csvtool/infrastructure/output/csv_file_writer.rb +1 -7
  18. data/lib/csvtool/infrastructure/output/csv_randomized_row_file_writer.rb +23 -0
  19. data/lib/csvtool/infrastructure/output/csv_row_file_writer.rb +2 -9
  20. data/lib/csvtool/interface/cli/errors/presenter.rb +4 -0
  21. data/lib/csvtool/interface/cli/menu_loop.rb +5 -2
  22. data/lib/csvtool/interface/cli/prompts/dedupe_key_selector_prompt.rb +30 -0
  23. data/lib/csvtool/interface/cli/prompts/file_path_prompt.rb +4 -2
  24. data/lib/csvtool/interface/cli/prompts/headers_present_prompt.rb +4 -2
  25. data/lib/csvtool/interface/cli/prompts/separator_prompt.rb +4 -2
  26. data/lib/csvtool/interface/cli/prompts/yes_no_prompt.rb +26 -0
  27. data/lib/csvtool/interface/cli/workflows/builders/column_session_builder.rb +32 -0
  28. data/lib/csvtool/interface/cli/workflows/builders/cross_csv_dedupe_session_builder.rb +35 -0
  29. data/lib/csvtool/interface/cli/workflows/builders/csv_parity_session_builder.rb +33 -0
  30. data/lib/csvtool/interface/cli/workflows/builders/row_extraction_session_builder.rb +22 -0
  31. data/lib/csvtool/interface/cli/workflows/builders/row_randomization_session_builder.rb +28 -0
  32. data/lib/csvtool/interface/cli/workflows/presenters/column_extraction_presenter.rb +25 -0
  33. data/lib/csvtool/interface/cli/workflows/presenters/cross_csv_dedupe_presenter.rb +39 -0
  34. data/lib/csvtool/interface/cli/workflows/presenters/csv_parity_presenter.rb +38 -0
  35. data/lib/csvtool/interface/cli/workflows/presenters/row_extraction_presenter.rb +34 -0
  36. data/lib/csvtool/interface/cli/workflows/presenters/row_randomization_presenter.rb +34 -0
  37. data/lib/csvtool/interface/cli/workflows/run_cross_csv_dedupe_workflow.rb +48 -125
  38. data/lib/csvtool/interface/cli/workflows/run_csv_parity_workflow.rb +66 -0
  39. data/lib/csvtool/interface/cli/workflows/run_extraction_workflow.rb +88 -0
  40. data/lib/csvtool/interface/cli/workflows/run_row_extraction_workflow.rb +86 -0
  41. data/lib/csvtool/interface/cli/workflows/run_row_randomization_workflow.rb +80 -0
  42. data/lib/csvtool/interface/cli/workflows/steps/cross_csv_dedupe/collect_options_step.rb +55 -0
  43. data/lib/csvtool/interface/cli/workflows/steps/cross_csv_dedupe/collect_profiles_step.rb +52 -0
  44. data/lib/csvtool/interface/cli/workflows/steps/cross_csv_dedupe/execute_step.rb +34 -0
  45. data/lib/csvtool/interface/cli/workflows/steps/extraction/build_preview_step.rb +40 -0
  46. data/lib/csvtool/interface/cli/workflows/steps/extraction/collect_destination_step.rb +28 -0
  47. data/lib/csvtool/interface/cli/workflows/steps/extraction/collect_inputs_step.rb +47 -0
  48. data/lib/csvtool/interface/cli/workflows/steps/extraction/execute_step.rb +32 -0
  49. data/lib/csvtool/interface/cli/workflows/steps/parity/build_session_step.rb +25 -0
  50. data/lib/csvtool/interface/cli/workflows/steps/parity/collect_inputs_step.rb +32 -0
  51. data/lib/csvtool/interface/cli/workflows/steps/parity/execute_step.rb +26 -0
  52. data/lib/csvtool/interface/cli/workflows/steps/row_extraction/collect_destination_step.rb +33 -0
  53. data/lib/csvtool/interface/cli/workflows/steps/row_extraction/collect_range_step.rb +35 -0
  54. data/lib/csvtool/interface/cli/workflows/steps/row_extraction/collect_source_step.rb +32 -0
  55. data/lib/csvtool/interface/cli/workflows/steps/row_extraction/execute_step.rb +43 -0
  56. data/lib/csvtool/interface/cli/workflows/steps/row_extraction/read_headers_step.rb +29 -0
  57. data/lib/csvtool/interface/cli/workflows/steps/row_randomization/collect_destination_step.rb +34 -0
  58. data/lib/csvtool/interface/cli/workflows/steps/row_randomization/collect_inputs_step.rb +49 -0
  59. data/lib/csvtool/interface/cli/workflows/steps/row_randomization/execute_step.rb +37 -0
  60. data/lib/csvtool/interface/cli/workflows/steps/workflow_step_pipeline.rb +25 -0
  61. data/lib/csvtool/interface/cli/workflows/support/output_destination_mapper.rb +23 -0
  62. data/lib/csvtool/interface/cli/workflows/support/result_error_handler.rb +22 -0
  63. data/lib/csvtool/version.rb +1 -1
  64. data/test/csvtool/application/use_cases/io_boundary_test.rb +26 -0
  65. data/test/csvtool/application/use_cases/run_cross_csv_dedupe_test.rb +28 -0
  66. data/test/csvtool/application/use_cases/run_csv_parity_test.rb +160 -0
  67. data/test/csvtool/application/use_cases/run_extraction_test.rb +72 -16
  68. data/test/csvtool/application/use_cases/run_row_extraction_test.rb +82 -102
  69. data/test/csvtool/application/use_cases/run_row_randomization_test.rb +96 -86
  70. data/test/csvtool/cli_test.rb +175 -21
  71. data/test/csvtool/cli_unit_test.rb +4 -4
  72. data/test/csvtool/domain/csv_parity_session/parity_options_test.rb +17 -0
  73. data/test/csvtool/domain/csv_parity_session/parity_session_test.rb +18 -0
  74. data/test/csvtool/domain/csv_parity_session/source_pair_test.rb +11 -0
  75. data/test/csvtool/infrastructure/csv/csv_parity_comparator_test.rb +78 -0
  76. data/test/csvtool/infrastructure/output/csv_cross_csv_dedupe_file_writer_test.rb +32 -0
  77. data/test/csvtool/infrastructure/output/csv_file_writer_test.rb +0 -4
  78. data/test/csvtool/infrastructure/output/csv_randomized_row_file_writer_test.rb +32 -0
  79. data/test/csvtool/infrastructure/output/csv_row_file_writer_test.rb +1 -4
  80. data/test/csvtool/interface/cli/errors/presenter_test.rb +2 -0
  81. data/test/csvtool/interface/cli/menu_loop_test.rb +59 -16
  82. data/test/csvtool/interface/cli/prompts/dedupe_key_selector_prompt_test.rb +30 -0
  83. data/test/csvtool/interface/cli/prompts/file_path_prompt_test.rb +9 -0
  84. data/test/csvtool/interface/cli/prompts/headers_present_prompt_test.rb +10 -0
  85. data/test/csvtool/interface/cli/prompts/separator_prompt_test.rb +10 -0
  86. data/test/csvtool/interface/cli/prompts/yes_no_prompt_test.rb +22 -0
  87. data/test/csvtool/interface/cli/workflows/builders/column_session_builder_test.rb +17 -0
  88. data/test/csvtool/interface/cli/workflows/builders/cross_csv_dedupe_session_builder_test.rb +36 -0
  89. data/test/csvtool/interface/cli/workflows/builders/csv_parity_session_builder_test.rb +20 -0
  90. data/test/csvtool/interface/cli/workflows/builders/row_extraction_session_builder_test.rb +21 -0
  91. data/test/csvtool/interface/cli/workflows/builders/row_randomization_session_builder_test.rb +26 -0
  92. data/test/csvtool/interface/cli/workflows/presenters/column_extraction_presenter_test.rb +24 -0
  93. data/test/csvtool/interface/cli/workflows/presenters/cross_csv_dedupe_presenter_test.rb +30 -0
  94. data/test/csvtool/interface/cli/workflows/presenters/csv_parity_presenter_test.rb +43 -0
  95. data/test/csvtool/interface/cli/workflows/presenters/row_extraction_presenter_test.rb +33 -0
  96. data/test/csvtool/interface/cli/workflows/presenters/row_randomization_presenter_test.rb +33 -0
  97. data/test/csvtool/interface/cli/workflows/run_csv_parity_workflow_test.rb +94 -0
  98. data/test/csvtool/interface/cli/workflows/run_extraction_workflow_test.rb +56 -0
  99. data/test/csvtool/interface/cli/workflows/run_row_extraction_workflow_test.rb +83 -0
  100. data/test/csvtool/interface/cli/workflows/run_row_randomization_workflow_test.rb +69 -0
  101. data/test/csvtool/interface/cli/workflows/steps/cross_csv_dedupe/collect_options_step_test.rb +41 -0
  102. data/test/csvtool/interface/cli/workflows/steps/extraction/collect_inputs_step_test.rb +66 -0
  103. data/test/csvtool/interface/cli/workflows/steps/parity/build_session_step_test.rb +41 -0
  104. data/test/csvtool/interface/cli/workflows/steps/parity/collect_inputs_step_test.rb +30 -0
  105. data/test/csvtool/interface/cli/workflows/steps/parity/execute_step_test.rb +40 -0
  106. data/test/csvtool/interface/cli/workflows/steps/row_extraction/collect_source_step_test.rb +39 -0
  107. data/test/csvtool/interface/cli/workflows/steps/row_extraction/execute_step_test.rb +91 -0
  108. data/test/csvtool/interface/cli/workflows/steps/row_extraction/read_headers_step_test.rb +57 -0
  109. data/test/csvtool/interface/cli/workflows/steps/row_randomization/collect_inputs_step_test.rb +37 -0
  110. data/test/csvtool/interface/cli/workflows/steps/workflow_step_pipeline_test.rb +30 -0
  111. data/test/csvtool/interface/cli/workflows/support/output_destination_mapper_test.rb +23 -0
  112. data/test/csvtool/interface/cli/workflows/support/result_error_handler_test.rb +34 -0
  113. data/test/fixtures/parity_duplicates_left.csv +4 -0
  114. data/test/fixtures/parity_duplicates_right.csv +3 -0
  115. data/test/fixtures/parity_people_header_mismatch.csv +4 -0
  116. data/test/fixtures/parity_people_many_reordered.csv +13 -0
  117. data/test/fixtures/parity_people_mismatch.csv +4 -0
  118. data/test/fixtures/parity_people_reordered.csv +4 -0
  119. data/test/fixtures/parity_people_reordered.tsv +4 -0
  120. metadata +90 -1
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../../../../../test_helper"
4
+ require "csvtool/interface/cli/workflows/steps/row_extraction/execute_step"
5
+
6
+ class ExecuteStepTest < Minitest::Test
7
+ Result = Struct.new(:ok, :data) do
8
+ def ok? = ok
9
+ end
10
+
11
+ class FakeUseCase
12
+ def initialize(result)
13
+ @result = result
14
+ end
15
+
16
+ def extract(session:, headers:, on_row:)
17
+ @called = true
18
+ on_row.call(["Bob", "Paris"]) if @result.ok?
19
+ @result
20
+ end
21
+
22
+ attr_reader :called
23
+ end
24
+
25
+ class FakePresenter
26
+ attr_reader :rows, :written
27
+
28
+ def initialize(stdout:, headers:, col_sep:)
29
+ @rows = []
30
+ @written = nil
31
+ end
32
+
33
+ def print_row(fields)
34
+ @rows << fields
35
+ end
36
+
37
+ def print_file_written(path)
38
+ @written = path
39
+ end
40
+ end
41
+
42
+ class FakeErrors
43
+ attr_reader :out_of_bounds
44
+
45
+ def row_range_out_of_bounds(count)
46
+ @out_of_bounds = count
47
+ end
48
+ end
49
+
50
+ def test_prints_rows_and_reports_out_of_bounds
51
+ errors = FakeErrors.new
52
+ step = Csvtool::Interface::CLI::Workflows::Steps::RowExtraction::ExecuteStep.new(
53
+ stdout: StringIO.new,
54
+ errors: errors,
55
+ presenter_class: FakePresenter
56
+ )
57
+ use_case = FakeUseCase.new(Result.new(true, { matched: false, row_count: 3, wrote_rows: false }))
58
+ context = {
59
+ session: Object.new,
60
+ headers: ["name", "city"],
61
+ use_case: use_case,
62
+ handle_error: ->(_r) { raise "unexpected" }
63
+ }
64
+
65
+ result = step.call(context)
66
+
67
+ assert_nil result
68
+ assert_equal 3, errors.out_of_bounds
69
+ end
70
+
71
+ def test_halts_on_use_case_failure
72
+ handled = []
73
+ step = Csvtool::Interface::CLI::Workflows::Steps::RowExtraction::ExecuteStep.new(
74
+ stdout: StringIO.new,
75
+ errors: FakeErrors.new,
76
+ presenter_class: FakePresenter
77
+ )
78
+ fail_result = Result.new(false, {})
79
+ use_case = FakeUseCase.new(fail_result)
80
+
81
+ result = step.call(
82
+ session: Object.new,
83
+ headers: ["name", "city"],
84
+ use_case: use_case,
85
+ handle_error: ->(r) { handled << r }
86
+ )
87
+
88
+ assert_equal :halt, result
89
+ assert_equal [fail_result], handled
90
+ end
91
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../../../../../test_helper"
4
+ require "csvtool/interface/cli/workflows/steps/row_extraction/read_headers_step"
5
+
6
+ class ReadHeadersStepTest < Minitest::Test
7
+ Result = Struct.new(:ok, :data) do
8
+ def ok? = ok
9
+ end
10
+
11
+ class FakeUseCase
12
+ def initialize(result)
13
+ @result = result
14
+ end
15
+
16
+ def read_headers(file_path:, col_sep:)
17
+ @file_path = file_path
18
+ @col_sep = col_sep
19
+ @result
20
+ end
21
+
22
+ attr_reader :file_path, :col_sep
23
+ end
24
+
25
+ def test_sets_headers_on_success
26
+ use_case = FakeUseCase.new(Result.new(true, { headers: ["name", "city"] }))
27
+ step = Csvtool::Interface::CLI::Workflows::Steps::RowExtraction::ReadHeadersStep.new
28
+ context = {
29
+ use_case: use_case,
30
+ file_path: "/tmp/data.csv",
31
+ col_sep: ",",
32
+ handle_error: ->(_result) { raise "should not be called" }
33
+ }
34
+
35
+ result = step.call(context)
36
+
37
+ assert_nil result
38
+ assert_equal ["name", "city"], context[:headers]
39
+ end
40
+
41
+ def test_halts_and_routes_error_when_failure
42
+ failing_result = Result.new(false, {})
43
+ use_case = FakeUseCase.new(failing_result)
44
+ handled = []
45
+ step = Csvtool::Interface::CLI::Workflows::Steps::RowExtraction::ReadHeadersStep.new
46
+
47
+ result = step.call(
48
+ use_case: use_case,
49
+ file_path: "/tmp/data.csv",
50
+ col_sep: ",",
51
+ handle_error: ->(r) { handled << r }
52
+ )
53
+
54
+ assert_equal :halt, result
55
+ assert_equal [failing_result], handled
56
+ end
57
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../../../../../test_helper"
4
+ require "csvtool/interface/cli/workflows/steps/row_randomization/collect_inputs_step"
5
+ require "csvtool/interface/cli/prompts/seed_prompt"
6
+
7
+ class RowRandomizationCollectInputsStepTest < Minitest::Test
8
+ Result = Struct.new(:ok, :data) do
9
+ def ok? = ok
10
+ end
11
+
12
+ class FakeUseCase
13
+ def read_headers(file_path:, col_sep:, headers_present:)
14
+ Result.new(true, { headers: ["name"] })
15
+ end
16
+ end
17
+
18
+ def test_halts_when_seed_invalid
19
+ file_prompt = Object.new
20
+ separator_prompt = Object.new
21
+ headers_prompt = Object.new
22
+ seed_prompt = Object.new
23
+ def file_prompt.call = "/tmp/data.csv"
24
+ def separator_prompt.call = ","
25
+ def headers_prompt.call = true
26
+ def seed_prompt.call = Csvtool::Interface::CLI::Prompts::SeedPrompt::INVALID
27
+
28
+ step = Csvtool::Interface::CLI::Workflows::Steps::RowRandomization::CollectInputsStep.new(
29
+ file_path_prompt: file_prompt,
30
+ separator_prompt: separator_prompt,
31
+ headers_present_prompt: headers_prompt,
32
+ seed_prompt: seed_prompt
33
+ )
34
+
35
+ assert_equal :halt, step.call(use_case: FakeUseCase.new, handle_error: ->(_r) {})
36
+ end
37
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../../../../test_helper"
4
+ require "csvtool/interface/cli/workflows/steps/workflow_step_pipeline"
5
+
6
+ class WorkflowStepPipelineTest < Minitest::Test
7
+ def test_runs_all_steps_when_no_halt
8
+ calls = []
9
+ step_1 = ->(_ctx) { calls << :one; nil }
10
+ step_2 = ->(_ctx) { calls << :two; nil }
11
+ pipeline = Csvtool::Interface::CLI::Workflows::Steps::WorkflowStepPipeline.new(steps: [step_1, step_2])
12
+
13
+ result = pipeline.call({})
14
+
15
+ assert_equal true, result
16
+ assert_equal %i[one two], calls
17
+ end
18
+
19
+ def test_stops_on_halt
20
+ calls = []
21
+ step_1 = ->(_ctx) { calls << :one; :halt }
22
+ step_2 = ->(_ctx) { calls << :two; nil }
23
+ pipeline = Csvtool::Interface::CLI::Workflows::Steps::WorkflowStepPipeline.new(steps: [step_1, step_2])
24
+
25
+ result = pipeline.call({})
26
+
27
+ assert_equal false, result
28
+ assert_equal [:one], calls
29
+ end
30
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../../../../test_helper"
4
+ require "csvtool/interface/cli/workflows/support/output_destination_mapper"
5
+
6
+ class OutputDestinationMapperTest < Minitest::Test
7
+ def test_maps_console_destination
8
+ mapper = Csvtool::Interface::CLI::Workflows::Support::OutputDestinationMapper.new
9
+
10
+ destination = mapper.call({ mode: :console })
11
+
12
+ assert_equal true, destination.console?
13
+ end
14
+
15
+ def test_maps_file_destination
16
+ mapper = Csvtool::Interface::CLI::Workflows::Support::OutputDestinationMapper.new
17
+
18
+ destination = mapper.call({ mode: :file, path: "/tmp/out.csv" })
19
+
20
+ assert_equal true, destination.file?
21
+ assert_equal "/tmp/out.csv", destination.path
22
+ end
23
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../../../../test_helper"
4
+ require "csvtool/interface/cli/workflows/support/result_error_handler"
5
+
6
+ class ResultErrorHandlerTest < Minitest::Test
7
+ Result = Struct.new(:error)
8
+
9
+ def test_dispatches_mapped_error_action
10
+ calls = []
11
+ errors = Object.new
12
+ handler = Csvtool::Interface::CLI::Workflows::Support::ResultErrorHandler.new(errors: errors)
13
+ result = Result.new(:no_headers)
14
+
15
+ handler.call(result, {
16
+ no_headers: ->(_r, _e) { calls << :called }
17
+ })
18
+
19
+ assert_equal [:called], calls
20
+ end
21
+
22
+ def test_ignores_unmapped_error
23
+ calls = []
24
+ errors = Object.new
25
+ handler = Csvtool::Interface::CLI::Workflows::Support::ResultErrorHandler.new(errors: errors)
26
+ result = Result.new(:unknown)
27
+
28
+ handler.call(result, {
29
+ no_headers: ->(_r, _e) { calls << :called }
30
+ })
31
+
32
+ assert_empty calls
33
+ end
34
+ end
@@ -0,0 +1,4 @@
1
+ id,name
2
+ 1,Alice
3
+ 1,Alice
4
+ 2,Bob
@@ -0,0 +1,3 @@
1
+ id,name
2
+ 1,Alice
3
+ 2,Bob
@@ -0,0 +1,4 @@
1
+ full_name,city
2
+ Alice,London
3
+ Bob,Paris
4
+ Cara,Berlin
@@ -0,0 +1,13 @@
1
+ name
2
+ Name12
3
+ Name11
4
+ Name10
5
+ Name09
6
+ Name08
7
+ Name07
8
+ Name06
9
+ Name05
10
+ Name04
11
+ Name03
12
+ Name02
13
+ Name01
@@ -0,0 +1,4 @@
1
+ name,city
2
+ Alice,London
3
+ Bob,Paris
4
+ Dina,Rome
@@ -0,0 +1,4 @@
1
+ name,city
2
+ Cara,Berlin
3
+ Alice,London
4
+ Bob,Paris
@@ -0,0 +1,4 @@
1
+ name city
2
+ Cara Berlin
3
+ Alice London
4
+ Bob Paris
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: csvops
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0.alpha
4
+ version: 0.6.0.alpha
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Hall
@@ -72,8 +72,11 @@ files:
72
72
  - docs/release-v0.2.0-alpha.md
73
73
  - docs/release-v0.3.0-alpha.md
74
74
  - docs/release-v0.4.0-alpha.md
75
+ - docs/release-v0.5.0-alpha.md
76
+ - docs/release-v0.6.0-alpha.md
75
77
  - exe/csvtool
76
78
  - lib/csvtool/application/use_cases/run_cross_csv_dedupe.rb
79
+ - lib/csvtool/application/use_cases/run_csv_parity.rb
77
80
  - lib/csvtool/application/use_cases/run_extraction.rb
78
81
  - lib/csvtool/application/use_cases/run_row_extraction.rb
79
82
  - lib/csvtool/application/use_cases/run_row_randomization.rb
@@ -90,6 +93,9 @@ files:
90
93
  - lib/csvtool/domain/cross_csv_dedupe_session/csv_profile.rb
91
94
  - lib/csvtool/domain/cross_csv_dedupe_session/key_mapping.rb
92
95
  - lib/csvtool/domain/cross_csv_dedupe_session/match_options.rb
96
+ - lib/csvtool/domain/csv_parity_session/parity_options.rb
97
+ - lib/csvtool/domain/csv_parity_session/parity_session.rb
98
+ - lib/csvtool/domain/csv_parity_session/source_pair.rb
93
99
  - lib/csvtool/domain/row_randomization_session/randomization_options.rb
94
100
  - lib/csvtool/domain/row_randomization_session/randomization_session.rb
95
101
  - lib/csvtool/domain/row_randomization_session/randomization_source.rb
@@ -98,29 +104,71 @@ files:
98
104
  - lib/csvtool/domain/row_session/row_source.rb
99
105
  - lib/csvtool/domain/shared/output_destination.rb
100
106
  - lib/csvtool/infrastructure/csv/cross_csv_deduper.rb
107
+ - lib/csvtool/infrastructure/csv/csv_parity_comparator.rb
101
108
  - lib/csvtool/infrastructure/csv/header_reader.rb
102
109
  - lib/csvtool/infrastructure/csv/row_randomizer.rb
103
110
  - lib/csvtool/infrastructure/csv/row_streamer.rb
104
111
  - lib/csvtool/infrastructure/csv/selector_validator.rb
105
112
  - lib/csvtool/infrastructure/csv/value_streamer.rb
106
113
  - lib/csvtool/infrastructure/output/console_writer.rb
114
+ - lib/csvtool/infrastructure/output/csv_cross_csv_dedupe_file_writer.rb
107
115
  - lib/csvtool/infrastructure/output/csv_file_writer.rb
116
+ - lib/csvtool/infrastructure/output/csv_randomized_row_file_writer.rb
108
117
  - lib/csvtool/infrastructure/output/csv_row_console_writer.rb
109
118
  - lib/csvtool/infrastructure/output/csv_row_file_writer.rb
110
119
  - lib/csvtool/interface/cli/errors/presenter.rb
111
120
  - lib/csvtool/interface/cli/menu_loop.rb
112
121
  - lib/csvtool/interface/cli/prompts/column_selector_prompt.rb
113
122
  - lib/csvtool/interface/cli/prompts/confirm_prompt.rb
123
+ - lib/csvtool/interface/cli/prompts/dedupe_key_selector_prompt.rb
114
124
  - lib/csvtool/interface/cli/prompts/file_path_prompt.rb
115
125
  - lib/csvtool/interface/cli/prompts/headers_present_prompt.rb
116
126
  - lib/csvtool/interface/cli/prompts/output_destination_prompt.rb
117
127
  - lib/csvtool/interface/cli/prompts/seed_prompt.rb
118
128
  - lib/csvtool/interface/cli/prompts/separator_prompt.rb
119
129
  - lib/csvtool/interface/cli/prompts/skip_blanks_prompt.rb
130
+ - lib/csvtool/interface/cli/prompts/yes_no_prompt.rb
131
+ - lib/csvtool/interface/cli/workflows/builders/column_session_builder.rb
132
+ - lib/csvtool/interface/cli/workflows/builders/cross_csv_dedupe_session_builder.rb
133
+ - lib/csvtool/interface/cli/workflows/builders/csv_parity_session_builder.rb
134
+ - lib/csvtool/interface/cli/workflows/builders/row_extraction_session_builder.rb
135
+ - lib/csvtool/interface/cli/workflows/builders/row_randomization_session_builder.rb
136
+ - lib/csvtool/interface/cli/workflows/presenters/column_extraction_presenter.rb
137
+ - lib/csvtool/interface/cli/workflows/presenters/cross_csv_dedupe_presenter.rb
138
+ - lib/csvtool/interface/cli/workflows/presenters/csv_parity_presenter.rb
139
+ - lib/csvtool/interface/cli/workflows/presenters/row_extraction_presenter.rb
140
+ - lib/csvtool/interface/cli/workflows/presenters/row_randomization_presenter.rb
120
141
  - lib/csvtool/interface/cli/workflows/run_cross_csv_dedupe_workflow.rb
142
+ - lib/csvtool/interface/cli/workflows/run_csv_parity_workflow.rb
143
+ - lib/csvtool/interface/cli/workflows/run_extraction_workflow.rb
144
+ - lib/csvtool/interface/cli/workflows/run_row_extraction_workflow.rb
145
+ - lib/csvtool/interface/cli/workflows/run_row_randomization_workflow.rb
146
+ - lib/csvtool/interface/cli/workflows/steps/cross_csv_dedupe/collect_options_step.rb
147
+ - lib/csvtool/interface/cli/workflows/steps/cross_csv_dedupe/collect_profiles_step.rb
148
+ - lib/csvtool/interface/cli/workflows/steps/cross_csv_dedupe/execute_step.rb
149
+ - lib/csvtool/interface/cli/workflows/steps/extraction/build_preview_step.rb
150
+ - lib/csvtool/interface/cli/workflows/steps/extraction/collect_destination_step.rb
151
+ - lib/csvtool/interface/cli/workflows/steps/extraction/collect_inputs_step.rb
152
+ - lib/csvtool/interface/cli/workflows/steps/extraction/execute_step.rb
153
+ - lib/csvtool/interface/cli/workflows/steps/parity/build_session_step.rb
154
+ - lib/csvtool/interface/cli/workflows/steps/parity/collect_inputs_step.rb
155
+ - lib/csvtool/interface/cli/workflows/steps/parity/execute_step.rb
156
+ - lib/csvtool/interface/cli/workflows/steps/row_extraction/collect_destination_step.rb
157
+ - lib/csvtool/interface/cli/workflows/steps/row_extraction/collect_range_step.rb
158
+ - lib/csvtool/interface/cli/workflows/steps/row_extraction/collect_source_step.rb
159
+ - lib/csvtool/interface/cli/workflows/steps/row_extraction/execute_step.rb
160
+ - lib/csvtool/interface/cli/workflows/steps/row_extraction/read_headers_step.rb
161
+ - lib/csvtool/interface/cli/workflows/steps/row_randomization/collect_destination_step.rb
162
+ - lib/csvtool/interface/cli/workflows/steps/row_randomization/collect_inputs_step.rb
163
+ - lib/csvtool/interface/cli/workflows/steps/row_randomization/execute_step.rb
164
+ - lib/csvtool/interface/cli/workflows/steps/workflow_step_pipeline.rb
165
+ - lib/csvtool/interface/cli/workflows/support/output_destination_mapper.rb
166
+ - lib/csvtool/interface/cli/workflows/support/result_error_handler.rb
121
167
  - lib/csvtool/services/preview_builder.rb
122
168
  - lib/csvtool/version.rb
169
+ - test/csvtool/application/use_cases/io_boundary_test.rb
123
170
  - test/csvtool/application/use_cases/run_cross_csv_dedupe_test.rb
171
+ - test/csvtool/application/use_cases/run_csv_parity_test.rb
124
172
  - test/csvtool/application/use_cases/run_extraction_test.rb
125
173
  - test/csvtool/application/use_cases/run_row_extraction_test.rb
126
174
  - test/csvtool/application/use_cases/run_row_randomization_test.rb
@@ -138,6 +186,9 @@ files:
138
186
  - test/csvtool/domain/cross_csv_dedupe_session/csv_profile_test.rb
139
187
  - test/csvtool/domain/cross_csv_dedupe_session/key_mapping_test.rb
140
188
  - test/csvtool/domain/cross_csv_dedupe_session/match_options_test.rb
189
+ - test/csvtool/domain/csv_parity_session/parity_options_test.rb
190
+ - test/csvtool/domain/csv_parity_session/parity_session_test.rb
191
+ - test/csvtool/domain/csv_parity_session/source_pair_test.rb
141
192
  - test/csvtool/domain/row_randomization_session/randomization_options_test.rb
142
193
  - test/csvtool/domain/row_randomization_session/randomization_session_test.rb
143
194
  - test/csvtool/domain/row_randomization_session/randomization_source_test.rb
@@ -146,26 +197,57 @@ files:
146
197
  - test/csvtool/domain/row_session/row_source_test.rb
147
198
  - test/csvtool/domain/shared/output_destination_test.rb
148
199
  - test/csvtool/infrastructure/csv/cross_csv_deduper_test.rb
200
+ - test/csvtool/infrastructure/csv/csv_parity_comparator_test.rb
149
201
  - test/csvtool/infrastructure/csv/header_reader_test.rb
150
202
  - test/csvtool/infrastructure/csv/row_randomizer_test.rb
151
203
  - test/csvtool/infrastructure/csv/row_streamer_test.rb
152
204
  - test/csvtool/infrastructure/csv/selector_validator_test.rb
153
205
  - test/csvtool/infrastructure/csv/value_streamer_test.rb
154
206
  - test/csvtool/infrastructure/output/console_writer_test.rb
207
+ - test/csvtool/infrastructure/output/csv_cross_csv_dedupe_file_writer_test.rb
155
208
  - test/csvtool/infrastructure/output/csv_file_writer_test.rb
209
+ - test/csvtool/infrastructure/output/csv_randomized_row_file_writer_test.rb
156
210
  - test/csvtool/infrastructure/output/csv_row_console_writer_test.rb
157
211
  - test/csvtool/infrastructure/output/csv_row_file_writer_test.rb
158
212
  - test/csvtool/interface/cli/errors/presenter_test.rb
159
213
  - test/csvtool/interface/cli/menu_loop_test.rb
160
214
  - test/csvtool/interface/cli/prompts/column_selector_prompt_test.rb
161
215
  - test/csvtool/interface/cli/prompts/confirm_prompt_test.rb
216
+ - test/csvtool/interface/cli/prompts/dedupe_key_selector_prompt_test.rb
162
217
  - test/csvtool/interface/cli/prompts/file_path_prompt_test.rb
163
218
  - test/csvtool/interface/cli/prompts/headers_present_prompt_test.rb
164
219
  - test/csvtool/interface/cli/prompts/output_destination_prompt_test.rb
165
220
  - test/csvtool/interface/cli/prompts/seed_prompt_test.rb
166
221
  - test/csvtool/interface/cli/prompts/separator_prompt_test.rb
167
222
  - test/csvtool/interface/cli/prompts/skip_blanks_prompt_test.rb
223
+ - test/csvtool/interface/cli/prompts/yes_no_prompt_test.rb
224
+ - test/csvtool/interface/cli/workflows/builders/column_session_builder_test.rb
225
+ - test/csvtool/interface/cli/workflows/builders/cross_csv_dedupe_session_builder_test.rb
226
+ - test/csvtool/interface/cli/workflows/builders/csv_parity_session_builder_test.rb
227
+ - test/csvtool/interface/cli/workflows/builders/row_extraction_session_builder_test.rb
228
+ - test/csvtool/interface/cli/workflows/builders/row_randomization_session_builder_test.rb
229
+ - test/csvtool/interface/cli/workflows/presenters/column_extraction_presenter_test.rb
230
+ - test/csvtool/interface/cli/workflows/presenters/cross_csv_dedupe_presenter_test.rb
231
+ - test/csvtool/interface/cli/workflows/presenters/csv_parity_presenter_test.rb
232
+ - test/csvtool/interface/cli/workflows/presenters/row_extraction_presenter_test.rb
233
+ - test/csvtool/interface/cli/workflows/presenters/row_randomization_presenter_test.rb
168
234
  - test/csvtool/interface/cli/workflows/run_cross_csv_dedupe_workflow_test.rb
235
+ - test/csvtool/interface/cli/workflows/run_csv_parity_workflow_test.rb
236
+ - test/csvtool/interface/cli/workflows/run_extraction_workflow_test.rb
237
+ - test/csvtool/interface/cli/workflows/run_row_extraction_workflow_test.rb
238
+ - test/csvtool/interface/cli/workflows/run_row_randomization_workflow_test.rb
239
+ - test/csvtool/interface/cli/workflows/steps/cross_csv_dedupe/collect_options_step_test.rb
240
+ - test/csvtool/interface/cli/workflows/steps/extraction/collect_inputs_step_test.rb
241
+ - test/csvtool/interface/cli/workflows/steps/parity/build_session_step_test.rb
242
+ - test/csvtool/interface/cli/workflows/steps/parity/collect_inputs_step_test.rb
243
+ - test/csvtool/interface/cli/workflows/steps/parity/execute_step_test.rb
244
+ - test/csvtool/interface/cli/workflows/steps/row_extraction/collect_source_step_test.rb
245
+ - test/csvtool/interface/cli/workflows/steps/row_extraction/execute_step_test.rb
246
+ - test/csvtool/interface/cli/workflows/steps/row_extraction/read_headers_step_test.rb
247
+ - test/csvtool/interface/cli/workflows/steps/row_randomization/collect_inputs_step_test.rb
248
+ - test/csvtool/interface/cli/workflows/steps/workflow_step_pipeline_test.rb
249
+ - test/csvtool/interface/cli/workflows/support/output_destination_mapper_test.rb
250
+ - test/csvtool/interface/cli/workflows/support/result_error_handler_test.rb
169
251
  - test/csvtool/services/preview_builder_test.rb
170
252
  - test/fixtures/dedupe_reference.csv
171
253
  - test/fixtures/dedupe_reference.tsv
@@ -178,6 +260,13 @@ files:
178
260
  - test/fixtures/dedupe_source_no_headers.csv
179
261
  - test/fixtures/dedupe_source_normalization.csv
180
262
  - test/fixtures/empty.csv
263
+ - test/fixtures/parity_duplicates_left.csv
264
+ - test/fixtures/parity_duplicates_right.csv
265
+ - test/fixtures/parity_people_header_mismatch.csv
266
+ - test/fixtures/parity_people_many_reordered.csv
267
+ - test/fixtures/parity_people_mismatch.csv
268
+ - test/fixtures/parity_people_reordered.csv
269
+ - test/fixtures/parity_people_reordered.tsv
181
270
  - test/fixtures/sample_people.csv
182
271
  - test/fixtures/sample_people.tsv
183
272
  - test/fixtures/sample_people_bad_tail.csv