renogen 1.2.0 → 1.4.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 (46) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +119 -26
  3. data/lib/renogen/change_log.rb +1 -0
  4. data/lib/renogen/change_log/item.rb +6 -4
  5. data/lib/renogen/change_log/model.rb +9 -0
  6. data/lib/renogen/change_log/validator.rb +61 -0
  7. data/lib/renogen/change_log/writer.rb +35 -3
  8. data/lib/renogen/cli.rb +7 -4
  9. data/lib/renogen/config.rb +16 -15
  10. data/lib/renogen/exceptions.rb +5 -0
  11. data/lib/renogen/exceptions/invalid_item_found.rb +32 -0
  12. data/lib/renogen/exceptions/yaml_file_blank.rb +21 -0
  13. data/lib/renogen/exceptions/yaml_file_invalid.rb +20 -0
  14. data/lib/renogen/extraction_stratagies.rb +0 -2
  15. data/lib/renogen/extraction_stratagies/yaml_file.rb +0 -1
  16. data/lib/renogen/extraction_stratagies/yaml_file/parser.rb +5 -4
  17. data/lib/renogen/extraction_stratagies/yaml_file/reader.rb +20 -11
  18. data/lib/renogen/formatters.rb +2 -0
  19. data/lib/renogen/formatters/base.rb +14 -4
  20. data/lib/renogen/formatters/csv.rb +42 -0
  21. data/lib/renogen/formatters/html.rb +1 -1
  22. data/lib/renogen/formatters/markdown.rb +2 -2
  23. data/lib/renogen/formatters/markdown_table.rb +58 -0
  24. data/lib/renogen/generator.rb +8 -1
  25. data/lib/renogen/version.rb +1 -1
  26. data/lib/renogen/writers/csv.rb +23 -0
  27. data/spec/lib/renogen/change_log/item_spec.rb +1 -1
  28. data/spec/lib/renogen/change_log/model_spec.rb +1 -1
  29. data/spec/lib/renogen/change_log/validator_spec.rb +38 -0
  30. data/spec/lib/renogen/change_log/writer_spec.rb +199 -2
  31. data/spec/lib/renogen/config_spec.rb +7 -2
  32. data/spec/lib/renogen/exceptions/invalid_item_found_spec.rb +35 -0
  33. data/spec/lib/renogen/exceptions/stratagy_not_found_spec.rb +2 -1
  34. data/spec/lib/renogen/{extraction_stratagies/yaml_file/exceptions → exceptions}/yaml_file_blank_spec.rb +1 -1
  35. data/spec/lib/renogen/exceptions/yaml_file_invalid_spec.rb +12 -0
  36. data/spec/lib/renogen/extraction_stratagies/yaml_file/parser_spec.rb +3 -3
  37. data/spec/lib/renogen/extraction_stratagies/yaml_file/reader_spec.rb +11 -5
  38. data/spec/lib/renogen/formatters/base_spec.rb +8 -8
  39. data/spec/lib/renogen/formatters/csv_spec.rb +49 -0
  40. data/spec/lib/renogen/formatters/html_spec.rb +1 -1
  41. data/spec/lib/renogen/formatters/markdown_spec.rb +2 -2
  42. data/spec/spec_helper.rb +5 -0
  43. data/spec/support/renogen_helper.rb +9 -0
  44. metadata +17 -8
  45. data/lib/renogen/extraction_stratagies/yaml_file/exceptions.rb +0 -12
  46. data/lib/renogen/extraction_stratagies/yaml_file/exceptions/yaml_file_blank.rb +0 -25
@@ -1,3 +1,3 @@
1
1
  module Renogen
2
- VERSION='1.2.0'.freeze # :nodoc:
2
+ VERSION = '1.4.1'.freeze # :nodoc:
3
3
  end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Renogen
4
+ module Writers
5
+ # Writes out the change log in CSV format
6
+ class Csv < Base
7
+ register :csv
8
+
9
+ def write!(changelog)
10
+ puts formatter.write_headings(changelog)
11
+ output_files(changelog)
12
+ end
13
+
14
+ private
15
+
16
+ def output_files(changelog)
17
+ changelog.files.each do |file|
18
+ puts formatter.write_file(file, changelog)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -2,7 +2,7 @@ require 'spec_helper'
2
2
 
3
3
  describe Renogen::ChangeLog::Item do
4
4
  let(:change) { Array.new }
5
- subject { described_class.new('foo', change) }
5
+ subject { described_class.new(1, 'foo', change) }
6
6
 
7
7
  describe '#to_s' do
