app_archetype 1.2.3
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 +7 -0
- data/.doxie.json +25 -0
- data/.github/workflows/build.yml +25 -0
- data/.gitignore +22 -0
- data/.rubocop.yml +35 -0
- data/.ruby-version +1 -0
- data/CONTRIBUTING.md +51 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +172 -0
- data/LICENSE +21 -0
- data/README.md +138 -0
- data/Rakefile +19 -0
- data/app_archetype.gemspec +39 -0
- data/bin/archetype +20 -0
- data/lib/app_archetype.rb +14 -0
- data/lib/app_archetype/cli.rb +204 -0
- data/lib/app_archetype/cli/presenters.rb +106 -0
- data/lib/app_archetype/cli/prompts.rb +152 -0
- data/lib/app_archetype/generators.rb +95 -0
- data/lib/app_archetype/logger.rb +69 -0
- data/lib/app_archetype/renderer.rb +116 -0
- data/lib/app_archetype/template.rb +12 -0
- data/lib/app_archetype/template/helpers.rb +216 -0
- data/lib/app_archetype/template/manifest.rb +193 -0
- data/lib/app_archetype/template/plan.rb +172 -0
- data/lib/app_archetype/template/source.rb +39 -0
- data/lib/app_archetype/template/variable.rb +237 -0
- data/lib/app_archetype/template/variable_manager.rb +75 -0
- data/lib/app_archetype/template_manager.rb +113 -0
- data/lib/app_archetype/version.rb +6 -0
- data/lib/core_ext/string.rb +67 -0
- data/spec/app_archetype/cli/presenters_spec.rb +99 -0
- data/spec/app_archetype/cli/prompts_spec.rb +292 -0
- data/spec/app_archetype/cli_spec.rb +132 -0
- data/spec/app_archetype/generators_spec.rb +119 -0
- data/spec/app_archetype/logger_spec.rb +86 -0
- data/spec/app_archetype/renderer_spec.rb +291 -0
- data/spec/app_archetype/template/helpers_spec.rb +251 -0
- data/spec/app_archetype/template/manifest_spec.rb +245 -0
- data/spec/app_archetype/template/plan_spec.rb +191 -0
- data/spec/app_archetype/template/source_spec.rb +60 -0
- data/spec/app_archetype/template/variable_manager_spec.rb +103 -0
- data/spec/app_archetype/template/variable_spec.rb +245 -0
- data/spec/app_archetype/template_manager_spec.rb +221 -0
- data/spec/core_ext/string_spec.rb +143 -0
- data/spec/spec_helper.rb +29 -0
- metadata +370 -0
@@ -0,0 +1,132 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe AppArchetype::CLI do
|
4
|
+
subject { described_class.new }
|
5
|
+
|
6
|
+
describe '.manager' do
|
7
|
+
let(:manager) { double }
|
8
|
+
let(:template_dir) { 'path/to/templates' }
|
9
|
+
|
10
|
+
before do
|
11
|
+
allow(described_class).to receive(:template_dir).and_return(template_dir)
|
12
|
+
allow(AppArchetype::TemplateManager).to receive(:new).and_return(manager)
|
13
|
+
|
14
|
+
allow(manager).to receive(:load)
|
15
|
+
|
16
|
+
@manager = described_class.manager
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'creates a manager' do
|
20
|
+
expect(AppArchetype::TemplateManager)
|
21
|
+
.to have_received(:new)
|
22
|
+
.with(template_dir)
|
23
|
+
|
24
|
+
expect(manager).to have_received(:load)
|
25
|
+
expect(@manager).to eq manager
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '.template_dir' do
|
30
|
+
let(:env_template_dir) { 'path/to/templates' }
|
31
|
+
let(:exist) { true }
|
32
|
+
|
33
|
+
before do
|
34
|
+
allow(ENV).to receive(:[])
|
35
|
+
.with('ARCHETYPE_TEMPLATE_DIR')
|
36
|
+
.and_return(env_template_dir)
|
37
|
+
|
38
|
+
allow(File).to receive(:exist?).and_return(exist)
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'returns template dir' do
|
42
|
+
expect(described_class.template_dir).to eq env_template_dir
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'when ARCHETYPE_TEMPLATE_DIR environment variable not set' do
|
46
|
+
let(:env_template_dir) { nil }
|
47
|
+
|
48
|
+
it 'raises environment not set error' do
|
49
|
+
expect { described_class.template_dir }.to raise_error(
|
50
|
+
RuntimeError,
|
51
|
+
'ARCHETYPE_TEMPLATE_DIR environment variable not set'
|
52
|
+
)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context 'when templates do not exist' do
|
57
|
+
let(:exist) { false }
|
58
|
+
|
59
|
+
it 'raises environment not set error' do
|
60
|
+
expect { described_class.template_dir }.to raise_error(
|
61
|
+
RuntimeError,
|
62
|
+
"ARCHETYPE_TEMPLATE_DIR #{env_template_dir} does not exist"
|
63
|
+
)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe '.editor' do
|
69
|
+
let(:env_editor) { 'ivm' }
|
70
|
+
let(:exit_status) { 0 }
|
71
|
+
|
72
|
+
before do
|
73
|
+
allow(ENV).to receive(:[])
|
74
|
+
.with('ARCHETYPE_EDITOR')
|
75
|
+
.and_return(env_editor)
|
76
|
+
|
77
|
+
allow(described_class).to receive(:`)
|
78
|
+
allow($?).to receive(:exitstatus).and_return(exit_status)
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'returns editor' do
|
82
|
+
expect(described_class.editor).to eq env_editor
|
83
|
+
end
|
84
|
+
|
85
|
+
context 'when ARCHETYPE_EDITOR environment variable not set' do
|
86
|
+
let(:env_editor) { nil }
|
87
|
+
|
88
|
+
it 'raises environment not set error' do
|
89
|
+
expect { described_class.editor }.to raise_error(
|
90
|
+
RuntimeError,
|
91
|
+
'ARCHETYPE_EDITOR environment variable not set'
|
92
|
+
)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
context 'when editor check does not pass' do
|
97
|
+
let(:exit_status) { 1 }
|
98
|
+
|
99
|
+
before do
|
100
|
+
allow(AppArchetype::CLI).to receive(:print_warning)
|
101
|
+
described_class.editor
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'logs a warning' do
|
105
|
+
expect(AppArchetype::CLI)
|
106
|
+
.to have_received(:print_warning)
|
107
|
+
.with(
|
108
|
+
"WARN: Configured editor #{env_editor} is not installed correctly "\
|
109
|
+
'please check your configuration'
|
110
|
+
)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
describe '.exit_on_failure?' do
|
116
|
+
it 'returns true' do
|
117
|
+
expect(described_class.exit_on_failure?).to be true
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
describe '#version' do
|
122
|
+
before do
|
123
|
+
allow(subject).to receive(:print_message)
|
124
|
+
subject.version
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'prints current version number' do
|
128
|
+
expect(subject).to have_received(:print_message)
|
129
|
+
.with(AppArchetype::VERSION)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe AppArchetype::Generators do
|
4
|
+
describe '::TEMPLATE_MANIFEST' do
|
5
|
+
let(:name) { 'project' }
|
6
|
+
|
7
|
+
before do
|
8
|
+
@manifest = OpenStruct.new(
|
9
|
+
described_class::TEMPLATE_MANIFEST.call(name)
|
10
|
+
)
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'has expected name' do
|
14
|
+
expect(@manifest.name).to eq name
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'has expected version' do
|
18
|
+
expect(@manifest.version).to eq '1.0.0'
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'has app archetype metadata' do
|
22
|
+
expect(@manifest.metadata['app_archetype']).not_to be nil
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'renders app version into archetype metadata' do
|
26
|
+
expect(@manifest.metadata['app_archetype']['version'])
|
27
|
+
.to eq AppArchetype::VERSION
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'has default variables' do
|
31
|
+
expect(@manifest.variables).to eq described_class::DEFAULT_VARS
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'renders a manifest that is compliant with the manifest schema' do
|
35
|
+
expect(
|
36
|
+
JSON::Validator.fully_validate(
|
37
|
+
AppArchetype::Template::Manifest::SCHEMA,
|
38
|
+
@manifest.to_h.to_json,
|
39
|
+
strict: true
|
40
|
+
).empty?
|
41
|
+
).to be true
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe '::TEMPLATE_README' do
|
46
|
+
let(:name) { 'project' }
|
47
|
+
|
48
|
+
before do
|
49
|
+
@readme = described_class::TEMPLATE_README.call(name)
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'renders name into heading' do
|
53
|
+
expect(@readme.include?("# #{name} Template")).to be true
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'renders name into generation example' do
|
57
|
+
expect(@readme.include?("mkdir my_#{name}")).to be true
|
58
|
+
expect(@readme.include?("cd $HOME/Code/my_#{name}")).to be true
|
59
|
+
expect(@readme.include?("archetype render #{name}")).to be true
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe '.render_empty_template' do
|
64
|
+
let(:manifest_file) { double }
|
65
|
+
let(:manifest_path) { File.join(templates_path, 'manifest.json') }
|
66
|
+
|
67
|
+
let(:readme_file) { double }
|
68
|
+
let(:readme_path) { File.join(templates_path, 'README.md') }
|
69
|
+
|
70
|
+
let(:name) { 'new_template' }
|
71
|
+
let(:templates_path) { 'path/to/templates' }
|
72
|
+
|
73
|
+
let(:manifest) { 'manifest' }
|
74
|
+
let(:readme) { 'readme' }
|
75
|
+
|
76
|
+
before do
|
77
|
+
allow(File).to receive(:open)
|
78
|
+
.with(manifest_path, 'w')
|
79
|
+
.and_yield(manifest_file)
|
80
|
+
allow(manifest_file).to receive(:write)
|
81
|
+
|
82
|
+
allow(File).to receive(:open)
|
83
|
+
.with(readme_path, 'w')
|
84
|
+
.and_yield(readme_file)
|
85
|
+
allow(readme_file).to receive(:write)
|
86
|
+
|
87
|
+
allow(FileUtils).to receive(:mkdir_p)
|
88
|
+
|
89
|
+
allow(described_class::TEMPLATE_MANIFEST)
|
90
|
+
.to receive(:call).and_return(manifest)
|
91
|
+
|
92
|
+
allow(described_class::TEMPLATE_README)
|
93
|
+
.to receive(:call).and_return(readme)
|
94
|
+
|
95
|
+
described_class.render_empty_template(
|
96
|
+
name,
|
97
|
+
templates_path
|
98
|
+
)
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'makes template dir' do
|
102
|
+
expect(FileUtils)
|
103
|
+
.to have_received(:mkdir_p)
|
104
|
+
.with(File.join(templates_path, name))
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'renders blank manifest' do
|
108
|
+
expect(manifest_file)
|
109
|
+
.to have_received(:write)
|
110
|
+
.with("\"#{manifest}\"")
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'renders readme' do
|
114
|
+
expect(readme_file)
|
115
|
+
.to have_received(:write)
|
116
|
+
.with(readme)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe AppArchetype::Logger do
|
4
|
+
let(:logger) { double(Logger) }
|
5
|
+
let(:err_logger) { double(Logger) }
|
6
|
+
let(:message) { 'All work and no play makes Jack a dull boy' }
|
7
|
+
|
8
|
+
subject { Object.new.extend(described_class) }
|
9
|
+
|
10
|
+
before do
|
11
|
+
allow(subject).to receive(:exit).and_return(double)
|
12
|
+
end
|
13
|
+
|
14
|
+
describe '.logger' do
|
15
|
+
let(:out) { double(STDOUT) }
|
16
|
+
before do
|
17
|
+
allow(Logger).to receive(:new).and_return(logger)
|
18
|
+
allow(logger).to receive(:formatter=)
|
19
|
+
|
20
|
+
subject.logger(out)
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'creates a new logger to STDOUT' do
|
24
|
+
expect(Logger).to have_received(:new).with(out)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '.print_message' do
|
29
|
+
let(:logger) { double(Logger) }
|
30
|
+
|
31
|
+
before do
|
32
|
+
allow(subject).to receive(:logger).and_return(logger)
|
33
|
+
allow(logger).to receive(:info)
|
34
|
+
subject.print_message(message)
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'prints message to stdout' do
|
38
|
+
expect(logger).to have_received(:info).with(message)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe '.print_warning' do
|
43
|
+
let(:logger) { double(Logger) }
|
44
|
+
|
45
|
+
before do
|
46
|
+
allow(subject).to receive(:logger).and_return(logger)
|
47
|
+
allow(logger).to receive(:warn)
|
48
|
+
subject.print_warning(message)
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'prints message to stdout' do
|
52
|
+
expect(logger).to have_received(:warn).with(message)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe '.print_error' do
|
57
|
+
let(:logger) { double(Logger) }
|
58
|
+
|
59
|
+
before do
|
60
|
+
allow(subject).to receive(:logger).and_return(logger)
|
61
|
+
allow(logger).to receive(:error)
|
62
|
+
subject.print_error(message)
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'prints message to stderr' do
|
66
|
+
expect(logger).to have_received(:error).with(message)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe '.print_message_and_exit' do
|
71
|
+
let(:exit_code) { 2 }
|
72
|
+
|
73
|
+
before do
|
74
|
+
allow(subject).to receive(:print_message)
|
75
|
+
subject.print_message_and_exit(message, exit_code)
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'prints message' do
|
79
|
+
expect(subject).to have_received(:print_message).with(message)
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'exits with set status' do
|
83
|
+
expect(subject).to have_received(:exit).with(exit_code)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,291 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe AppArchetype::Renderer do
|
4
|
+
let(:logger) { double(Logger) }
|
5
|
+
let(:template) { AppArchetype::Template::Source.new('path/to/template') }
|
6
|
+
let(:destination) { 'path/to/destination' }
|
7
|
+
let(:variables) do
|
8
|
+
OpenStruct.new(
|
9
|
+
foo: 'bar'
|
10
|
+
)
|
11
|
+
end
|
12
|
+
let(:plan) do
|
13
|
+
AppArchetype::Template::Plan.new(
|
14
|
+
template,
|
15
|
+
variables,
|
16
|
+
destination_path: destination
|
17
|
+
)
|
18
|
+
end
|
19
|
+
let(:overwrite) { false }
|
20
|
+
|
21
|
+
before do
|
22
|
+
allow(subject).to receive(:logger).and_return(logger)
|
23
|
+
allow(logger).to receive(:info)
|
24
|
+
end
|
25
|
+
|
26
|
+
subject { described_class.new(plan, overwrite) }
|
27
|
+
|
28
|
+
describe '#render' do
|
29
|
+
let(:file) do
|
30
|
+
AppArchetype::Template::OutputFile.new(
|
31
|
+
'path/to/source/file',
|
32
|
+
'path/to/destination/file'
|
33
|
+
)
|
34
|
+
end
|
35
|
+
|
36
|
+
let(:erb_template) do
|
37
|
+
AppArchetype::Template::OutputFile.new(
|
38
|
+
'path/to/template.erb',
|
39
|
+
'path/to/destination/template'
|
40
|
+
)
|
41
|
+
end
|
42
|
+
|
43
|
+
let(:hbs_template) do
|
44
|
+
AppArchetype::Template::OutputFile.new(
|
45
|
+
'path/to/template.hbs',
|
46
|
+
'path/to/destination/template'
|
47
|
+
)
|
48
|
+
end
|
49
|
+
|
50
|
+
let(:directory) do
|
51
|
+
AppArchetype::Template::OutputFile.new(
|
52
|
+
'path/to/source/dir',
|
53
|
+
'path/to/destination/dir'
|
54
|
+
)
|
55
|
+
end
|
56
|
+
|
57
|
+
let(:file_double) { double(File) }
|
58
|
+
|
59
|
+
before do
|
60
|
+
allow(subject).to receive(:write_dir)
|
61
|
+
allow(subject).to receive(:render_erb_file)
|
62
|
+
allow(subject).to receive(:render_hbs_file)
|
63
|
+
allow(subject).to receive(:copy_file)
|
64
|
+
|
65
|
+
allow(File).to receive(:new).and_return(file_double)
|
66
|
+
|
67
|
+
allow(file).to receive(:source_file?).and_return(true)
|
68
|
+
allow(erb_template).to receive(:source_erb?).and_return(true)
|
69
|
+
allow(hbs_template).to receive(:source_hbs?).and_return(true)
|
70
|
+
allow(directory).to receive(:source_directory?).and_return(true)
|
71
|
+
|
72
|
+
plan.instance_variable_set(
|
73
|
+
:@files,
|
74
|
+
[file, erb_template, hbs_template, directory]
|
75
|
+
)
|
76
|
+
|
77
|
+
subject.render
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'creates destination directory' do
|
81
|
+
expect(subject).to have_received(:write_dir).with(file_double)
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'creates directory' do
|
85
|
+
expect(subject).to have_received(:write_dir).with(directory)
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'renders erb template' do
|
89
|
+
expect(subject).to have_received(:render_erb_file).with(erb_template)
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'renders hbs template' do
|
93
|
+
expect(subject).to have_received(:render_hbs_file).with(hbs_template)
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'copies file' do
|
97
|
+
expect(subject).to have_received(:copy_file).with(file)
|
98
|
+
end
|
99
|
+
|
100
|
+
context 'when no method error is raised' do
|
101
|
+
before do
|
102
|
+
allow(subject).to receive(:render_erb_file).and_raise(NoMethodError.new)
|
103
|
+
|
104
|
+
plan.instance_variable_set(
|
105
|
+
:@files,
|
106
|
+
[erb_template]
|
107
|
+
)
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'raises missing variable error' do
|
111
|
+
expect { subject.render }.to raise_error(
|
112
|
+
RuntimeError,
|
113
|
+
'error rendering path/to/destination/template cannot '\
|
114
|
+
'find variable `` in template'
|
115
|
+
)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
context 'when no template is invalid' do
|
120
|
+
before do
|
121
|
+
allow(subject).to receive(:render_erb_file).and_raise(SyntaxError.new)
|
122
|
+
|
123
|
+
plan.instance_variable_set(
|
124
|
+
:@files,
|
125
|
+
[erb_template]
|
126
|
+
)
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'raises missing variable error' do
|
130
|
+
expect { subject.render }.to raise_error(
|
131
|
+
RuntimeError,
|
132
|
+
'error parsing path/to/destination/template template is invalid'
|
133
|
+
)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
describe '#write_dir' do
|
139
|
+
let(:source_path) { 'path/to/template/dir' }
|
140
|
+
let(:dest_path) { 'path/to/destination/dir' }
|
141
|
+
let(:dir) { AppArchetype::Template::OutputFile.new(source_path, dest_path) }
|
142
|
+
let(:exists) { false }
|
143
|
+
|
144
|
+
before do
|
145
|
+
allow(FileUtils).to receive(:mkdir_p)
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'creates directory' do
|
149
|
+
subject.write_dir(dir)
|
150
|
+
expect(FileUtils).to have_received(:mkdir_p).with(dest_path)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
describe '#render_erb_file' do
|
155
|
+
let(:source_path) { 'path/to/template/file' }
|
156
|
+
let(:dest_path) { 'path/to/destination/file' }
|
157
|
+
|
158
|
+
let(:file) do
|
159
|
+
AppArchetype::Template::OutputFile.new(source_path, dest_path)
|
160
|
+
end
|
161
|
+
|
162
|
+
let(:input) do
|
163
|
+
<<~INPUT
|
164
|
+
this is the content of the <%= foo %> file
|
165
|
+
INPUT
|
166
|
+
end
|
167
|
+
|
168
|
+
let(:expected_output) do
|
169
|
+
<<~OUTPUT
|
170
|
+
this is the content of the bar file
|
171
|
+
OUTPUT
|
172
|
+
end
|
173
|
+
|
174
|
+
let(:write_double) { double }
|
175
|
+
|
176
|
+
before do
|
177
|
+
allow(File).to receive(:read).and_return(input)
|
178
|
+
allow(File).to receive(:open).and_yield(write_double)
|
179
|
+
allow(write_double).to receive(:write)
|
180
|
+
|
181
|
+
subject.render_erb_file(file)
|
182
|
+
end
|
183
|
+
|
184
|
+
it 'reads source' do
|
185
|
+
expect(File).to have_received(:read).with(source_path)
|
186
|
+
end
|
187
|
+
|
188
|
+
it 'writes rendered template' do
|
189
|
+
expect(write_double).to have_received(:write).with(expected_output)
|
190
|
+
end
|
191
|
+
|
192
|
+
context 'when a variable is missing' do
|
193
|
+
let(:vars) { OpenStruct.new }
|
194
|
+
let(:var_value) { '' }
|
195
|
+
|
196
|
+
it 'renders template with blank' do
|
197
|
+
expect(write_double).to have_received(:write).with(expected_output)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
describe '#render_hbs_file' do
|
203
|
+
let(:source_path) { 'path/to/template/file' }
|
204
|
+
let(:dest_path) { 'path/to/destination/file' }
|
205
|
+
|
206
|
+
let(:file) do
|
207
|
+
AppArchetype::Template::OutputFile.new(source_path, dest_path)
|
208
|
+
end
|
209
|
+
|
210
|
+
let(:input) do
|
211
|
+
<<~INPUT
|
212
|
+
this is the content of the {{ foo }} file
|
213
|
+
INPUT
|
214
|
+
end
|
215
|
+
|
216
|
+
let(:expected_output) do
|
217
|
+
<<~OUTPUT
|
218
|
+
this is the content of the bar file
|
219
|
+
OUTPUT
|
220
|
+
end
|
221
|
+
|
222
|
+
let(:write_double) { double }
|
223
|
+
|
224
|
+
before do
|
225
|
+
allow(File).to receive(:read).and_return(input)
|
226
|
+
allow(File).to receive(:open).and_yield(write_double)
|
227
|
+
allow(write_double).to receive(:write)
|
228
|
+
|
229
|
+
subject.render_hbs_file(file)
|
230
|
+
end
|
231
|
+
|
232
|
+
it 'reads source' do
|
233
|
+
expect(File).to have_received(:read).with(source_path)
|
234
|
+
end
|
235
|
+
|
236
|
+
it 'writes rendered template' do
|
237
|
+
expect(write_double).to have_received(:write).with(expected_output)
|
238
|
+
end
|
239
|
+
|
240
|
+
context 'when a variable is missing' do
|
241
|
+
let(:vars) { OpenStruct.new }
|
242
|
+
let(:var_value) { '' }
|
243
|
+
|
244
|
+
it 'renders template with blank' do
|
245
|
+
expect(write_double).to have_received(:write).with(expected_output)
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
describe '#copy_file' do
|
251
|
+
let(:source_path) { 'path/to/template/file' }
|
252
|
+
let(:dest_path) { 'path/to/destination/file' }
|
253
|
+
|
254
|
+
let(:file) do
|
255
|
+
AppArchetype::Template::OutputFile.new(source_path, dest_path)
|
256
|
+
end
|
257
|
+
|
258
|
+
let(:exists) { false }
|
259
|
+
|
260
|
+
before do
|
261
|
+
allow(FileUtils).to receive(:cp)
|
262
|
+
allow(file).to receive(:exist?).and_return(exists)
|
263
|
+
end
|
264
|
+
|
265
|
+
it 'copies file' do
|
266
|
+
subject.copy_file(file)
|
267
|
+
expect(FileUtils).to have_received(:cp).with(source_path, dest_path)
|
268
|
+
end
|
269
|
+
|
270
|
+
context 'when file already exists and overwrite not allowed' do
|
271
|
+
let(:exists) { true }
|
272
|
+
|
273
|
+
it 'raises error' do
|
274
|
+
expect do
|
275
|
+
subject.copy_file(file)
|
276
|
+
end.to raise_error('cannot overwrite file')
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
context 'when file already exists and overwrite is allowed' do
|
281
|
+
let(:exists) { true }
|
282
|
+
let(:overwrite) { true }
|
283
|
+
|
284
|
+
it 'raises error' do
|
285
|
+
expect do
|
286
|
+
subject.copy_file(file)
|
287
|
+
end.not_to raise_error
|
288
|
+
end
|
289
|
+
end
|
290
|
+
end
|
291
|
+
end
|