uh-wm 0.0.2.pre → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +3 -0
- data/.rspec +1 -0
- data/.travis.yml +15 -0
- data/Gemfile +5 -0
- data/Guardfile +12 -0
- data/LICENSE +30 -0
- data/README.md +68 -0
- data/Rakefile +40 -0
- data/bin/uhwm +5 -0
- data/config/cucumber.yaml +1 -0
- data/features/actions/execute.feature +9 -0
- data/features/actions/layout_delegation.feature +31 -0
- data/features/actions/quit.feature +9 -0
- data/features/cli/debug.feature +5 -0
- data/features/cli/layout.feature +15 -0
- data/features/cli/require.feature +5 -0
- data/features/cli/run_control.feature +9 -0
- data/features/cli/usage.feature +11 -0
- data/features/cli/verbose.feature +5 -0
- data/features/cli/version.feature +6 -0
- data/features/cli/worker.feature +9 -0
- data/features/layout/manage.feature +12 -0
- data/features/layout/protocol.feature +24 -0
- data/features/layout/unmanage.feature +10 -0
- data/features/manager/check_other_wm.feature +8 -0
- data/features/manager/input_events.feature +8 -0
- data/features/manager/manage.feature +14 -0
- data/features/manager/unmanage.feature +13 -0
- data/features/manager/x_errors.feature +17 -0
- data/features/run_control/evaluation.feature +18 -0
- data/features/run_control/key.feature +33 -0
- data/features/run_control/modifier.feature +10 -0
- data/features/run_control/worker.feature +9 -0
- data/features/session/connection.feature +5 -0
- data/features/session/termination.feature +13 -0
- data/features/steps/filesystem_steps.rb +3 -0
- data/features/steps/output_steps.rb +44 -0
- data/features/steps/run_control_steps.rb +3 -0
- data/features/steps/run_steps.rb +41 -0
- data/features/steps/x_steps.rb +53 -0
- data/features/support/env.rb +33 -0
- data/lib/uh/wm.rb +8 -0
- data/lib/uh/wm/actions_handler.rb +46 -0
- data/lib/uh/wm/cli.rb +20 -13
- data/lib/uh/wm/client.rb +64 -0
- data/lib/uh/wm/dispatcher.rb +3 -1
- data/lib/uh/wm/env.rb +15 -9
- data/lib/uh/wm/env_logging.rb +8 -0
- data/lib/uh/wm/logger_formatter.rb +16 -0
- data/lib/uh/wm/manager.rb +96 -14
- data/lib/uh/wm/run_control.rb +8 -3
- data/lib/uh/wm/runner.rb +82 -14
- data/lib/uh/wm/testing/acceptance_helpers.rb +140 -18
- data/lib/uh/wm/version.rb +1 -1
- data/lib/uh/wm/workers.rb +21 -0
- data/lib/uh/wm/workers/base.rb +27 -0
- data/lib/uh/wm/workers/blocking.rb +11 -0
- data/lib/uh/wm/workers/mux.rb +18 -0
- data/spec/spec_helper.rb +26 -0
- data/spec/support/exit_helpers.rb +6 -0
- data/spec/support/filesystem_helpers.rb +11 -0
- data/spec/uh/wm/actions_handler_spec.rb +30 -0
- data/spec/uh/wm/cli_spec.rb +214 -0
- data/spec/uh/wm/client_spec.rb +133 -0
- data/spec/uh/wm/dispatcher_spec.rb +76 -0
- data/spec/uh/wm/env_spec.rb +145 -0
- data/spec/uh/wm/manager_spec.rb +355 -0
- data/spec/uh/wm/run_control_spec.rb +102 -0
- data/spec/uh/wm/runner_spec.rb +186 -0
- data/uh-wm.gemspec +25 -0
- metadata +112 -9
@@ -1,7 +1,11 @@
|
|
1
|
+
require 'uh'
|
2
|
+
|
1
3
|
module Uh
|
2
4
|
module WM
|
3
5
|
module Testing
|
4
6
|
module AcceptanceHelpers
|
7
|
+
TIMEOUT_DEFAULT = 2
|
8
|
+
|
5
9
|
def uhwm_run options = '-v'
|
6
10
|
command = %w[uhwm]
|
7
11
|
command << options if options
|
@@ -9,7 +13,10 @@ module Uh
|
|
9
13
|
end
|
10
14
|
|
11
15
|
def uhwm_ensure_stop
|
12
|
-
|
16
|
+
if @process
|
17
|
+
x_key 'alt+shift+q'
|
18
|
+
@process.terminate
|
19
|
+
end
|
13
20
|
end
|
14
21
|
|
15
22
|
def uhwm_pid
|
@@ -20,33 +27,30 @@ module Uh
|
|
20
27
|
@process.stdout
|
21
28
|
end
|
22
29
|
|
23
|
-
def uhwm_wait_output message
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
end
|
30
|
-
sleep 0.1
|
30
|
+
def uhwm_wait_output message
|
31
|
+
output = -> { @process.stdout + @process.stderr }
|
32
|
+
timeout_until do
|
33
|
+
case message
|
34
|
+
when Regexp then output.call =~ message
|
35
|
+
when String then output.call.include? message
|
31
36
|
end
|
32
37
|
end
|
33
|
-
rescue
|
34
|
-
output = (@process.stdout + @process.stderr).lines
|
35
|
-
.map { |e| " #{e}" }
|
36
|
-
.join
|
38
|
+
rescue TimeoutError => e
|
37
39
|
fail [
|
38
|
-
"expected `#{message}' not seen after #{timeout} seconds in:",
|
39
|
-
" ```\n#{output} ```"
|
40
|
+
"expected `#{message}' not seen after #{e.timeout} seconds in:",
|
41
|
+
" ```\n#{output.call.lines.map { |e| " #{e}" }.join} ```"
|
40
42
|
].join "\n"
|
41
43
|
end
|
42
44
|
|
43
|
-
def uhwm_run_wait_ready
|
44
|
-
uhwm_run
|
45
|
+
def uhwm_run_wait_ready options = nil
|
46
|
+
if options then uhwm_run options else uhwm_run end
|
45
47
|
uhwm_wait_output 'Connected to'
|
46
48
|
end
|
47
49
|
|
48
50
|
def with_other_wm
|
49
|
-
@other_wm = ChildProcess.build('twm')
|
51
|
+
@other_wm = ChildProcess.build('twm')
|
52
|
+
@other_wm.start
|
53
|
+
yield
|
50
54
|
@other_wm.stop
|
51
55
|
end
|
52
56
|
|
@@ -54,6 +58,19 @@ module Uh
|
|
54
58
|
@other_wm
|
55
59
|
end
|
56
60
|
|
61
|
+
def x_client ident: :default
|
62
|
+
@x_clients ||= {}
|
63
|
+
@x_clients[ident] ||= XClient.new(ident)
|
64
|
+
end
|
65
|
+
|
66
|
+
def x_focused_window_id
|
67
|
+
Integer(`xdpyinfo`[/^focus:\s+window\s+(0x\h+)/, 1])
|
68
|
+
end
|
69
|
+
|
70
|
+
def x_input_event_masks
|
71
|
+
`xdpyinfo`[/current input event mask:\s+0x\h+([\w\s]+):/, 1].split(/\s+/).grep /Mask\z/
|
72
|
+
end
|
73
|
+
|
57
74
|
def x_key key
|
58
75
|
fail "cannot simulate X key `#{key}'" unless system "xdotool key #{key}"
|
59
76
|
end
|
@@ -66,6 +83,111 @@ module Uh
|
|
66
83
|
`sockstat -u`.lines.grep /\s+ruby.+\s+#{pid}/
|
67
84
|
end.any?
|
68
85
|
end
|
86
|
+
|
87
|
+
def x_window_id **options
|
88
|
+
x_client(options).window_id
|
89
|
+
end
|
90
|
+
|
91
|
+
def x_window_name
|
92
|
+
x_client.window_name
|
93
|
+
end
|
94
|
+
|
95
|
+
def x_window_map times: 1, **options
|
96
|
+
times.times { x_client(options).map }
|
97
|
+
x_client(options).sync
|
98
|
+
end
|
99
|
+
|
100
|
+
def x_window_map_state **options
|
101
|
+
`xwininfo -id #{x_window_id options}`[/Map State: (\w+)/, 1]
|
102
|
+
end
|
103
|
+
|
104
|
+
def x_window_unmap **options
|
105
|
+
x_client(options).unmap
|
106
|
+
x_client(options).sync
|
107
|
+
end
|
108
|
+
|
109
|
+
def x_window_destroy **options
|
110
|
+
x_client(options).destroy
|
111
|
+
x_client(options).sync
|
112
|
+
end
|
113
|
+
|
114
|
+
def x_clients_ensure_stop
|
115
|
+
@x_clients and @x_clients.any? and @x_clients.values.each &:terminate
|
116
|
+
end
|
117
|
+
|
118
|
+
|
119
|
+
private
|
120
|
+
|
121
|
+
def timeout_until
|
122
|
+
timeout = ENV.key?('UHWMTEST_TIMEOUT') ?
|
123
|
+
ENV['UHWMTEST_TIMEOUT'].to_i :
|
124
|
+
TIMEOUT_DEFAULT
|
125
|
+
Timeout.timeout(timeout) do
|
126
|
+
loop do
|
127
|
+
break if yield
|
128
|
+
sleep 0.1
|
129
|
+
end
|
130
|
+
end
|
131
|
+
rescue Timeout::Error
|
132
|
+
fail TimeoutError.new('execution expired', timeout)
|
133
|
+
end
|
134
|
+
|
135
|
+
|
136
|
+
class TimeoutError < ::StandardError
|
137
|
+
attr_reader :timeout
|
138
|
+
|
139
|
+
def initialize message, timeout
|
140
|
+
super message
|
141
|
+
@timeout = timeout
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
class XClient
|
146
|
+
attr_reader :name
|
147
|
+
|
148
|
+
def initialize name = object_id
|
149
|
+
@name = "#{self.class.name.split('::').last}/#{name}"
|
150
|
+
@geo = Geo.new(0, 0, 640, 480)
|
151
|
+
@display = Display.new.tap { |o| o.open }
|
152
|
+
end
|
153
|
+
|
154
|
+
def terminate
|
155
|
+
@display.close
|
156
|
+
end
|
157
|
+
|
158
|
+
def sync
|
159
|
+
@display.sync false
|
160
|
+
end
|
161
|
+
|
162
|
+
def window
|
163
|
+
@window ||= @display.create_window(@geo).tap do |o|
|
164
|
+
o.name = @name
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
def window_id
|
169
|
+
@window.id
|
170
|
+
end
|
171
|
+
|
172
|
+
def window_name
|
173
|
+
@name
|
174
|
+
end
|
175
|
+
|
176
|
+
def map
|
177
|
+
window.map
|
178
|
+
self
|
179
|
+
end
|
180
|
+
|
181
|
+
def unmap
|
182
|
+
window.unmap
|
183
|
+
self
|
184
|
+
end
|
185
|
+
|
186
|
+
def destroy
|
187
|
+
window.destroy
|
188
|
+
self
|
189
|
+
end
|
190
|
+
end
|
69
191
|
end
|
70
192
|
end
|
71
193
|
end
|
data/lib/uh/wm/version.rb
CHANGED
@@ -0,0 +1,21 @@
|
|
1
|
+
module Uh
|
2
|
+
module WM
|
3
|
+
module Workers
|
4
|
+
FACTORIES = {
|
5
|
+
block: ->(options) { Blocking.new(options) },
|
6
|
+
mux: ->(options) { Mux.new(options) }
|
7
|
+
}.freeze
|
8
|
+
|
9
|
+
class << self
|
10
|
+
def types
|
11
|
+
FACTORIES.keys
|
12
|
+
end
|
13
|
+
|
14
|
+
def build type, **options
|
15
|
+
(FACTORIES[type] or fail ArgumentError, "unknown worker: `#{type}'")
|
16
|
+
.call options
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Uh
|
2
|
+
module WM
|
3
|
+
module Workers
|
4
|
+
class Base
|
5
|
+
CALLBACKS = %w[before_wait on_timeout on_read on_read_next].freeze
|
6
|
+
|
7
|
+
def initialize **options
|
8
|
+
@ios = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def watch io
|
12
|
+
@ios << io
|
13
|
+
end
|
14
|
+
|
15
|
+
CALLBACKS.each do |m|
|
16
|
+
define_method m do |*_, &block|
|
17
|
+
if block
|
18
|
+
instance_variable_set "@#{m}".to_sym, block
|
19
|
+
else
|
20
|
+
instance_variable_get "@#{m}".to_sym
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Uh
|
2
|
+
module WM
|
3
|
+
module Workers
|
4
|
+
class Mux < Base
|
5
|
+
def initialize timeout: 1
|
6
|
+
super
|
7
|
+
@timeout = timeout
|
8
|
+
end
|
9
|
+
|
10
|
+
def work_events
|
11
|
+
@before_wait.call if @before_wait
|
12
|
+
if res = select(@ios, [], [], @timeout) then @on_read.call res
|
13
|
+
else @on_timeout.call if @on_timeout end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'headless'
|
2
|
+
|
3
|
+
require 'uh/wm'
|
4
|
+
|
5
|
+
RSpec.configure do |config|
|
6
|
+
config.expect_with :rspec do |expectations|
|
7
|
+
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
8
|
+
end
|
9
|
+
|
10
|
+
config.mock_with :rspec do |mocks|
|
11
|
+
mocks.verify_partial_doubles = true
|
12
|
+
end
|
13
|
+
|
14
|
+
config.disable_monkey_patching!
|
15
|
+
|
16
|
+
config.before :all do
|
17
|
+
# Ensure current X display is not available from rspec test suite.
|
18
|
+
ENV.delete 'DISPLAY'
|
19
|
+
end
|
20
|
+
|
21
|
+
config.around :example, :xvfb do |example|
|
22
|
+
Headless.ly do
|
23
|
+
example.run
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Uh
|
2
|
+
module WM
|
3
|
+
RSpec.describe ActionsHandler do
|
4
|
+
let(:env) { Env.new(StringIO.new) }
|
5
|
+
let(:events) { Dispatcher.new }
|
6
|
+
subject(:actions) { described_class.new env, events }
|
7
|
+
|
8
|
+
describe '#evaluate' do
|
9
|
+
it 'evaluates given code' do
|
10
|
+
expect { actions.evaluate proc { throw :action_code } }
|
11
|
+
.to throw_symbol :action_code
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe '#quit' do
|
16
|
+
it 'emits the quit event' do
|
17
|
+
expect(events).to receive(:emit).with :quit
|
18
|
+
actions.quit
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#layout_*' do
|
23
|
+
it 'delegates messages to the layout with handle_ prefix' do
|
24
|
+
expect(env.layout).to receive :handle_screen_sel
|
25
|
+
actions.layout_screen_sel :succ
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,214 @@
|
|
1
|
+
require 'support/exit_helpers'
|
2
|
+
|
3
|
+
module Uh
|
4
|
+
module WM
|
5
|
+
RSpec.describe CLI do
|
6
|
+
include ExitHelpers
|
7
|
+
|
8
|
+
let(:stdout) { StringIO.new }
|
9
|
+
let(:stderr) { StringIO.new }
|
10
|
+
let(:arguments) { [] }
|
11
|
+
subject(:cli) { described_class.new arguments, stdout: stdout }
|
12
|
+
|
13
|
+
describe '.run' do
|
14
|
+
subject(:run) do
|
15
|
+
described_class.run arguments, stdout: stdout, stderr: stderr
|
16
|
+
end
|
17
|
+
|
18
|
+
# Prevent Runner from connecting a Manager and blocking.
|
19
|
+
before { allow(Runner).to receive :run }
|
20
|
+
|
21
|
+
it 'builds a new CLI with given arguments' do
|
22
|
+
expect(described_class)
|
23
|
+
.to receive(:new).with(arguments, stdout: stdout).and_call_original
|
24
|
+
run
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'parses new CLI arguments' do
|
28
|
+
cli
|
29
|
+
allow(described_class).to receive(:new) { cli }
|
30
|
+
expect(cli).to receive :parse_arguments!
|
31
|
+
run
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'runs new CLI' do
|
35
|
+
cli
|
36
|
+
allow(described_class).to receive(:new) { cli }
|
37
|
+
expect(cli).to receive :run
|
38
|
+
run
|
39
|
+
end
|
40
|
+
|
41
|
+
context 'with invalid arguments' do
|
42
|
+
let(:arguments) { %w[--unknown-option] }
|
43
|
+
|
44
|
+
it 'prints the usage on standard error stream' do
|
45
|
+
trap_exit { run }
|
46
|
+
expect(stderr.string).to match /\AUsage: .+/
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'exits with a return status of 64' do
|
50
|
+
expect { run }.to raise_error(SystemExit) do |e|
|
51
|
+
expect(e.status).to eq 64
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context 'when the new CLI raises a runtime error' do
|
57
|
+
before do
|
58
|
+
allow(cli).to receive(:run) { fail RuntimeError, 'some error' }
|
59
|
+
allow(described_class).to receive(:new) { cli }
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'exits with a return status of 70' do
|
63
|
+
expect { run }.to raise_error(SystemExit) do |e|
|
64
|
+
expect(e.status).to eq 70
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'formats the error' do
|
69
|
+
trap_exit { run }
|
70
|
+
expect(stderr.string)
|
71
|
+
.to match /\AUh::WM::RuntimeError: some error\n/
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'does not output a backtrace' do
|
75
|
+
trap_exit { run }
|
76
|
+
expect(stderr.string).not_to include __FILE__
|
77
|
+
end
|
78
|
+
|
79
|
+
context 'when debug mode is enabled' do
|
80
|
+
let(:arguments) { %w[-d] }
|
81
|
+
|
82
|
+
it 'outputs a backtrace' do
|
83
|
+
trap_exit { run }
|
84
|
+
expect(stderr.string).to include __FILE__
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe '#initialize' do
|
91
|
+
it 'builds an env with given stdout' do
|
92
|
+
expect(cli.env.output).to be stdout
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'syncs the output' do
|
96
|
+
expect(stdout).to receive(:sync=).with(true)
|
97
|
+
cli
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
describe '#run' do
|
102
|
+
it 'runs a runner with the env' do
|
103
|
+
expect(Runner).to receive(:run).with(cli.env)
|
104
|
+
cli.run
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
describe '#parse_arguments!' do
|
109
|
+
context 'with verbose option' do
|
110
|
+
let(:arguments) { %w[-v] }
|
111
|
+
|
112
|
+
it 'sets the env as verbose' do
|
113
|
+
cli.parse_arguments!
|
114
|
+
expect(cli.env).to be_verbose
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'tells the env to log its logger level' do
|
118
|
+
expect(cli.env).to receive :log_logger_level
|
119
|
+
cli.parse_arguments!
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
context 'with debug option' do
|
124
|
+
let(:arguments) { %w[-d] }
|
125
|
+
|
126
|
+
it 'sets the env as debug' do
|
127
|
+
cli.parse_arguments!
|
128
|
+
expect(cli.env).to be_debug
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'tells the env to log its logger level' do
|
132
|
+
expect(cli.env).to receive :log_logger_level
|
133
|
+
cli.parse_arguments!
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
context 'with run control option' do
|
138
|
+
let(:arguments) { %w[-f uhwmrc.rb] }
|
139
|
+
|
140
|
+
it 'assigns run control file path in the env' do
|
141
|
+
cli.parse_arguments!
|
142
|
+
expect(cli.env.rc_path).to eq 'uhwmrc.rb'
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
context 'with require option' do
|
147
|
+
let(:arguments) { %w[-r abbrev] }
|
148
|
+
|
149
|
+
it 'requires the given ruby feature' do
|
150
|
+
expect { cli.parse_arguments! }
|
151
|
+
.to change { $LOADED_FEATURES.grep(/abbrev/).any? }
|
152
|
+
.from(false).to(true)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
context 'with layout option' do
|
157
|
+
let(:arguments) { %w[-l Object] }
|
158
|
+
|
159
|
+
it 'assigns the layout class in the env' do
|
160
|
+
cli.parse_arguments!
|
161
|
+
expect(cli.env.layout_class).to eq Object
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
context 'with worker option' do
|
166
|
+
let(:arguments) { %w[-w mux] }
|
167
|
+
|
168
|
+
it 'assigns the worker type in the env' do
|
169
|
+
cli.parse_arguments!
|
170
|
+
expect(cli.env.worker).to eq :mux
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
context 'with help option' do
|
175
|
+
let(:arguments) { %w[-h] }
|
176
|
+
|
177
|
+
it 'prints the usage banner on standard output' do
|
178
|
+
trap_exit { cli.parse_arguments! }
|
179
|
+
expect(stdout.string).to match /\AUsage: .+/
|
180
|
+
end
|
181
|
+
|
182
|
+
it 'prints options usage on standard output' do
|
183
|
+
trap_exit { cli.parse_arguments! }
|
184
|
+
expect(stdout.string).to match /\n^options:\n\s+-/
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
context 'with version option' do
|
189
|
+
let(:arguments) { %w[-V] }
|
190
|
+
|
191
|
+
it 'prints the version on standard output' do
|
192
|
+
trap_exit { cli.parse_arguments! }
|
193
|
+
expect(stdout.string).to eq "#{::Uh::WM::VERSION}\n"
|
194
|
+
end
|
195
|
+
|
196
|
+
it 'exits with a return status of 0' do
|
197
|
+
expect { cli.parse_arguments! }.to raise_error(SystemExit) do |e|
|
198
|
+
expect(e.status).to eq 0
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
context 'with invalid option' do
|
204
|
+
let(:arguments) { %w[--unknown-option] }
|
205
|
+
|
206
|
+
it 'raises a CLI::ArgumentError' do
|
207
|
+
expect { cli.parse_arguments! }
|
208
|
+
.to raise_error CLI::ArgumentError
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|