8
8
  context "when change type is nil" do
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Renogen::ChangeLog::Model do
4
- let(:change_item) { Renogen::ChangeLog::Item.new('foo', 'bar') }
4
+ let(:change_item) { Renogen::ChangeLog::Item.new(1, 'foo', 'bar') }
5
5
 
6
6
  describe '#groups' do
7
7
  it 'returns an empty hash when no changes' do
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Renogen::ChangeLog::Validator do
6
+ let(:change_log) { Renogen::ChangeLog::Model.new }
7
+ let(:validations) { { 'foo' => %w(bar baz) } }
8
+
9
+ subject { described_class.new(double('Formatter', options: { 'allowed_values' => validations })) }
10
+
11
+ before(:each) { change_log.add_change(Renogen::ChangeLog::Item.new(1, 'foo', 'bar')) }
12
+
13
+ describe '#validate!' do
14
+ context 'when no validations are available' do
15
+ let(:validations) { nil }
16
+
17
+ it 'successfully passes the validation process' do
18
+ expect { subject.validate!(change_log) }.to_not raise_error
19
+ subject.validate!(change_log)
20
+ end
21
+ end
22
+
23
+ context 'when validation is successful' do
24
+ it 'successfully passes the validation process' do
25
+ expect { subject.validate!(change_log) }.to_not raise_error
26
+ subject.validate!(change_log)
27
+ end
28
+ end
29
+
30
+ context 'when validation has failed' do
31
+ let(:validations) { { 'foo' => ['baz'] } }
32
+
33
+ it 'fails validation' do
34
+ expect { subject.validate!(change_log) }.to raise_error(Renogen::Exceptions::InvalidItemFound)
35
+ end
36
+ end
37
+ end
38
+ end
@@ -1,8 +1,205 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Renogen::ChangeLog::Writer do
4
-
5
6
  describe '#write!' do
