csvops 0.8.0.alpha → 0.9.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 (44) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +23 -3
  3. data/docs/architecture.md +3 -0
  4. data/docs/cli-output-conventions.md +49 -0
  5. data/docs/release-v0.9.0-alpha.md +80 -0
  6. data/lib/csvtool/cli.rb +132 -12
  7. data/lib/csvtool/interface/cli/menu_loop.rb +6 -5
  8. data/lib/csvtool/interface/cli/output/color_policy.rb +25 -0
  9. data/lib/csvtool/interface/cli/output/colorizer.rb +27 -0
  10. data/lib/csvtool/interface/cli/output/formatters/csv_row_formatter.rb +19 -0
  11. data/lib/csvtool/interface/cli/output/formatters/stats_formatter.rb +57 -0
  12. data/lib/csvtool/interface/cli/output/streams.rb +22 -0
  13. data/lib/csvtool/interface/cli/output/table_renderer.rb +70 -0
  14. data/lib/csvtool/interface/cli/workflows/presenters/cross_csv_dedupe_presenter.rb +17 -5
  15. data/lib/csvtool/interface/cli/workflows/presenters/csv_parity_presenter.rb +15 -4
  16. data/lib/csvtool/interface/cli/workflows/presenters/csv_split_presenter.rb +15 -6
  17. data/lib/csvtool/interface/cli/workflows/presenters/csv_stats_presenter.rb +18 -9
  18. data/lib/csvtool/interface/cli/workflows/presenters/row_extraction_presenter.rb +5 -4
  19. data/lib/csvtool/interface/cli/workflows/presenters/row_randomization_presenter.rb +5 -4
  20. data/lib/csvtool/interface/cli/workflows/run_cross_csv_dedupe_workflow.rb +9 -8
  21. data/lib/csvtool/interface/cli/workflows/run_csv_parity_workflow.rb +6 -5
  22. data/lib/csvtool/interface/cli/workflows/run_csv_split_workflow.rb +11 -10
  23. data/lib/csvtool/interface/cli/workflows/run_csv_stats_workflow.rb +7 -6
  24. data/lib/csvtool/interface/cli/workflows/run_extraction_workflow.rb +9 -8
  25. data/lib/csvtool/interface/cli/workflows/run_row_extraction_workflow.rb +7 -6
  26. data/lib/csvtool/interface/cli/workflows/run_row_randomization_workflow.rb +8 -7
  27. data/lib/csvtool/version.rb +1 -1
  28. data/test/csvtool/cli_test.rb +289 -44
  29. data/test/csvtool/cli_unit_test.rb +5 -5
  30. data/test/csvtool/interface/cli/output/color_policy_test.rb +40 -0
  31. data/test/csvtool/interface/cli/output/colorizer_test.rb +28 -0
  32. data/test/csvtool/interface/cli/output/formatters/csv_row_formatter_test.rb +22 -0
  33. data/test/csvtool/interface/cli/output/formatters/stats_formatter_test.rb +51 -0
  34. data/test/csvtool/interface/cli/output/streams_test.rb +25 -0
  35. data/test/csvtool/interface/cli/output/table_renderer_test.rb +36 -0
  36. data/test/csvtool/interface/cli/workflows/presenters/cross_csv_dedupe_presenter_test.rb +4 -1
  37. data/test/csvtool/interface/cli/workflows/presenters/csv_parity_presenter_test.rb +5 -1
  38. data/test/csvtool/interface/cli/workflows/presenters/csv_split_presenter_test.rb +22 -4
  39. data/test/csvtool/interface/cli/workflows/presenters/csv_stats_presenter_test.rb +7 -5
  40. data/test/csvtool/interface/cli/workflows/run_cross_csv_dedupe_workflow_test.rb +10 -7
  41. data/test/csvtool/interface/cli/workflows/run_csv_parity_workflow_test.rb +3 -1
  42. data/test/csvtool/interface/cli/workflows/run_csv_split_workflow_test.rb +5 -3
  43. data/test/csvtool/interface/cli/workflows/run_csv_stats_workflow_test.rb +23 -18
  44. metadata +15 -1
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../../../test_helper"
4
+ require "csvtool/interface/cli/output/colorizer"
5
+
6
+ class ColorizerTest < Minitest::Test
7
+ class FakePolicy
8
+ def initialize(enabled)
9
+ @enabled = enabled
10
+ end
11
+
12
+ def enabled?
13
+ @enabled
14
+ end
15
+ end
16
+
17
+ def test_wraps_text_when_enabled
18
+ colorizer = Csvtool::Interface::CLI::Output::Colorizer.new(policy: FakePolicy.new(true))
19
+
20
+ assert_equal "\e[31mMISMATCH\e[0m", colorizer.call("MISMATCH", code: "31")
21
+ end
22
+
23
+ def test_returns_text_when_disabled
24
+ colorizer = Csvtool::Interface::CLI::Output::Colorizer.new(policy: FakePolicy.new(false))
25
+
26
+ assert_equal "MATCH", colorizer.call("MATCH", code: "32")
27
+ end
28
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../../../../test_helper"
4
+ require "csvtool/interface/cli/output/formatters/csv_row_formatter"
5
+
6
+ class CsvRowFormatterTest < Minitest::Test
7
+ def test_formats_row_with_separator
8
+ formatter = Csvtool::Interface::CLI::Output::Formatters::CsvRowFormatter.new
9
+
10
+ row = formatter.call(fields: ["Alice", "London"], col_sep: ",")
11
+
12
+ assert_equal "Alice,London", row
13
+ end
14
+
15
+ def test_quotes_values_when_needed
16
+ formatter = Csvtool::Interface::CLI::Output::Formatters::CsvRowFormatter.new
17
+
18
+ row = formatter.call(fields: ["Alice, Jr", "London"], col_sep: ",")
19
+
20
+ assert_equal '"Alice, Jr",London', row
21
+ end
22
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../../../../test_helper"
4
+ require "csvtool/interface/cli/output/formatters/stats_formatter"
5
+ require "csvtool/interface/cli/output/table_renderer"
6
+ require "json"
7
+
8
+ class StatsFormatterTest < Minitest::Test
9
+ def sample_data
10
+ {
11
+ row_count: 3,
12
+ column_count: 2,
13
+ headers: ["name", "city"],
14
+ column_stats: [
15
+ { name: "name", non_blank_count: 3, blank_count: 0 },
16
+ { name: "city", non_blank_count: 2, blank_count: 1 }
17
+ ]
18
+ }
19
+ end
20
+
21
+ def formatter
22
+ Csvtool::Interface::CLI::Output::Formatters::StatsFormatter.new(
23
+ table_renderer: Csvtool::Interface::CLI::Output::TableRenderer.new
24
+ )
25
+ end
26
+
27
+ def test_formats_text_summary
28
+ text = formatter.call(data: sample_data, format: "text", max_width: 80)
29
+
30
+ assert_includes text, "CSV Stats Summary"
31
+ assert_includes text, "Metric"
32
+ assert_includes text, "Column completeness:"
33
+ end
34
+
35
+ def test_formats_json_summary
36
+ json = formatter.call(data: sample_data, format: "json", max_width: 80)
37
+
38
+ parsed = JSON.parse(json, symbolize_names: true)
39
+ assert_equal 3, parsed[:row_count]
40
+ assert_equal 2, parsed[:column_count]
41
+ end
42
+
43
+ def test_formats_csv_summary
44
+ csv = formatter.call(data: sample_data, format: "csv", max_width: 80)
45
+
46
+ lines = csv.lines.map(&:chomp)
47
+ assert_equal "metric,value", lines.first
48
+ assert_includes lines, "row_count,3"
49
+ assert_includes lines, "column.city.blank,1"
50
+ end
51
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../../../test_helper"
4
+ require "csvtool/interface/cli/output/streams"
5
+
6
+ class StreamsTest < Minitest::Test
7
+ def test_builds_data_and_ui_streams
8
+ data = StringIO.new
9
+ ui = StringIO.new
10
+
11
+ streams = Csvtool::Interface::CLI::Output::Streams.build(data: data, ui: ui)
12
+
13
+ assert_same data, streams.data
14
+ assert_same ui, streams.ui
15
+ end
16
+
17
+ def test_defaults_ui_to_data_stream
18
+ data = StringIO.new
19
+
20
+ streams = Csvtool::Interface::CLI::Output::Streams.build(data: data)
21
+
22
+ assert_same data, streams.data
23
+ assert_same data, streams.ui
24
+ end
25
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../../../test_helper"
4
+ require "csvtool/interface/cli/output/table_renderer"
5
+
6
+ class TableRendererTest < Minitest::Test
7
+ def test_renders_aligned_table
8
+ renderer = Csvtool::Interface::CLI::Output::TableRenderer.new
9
+
10
+ text = renderer.render(
11
+ headers: ["Metric", "Value"],
12
+ rows: [["Rows", "3"], ["Columns", "2"]],
13
+ max_width: 80
14
+ )
15
+
16
+ lines = text.lines.map(&:chomp)
17
+ assert_equal "Metric | Value", lines[0]
18
+ assert_equal "--------+------", lines[1]
19
+ assert_equal "Rows | 3 ", lines[2]
20
+ assert_equal "Columns | 2 ", lines[3]
21
+ end
22
+
23
+ def test_truncates_cells_when_width_is_narrow
24
+ renderer = Csvtool::Interface::CLI::Output::TableRenderer.new
25
+
26
+ text = renderer.render(
27
+ headers: ["Column", "Non-blank", "Blank"],
28
+ rows: [["very_long_column_name", "123456", "0"]],
29
+ max_width: 26
30
+ )
31
+
32
+ lines = text.lines.map(&:chomp)
33
+ assert lines.all? { |line| line.length <= 26 }
34
+ assert_includes lines[2], "..."
35
+ end
36
+ end
@@ -14,7 +14,10 @@ class CrossCsvDedupePresenterTest < Minitest::Test
14
14
 
