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,75 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module AppArchetype
|
5
|
+
module Template
|
6
|
+
# Manages a collection of variables
|
7
|
+
class VariableManager
|
8
|
+
def initialize(vars)
|
9
|
+
vars ||= []
|
10
|
+
@data = []
|
11
|
+
|
12
|
+
vars.each do |name, spec|
|
13
|
+
@data << AppArchetype::Template::Variable.new(name, spec)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
##
|
18
|
+
# Returns all variables managed by the variable manager.
|
19
|
+
#
|
20
|
+
# @return [Array]
|
21
|
+
#
|
22
|
+
def all
|
23
|
+
@data
|
24
|
+
end
|
25
|
+
|
26
|
+
##
|
27
|
+
# Retrieves a variable by name from the variable manager.
|
28
|
+
#
|
29
|
+
# @param [String] name
|
30
|
+
#
|
31
|
+
# @return [AppArchetype::Template::Variable]
|
32
|
+
#
|
33
|
+
def get(name)
|
34
|
+
@data.detect { |var| var.name == name }
|
35
|
+
end
|
36
|
+
|
37
|
+
##
|
38
|
+
# Creates a hash representation of variables.
|
39
|
+
#
|
40
|
+
# The variable name is the key, and the currrent value
|
41
|
+
# is the value.
|
42
|
+
#
|
43
|
+
# @return [Hash]
|
44
|
+
#
|
45
|
+
def to_h
|
46
|
+
var_hash = {}
|
47
|
+
|
48
|
+
@data.each do |var|
|
49
|
+
var_hash[var.name] = var.value
|
50
|
+
end
|
51
|
+
|
52
|
+
var_hash
|
53
|
+
end
|
54
|
+
|
55
|
+
##
|
56
|
+
# Method missing retrieves variable from manager and
|
57
|
+
# returns the value to the caller if it is found.
|
58
|
+
#
|
59
|
+
# When a call is made to an undefined variable, a
|
60
|
+
# MethodMissing error will be raised.
|
61
|
+
#
|
62
|
+
# @param [Symbol] method
|
63
|
+
# @param [Array] args
|
64
|
+
#
|
65
|
+
# @return [Object]
|
66
|
+
#
|
67
|
+
def method_missing(method, *args)
|
68
|
+
var = get(method.to_s)
|
69
|
+
return var.value if var
|
70
|
+
|
71
|
+
super
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
module AppArchetype
|
2
|
+
# Manager looks after a set of archetypes
|
3
|
+
class TemplateManager
|
4
|
+
##
|
5
|
+
# Default filter is a lambda that returns true for all manifests
|
6
|
+
#
|
7
|
+
DEFAULT_QUERY = ->(_manifest) { return true }
|
8
|
+
|
9
|
+
attr_reader :manifests
|
10
|
+
|
11
|
+
##
|
12
|
+
# Creates a manager
|
13
|
+
#
|
14
|
+
# @param [String] template_dir
|
15
|
+
#
|
16
|
+
def initialize(template_dir)
|
17
|
+
@template_dir = template_dir
|
18
|
+
@manifests = []
|
19
|
+
end
|
20
|
+
|
21
|
+
##
|
22
|
+
# Loads and parses each manifest within the template directory into
|
23
|
+
# memory. Any invalid manifests are ignored and a message is printed
|
24
|
+
# to STDOUT indicating which manifest is not valid.
|
25
|
+
#
|
26
|
+
def load
|
27
|
+
Dir.glob(
|
28
|
+
File.join(@template_dir, '**', 'manifest.json*')
|
29
|
+
).each do |manifest|
|
30
|
+
begin
|
31
|
+
@manifests << AppArchetype::Template::Manifest.new_from_file(manifest)
|
32
|
+
rescue StandardError
|
33
|
+
puts "WARN: `#{manifest}` is invalid, skipping"
|
34
|
+
next
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
##
|
40
|
+
# Filter executes a query function in a select call against each manifest
|
41
|
+
# in the manager's collection.
|
42
|
+
#
|
43
|
+
# The given query function should be something that will evaluate to true
|
44
|
+
# when the manifest matches - this will hence filter the manifest set to
|
45
|
+
# the filtered set.
|
46
|
+
#
|
47
|
+
# @example
|
48
|
+
# manager = AppArchetype::TemplateManager.new('/path/to/templates')
|
49
|
+
# query = -> (manifest) { manifest.name = "fudge" }
|
50
|
+
#
|
51
|
+
# fudge_templates = manager.filter(query)
|
52
|
+
#
|
53
|
+
# @param [Lambda] query
|
54
|
+
#
|
55
|
+
# @return [Array]
|
56
|
+
def filter(query = DEFAULT_QUERY)
|
57
|
+
@manifests.select do |template|
|
58
|
+
query.call(template)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
##
|
63
|
+
# Searches for manifests matching given name and returns it to caller.
|
64
|
+
#
|
65
|
+
# @example:
|
66
|
+
# manager = AppArchetype::TemplateManager.new('/path/to/templates')
|
67
|
+
# fudge_manifest = manager.find('fudge')
|
68
|
+
#
|
69
|
+
# @param [String] name
|
70
|
+
#
|
71
|
+
# @return [Array]
|
72
|
+
#
|
73
|
+
def search_by_name(name)
|
74
|
+
name_query = lambda do |template|
|
75
|
+
template.name.include?(name)
|
76
|
+
end
|
77
|
+
|
78
|
+
filter(name_query)
|
79
|
+
end
|
80
|
+
|
81
|
+
##
|
82
|
+
# Finds a specific manifest by name and returns it to the caller.
|
83
|
+
#
|
84
|
+
# It is possible that a more than one manifest is found when searching
|
85
|
+
# by name. If this happens while ignore_dupe is set to false, then a
|
86
|
+
# Runtime error is raised. If ignore_dupe is set to false then the first
|
87
|
+
# matching manifest is returned.
|
88
|
+
#
|
89
|
+
# @example:
|
90
|
+
# manager = AppArchetype::TemplateManager.new('/path/to/templates')
|
91
|
+
# fudge_manifest = manager.find('fudge')
|
92
|
+
#
|
93
|
+
# @param [String] name
|
94
|
+
# @param [Boolean] ignore_dupe
|
95
|
+
#
|
96
|
+
# @return [AppArchetype::Template::Manifest]
|
97
|
+
#
|
98
|
+
def find_by_name(name, ignore_dupe: false)
|
99
|
+
name_query = lambda do |template|
|
100
|
+
template.name == name
|
101
|
+
end
|
102
|
+
|
103
|
+
results = filter(name_query)
|
104
|
+
|
105
|
+
if results.count > 1 && ignore_dupe == false
|
106
|
+
raise 'more than one manifest matching the'\
|
107
|
+
' given name were found'
|
108
|
+
end
|
109
|
+
|
110
|
+
results.first
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'app_archetype/template/helpers'
|
2
|
+
|
3
|
+
# Archetype extensions for String
|
4
|
+
class String
|
5
|
+
##
|
6
|
+
# Converts string to snake case
|
7
|
+
#
|
8
|
+
# @return [String]
|
9
|
+
#
|
10
|
+
def snake_case
|
11
|
+
helper.snake_case(self)
|
12
|
+
end
|
13
|
+
|
14
|
+
##
|
15
|
+
# Converts string to dash case
|
16
|
+
#
|
17
|
+
# @return [String]
|
18
|
+
#
|
19
|
+
def dash_case
|
20
|
+
helper.dash_case(self)
|
21
|
+
end
|
22
|
+
|
23
|
+
##
|
24
|
+
# Converts a string to camel case
|
25
|
+
#
|
26
|
+
# @return [String]
|
27
|
+
#
|
28
|
+
def camel_case
|
29
|
+
helper.camel_case(self)
|
30
|
+
end
|
31
|
+
|
32
|
+
##
|
33
|
+
# Attempts to pluralize a word
|
34
|
+
#
|
35
|
+
# @return [String]
|
36
|
+
#
|
37
|
+
def pluralize
|
38
|
+
helper.pluralize(self)
|
39
|
+
end
|
40
|
+
|
41
|
+
##
|
42
|
+
# Attempts to singluarize a word
|
43
|
+
#
|
44
|
+
# @return [String]
|
45
|
+
#
|
46
|
+
def singularize
|
47
|
+
helper.singularize(self)
|
48
|
+
end
|
49
|
+
|
50
|
+
##
|
51
|
+
# Adds a random string of specified length at the end
|
52
|
+
#
|
53
|
+
# @return [String]
|
54
|
+
#
|
55
|
+
def randomize(size = 5)
|
56
|
+
helper.randomize(self, size.to_s)
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
# Instance helper methods
|
62
|
+
def helper
|
63
|
+
Object
|
64
|
+
.new
|
65
|
+
.extend(AppArchetype::Template::Helpers)
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe AppArchetype::CLI::Presenters do
|
4
|
+
describe '.manifest_list' do
|
5
|
+
let(:manifest) do
|
6
|
+
double(
|
7
|
+
AppArchetype::Template::Manifest,
|
8
|
+
name: 'test_manifest',
|
9
|
+
version: '1.0.0'
|
10
|
+
)
|
11
|
+
end
|
12
|
+
let(:manifest_list_row) { ['test_manifest', '1.0.0'] }
|
13
|
+
|
14
|
+
let(:presenter) { double(CliFormat::Presenter) }
|
15
|
+
let(:manifests) { [manifest, manifest] }
|
16
|
+
|
17
|
+
before do
|
18
|
+
allow(presenter).to receive(:show)
|
19
|
+
allow(subject).to receive(:table).and_return(presenter)
|
20
|
+
|
21
|
+
described_class.manifest_list(manifests)
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'builds table presenter' do
|
25
|
+
expect(subject).to have_received(:table).with(
|
26
|
+
header: AppArchetype::CLI::Presenters::RESULT_HEADER,
|
27
|
+
data: [manifest_list_row, manifest_list_row]
|
28
|
+
)
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'shows table' do
|
32
|
+
expect(presenter).to have_received(:show)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe '.variable_list' do
|
37
|
+
let(:variable) do
|
38
|
+
double(
|
39
|
+
AppArchetype::Template::Variable,
|
40
|
+
name: 'foo',
|
41
|
+
description: 'a foo',
|
42
|
+
default: 'yolo',
|
43
|
+
value: 'bar'
|
44
|
+
)
|
45
|
+
end
|
46
|
+
let(:variable_row) { ['foo', 'a foo', 'yolo'] }
|
47
|
+
|
48
|
+
let(:presenter) { double(CliFormat::Presenter) }
|
49
|
+
let(:variables) { [variable, variable] }
|
50
|
+
|
51
|
+
before do
|
52
|
+
allow(presenter).to receive(:show)
|
53
|
+
allow(subject).to receive(:table).and_return(presenter)
|
54
|
+
|
55
|
+
described_class.variable_list(variables)
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'builds table presenter' do
|
59
|
+
expect(subject).to have_received(:table).with(
|
60
|
+
header: AppArchetype::CLI::Presenters::VARIABLE_HEADER,
|
61
|
+
data: [variable_row, variable_row]
|
62
|
+
)
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'shows table' do
|
66
|
+
expect(presenter).to have_received(:show)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe '.validation_results' do
|
71
|
+
let(:results) do
|
72
|
+
[
|
73
|
+
'something went wrong',
|
74
|
+
'something went wrong'
|
75
|
+
]
|
76
|
+
end
|
77
|
+
|
78
|
+
let(:result_row) { ['something went wrong'] }
|
79
|
+
let(:presenter) { double(CliFormat::Presenter) }
|
80
|
+
|
81
|
+
before do
|
82
|
+
allow(presenter).to receive(:show)
|
83
|
+
allow(subject).to receive(:table).and_return(presenter)
|
84
|
+
|
85
|
+
described_class.validation_result(results)
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'builds table presenter' do
|
89
|
+
expect(subject).to have_received(:table).with(
|
90
|
+
header: AppArchetype::CLI::Presenters::VALIDATION_HEADER,
|
91
|
+
data: [result_row, result_row]
|
92
|
+
)
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'shows table' do
|
96
|
+
expect(presenter).to have_received(:show)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,292 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe AppArchetype::CLI::Prompts do
|
4
|
+
let(:var_name) { 'foo' }
|
5
|
+
let(:var_type) { 'string' }
|
6
|
+
let(:var_desc) { 'a foo' }
|
7
|
+
let(:var_default) { 'bar' }
|
8
|
+
let(:var_value) { nil }
|
9
|
+
|
10
|
+
let(:variable) do
|
11
|
+
double(
|
12
|
+
AppArchetype::Template::Variable,
|
13
|
+
name: var_name,
|
14
|
+
description: var_desc,
|
15
|
+
type: var_type,
|
16
|
+
default: var_default,
|
17
|
+
value: var_value
|
18
|
+
)
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '::VAR_PROMPT_MESSAGE' do
|
22
|
+
before do
|
23
|
+
@prompt = described_class::VAR_PROMPT_MESSAGE.call(variable)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'displays prompt' do
|
27
|
+
expect(
|
28
|
+
@prompt.include?("Enter value for `#{var_name}` variable")
|
29
|
+
).to be true
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'displays variable description' do
|
33
|
+
expect(@prompt.include?("DESCRIPTION: #{var_desc}")).to be true
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'displays variable type' do
|
37
|
+
expect(@prompt.include?("TYPE: #{var_type}")).to be true
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'displays variable default' do
|
41
|
+
expect(@prompt.include?("DEFAULT: #{var_default}")).to be true
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe '.prompt' do
|
46
|
+
it 'returns a prompt' do
|
47
|
+
expect(described_class.prompt).to be_a(HighLine)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe '.yes?' do
|
52
|
+
let(:prompt) { double(HighLine) }
|
53
|
+
let(:message) { 'Would you like to do stuff?' }
|
54
|
+
let(:response) { 'Y' }
|
55
|
+
|
56
|
+
before do
|
57
|
+
allow(subject).to receive(:prompt).and_return(prompt)
|
58
|
+
allow(prompt).to receive(:ask).and_yield(response)
|
59
|
+
|
60
|
+
@resp = subject.yes?(message)
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'asks question' do
|
64
|
+
expect(prompt).to have_received(:ask).with("#{message} [Y/n]", String)
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'returns true when user responds Y' do
|
68
|
+
expect(@resp).to be true
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'when user inputs anything other than Y' do
|
72
|
+
let(:response) { 'Nope' }
|
73
|
+
|
74
|
+
it 'returns false' do
|
75
|
+
expect(@resp).to be false
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe '.ask' do
|
81
|
+
let(:prompt) { double(HighLine) }
|
82
|
+
|
83
|
+
let(:message) { 'Give me some info' }
|
84
|
+
let(:validator) { String }
|
85
|
+
let(:default) { 'Default' }
|
86
|
+
|
87
|
+
let(:response) { 'Sure here it is' }
|
88
|
+
|
89
|
+
before do
|
90
|
+
allow(subject).to receive(:prompt).and_return(prompt)
|
91
|
+
allow(prompt).to receive(:ask).and_return(response)
|
92
|
+
|
93
|
+
@resp = subject.ask(message, validator: validator, default: default)
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'asks question with validator' do
|
97
|
+
expect(prompt).to have_received(:ask).with(message, validator)
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'returns user response as string' do
|
101
|
+
expect(@resp).to eq response
|
102
|
+
end
|
103
|
+
|
104
|
+
context 'when default is specifed and empty response' do
|
105
|
+
let(:response) { '' }
|
106
|
+
|
107
|
+
it 'returns default' do
|
108
|
+
expect(@resp).to eq default
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
context 'when empty and no default specified' do
|
113
|
+
let(:default) { nil }
|
114
|
+
let(:response) { '' }
|
115
|
+
|
116
|
+
it 'returns empty string' do
|
117
|
+
expect(@resp).to eq ''
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
context 'when asking for an integer' do
|
122
|
+
let(:response) { 1 }
|
123
|
+
let(:validator) { Integer }
|
124
|
+
|
125
|
+
it 'returns user response as integer' do
|
126
|
+
expect(@resp).to eq 1
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
describe '.delete_template' do
|
132
|
+
let(:prompt) { double(HighLine) }
|
133
|
+
|
134
|
+
let(:manifest_name) { 'test_manifest' }
|
135
|
+
let(:manifest) do
|
136
|
+
double(AppArchetype::Template::Manifest, name: manifest_name)
|
137
|
+
end
|
138
|
+
|
139
|
+
let(:choice) { false }
|
140
|
+
|
141
|
+
before do
|
142
|
+
allow(subject).to receive(:prompt).and_return(prompt)
|
143
|
+
allow(subject).to receive(:yes?).and_return(choice)
|
144
|
+
|
145
|
+
@result = described_class.delete_template(manifest)
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'asks if it is okay to delete template' do
|
149
|
+
expect(subject).to have_received(:yes?)
|
150
|
+
.with('Are you sure you want to delete `test_manifest`?')
|
151
|
+
end
|
152
|
+
|
153
|
+
it 'returns user choice' do
|
154
|
+
expect(@result).to eq choice
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
describe '.variable_prompt_for' do
|
159
|
+
let(:has_value) { false }
|
160
|
+
|
161
|
+
before do
|
162
|
+
allow(variable).to receive(:value?).and_return(has_value)
|
163
|
+
|
164
|
+
allow(described_class).to receive(:boolean_variable_prompt)
|
165
|
+
allow(described_class).to receive(:integer_variable_prompt)
|
166
|
+
allow(described_class).to receive(:string_variable_prompt)
|
167
|
+
end
|
168
|
+
|
169
|
+
context 'when variable value is set' do
|
170
|
+
let(:has_value) { true }
|
171
|
+
let(:var_value) { 'some-value' }
|
172
|
+
|
173
|
+
it 'returns value' do
|
174
|
+
expect(
|
175
|
+
described_class.variable_prompt_for(variable)
|
176
|
+
).to eq var_value
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
context 'when variable type is a boolean' do
|
181
|
+
let(:var_type) { 'boolean' }
|
182
|
+
|
183
|
+
before { described_class.variable_prompt_for(variable) }
|
184
|
+
|
185
|
+
it 'calls boolean variable prompt' do
|
186
|
+
expect(described_class)
|
187
|
+
.to have_received(:boolean_variable_prompt)
|
188
|
+
.with(variable)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
context 'when variable type is an integer' do
|
193
|
+
let(:var_type) { 'integer' }
|
194
|
+
|
195
|
+
before { described_class.variable_prompt_for(variable) }
|
196
|
+
|
197
|
+
it 'calls integer variable prompt' do
|
198
|
+
expect(described_class)
|
199
|
+
.to have_received(:integer_variable_prompt)
|
200
|
+
.with(variable)
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
context 'when variable type is a string' do
|
205
|
+
let(:var_type) { 'string' }
|
206
|
+
|
207
|
+
before { described_class.variable_prompt_for(variable) }
|
208
|
+
|
209
|
+
it 'calls string variable prompt' do
|
210
|
+
expect(described_class)
|
211
|
+
.to have_received(:string_variable_prompt)
|
212
|
+
.with(variable)
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
context 'treats variables as strings by default' do
|
217
|
+
let(:var_type) { nil }
|
218
|
+
|
219
|
+
before { described_class.variable_prompt_for(variable) }
|
220
|
+
|
221
|
+
it 'calls string variable prompt' do
|
222
|
+
expect(described_class)
|
223
|
+
.to have_received(:string_variable_prompt)
|
224
|
+
.with(variable)
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
describe '.boolean_variable_prompt' do
|
230
|
+
let(:choice) { false }
|
231
|
+
|
232
|
+
before do
|
233
|
+
allow(subject).to receive(:yes?).and_return(choice)
|
234
|
+
@result = described_class.boolean_variable_prompt(variable)
|
235
|
+
end
|
236
|
+
|
237
|
+
it 'asks for boolean input' do
|
238
|
+
expect(subject).to have_received(:yes?)
|
239
|
+
.with(
|
240
|
+
AppArchetype::CLI::Prompts::VAR_PROMPT_MESSAGE.call(variable)
|
241
|
+
)
|
242
|
+
end
|
243
|
+
|
244
|
+
it 'returns user choice' do
|
245
|
+
expect(@result).to eq choice
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
describe '.integer_variable_prompt' do
|
250
|
+
let(:choice) { 1 }
|
251
|
+
|
252
|
+
before do
|
253
|
+
allow(subject).to receive(:ask).and_return(choice)
|
254
|
+
@result = described_class.integer_variable_prompt(variable)
|
255
|
+
end
|
256
|
+
|
257
|
+
it 'asks for boolean input' do
|
258
|
+
expect(subject).to have_received(:ask)
|
259
|
+
.with(
|
260
|
+
AppArchetype::CLI::Prompts::VAR_PROMPT_MESSAGE.call(variable),
|
261
|
+
default: variable.default,
|
262
|
+
validator: Integer
|
263
|
+
)
|
264
|
+
end
|
265
|
+
|
266
|
+
it 'returns user choice' do
|
267
|
+
expect(@result).to eq choice
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
describe '.string_variable_prompt' do
|
272
|
+
let(:choice) { 'some string' }
|
273
|
+
|
274
|
+
before do
|
275
|
+
allow(subject).to receive(:ask).and_return(choice)
|
276
|
+
|
277
|
+
@result = described_class.string_variable_prompt(variable)
|
278
|
+
end
|
279
|
+
|
280
|
+
it 'asks for boolean input' do
|
281
|
+
expect(subject).to have_received(:ask)
|
282
|
+
.with(
|
283
|
+
AppArchetype::CLI::Prompts::VAR_PROMPT_MESSAGE.call(variable),
|
284
|
+
default: variable.default
|
285
|
+
)
|
286
|
+
end
|
287
|
+
|
288
|
+
it 'returns user choice' do
|
289
|
+
expect(@result).to eq choice
|
290
|
+
end
|
291
|
+
end
|
292
|
+
end
|