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.
- checksums.yaml +4 -4
- data/README.md +23 -3
- data/docs/architecture.md +3 -0
- data/docs/cli-output-conventions.md +49 -0
- data/docs/release-v0.9.0-alpha.md +80 -0
- data/lib/csvtool/cli.rb +132 -12
- data/lib/csvtool/interface/cli/menu_loop.rb +6 -5
- data/lib/csvtool/interface/cli/output/color_policy.rb +25 -0
- data/lib/csvtool/interface/cli/output/colorizer.rb +27 -0
- data/lib/csvtool/interface/cli/output/formatters/csv_row_formatter.rb +19 -0
- data/lib/csvtool/interface/cli/output/formatters/stats_formatter.rb +57 -0
- data/lib/csvtool/interface/cli/output/streams.rb +22 -0
- data/lib/csvtool/interface/cli/output/table_renderer.rb +70 -0
- data/lib/csvtool/interface/cli/workflows/presenters/cross_csv_dedupe_presenter.rb +17 -5
- data/lib/csvtool/interface/cli/workflows/presenters/csv_parity_presenter.rb +15 -4
- data/lib/csvtool/interface/cli/workflows/presenters/csv_split_presenter.rb +15 -6
- data/lib/csvtool/interface/cli/workflows/presenters/csv_stats_presenter.rb +18 -9
- data/lib/csvtool/interface/cli/workflows/presenters/row_extraction_presenter.rb +5 -4
- data/lib/csvtool/interface/cli/workflows/presenters/row_randomization_presenter.rb +5 -4
- data/lib/csvtool/interface/cli/workflows/run_cross_csv_dedupe_workflow.rb +9 -8
- data/lib/csvtool/interface/cli/workflows/run_csv_parity_workflow.rb +6 -5
- data/lib/csvtool/interface/cli/workflows/run_csv_split_workflow.rb +11 -10
- data/lib/csvtool/interface/cli/workflows/run_csv_stats_workflow.rb +7 -6
- data/lib/csvtool/interface/cli/workflows/run_extraction_workflow.rb +9 -8
- data/lib/csvtool/interface/cli/workflows/run_row_extraction_workflow.rb +7 -6
- data/lib/csvtool/interface/cli/workflows/run_row_randomization_workflow.rb +8 -7
- data/lib/csvtool/version.rb +1 -1
- data/test/csvtool/cli_test.rb +289 -44
- data/test/csvtool/cli_unit_test.rb +5 -5
- data/test/csvtool/interface/cli/output/color_policy_test.rb +40 -0
- data/test/csvtool/interface/cli/output/colorizer_test.rb +28 -0
- data/test/csvtool/interface/cli/output/formatters/csv_row_formatter_test.rb +22 -0
- data/test/csvtool/interface/cli/output/formatters/stats_formatter_test.rb +51 -0
- data/test/csvtool/interface/cli/output/streams_test.rb +25 -0
- data/test/csvtool/interface/cli/output/table_renderer_test.rb +36 -0
- data/test/csvtool/interface/cli/workflows/presenters/cross_csv_dedupe_presenter_test.rb +4 -1
- data/test/csvtool/interface/cli/workflows/presenters/csv_parity_presenter_test.rb +5 -1
- data/test/csvtool/interface/cli/workflows/presenters/csv_split_presenter_test.rb +22 -4
- data/test/csvtool/interface/cli/workflows/presenters/csv_stats_presenter_test.rb +7 -5
- data/test/csvtool/interface/cli/workflows/run_cross_csv_dedupe_workflow_test.rb +10 -7
- data/test/csvtool/interface/cli/workflows/run_csv_parity_workflow_test.rb +3 -1
- data/test/csvtool/interface/cli/workflows/run_csv_split_workflow_test.rb +5 -3
- data/test/csvtool/interface/cli/workflows/run_csv_stats_workflow_test.rb +23 -18
- 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
|
|
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, "
|
|
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, "
|
|
21
|
-
assert_includes out.string, "
|
|
22
|
-
assert_includes out.string, "
|
|
23
|
-
assert_includes out.string, "
|
|
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, "
|
|
23
|
-
assert_includes out.string, "
|
|
24
|
-
assert_includes out.string, "
|
|
25
|
-
assert_includes out.string, "
|
|
26
|
-
assert_includes out.string, "
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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, "
|
|
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, "
|
|
28
|
-
assert_includes out.string, "
|
|
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
|
|
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, "
|
|
23
|
-
assert_includes out.string, "
|
|
24
|
-
assert_includes out.string, "
|
|
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
|
|
27
|
-
assert_includes out.string, "city
|
|
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
|
|
40
|
-
assert_includes out.string, "Columns
|
|
41
|
-
assert_includes out.string, "Headers
|
|
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
|
|
54
|
-
assert_includes out.string, "Columns
|
|
55
|
-
refute_includes out.string, "Headers
|
|
56
|
-
assert_includes out.string, "column_1
|
|
57
|
-
assert_includes out.string, "column_2
|
|
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
|
|
70
|
-
assert_includes out.string, "Columns
|
|
71
|
-
assert_includes out.string, "Headers
|
|
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
|
|
84
|
-
assert_includes out.string, "
|
|
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.
|
|
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
|