15
15
  assert_includes out.string, "\nid,name\n"
16
16
  assert_includes out.string, "1,Alice"
17
- assert_includes out.string, "Summary: source_rows=5 removed_rows=3 kept_rows=2"
17
+ assert_includes out.string, "Summary"
18
+ assert_includes out.string, "Source rows"
19
+ assert_includes out.string, "Removed rows"
20
+ assert_includes out.string, "Kept rows"
18
21
  end
19
22
 
20
23
  def test_prints_zero_and_all_removed_messages
@@ -17,7 +17,11 @@ class CsvParityPresenterTest < Minitest::Test
17
17
  )
18
18
 
19
19
  assert_includes out.string, "MATCH"
20
- assert_includes out.string, "Summary: left_rows=3 right_rows=3 left_only=0 right_only=0"
20
+ assert_includes out.string, "Metric"
21
+ assert_includes out.string, "Left rows"
22
+ assert_includes out.string, "Right rows"
23
+ assert_includes out.string, "Left only"
24
+ assert_includes out.string, "Right only"
21
25
  end
22
26
 
23
27
  def test_prints_mismatch_examples
@@ -17,10 +17,28 @@ class CsvSplitPresenterTest < Minitest::Test
17
17
  )
18
18
 
19
19
  assert_includes out.string, "Split complete."