7
+ shared_examples 'a valid output format' do
8
+ let(:changelog) do
9
+ Renogen::ChangeLog::Model.new(
10
+ version: 'test',
11
+ date: Date.new(2020, 7, 8)
12
+ )
13
+ end
14
+
15
+ let(:changes) do
16
+ [
17
+ renogen_change(1, 'Group 1', 'This is a Group 1 change'),
18
+ renogen_change(1, 'Group 2', 'This is a Group 2 change')
19
+ ]
20
+ end
21
+
22
+ subject { Renogen::ChangeLog::Writer.new(formatter) }
23
+
24
+ before do
25
+ changes.each { |c| changelog.add_change(c) }
26
+ $stdout = StringIO.new
27
+ end
28
+
29
+ after do
30
+ $stdout = STDOUT
31
+ end
32
+
33
+ it 'writes all lines' do
34
+ subject.write!(changelog)
35
+ $stdout.rewind
36
+ expected_output.split("\n").each do |line|
37
+ expect($stdout.gets.strip).to eq(line)
38
+ end
39
+
40
+ # read remaining output and check we reached the end
41
+ expect($stdout.read.gsub("\n", '')).to be_empty
42
+ end
43
+ end
44
+
45
+ context 'when formatter is CSV' do
46
+ let(:formatter) { Renogen::Formatters::Csv.new }
47
+ let(:expected_output) do
48
+ <<~EOS
49
+ Group 1,Group 2
50
+ This is a Group 1 change,This is a Group 2 change
51
+ EOS
52
+ end
53
+
54
+ it_behaves_like 'a valid output format'
55
+
56
+ context 'when changes contain commas' do
57
+ it_behaves_like 'a valid output format' do
58
+ let(:changes) do
59
+ [
60
+ renogen_change(1, 'Group 1', 'This,is,a,Group 1,change'),
61
+ renogen_change(1, 'Group 2', 'This is a Group 2 change')
62
+ ]
63
+ end
64
+
65
+ let(:expected_output) do
66
+ <<~EOS
67
+ Group 1,Group 2
68
+ "This,is,a,Group 1,change",This is a Group 2 change
69
+ EOS
70
+ end
71
+ end
72
+ end
73
+ end
74
+
75
+ context 'when formatter is HTML' do
76
+ let(:formatter) { Renogen::Formatters::Html.new }
77
+ let(:expected_output) do
78
+ <<~EOS
79
+ <html>
80
+ <h1>test (2020-07-08)</h1>
81
+ <h2>Group 1</h2>
82
+ <ul>
83
+ <li>This is a Group 1 change
84
+ </li>
85
+ </ul>
86
+ <h2>Group 2</h2>
87
+ <ul>
88
+ <li>This is a Group 2 change
89
+ </li>
90
+ </ul>
91
+ </html>
92
+ EOS
93
+ end
94
+
95
+ it_behaves_like 'a valid output format'
96
+ end
97
+
98
+ context 'when formatter is Markdown' do
99
+ let(:formatter) { Renogen::Formatters::Markdown.new }
100
+ let(:expected_output) do
101
+ <<~EOS
102
+ # test (2020-07-08)
103
+
104
+ ## Group 1
105
+
106
+ * This is a Group 1 change
107
+
108
+ ## Group 2
109
+
110
+ * This is a Group 2 change
111
+ EOS
112
+ end
113
+
114
+ it_behaves_like 'a valid output format'
115
+ end
116
+
117
+ context 'when formatter is MarkdownTable' do
118
+ let(:formatter) { Renogen::Formatters::MarkdownTable.new }
119
+
120
+ let(:expected_output) do
121
+ <<~EOS
122
+ # test (2020-07-08)
123
+
124
+ | Group 1 | Group 2 |
125
+ | - | - |
126
+ | This is a Group 1 change<br> | This is a Group 2 change<br> |
127
+ EOS
128
+ end
129
+
130
+ it_behaves_like 'a valid output format'
131
+ end
132
+
133
+ context 'when formatter is PlainText' do
134
+ let(:formatter) { Renogen::Formatters::PlainText.new }
135
+ let(:expected_output) do
136
+ <<~EOS
137
+ test (2020-07-08)
138
+
139
+ Group 1
140
+ - This is a Group 1 change
141
+
142
+ Group 2
143
+ - This is a Group 2 change
144
+ EOS
145
+ end
146
+
147
+ it_behaves_like 'a valid output format'
148
+ end
149
+
150
+ describe 'duplicates' do
151
+ let(:formatter) { Renogen::Formatters::PlainText.new }
152
+ let(:changes_with_duplicates) do
153
+ [
154
+ renogen_change(1, 'Group 1', 'This is a Group 1 change'),
155
+ renogen_change(1, 'Group 2', 'This is a Group 2 change'),
156
+ renogen_change(2, 'Group 1', 'This is a Group 1 change'),
157
+ renogen_change(2, 'Group 2', 'This is a Group 2 change')
158
+ ]
159
+ end
160
+
161
+ context 'when remove duplicates is false in config (default)' do
162
+ it_behaves_like 'a valid output format' do
163
+ let(:changes) { changes_with_duplicates }
164
+
165
+ let(:expected_output) do
166
+ <<~EOS
167
+ test (2020-07-08)
168
+
169
+ Group 1
170
+ - This is a Group 1 change
171
+ - This is a Group 1 change
172
+
173
+ Group 2
174
+ - This is a Group 2 change
175
+ - This is a Group 2 change
176
+ EOS
177
+ end
178
+ end
179
+ end
180
+
181
+ context 'when remove duplicates is true in config' do
182
+ before do
183
+ allow(Renogen::Config.instance)
184
+ .to receive(:remove_duplicates).and_return(true)
185
+ end
186
+
187
+ it_behaves_like 'a valid output format' do
188
+ let(:changes) { changes_with_duplicates }
189
+
190
+ let(:expected_output) do
191
+ <<~EOS
192
+ test (2020-07-08)
193
+
194
+ Group 1
195
+ - This is a Group 1 change
196
+
197
+ Group 2
198
+ - This is a Group 2 change
199
+ EOS
200
+ end
201
+ end
202
+ end
203
+ end
6
204
  end
7
205
  end
8
-
@@ -1,19 +1,24 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Renogen::Config do
4
-
5
6
  subject { described_class.instance }
6
7
 
7
8
  describe '#configure' do
8
9
  before :each do
9
10
  described_class.configure do |config|
10
11
  config.single_line_format = 'bar'
12
+ config.validations = ['test']
11
13
  end
12
14
  end
13
15
 
14
16
  it 'can set value' do
15
17
  expect(subject.single_line_format).to eql 'bar'
16
18
  end
17
- end
18
19
 
20
+ it 'sets the validations value' do
21
+ expect(subject.validations).to eql ['test']
22
+ end
23
+ end
19
24
  end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Renogen::Exceptions::InvalidItemFound do
