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.
- checksums.yaml +5 -5
- data/README.md +119 -26
- data/lib/renogen/change_log.rb +1 -0
- data/lib/renogen/change_log/item.rb +6 -4
- data/lib/renogen/change_log/model.rb +9 -0
- data/lib/renogen/change_log/validator.rb +61 -0
- data/lib/renogen/change_log/writer.rb +35 -3
- data/lib/renogen/cli.rb +7 -4
- data/lib/renogen/config.rb +16 -15
- data/lib/renogen/exceptions.rb +5 -0
- data/lib/renogen/exceptions/invalid_item_found.rb +32 -0
- data/lib/renogen/exceptions/yaml_file_blank.rb +21 -0
- data/lib/renogen/exceptions/yaml_file_invalid.rb +20 -0
- data/lib/renogen/extraction_stratagies.rb +0 -2
- data/lib/renogen/extraction_stratagies/yaml_file.rb +0 -1
- data/lib/renogen/extraction_stratagies/yaml_file/parser.rb +5 -4
- data/lib/renogen/extraction_stratagies/yaml_file/reader.rb +20 -11
- data/lib/renogen/formatters.rb +2 -0
- data/lib/renogen/formatters/base.rb +14 -4
- data/lib/renogen/formatters/csv.rb +42 -0
- data/lib/renogen/formatters/html.rb +1 -1
- data/lib/renogen/formatters/markdown.rb +2 -2
- data/lib/renogen/formatters/markdown_table.rb +58 -0
- data/lib/renogen/generator.rb +8 -1
- data/lib/renogen/version.rb +1 -1
- data/lib/renogen/writers/csv.rb +23 -0
- data/spec/lib/renogen/change_log/item_spec.rb +1 -1
- data/spec/lib/renogen/change_log/model_spec.rb +1 -1
- data/spec/lib/renogen/change_log/validator_spec.rb +38 -0
- data/spec/lib/renogen/change_log/writer_spec.rb +199 -2
- data/spec/lib/renogen/config_spec.rb +7 -2
- data/spec/lib/renogen/exceptions/invalid_item_found_spec.rb +35 -0
- data/spec/lib/renogen/exceptions/stratagy_not_found_spec.rb +2 -1
- data/spec/lib/renogen/{extraction_stratagies/yaml_file/exceptions → exceptions}/yaml_file_blank_spec.rb +1 -1
- data/spec/lib/renogen/exceptions/yaml_file_invalid_spec.rb +12 -0
- data/spec/lib/renogen/extraction_stratagies/yaml_file/parser_spec.rb +3 -3
- data/spec/lib/renogen/extraction_stratagies/yaml_file/reader_spec.rb +11 -5
- data/spec/lib/renogen/formatters/base_spec.rb +8 -8
- data/spec/lib/renogen/formatters/csv_spec.rb +49 -0
- data/spec/lib/renogen/formatters/html_spec.rb +1 -1
- data/spec/lib/renogen/formatters/markdown_spec.rb +2 -2
- data/spec/spec_helper.rb +5 -0
- data/spec/support/renogen_helper.rb +9 -0
- metadata +17 -8
- data/lib/renogen/extraction_stratagies/yaml_file/exceptions.rb +0 -12
- data/lib/renogen/extraction_stratagies/yaml_file/exceptions/yaml_file_blank.rb +0 -25
data/lib/renogen/version.rb
CHANGED
@@ -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
|
@@ -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
|
@@ -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' => '
|
11
|
+
let(:file_contents) { { 'Foo' => 'bar' }.to_json }
|
10
12
|
|
11
|
-
|
12
|
-
allow(Dir).to receive(:glob).with([File.join(directory_path, 'next',
|
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 '
|
17
|
-
|
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
|