20
- assert_includes out.string, "Chunk size: 10"
21
- assert_includes out.string, "Data rows: 25"
22
- assert_includes out.string, "Chunks written: 3"
23
- assert_includes out.string, "Manifest: /tmp/manifest.csv"
20
+ assert_includes out.string, "Metric"
21
+ assert_includes out.string, "Chunk size"
22
+ assert_includes out.string, "Data rows"
23
+ assert_includes out.string, "Chunks written"
24
+ assert_includes out.string, "Manifest"
24
25
  assert_includes out.string, "/tmp/people_part_001.csv"
25
26
  end
27
+
28
+ def test_truncates_summary_table_for_narrow_width
29
+ out = StringIO.new
30
+ presenter = Csvtool::Interface::CLI::Workflows::Presenters::CsvSplitPresenter.new(stdout: out, max_width: 26)
31
+
32
+ presenter.print_summary(
33
+ chunk_size: 10,
34
+ data_rows: 25,
35
+ chunk_count: 3,
36
+ manifest_path: "/tmp/very/long/path/manifest.csv",
37
+ chunk_paths: []
38
+ )
39
+
40
+ lines = out.string.lines.map(&:chomp)
41
+ assert lines.all? { |line| line.empty? || line.length <= 26 }
42
+ assert_includes out.string, "..."
43
+ end
26
44
  end
@@ -19,11 +19,13 @@ class CsvStatsPresenterTest < Minitest::Test
19
19
  )
20
20
 
