license-acceptance 0.0.1 → 0.2.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 +4 -4
- data/Gemfile +2 -0
- data/Gemfile.lock +97 -0
- data/config/product_info.toml +1 -0
- data/lib/license_acceptance/acceptor.rb +117 -0
- data/lib/license_acceptance/arg_acceptance.rb +33 -0
- data/lib/license_acceptance/cli_flags/mixlib_cli.rb +22 -0
- data/lib/license_acceptance/cli_flags/thor.rb +21 -0
- data/lib/license_acceptance/config.rb +65 -0
- data/lib/license_acceptance/env_acceptance.rb +19 -0
- data/lib/license_acceptance/file_acceptance.rb +97 -0
- data/lib/license_acceptance/logger.rb +19 -0
- data/lib/license_acceptance/product.rb +23 -0
- data/lib/license_acceptance/product_reader.rb +108 -0
- data/lib/license_acceptance/product_relationship.rb +13 -0
- data/lib/license_acceptance/prompt_acceptance.rb +104 -0
- data/lib/license_acceptance/version.rb +3 -0
- data/spec/license_acceptance/acceptor_spec.rb +222 -0
- data/spec/license_acceptance/arg_acceptance_spec.rb +37 -0
- data/spec/license_acceptance/cli_flags/mixlib_cli_spec.rb +14 -0
- data/spec/license_acceptance/cli_flags/thor_spec.rb +14 -0
- data/spec/license_acceptance/config_spec.rb +113 -0
- data/spec/license_acceptance/env_acceptance_spec.rb +43 -0
- data/spec/license_acceptance/file_acceptance_spec.rb +121 -0
- data/spec/license_acceptance/product_reader_spec.rb +139 -0
- data/spec/license_acceptance/product_spec.rb +13 -0
- data/spec/license_acceptance/prompt_acceptance_spec.rb +100 -0
- data/spec/spec_helper.rb +25 -0
- metadata +184 -22
- data/.gitignore +0 -11
- data/.rspec +0 -3
- data/.travis.yml +0 -7
- data/LICENSE +0 -1
- data/README.md +0 -35
- data/lib/license/acceptance/version.rb +0 -5
- data/lib/license/acceptance.rb +0 -8
- data/license-acceptance.gemspec +0 -42
@@ -0,0 +1,23 @@
|
|
1
|
+
module LicenseAcceptance
|
2
|
+
class Product
|
3
|
+
|
4
|
+
attr_reader :name, :pretty_name, :filename
|
5
|
+
|
6
|
+
def initialize(name, pretty_name, filename)
|
7
|
+
@name = name
|
8
|
+
@pretty_name = pretty_name
|
9
|
+
@filename = filename
|
10
|
+
end
|
11
|
+
|
12
|
+
def ==(other)
|
13
|
+
return false if other.class != Product
|
14
|
+
if other.name == name &&
|
15
|
+
other.pretty_name == pretty_name &&
|
16
|
+
other.filename == filename
|
17
|
+
return true
|
18
|
+
end
|
19
|
+
return false
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
require "tomlrb"
|
2
|
+
require "license_acceptance/logger"
|
3
|
+
require "license_acceptance/product"
|
4
|
+
require "license_acceptance/product_relationship"
|
5
|
+
|
6
|
+
module LicenseAcceptance
|
7
|
+
class ProductReader
|
8
|
+
include Logger
|
9
|
+
|
10
|
+
attr_accessor :products, :relationships
|
11
|
+
|
12
|
+
def read
|
13
|
+
logger.debug("Reading products and relationships...")
|
14
|
+
location = get_location
|
15
|
+
self.products = {}
|
16
|
+
self.relationships = {}
|
17
|
+
|
18
|
+
toml = Tomlrb.load_file(location, symbolize_keys: false)
|
19
|
+
raise InvalidProductInfo.new(location) if toml.empty? || toml["products"].nil? || toml["relationships"].nil?
|
20
|
+
|
21
|
+
for product in toml["products"]
|
22
|
+
products[product["name"]] = Product.new(product["name"], product["pretty_name"], product["filename"])
|
23
|
+
end
|
24
|
+
|
25
|
+
for parent_name, children in toml["relationships"]
|
26
|
+
parent = products[parent_name]
|
27
|
+
raise UnknownParent.new(parent_name) if parent.nil?
|
28
|
+
# Its fine to not have a relationship entry, but not fine to have
|
29
|
+
# a relationship where the children are nil or empty.
|
30
|
+
if children.nil? || children.empty? || !children.is_a?(Array)
|
31
|
+
raise NoChildRelationships.new(parent)
|
32
|
+
end
|
33
|
+
children.map! do |child_name|
|
34
|
+
child = products[child_name]
|
35
|
+
raise UnknownChild.new(child_name) if child.nil?
|
36
|
+
child
|
37
|
+
end
|
38
|
+
relationships[parent] = children
|
39
|
+
end
|
40
|
+
|
41
|
+
logger.debug("Successfully read products and relationships")
|
42
|
+
end
|
43
|
+
|
44
|
+
def get_location
|
45
|
+
# For local development point this to the product_info.toml at the root of the repo.
|
46
|
+
# When bundled as a gem we will use the the relative path to find the file in the
|
47
|
+
# gem package.
|
48
|
+
if ENV["CHEF_LICENSE_PRODUCT_INFO"]
|
49
|
+
return ENV["CHEF_LICENSE_PRODUCT_INFO"]
|
50
|
+
end
|
51
|
+
File.absolute_path(File.join(__FILE__, "../../../config/product_info.toml"))
|
52
|
+
end
|
53
|
+
|
54
|
+
def lookup(parent_name, parent_version)
|
55
|
+
parent_product = products.fetch(parent_name) do
|
56
|
+
raise UnknownProduct.new(parent_name)
|
57
|
+
end
|
58
|
+
children = relationships.fetch(parent_product, [])
|
59
|
+
if !parent_version.is_a? String
|
60
|
+
raise ProductVersionTypeError.new(parent_version)
|
61
|
+
end
|
62
|
+
ProductRelationship.new(parent_product, children, parent_version)
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
class UnknownProduct < RuntimeError
|
68
|
+
def initialize(product)
|
69
|
+
msg = "Unknown product '#{product}' - this represents a developer error"
|
70
|
+
super(msg)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
class InvalidProductInfo < RuntimeError
|
75
|
+
def initialize(path)
|
76
|
+
msg = "Product info at path #{path} is invalid. Must list Products and relationships."
|
77
|
+
super(msg)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
class UnknownParent < RuntimeError
|
82
|
+
def initialize(product)
|
83
|
+
msg = "Could not find product #{product} from relationship parents"
|
84
|
+
super(msg)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
class UnknownChild < RuntimeError
|
89
|
+
def initialize(product)
|
90
|
+
msg = "Could not find product #{product} from relationship children"
|
91
|
+
super(msg)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
class NoChildRelationships < RuntimeError
|
96
|
+
def initialize(product)
|
97
|
+
msg = "No child relationships for #{product.name}, should be removed from product info or fixed"
|
98
|
+
super(msg)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
class ProductVersionTypeError < RuntimeError
|
103
|
+
def initialize(product_version)
|
104
|
+
msg = "Product versions must be specified as a string, provided type is '#{product_version.class}'"
|
105
|
+
super(msg)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module LicenseAcceptance
|
2
|
+
class ProductRelationship
|
3
|
+
|
4
|
+
attr_reader :parent, :children, :parent_version
|
5
|
+
|
6
|
+
def initialize(parent, children, parent_version)
|
7
|
+
@parent = parent
|
8
|
+
@children = children
|
9
|
+
@parent_version = parent_version
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'tty-prompt'
|
2
|
+
require 'pastel'
|
3
|
+
require "license_acceptance/logger"
|
4
|
+
require "timeout"
|
5
|
+
|
6
|
+
module LicenseAcceptance
|
7
|
+
class PromptAcceptance
|
8
|
+
include Logger
|
9
|
+
|
10
|
+
attr_reader :output
|
11
|
+
|
12
|
+
def initialize(config)
|
13
|
+
@output = config.output
|
14
|
+
end
|
15
|
+
|
16
|
+
WIDTH = 50.freeze
|
17
|
+
PASTEL = Pastel.new
|
18
|
+
BORDER = "+---------------------------------------------+".freeze
|
19
|
+
YES = PASTEL.green.bold("yes")
|
20
|
+
CHECK = PASTEL.green("✔")
|
21
|
+
|
22
|
+
def request(missing_licenses, &persist_callback)
|
23
|
+
logger.debug("Requesting a license for #{missing_licenses.map(&:name)}")
|
24
|
+
c = missing_licenses.size
|
25
|
+
s = c > 1 ? "s": ""
|
26
|
+
|
27
|
+
acceptance_question = "Do you accept the #{c} product license#{s} (#{YES}/no)?"
|
28
|
+
output.puts <<~EOM
|
29
|
+
#{BORDER}
|
30
|
+
Chef License Acceptance
|
31
|
+
|
32
|
+
Before you can continue, #{c} product license#{s}
|
33
|
+
must be accepted. View the license at
|
34
|
+
https://www.chef.io/end-user-license-agreement/
|
35
|
+
|
36
|
+
License#{s} that need accepting:
|
37
|
+
* #{missing_licenses.map(&:pretty_name).join("\n * ")}
|
38
|
+
|
39
|
+
#{acceptance_question}
|
40
|
+
|
41
|
+
EOM
|
42
|
+
|
43
|
+
if ask(output, c, s, persist_callback)
|
44
|
+
output.puts BORDER
|
45
|
+
return true
|
46
|
+
end
|
47
|
+
|
48
|
+
output.puts <<~EOM
|
49
|
+
|
50
|
+
If you do not accept this license you will
|
51
|
+
not be able to use Chef products.
|
52
|
+
|
53
|
+
#{acceptance_question}
|
54
|
+
|
55
|
+
EOM
|
56
|
+
|
57
|
+
answer = ask(output, c, s, persist_callback)
|
58
|
+
if answer != "yes"
|
59
|
+
output.puts BORDER
|
60
|
+
end
|
61
|
+
return answer
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def ask(output, c, s, persist_callback)
|
67
|
+
logger.debug("Attempting to request interactive prompt on TTY")
|
68
|
+
prompt = TTY::Prompt.new(track_history: false, active_color: :bold, interrupt: :exit, output: output)
|
69
|
+
|
70
|
+
answer = "no"
|
71
|
+
Timeout::timeout(60, PromptTimeout) do
|
72
|
+
answer = prompt.ask(">") do |q|
|
73
|
+
q.modify :down, :trim
|
74
|
+
q.required true
|
75
|
+
q.messages[:required?] = "You must enter 'yes' or 'no'"
|
76
|
+
q.validate /^\s*(yes|no)\s*$/i
|
77
|
+
q.messages[:valid?] = "You must enter 'yes' or 'no'"
|
78
|
+
end
|
79
|
+
rescue PromptTimeout
|
80
|
+
prompt.unsubscribe(prompt.reader)
|
81
|
+
output.puts "Prompt timed out. Use non-interactive flags or enter an answer within 60 seconds."
|
82
|
+
end
|
83
|
+
|
84
|
+
if answer == "yes"
|
85
|
+
output.puts
|
86
|
+
output.puts "Persisting #{c} product license#{s}..."
|
87
|
+
errs = persist_callback.call
|
88
|
+
if errs.empty?
|
89
|
+
output.puts "#{CHECK} #{c} product license#{s} persisted.\n\n"
|
90
|
+
else
|
91
|
+
output.puts <<~EOM
|
92
|
+
#{CHECK} #{c} product license#{s} accepted.
|
93
|
+
Could not persist acceptance:\n\t* #{errs.map(&:message).join("\n\t* ")}
|
94
|
+
EOM
|
95
|
+
end
|
96
|
+
return true
|
97
|
+
end
|
98
|
+
return false
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
class PromptTimeout < StandardError; end
|
104
|
+
end
|
@@ -0,0 +1,222 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "license_acceptance/acceptor"
|
3
|
+
|
4
|
+
RSpec.describe LicenseAcceptance::Acceptor do
|
5
|
+
it "has a version number" do
|
6
|
+
expect(LicenseAcceptance::VERSION).not_to be nil
|
7
|
+
end
|
8
|
+
|
9
|
+
let(:output) do
|
10
|
+
d = StringIO.new
|
11
|
+
allow(d).to receive(:isatty).and_return(true)
|
12
|
+
d
|
13
|
+
end
|
14
|
+
let(:opts) { { output: output } }
|
15
|
+
let(:acc) { LicenseAcceptance::Acceptor.new(opts) }
|
16
|
+
let(:product) { "chef_client" }
|
17
|
+
let(:version) { "version" }
|
18
|
+
let(:relationship) { instance_double(LicenseAcceptance::ProductRelationship) }
|
19
|
+
let(:p1) { instance_double(LicenseAcceptance::Product) }
|
20
|
+
let(:missing) { [p1] }
|
21
|
+
|
22
|
+
describe "#check_and_persist!" do
|
23
|
+
let(:err) { LicenseAcceptance::LicenseNotAcceptedError.new([product]) }
|
24
|
+
it "outputs an error message to stdout and exits when license acceptance is declined" do
|
25
|
+
expect(acc).to receive(:check_and_persist).and_raise(err)
|
26
|
+
expect { acc.check_and_persist!(product, version) }.to raise_error(SystemExit)
|
27
|
+
expect(output.string).to match(/#{product}/)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "#check_and_persist" do
|
32
|
+
let(:reader) { instance_double(LicenseAcceptance::ProductReader) }
|
33
|
+
let(:file_acc) { instance_double(LicenseAcceptance::FileAcceptance) }
|
34
|
+
let(:arg_acc) { instance_double(LicenseAcceptance::ArgAcceptance) }
|
35
|
+
let(:prompt_acc) { instance_double(LicenseAcceptance::PromptAcceptance) }
|
36
|
+
let(:env_acc) { instance_double(LicenseAcceptance::EnvAcceptance) }
|
37
|
+
|
38
|
+
before do
|
39
|
+
expect(LicenseAcceptance::ProductReader).to receive(:new).and_return(reader)
|
40
|
+
expect(LicenseAcceptance::FileAcceptance).to receive(:new).and_return(file_acc)
|
41
|
+
expect(LicenseAcceptance::ArgAcceptance).to receive(:new).and_return(arg_acc)
|
42
|
+
expect(LicenseAcceptance::PromptAcceptance).to receive(:new).and_return(prompt_acc)
|
43
|
+
expect(LicenseAcceptance::EnvAcceptance).to receive(:new).and_return(env_acc)
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "when check-no-persist environment variable is set" do
|
47
|
+
it "returns true" do
|
48
|
+
expect(env_acc).to receive(:check_no_persist).and_return(true)
|
49
|
+
expect(acc.check_and_persist(product, version)).to eq(true)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "when check-no-persist command line argument is set" do
|
54
|
+
it "returns true" do
|
55
|
+
expect(env_acc).to receive(:check_no_persist).and_return(false)
|
56
|
+
expect(arg_acc).to receive(:check_no_persist).and_return(true)
|
57
|
+
expect(acc.check_and_persist(product, version)).to eq(true)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "when there are no missing licenses" do
|
62
|
+
it "returns true" do
|
63
|
+
expect(env_acc).to receive(:check_no_persist).and_return(false)
|
64
|
+
expect(arg_acc).to receive(:check_no_persist).and_return(false)
|
65
|
+
expect(reader).to receive(:read)
|
66
|
+
expect(reader).to receive(:lookup).with(product, version).and_return(relationship)
|
67
|
+
expect(file_acc).to receive(:check).with(relationship).and_return([])
|
68
|
+
expect(acc.check_and_persist(product, version)).to eq(true)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe "when the user accepts as an environment variable" do
|
73
|
+
it "returns true" do
|
74
|
+
expect(env_acc).to receive(:check_no_persist).and_return(false)
|
75
|
+
expect(arg_acc).to receive(:check_no_persist).and_return(false)
|
76
|
+
expect(reader).to receive(:read)
|
77
|
+
expect(reader).to receive(:lookup).with(product, version).and_return(relationship)
|
78
|
+
expect(file_acc).to receive(:check).with(relationship).and_return(missing)
|
79
|
+
expect(env_acc).to receive(:check).with(ENV).and_return(true)
|
80
|
+
expect(file_acc).to receive(:persist).with(relationship, missing).and_return([])
|
81
|
+
expect(acc.check_and_persist(product, version)).to eq(true)
|
82
|
+
expect(output.string).to match(/1 product license accepted./)
|
83
|
+
end
|
84
|
+
|
85
|
+
describe "when persist is set to false" do
|
86
|
+
let(:opts) { { output: output, persist: false } }
|
87
|
+
|
88
|
+
it "returns true" do
|
89
|
+
expect(env_acc).to receive(:check_no_persist).and_return(false)
|
90
|
+
expect(arg_acc).to receive(:check_no_persist).and_return(false)
|
91
|
+
expect(reader).to receive(:read)
|
92
|
+
expect(reader).to receive(:lookup).with(product, version).and_return(relationship)
|
93
|
+
expect(file_acc).to receive(:check).with(relationship).and_return(missing)
|
94
|
+
expect(env_acc).to receive(:check).with(ENV).and_return(true)
|
95
|
+
expect(acc.check_and_persist(product, version)).to eq(true)
|
96
|
+
expect(output.string).to_not match(/accepted./)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe "when file persistance fails" do
|
101
|
+
it "returns true" do
|
102
|
+
expect(env_acc).to receive(:check_no_persist).and_return(false)
|
103
|
+
expect(arg_acc).to receive(:check_no_persist).and_return(false)
|
104
|
+
expect(reader).to receive(:read)
|
105
|
+
expect(reader).to receive(:lookup).with(product, version).and_return(relationship)
|
106
|
+
expect(file_acc).to receive(:check).with(relationship).and_return(missing)
|
107
|
+
expect(env_acc).to receive(:check).with(ENV).and_return(true)
|
108
|
+
expect(file_acc).to receive(:persist).with(relationship, missing).and_return([StandardError.new("foo")])
|
109
|
+
expect(acc.check_and_persist(product, version)).to eq(true)
|
110
|
+
expect(output.string).to match(/Could not persist acceptance:/)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
describe "when the user accepts as an arg" do
|
116
|
+
it "returns true" do
|
117
|
+
expect(env_acc).to receive(:check_no_persist).and_return(false)
|
118
|
+
expect(arg_acc).to receive(:check_no_persist).and_return(false)
|
119
|
+
expect(reader).to receive(:read)
|
120
|
+
expect(reader).to receive(:lookup).with(product, version).and_return(relationship)
|
121
|
+
expect(file_acc).to receive(:check).with(relationship).and_return(missing)
|
122
|
+
expect(env_acc).to receive(:check).and_return(false)
|
123
|
+
expect(arg_acc).to receive(:check).with(ARGV).and_return(true)
|
124
|
+
expect(file_acc).to receive(:persist).with(relationship, missing).and_return([])
|
125
|
+
expect(acc.check_and_persist(product, version)).to eq(true)
|
126
|
+
expect(output.string).to match(/1 product license accepted./)
|
127
|
+
end
|
128
|
+
|
129
|
+
describe "when persist is set to false" do
|
130
|
+
let(:opts) { { output: output, persist: false } }
|
131
|
+
|
132
|
+
it "returns true" do
|
133
|
+
expect(env_acc).to receive(:check_no_persist).and_return(false)
|
134
|
+
expect(arg_acc).to receive(:check_no_persist).and_return(false)
|
135
|
+
expect(reader).to receive(:read)
|
136
|
+
expect(reader).to receive(:lookup).with(product, version).and_return(relationship)
|
137
|
+
expect(file_acc).to receive(:check).with(relationship).and_return(missing)
|
138
|
+
expect(env_acc).to receive(:check).and_return(false)
|
139
|
+
expect(arg_acc).to receive(:check).with(ARGV).and_return(true)
|
140
|
+
expect(acc.check_and_persist(product, version)).to eq(true)
|
141
|
+
expect(output.string).to_not match(/accepted./)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
describe "when file persistance fails" do
|
146
|
+
it "returns true" do
|
147
|
+
expect(env_acc).to receive(:check_no_persist).and_return(false)
|
148
|
+
expect(arg_acc).to receive(:check_no_persist).and_return(false)
|
149
|
+
expect(reader).to receive(:read)
|
150
|
+
expect(reader).to receive(:lookup).with(product, version).and_return(relationship)
|
151
|
+
expect(file_acc).to receive(:check).with(relationship).and_return(missing)
|
152
|
+
expect(env_acc).to receive(:check).and_return(false)
|
153
|
+
expect(arg_acc).to receive(:check).with(ARGV).and_return(true)
|
154
|
+
expect(file_acc).to receive(:persist).with(relationship, missing).and_return([StandardError.new("bar")])
|
155
|
+
expect(acc.check_and_persist(product, version)).to eq(true)
|
156
|
+
expect(output.string).to match(/Could not persist acceptance:/)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
describe "when the prompt is not a tty" do
|
162
|
+
let(:opts) { { output: File.open(File::NULL, "w") } }
|
163
|
+
it "raises a LicenseNotAcceptedError error" do
|
164
|
+
expect(env_acc).to receive(:check_no_persist).and_return(false)
|
165
|
+
expect(arg_acc).to receive(:check_no_persist).and_return(false)
|
166
|
+
expect(reader).to receive(:read)
|
167
|
+
expect(reader).to receive(:lookup).with(product, version).and_return(relationship)
|
168
|
+
expect(file_acc).to receive(:check).with(relationship).and_return(missing)
|
169
|
+
expect(env_acc).to receive(:check).and_return(false)
|
170
|
+
expect(arg_acc).to receive(:check).and_return(false)
|
171
|
+
expect(prompt_acc).to_not receive(:request)
|
172
|
+
expect { acc.check_and_persist(product, version) }.to raise_error(LicenseAcceptance::LicenseNotAcceptedError)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
describe "when the user accepts with the prompt" do
|
177
|
+
it "returns true" do
|
178
|
+
expect(env_acc).to receive(:check_no_persist).and_return(false)
|
179
|
+
expect(arg_acc).to receive(:check_no_persist).and_return(false)
|
180
|
+
expect(reader).to receive(:read)
|
181
|
+
expect(reader).to receive(:lookup).with(product, version).and_return(relationship)
|
182
|
+
expect(file_acc).to receive(:check).with(relationship).and_return(missing)
|
183
|
+
expect(env_acc).to receive(:check).and_return(false)
|
184
|
+
expect(arg_acc).to receive(:check).and_return(false)
|
185
|
+
expect(prompt_acc).to receive(:request).with(missing).and_yield.and_return(true)
|
186
|
+
expect(file_acc).to receive(:persist).with(relationship, missing)
|
187
|
+
expect(acc.check_and_persist(product, version)).to eq(true)
|
188
|
+
end
|
189
|
+
|
190
|
+
describe "when persist is set to false" do
|
191
|
+
let(:opts) { { output: output, persist: false } }
|
192
|
+
|
193
|
+
it "returns true" do
|
194
|
+
expect(env_acc).to receive(:check_no_persist).and_return(false)
|
195
|
+
expect(arg_acc).to receive(:check_no_persist).and_return(false)
|
196
|
+
expect(reader).to receive(:read)
|
197
|
+
expect(reader).to receive(:lookup).with(product, version).and_return(relationship)
|
198
|
+
expect(file_acc).to receive(:check).with(relationship).and_return(missing)
|
199
|
+
expect(env_acc).to receive(:check).and_return(false)
|
200
|
+
expect(arg_acc).to receive(:check).and_return(false)
|
201
|
+
expect(prompt_acc).to receive(:request).with(missing).and_yield.and_return(true)
|
202
|
+
expect(acc.check_and_persist(product, version)).to eq(true)
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
describe "when the user declines with the prompt" do
|
208
|
+
it "raises a LicenseNotAcceptedError error" do
|
209
|
+
expect(env_acc).to receive(:check_no_persist).and_return(false)
|
210
|
+
expect(arg_acc).to receive(:check_no_persist).and_return(false)
|
211
|
+
expect(reader).to receive(:read)
|
212
|
+
expect(reader).to receive(:lookup).with(product, version).and_return(relationship)
|
213
|
+
expect(file_acc).to receive(:check).with(relationship).and_return(missing)
|
214
|
+
expect(env_acc).to receive(:check).and_return(false)
|
215
|
+
expect(arg_acc).to receive(:check).and_return(false)
|
216
|
+
expect(prompt_acc).to receive(:request).with(missing).and_return(false)
|
217
|
+
expect { acc.check_and_persist(product, version) }.to raise_error(LicenseAcceptance::LicenseNotAcceptedError)
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
end
|
222
|
+
end
|