6
+ subject { described_class.new(invalid_items) }
7
+
8
+ describe '#message' do
9
+ context 'valid_values is an array' do
10
+ let(:invalid_items) do
11
+ [
12
+ { group_name: 'Product', invalid_value: 'Foo', valid_values: %w(Bar Baz) },
13
+ { group_name: 'Country', invalid_value: 'LL', valid_values: %w(UK IE) }
14
+ ]
15
+ end
16
+ let(:expected_error) do
17
+ "Invalid items:\nGroup: Product, Content: Foo, Valid Values: [\"Bar\", \"Baz\"]" \
18
+ "\nGroup: Country, Content: LL, Valid Values: [\"UK\", \"IE\"]"
19
+ end
20
+
21
+ it 'returns a user friendly error message' do
22
+ expect(subject.message).to eql expected_error
23
+ end
24
+ end
25
+
26
+ context 'valid_values is a RegExp' do
27
+ let(:invalid_items) { [{ group_name: 'Product', invalid_value: 'Foo', valid_values: /\b(Bar|Baz)\b/ }] }
28
+ let(:expected_error) { "Invalid items:\nGroup: Product, Content: Foo, Pattern: #{/\b(Bar|Baz)\b/.inspect}" }
29
+
30
+ it 'returns a user friendly error message' do
31
+ expect(subject.message).to eql expected_error
32
+ end
33
+ end
34
+ end
35
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Renogen::Exceptions::StratagyNotFound do
@@ -8,6 +10,5 @@ describe Renogen::Exceptions::StratagyNotFound do
8
10
  it 'returns friendly error message' do
9
11
  expect(subject.message).to eql "Error: Stratagy type '#{name}' not found"
10
12
  end
11
-
12
13
  end
13
14
  end
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Renogen::ExtractionStratagies::YamlFile::Exceptions::YamlFileBlank do
3
+ describe Renogen::Exceptions::YamlFileBlank do
4
4
  let(:name) { 'foobar' }
5
5
  subject { described_class.new(name) }
6
6
 
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe Renogen::Exceptions::YamlFileInvalid do
4
+ let(:name) { 'foobar' }
5
+ subject { described_class.new(name) }
6
+
7
+ describe '#message' do
8
+ it 'returns friendly error message' do
9
+ expect(subject.message).to eql "Error: File contents invalid '#{name}'"
10
+ end
11
+ end
12
+ end
@@ -6,13 +6,13 @@ describe Renogen::ExtractionStratagies::YamlFile::Parser do
6
6
  describe '#parse!' do
7
7
  before :each do
8
8
  yaml_file_reader = double(Renogen::ExtractionStratagies::YamlFile::Reader)
9
- allow(yaml_file_reader).to receive(:each_yaml_file).and_yield(file_contents)
9
+ allow(yaml_file_reader).to receive(:each_yaml_file).and_yield(file_contents, 1)
10
10
  allow(Renogen::ExtractionStratagies::YamlFile::Reader).to receive(:new).and_return(yaml_file_reader)
11
11
  end
12
12
 
13
13
  it 'extracts contents from file' do
14
- changelog_item = Renogen::ChangeLog::Item.new('Foo', 'Bar')
15
- allow(Renogen::ChangeLog::Item).to receive(:new).with('Foo', 'Bar').and_return changelog_item
14
+ changelog_item = Renogen::ChangeLog::Item.new(1, 'Foo', 'Bar')
15
+ allow(Renogen::ChangeLog::Item).to receive(:new).with(1, 'Foo', 'Bar').and_return changelog_item
16
16
 
17
17
  changelog = subject.parse!
18
18
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
  require 'json'
3
5
 
@@ -6,15 +8,19 @@ describe Renogen::ExtractionStratagies::YamlFile::Reader do
6
8
  subject { described_class.new(directory_path) }
7
9
 
8
10
  describe '#each_yaml_file' do
9
- let(:file_contents) { { 'Foo' => 'Bar' }.to_json }
11
+ let(:file_contents) { { 'Foo' => 'bar' }.to_json }
10
12
 
11
- before :each do
12
- allow(Dir).to receive(:glob).with([File.join(directory_path, 'next', "*.yml")]).and_return(['foo_file'])
13
+ it 'yields each yaml file within given directory' do
14
+ allow(Dir).to receive(:glob).with([File.join(directory_path, 'next', '*.yml')]).and_return(['foo_file'])
13
15
  allow(YAML).to receive(:load_file).with('foo_file').and_return(file_contents)
16
+ expect { |b| subject.each_yaml_file(&b) }.to yield_with_args(file_contents, 0)
14
17
  end
15
18
 
16
- it 'yields each yaml file within given directory' do
17
- expect{ |b| subject.each_yaml_file(&b) }.to yield_with_args(file_contents)
19
+ it 'throws invalid yaml file when missing quotes' do
20
+ allow(subject).to receive(:change_directories).and_return(%w(foo bar))
21
+ foo = Psych::SyntaxError.new('a', 1, 2, 'd', 'e', 'f')
22
+ allow(YAML).to receive(:load_file).and_raise(foo)
23
+ expect { subject.each_yaml_file }.to raise_error(Renogen::Exceptions::YamlFileInvalid)
18
24
  end
19
25
  end
20
26
  end