21
21
  assert_includes out.string, "CSV Stats Summary"
22
- assert_includes out.string, "Rows: 3"
23
- assert_includes out.string, "Columns: 2"
24
- assert_includes out.string, "Headers: name, city"
25
- assert_includes out.string, "name: non_blank=3 blank=0"
26
- assert_includes out.string, "city: non_blank=2 blank=1"
22
+ assert_includes out.string, "Metric"
23
+ assert_includes out.string, "Rows"
24
+ assert_includes out.string, "Columns"
25
+ assert_includes out.string, "Headers"
26
+ assert_includes out.string, "Column completeness:"
27
+ assert_includes out.string, "name"
28
+ assert_includes out.string, "city"
27
29
  end
28
30
 
29
31
  def test_prints_file_written_message
@@ -38,7 +38,10 @@ class RunCrossCsvDedupeWorkflowTest < Minitest::Test
38
38
  assert_includes output.string, "3,Cara"
39
39
  refute_includes output.string, "2,Bob"
40
40
  refute_includes output.string, "4,Dan"
41
- assert_includes output.string, "Summary: source_rows=5 removed_rows=3 kept_rows=2"
41
+ assert_includes output.string, "Summary"
42
+ assert_includes output.string, "Source rows"
43
+ assert_includes output.string, "Removed rows"
44
+ assert_includes output.string, "Kept rows"
42
45
  end
43
46
 
44
47
  def test_can_write_deduped_rows_to_file
@@ -67,7 +70,7 @@ class RunCrossCsvDedupeWorkflowTest < Minitest::Test
67
70
 
68
71
  assert_includes output.string, "Wrote output to #{output_path}"
69
72
  assert_equal "customer_id,name\n1,Alice\n3,Cara\n", File.read(output_path)
70
- assert_includes output.string, "Summary: source_rows=5 removed_rows=3 kept_rows=2"
73
+ assert_includes output.string, "Summary"
71
74
  end
72
75
  end
73
76
 
@@ -119,7 +122,7 @@ class RunCrossCsvDedupeWorkflowTest < Minitest::Test
119
122
  refute_includes output.string, "customer_id,name"
120
123
  assert_includes output.string, "1,Alice"
121
124
  assert_includes output.string, "3,Cara"
122
- assert_includes output.string, "Summary: source_rows=5 removed_rows=3 kept_rows=2"
125
+ assert_includes output.string, "Summary"
123
126
  end
124
127
 
125
128
  def test_reports_column_not_found_when_missing
@@ -164,7 +167,7 @@ class RunCrossCsvDedupeWorkflowTest < Minitest::Test
164
167
  .new(stdin: StringIO.new(input), stdout: output)
165
168
  .call
166
169
 
167
- assert_includes output.string, "Summary: source_rows=5 removed_rows=0 kept_rows=5"
170
+ assert_includes output.string, "Summary"
168
171
  assert_includes output.string, "No rows removed; no matching keys found."
169
172
  end
170
173
 
@@ -188,7 +191,7 @@ class RunCrossCsvDedupeWorkflowTest < Minitest::Test
188
191
  .new(stdin: StringIO.new(input), stdout: output)
189
192
  .call
190
193
 
191
- assert_includes output.string, "Summary: source_rows=5 removed_rows=5 kept_rows=0"
194
+ assert_includes output.string, "Summary"
192
195
  assert_includes output.string, "All source rows were removed by dedupe."
193
196
  end
194
197
 
@@ -215,7 +218,7 @@ class RunCrossCsvDedupeWorkflowTest < Minitest::Test
215
218
  refute_includes output.string, " A1 ,Alice"
216
219
  refute_includes output.string, "c3,Cara"
217
220
  assert_includes output.string, "B2,Bob"
218
- assert_includes output.string, "Summary: source_rows=3 removed_rows=2 kept_rows=1"
221
+ assert_includes output.string, "Summary"
219
222
  end
220
223
 
221
224
  def test_normalization_disabled_preserves_exact_match_behavior
@@ -241,6 +244,6 @@ class RunCrossCsvDedupeWorkflowTest < Minitest::Test
241
244
  assert_includes output.string, " A1 ,Alice"
242
245
  assert_includes output.string, "B2,Bob"
243
246
  assert_includes output.string, "c3,Cara"
244
- assert_includes output.string, "Summary: source_rows=3 removed_rows=0 kept_rows=3"
247
+ assert_includes output.string, "Summary"
245
248
  end
246
249
  end
@@ -62,7 +62,9 @@ class RunCsvParityWorkflowTest < Minitest::Test
62
62
  assert_includes stdout.string, "Choose separator:"
63
63
  assert_includes stdout.string, "Headers present? [Y/n]: "
64
64
  assert_includes stdout.string, "MATCH"
65
- assert_includes stdout.string, "Summary: left_rows=3 right_rows=3 left_only=0 right_only=0"
65
+ assert_includes stdout.string, "Metric"
66
+ assert_includes stdout.string, "Left rows"
67
+ assert_includes stdout.string, "Right rows"
66
68
  end
67
69
 
68
70
  def test_prints_mismatch_examples_when_not_equal
@@ -24,8 +24,9 @@ class RunCsvSplitWorkflowTest < Minitest::Test
24
24
  ).call
25
25
 
26
26
  assert_includes out.string, "Split complete."
27
- assert_includes out.string, "Chunk size: 10"
28
- assert_includes out.string, "Chunks written: 3"
27
+ assert_includes out.string, "Metric"
28
+ assert_includes out.string, "Chunk size"
29
+ assert_includes out.string, "Chunks written"
29
30
  assert File.file?(File.join(dir, "people_part_001.csv"))
30
31
  assert File.file?(File.join(dir, "people_part_002.csv"))
31
32
  assert File.file?(File.join(dir, "people_part_003.csv"))
@@ -194,7 +195,8 @@ class RunCsvSplitWorkflowTest < Minitest::Test
194
195
  assert_includes lines[1], ",10"
195
196
  assert_includes lines[2], ",10"
196
197
  assert_includes lines[3], ",5"
197
- assert_includes out.string, "Manifest: #{manifest_path}"
198
+ assert_includes out.string, "Manifest"
199
+ assert_includes out.string, "manifest.csv"
198
200
  end
199
201
  end
200
202
  end
@@ -19,12 +19,13 @@ class RunCsvStatsWorkflowTest < Minitest::Test
19
19
  ).call
20
20
 
21
21
  assert_includes out.string, "CSV Stats Summary"
22
- assert_includes out.string, "Rows: 3"
23
- assert_includes out.string, "Columns: 2"
24
- assert_includes out.string, "Headers: name, city"
22
+ assert_includes out.string, "Metric"
23
+ assert_includes out.string, "Rows"
24
+ assert_includes out.string, "Columns"
25
+ assert_includes out.string, "Headers"
25
26
  assert_includes out.string, "Column completeness:"
26
- assert_includes out.string, "name: non_blank=3 blank=0"
27
- assert_includes out.string, "city: non_blank=3 blank=0"
27
+ assert_includes out.string, "name"
28
+ assert_includes out.string, "city"
28
29
  end
29
30
 
30
31
  def test_workflow_supports_tsv_separator
@@ -36,9 +37,9 @@ class RunCsvStatsWorkflowTest < Minitest::Test
36
37
  stdout: out
37
38
  ).call
38
39
 
39
- assert_includes out.string, "Rows: 3"
40
- assert_includes out.string, "Columns: 2"
41
- assert_includes out.string, "Headers: name, city"
40
+ assert_includes out.string, "Rows"
41
+ assert_includes out.string, "Columns"
42
+ assert_includes out.string, "Headers"
42
43
  end
43
44
 
44
45
  def test_workflow_supports_headerless_mode
@@ -50,11 +51,11 @@ class RunCsvStatsWorkflowTest < Minitest::Test
50
51
  stdout: out
51
52
  ).call
52
53
 
53
- assert_includes out.string, "Rows: 3"
54
- assert_includes out.string, "Columns: 2"
55
- refute_includes out.string, "Headers:"
56
- assert_includes out.string, "column_1: non_blank=3 blank=0"
57
- assert_includes out.string, "column_2: non_blank=3 blank=0"
54
+ assert_includes out.string, "Rows"
55
+ assert_includes out.string, "Columns"
56
+ refute_includes out.string, "Headers |"
57
+ assert_includes out.string, "column_1"
58
+ assert_includes out.string, "column_2"
58
59
  end
59
60
 
60
61
  def test_workflow_supports_custom_separator
@@ -66,9 +67,9 @@ class RunCsvStatsWorkflowTest < Minitest::Test
66
67
  stdout: out
67
68
  ).call
68
69
 
69
- assert_includes out.string, "Rows: 3"
70
- assert_includes out.string, "Columns: 2"
71
- assert_includes out.string, "Headers: name, city"
70
+ assert_includes out.string, "Rows"
71
+ assert_includes out.string, "Columns"
72
+ assert_includes out.string, "Headers"
72
73
  end
73
74
 
74
75
  def test_workflow_prints_column_completeness_for_blank_values
@@ -80,8 +81,12 @@ class RunCsvStatsWorkflowTest < Minitest::Test
80
81
  stdout: out
81
82
  ).call
82
83
 
83
- assert_includes out.string, "name: non_blank=3 blank=2"
84
- assert_includes out.string, "city: non_blank=4 blank=1"
84
+ assert_includes out.string, "name"
85
+ assert_includes out.string, "3"
86
+ assert_includes out.string, "2"
87
+ assert_includes out.string, "city"
88
+ assert_includes out.string, "4"
89
+ assert_includes out.string, "1"
85
90
  end
86
91
 
87
92
  def test_workflow_reports_missing_file
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.8.0.alpha
4
+ version: 0.9.0.alpha
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Hall
@@ -68,6 +68,7 @@ files:
68
68
  - bin/tool
69
69
  - csvops.gemspec
70
70
  - docs/architecture.md
71
+ - docs/cli-output-conventions.md
71
72
  - docs/release-v0.1.0-alpha.md
72
73
  - docs/release-v0.2.0-alpha.md
73
74
  - docs/release-v0.3.0-alpha.md
@@ -76,6 +77,7 @@ files:
76
77
  - docs/release-v0.6.0-alpha.md
77
78
  - docs/release-v0.7.0-alpha.md
78
79
  - docs/release-v0.8.0-alpha.md
80
+ - docs/release-v0.9.0-alpha.md
79
81
  - exe/csvtool
80
82
  - lib/csvtool/application/use_cases/run_cross_csv_dedupe.rb
81
83
  - lib/csvtool/application/use_cases/run_csv_parity.rb
@@ -132,6 +134,12 @@ files:
132
134
  - lib/csvtool/infrastructure/output/csv_stats_file_writer.rb
133
135
  - lib/csvtool/interface/cli/errors/presenter.rb
134
136
  - lib/csvtool/interface/cli/menu_loop.rb
137
+ - lib/csvtool/interface/cli/output/color_policy.rb
138
+ - lib/csvtool/interface/cli/output/colorizer.rb
139
+ - lib/csvtool/interface/cli/output/formatters/csv_row_formatter.rb
140
+ - lib/csvtool/interface/cli/output/formatters/stats_formatter.rb
141
+ - lib/csvtool/interface/cli/output/streams.rb
142
+ - lib/csvtool/interface/cli/output/table_renderer.rb
135
143
  - lib/csvtool/interface/cli/prompts/chunk_size_prompt.rb
136
144
  - lib/csvtool/interface/cli/prompts/column_selector_prompt.rb
137
145
  - lib/csvtool/interface/cli/prompts/confirm_prompt.rb
@@ -249,6 +257,12 @@ files:
249
257
  - test/csvtool/infrastructure/output/csv_stats_file_writer_test.rb
250
258
  - test/csvtool/interface/cli/errors/presenter_test.rb
251
259
  - test/csvtool/interface/cli/menu_loop_test.rb
260
+ - test/csvtool/interface/cli/output/color_policy_test.rb
261
+ - test/csvtool/interface/cli/output/colorizer_test.rb
262
+ - test/csvtool/interface/cli/output/formatters/csv_row_formatter_test.rb
263
+ - test/csvtool/interface/cli/output/formatters/stats_formatter_test.rb
264
+ - test/csvtool/interface/cli/output/streams_test.rb
265
+ - test/csvtool/interface/cli/output/table_renderer_test.rb
252
266
  - test/csvtool/interface/cli/prompts/chunk_size_prompt_test.rb
253
267
  - test/csvtool/interface/cli/prompts/column_selector_prompt_test.rb
254
268
  - test/csvtool/interface/cli/prompts/confirm_prompt_test.rb