ruby_wasm_ui 0.8.3 → 0.9.0
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/.github/workflows/rspec.yml +0 -2
- data/Makefile +53 -0
- data/README.md +22 -4
- data/examples/.gitignore +3 -0
- data/examples/Gemfile.lock +14 -16
- data/examples/src/index.html +21 -0
- data/examples/src/index.rb +26 -0
- data/exe/ruby-wasm-ui +6 -0
- data/lib/ruby_wasm_ui/cli/command/base.rb +174 -0
- data/lib/ruby_wasm_ui/cli/command/dev.rb +206 -0
- data/lib/ruby_wasm_ui/cli/command/pack.rb +36 -0
- data/lib/ruby_wasm_ui/cli/command/rebuild.rb +38 -0
- data/lib/ruby_wasm_ui/cli/command/setup.rb +130 -0
- data/lib/ruby_wasm_ui/cli/command.rb +48 -0
- data/lib/ruby_wasm_ui/version.rb +1 -1
- data/lib/ruby_wasm_ui.rb +8 -8
- data/package-lock.json +2 -2
- data/package.json +1 -1
- data/packages/npm-packages/runtime/package-lock.json +2 -2
- data/packages/npm-packages/runtime/package.json +1 -1
- data/packages/npm-packages/runtime/rollup.config.mjs +1 -1
- data/spec/ruby_wasm_ui/cli/command/base_spec.rb +358 -0
- data/spec/ruby_wasm_ui/cli/command/dev_spec.rb +412 -0
- data/spec/ruby_wasm_ui/cli/command/pack_spec.rb +127 -0
- data/spec/ruby_wasm_ui/cli/command/rebuild_spec.rb +95 -0
- data/spec/ruby_wasm_ui/cli/command/setup_spec.rb +186 -0
- data/spec/ruby_wasm_ui/cli/command_spec.rb +118 -0
- data/{packages/npm-packages/runtime/spec → spec}/spec_helper.rb +1 -1
- metadata +96 -38
- data/packages/npm-packages/runtime/Gemfile +0 -3
- data/packages/npm-packages/runtime/Gemfile.lock +0 -26
- /data/lib/ruby_wasm_ui/{app.rb → runtime/app.rb} +0 -0
- /data/lib/ruby_wasm_ui/{component.rb → runtime/component.rb} +0 -0
- /data/lib/ruby_wasm_ui/{dispatcher.rb → runtime/dispatcher.rb} +0 -0
- /data/lib/ruby_wasm_ui/{dom → runtime/dom}/attributes.rb +0 -0
- /data/lib/ruby_wasm_ui/{dom → runtime/dom}/destroy_dom.rb +0 -0
- /data/lib/ruby_wasm_ui/{dom → runtime/dom}/events.rb +0 -0
- /data/lib/ruby_wasm_ui/{dom → runtime/dom}/mount_dom.rb +0 -0
- /data/lib/ruby_wasm_ui/{dom → runtime/dom}/patch_dom.rb +0 -0
- /data/lib/ruby_wasm_ui/{dom → runtime/dom}/scheduler.rb +0 -0
- /data/lib/ruby_wasm_ui/{dom.rb → runtime/dom.rb} +0 -0
- /data/lib/ruby_wasm_ui/{nodes_equal.rb → runtime/nodes_equal.rb} +0 -0
- /data/lib/ruby_wasm_ui/{template → runtime/template}/build_conditional_group.rb +0 -0
- /data/lib/ruby_wasm_ui/{template → runtime/template}/build_for_group.rb +0 -0
- /data/lib/ruby_wasm_ui/{template → runtime/template}/build_vdom.rb +0 -0
- /data/lib/ruby_wasm_ui/{template → runtime/template}/parser.rb +0 -0
- /data/lib/ruby_wasm_ui/{template.rb → runtime/template.rb} +0 -0
- /data/lib/ruby_wasm_ui/{utils → runtime/utils}/arrays.rb +0 -0
- /data/lib/ruby_wasm_ui/{utils → runtime/utils}/objects.rb +0 -0
- /data/lib/ruby_wasm_ui/{utils → runtime/utils}/props.rb +0 -0
- /data/lib/ruby_wasm_ui/{utils → runtime/utils}/strings.rb +0 -0
- /data/lib/ruby_wasm_ui/{utils.rb → runtime/utils.rb} +0 -0
- /data/lib/ruby_wasm_ui/{vdom.rb → runtime/vdom.rb} +0 -0
- /data/{packages/npm-packages/runtime/spec/ruby_wasm_ui → spec/ruby_wasm_ui/runtime}/component_spec.rb +0 -0
- /data/{packages/npm-packages/runtime/spec/ruby_wasm_ui → spec/ruby_wasm_ui/runtime}/dom/scheduler_spec.rb +0 -0
- /data/{packages/npm-packages/runtime/spec/ruby_wasm_ui → spec/ruby_wasm_ui/runtime}/nodes_equal_spec.rb +0 -0
- /data/{packages/npm-packages/runtime/spec/ruby_wasm_ui → spec/ruby_wasm_ui/runtime}/template/build_conditional_group_spec.rb +0 -0
- /data/{packages/npm-packages/runtime/spec/ruby_wasm_ui → spec/ruby_wasm_ui/runtime}/template/build_for_group_spec.rb +0 -0
- /data/{packages/npm-packages/runtime/spec/ruby_wasm_ui → spec/ruby_wasm_ui/runtime}/template/build_vdom_spec.rb +0 -0
- /data/{packages/npm-packages/runtime/spec/ruby_wasm_ui → spec/ruby_wasm_ui/runtime}/template/parser_spec.rb +0 -0
- /data/{packages/npm-packages/runtime/spec/ruby_wasm_ui → spec/ruby_wasm_ui/runtime}/utils/arrays_spec.rb +0 -0
- /data/{packages/npm-packages/runtime/spec/ruby_wasm_ui → spec/ruby_wasm_ui/runtime}/utils/objects_spec.rb +0 -0
- /data/{packages/npm-packages/runtime/spec/ruby_wasm_ui → spec/ruby_wasm_ui/runtime}/utils/props_spec.rb +0 -0
- /data/{packages/npm-packages/runtime/spec/ruby_wasm_ui → spec/ruby_wasm_ui/runtime}/utils/strings_spec.rb +0 -0
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
require 'fileutils'
|
|
5
|
+
require 'tmpdir'
|
|
6
|
+
|
|
7
|
+
RSpec.describe RubyWasmUi::Cli::Command::Dev do
|
|
8
|
+
let(:dev_instance) { described_class.new }
|
|
9
|
+
let(:temp_dir) { Dir.mktmpdir }
|
|
10
|
+
let(:original_dir) { Dir.pwd }
|
|
11
|
+
|
|
12
|
+
around do |example|
|
|
13
|
+
begin
|
|
14
|
+
Dir.chdir(temp_dir) do
|
|
15
|
+
example.run
|
|
16
|
+
end
|
|
17
|
+
ensure
|
|
18
|
+
# 確実に元のディレクトリに戻る
|
|
19
|
+
begin
|
|
20
|
+
Dir.chdir(original_dir) if Dir.exist?(original_dir)
|
|
21
|
+
rescue => e
|
|
22
|
+
# ディレクトリが存在しない場合は無視
|
|
23
|
+
end
|
|
24
|
+
FileUtils.rm_rf(temp_dir) if Dir.exist?(temp_dir)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
describe '.description' do
|
|
29
|
+
it 'returns the description' do
|
|
30
|
+
expect(described_class.description).to eq('Start development server with file watching and auto-build')
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
describe '#run' do
|
|
35
|
+
let(:watcher_thread) { instance_double(Thread, kill: nil) }
|
|
36
|
+
|
|
37
|
+
before do
|
|
38
|
+
allow(dev_instance).to receive(:build).and_return(true)
|
|
39
|
+
allow(dev_instance).to receive(:start_file_watcher)
|
|
40
|
+
allow(dev_instance).to receive(:start_server)
|
|
41
|
+
allow(Thread).to receive(:new).and_return(watcher_thread)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
context 'when src directory does not exist' do
|
|
45
|
+
it 'outputs error message and exits' do
|
|
46
|
+
expect { dev_instance.run([]) }.to output(
|
|
47
|
+
/src directory not found. Please run 'ruby-wasm-ui setup' first./
|
|
48
|
+
).to_stdout.and raise_error(SystemExit)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it 'exits with status 1' do
|
|
52
|
+
expect { dev_instance.run([]) }.to raise_error(SystemExit) do |error|
|
|
53
|
+
expect(error.status).to eq(1)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
context 'when src directory exists' do
|
|
59
|
+
before do
|
|
60
|
+
FileUtils.mkdir_p('src')
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it 'outputs starting message' do
|
|
64
|
+
expect { dev_instance.run([]) }.to output(
|
|
65
|
+
/Starting development server/
|
|
66
|
+
).to_stdout
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it 'performs initial build' do
|
|
70
|
+
expect(dev_instance).to receive(:build).and_return(true)
|
|
71
|
+
dev_instance.run([])
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it 'outputs initial build completion message' do
|
|
75
|
+
expect { dev_instance.run([]) }.to output(
|
|
76
|
+
/Initial build completed/
|
|
77
|
+
).to_stdout
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it 'starts file watcher' do
|
|
81
|
+
file_watcher_called = false
|
|
82
|
+
# Allow Thread.new to actually create threads so start_file_watcher gets called
|
|
83
|
+
allow(Thread).to receive(:new).and_call_original
|
|
84
|
+
allow(dev_instance).to receive(:start_file_watcher) do
|
|
85
|
+
file_watcher_called = true
|
|
86
|
+
end
|
|
87
|
+
# Mock start_server to block briefly to allow thread to execute
|
|
88
|
+
allow(dev_instance).to receive(:start_server) do
|
|
89
|
+
sleep 0.1 # Give thread time to execute
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
dev_instance.run([])
|
|
93
|
+
|
|
94
|
+
expect(file_watcher_called).to be true
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
it 'starts development server' do
|
|
98
|
+
allow(dev_instance).to receive(:start_file_watcher).and_return(nil)
|
|
99
|
+
expect(dev_instance).to receive(:start_server)
|
|
100
|
+
dev_instance.run([])
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
context 'when build fails' do
|
|
104
|
+
before do
|
|
105
|
+
allow(dev_instance).to receive(:build).and_return(false)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
it 'still starts the server' do
|
|
109
|
+
expect(dev_instance).to receive(:start_server)
|
|
110
|
+
dev_instance.run([])
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
describe '#build' do
|
|
117
|
+
before do
|
|
118
|
+
FileUtils.mkdir_p('src')
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
context 'when command succeeds' do
|
|
122
|
+
before do
|
|
123
|
+
allow(dev_instance).to receive(:run_command).and_return(true)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
it 'executes rbwasm pack command via run_command' do
|
|
127
|
+
expect(dev_instance).to receive(:run_command).with(
|
|
128
|
+
'bundle exec rbwasm pack ruby.wasm --dir ./src::./src -o src.wasm',
|
|
129
|
+
exit_on_error: false
|
|
130
|
+
)
|
|
131
|
+
dev_instance.send(:build)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
it 'outputs build message' do
|
|
135
|
+
expect { dev_instance.send(:build) }.to output(
|
|
136
|
+
/Building: bundle exec rbwasm pack/
|
|
137
|
+
).to_stdout
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
it 'outputs success message' do
|
|
141
|
+
expect { dev_instance.send(:build) }.to output(
|
|
142
|
+
/Build completed/
|
|
143
|
+
).to_stdout
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
it 'returns true' do
|
|
147
|
+
result = dev_instance.send(:build)
|
|
148
|
+
expect(result).to be true
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
context 'when command fails' do
|
|
153
|
+
before do
|
|
154
|
+
allow(dev_instance).to receive(:run_command).and_return(false)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
it 'outputs error message' do
|
|
158
|
+
expect { dev_instance.send(:build) }.to output(
|
|
159
|
+
/Build failed/
|
|
160
|
+
).to_stdout
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
it 'returns false' do
|
|
164
|
+
result = dev_instance.send(:build)
|
|
165
|
+
expect(result).to be false
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
describe '#start_file_watcher' do
|
|
171
|
+
before do
|
|
172
|
+
FileUtils.mkdir_p('src')
|
|
173
|
+
@listener = instance_double(Listen::Listener, start: nil, stop: nil)
|
|
174
|
+
allow(Listen).to receive(:to).and_return(@listener)
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
it 'starts listening to src directory' do
|
|
178
|
+
expect(Listen).to receive(:to).with('src')
|
|
179
|
+
dev_instance.send(:start_file_watcher)
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
it 'starts the listener' do
|
|
183
|
+
expect(@listener).to receive(:start)
|
|
184
|
+
dev_instance.send(:start_file_watcher)
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
context 'when file changes occur' do
|
|
188
|
+
let(:callback_container) { {} }
|
|
189
|
+
|
|
190
|
+
before do
|
|
191
|
+
allow(Listen).to receive(:to) do |_dir, &block|
|
|
192
|
+
callback_container[:callback] = block
|
|
193
|
+
@listener
|
|
194
|
+
end
|
|
195
|
+
dev_instance.instance_variable_set(:@build_lock, Mutex.new)
|
|
196
|
+
dev_instance.instance_variable_set(:@build_queue, Queue.new)
|
|
197
|
+
allow(dev_instance).to receive(:build)
|
|
198
|
+
allow(dev_instance).to receive(:log_info)
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
it 'triggers rebuild on file change' do
|
|
202
|
+
dev_instance.send(:start_file_watcher)
|
|
203
|
+
callback = callback_container[:callback]
|
|
204
|
+
expect(callback).not_to be_nil
|
|
205
|
+
|
|
206
|
+
# Allow Thread.new to create actual threads for the debounce logic
|
|
207
|
+
allow(Thread).to receive(:new).and_call_original
|
|
208
|
+
|
|
209
|
+
callback.call(['src/app.rb'], [], [])
|
|
210
|
+
sleep 0.6 # Wait for debounce
|
|
211
|
+
expect(dev_instance).to have_received(:build)
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
it 'ignores temporary files' do
|
|
215
|
+
dev_instance.send(:start_file_watcher)
|
|
216
|
+
callback = callback_container[:callback]
|
|
217
|
+
expect(callback).not_to be_nil
|
|
218
|
+
|
|
219
|
+
# Allow Thread.new to create actual threads for the debounce logic
|
|
220
|
+
allow(Thread).to receive(:new).and_call_original
|
|
221
|
+
|
|
222
|
+
callback.call(['src/app.rb.swp'], [], [])
|
|
223
|
+
sleep 0.6
|
|
224
|
+
expect(dev_instance).not_to have_received(:build)
|
|
225
|
+
end
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
context 'when listener raises an error' do
|
|
229
|
+
before do
|
|
230
|
+
allow(Listen).to receive(:to).and_raise(StandardError.new('Listener error'))
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
it 'outputs error message' do
|
|
234
|
+
expect { dev_instance.send(:start_file_watcher) }.to output(
|
|
235
|
+
/File watcher error: Listener error/
|
|
236
|
+
).to_stdout
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
describe '#start_server' do
|
|
242
|
+
let(:puma_handler_class) do
|
|
243
|
+
Class.new do
|
|
244
|
+
def self.run(app, options = {})
|
|
245
|
+
# Blocking call - will be mocked
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
before do
|
|
251
|
+
FileUtils.mkdir_p('src')
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
context 'when Puma handler is available' do
|
|
255
|
+
before do
|
|
256
|
+
stub_const('Rack::Handler::Puma', puma_handler_class)
|
|
257
|
+
# Mock require to prevent LoadError for rack/handler/puma
|
|
258
|
+
allow(dev_instance).to receive(:require).with('rack/handler/puma').and_return(true)
|
|
259
|
+
# Prevent browser from opening in all tests by default
|
|
260
|
+
allow(dev_instance).to receive(:open_browser)
|
|
261
|
+
# Prevent Thread.new from creating actual threads by default
|
|
262
|
+
allow(Thread).to receive(:new).and_return(instance_double(Thread))
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
it 'outputs server start message' do
|
|
266
|
+
allow(Rack::Handler::Puma).to receive(:run)
|
|
267
|
+
expect { dev_instance.send(:start_server) }.to output(
|
|
268
|
+
a_string_including('Starting development server on http://localhost:8080')
|
|
269
|
+
).to_stdout
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
it 'outputs instructions message' do
|
|
273
|
+
allow(Rack::Handler::Puma).to receive(:run)
|
|
274
|
+
expect { dev_instance.send(:start_server) }.to output(
|
|
275
|
+
a_string_including('Press Ctrl+C to stop')
|
|
276
|
+
).to_stdout
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
it 'starts Puma server' do
|
|
280
|
+
expect(Rack::Handler::Puma).to receive(:run).with(
|
|
281
|
+
anything,
|
|
282
|
+
Port: 8080,
|
|
283
|
+
Host: '0.0.0.0'
|
|
284
|
+
)
|
|
285
|
+
dev_instance.send(:start_server)
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
it 'outputs handler info message' do
|
|
289
|
+
allow(Rack::Handler::Puma).to receive(:run)
|
|
290
|
+
expect { dev_instance.send(:start_server) }.to output(
|
|
291
|
+
a_string_including('Using handler: puma')
|
|
292
|
+
).to_stdout
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
it 'opens browser after server starts' do
|
|
296
|
+
allow(Rack::Handler::Puma).to receive(:run)
|
|
297
|
+
browser_thread_called = false
|
|
298
|
+
|
|
299
|
+
allow(Thread).to receive(:new) do |&block|
|
|
300
|
+
if block
|
|
301
|
+
browser_thread_called = true
|
|
302
|
+
# Execute block immediately for testing (without sleep)
|
|
303
|
+
allow(Kernel).to receive(:sleep)
|
|
304
|
+
block.call
|
|
305
|
+
end
|
|
306
|
+
instance_double(Thread)
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
expect(dev_instance).to receive(:open_browser).with('http://localhost:8080/src/index.html').and_return(nil)
|
|
310
|
+
|
|
311
|
+
dev_instance.send(:start_server)
|
|
312
|
+
|
|
313
|
+
expect(browser_thread_called).to be true
|
|
314
|
+
end
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
context 'when Puma handler is not available' do
|
|
318
|
+
before do
|
|
319
|
+
allow(dev_instance).to receive(:require).with('rack/handler/puma').and_raise(LoadError.new('cannot load such file'))
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
it 'outputs error message' do
|
|
323
|
+
expect { dev_instance.send(:start_server) }.to output(
|
|
324
|
+
/Puma handler not available/
|
|
325
|
+
).to_stdout.and raise_error(SystemExit)
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
it 'exits with status 1' do
|
|
329
|
+
expect { dev_instance.send(:start_server) }.to raise_error(SystemExit) do |error|
|
|
330
|
+
expect(error.status).to eq(1)
|
|
331
|
+
end
|
|
332
|
+
end
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
context 'when server raises an error' do
|
|
336
|
+
before do
|
|
337
|
+
stub_const('Rack::Handler::Puma', puma_handler_class)
|
|
338
|
+
allow(dev_instance).to receive(:require).with('rack/handler/puma').and_return(true)
|
|
339
|
+
allow(Rack::Handler::Puma).to receive(:run).and_raise(StandardError.new('Server error'))
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
it 'outputs error message and exits' do
|
|
343
|
+
expect { dev_instance.send(:start_server) }.to output(
|
|
344
|
+
/Server error: Server error/
|
|
345
|
+
).to_stdout.and raise_error(SystemExit)
|
|
346
|
+
end
|
|
347
|
+
end
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
describe '#open_browser' do
|
|
351
|
+
before do
|
|
352
|
+
FileUtils.mkdir_p('src')
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
context 'on macOS' do
|
|
356
|
+
before do
|
|
357
|
+
allow(RbConfig::CONFIG).to receive(:[]).with('host_os').and_return('darwin')
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
it 'calls open command' do
|
|
361
|
+
expect(dev_instance).to receive(:system).with('open', 'http://localhost:8080/src/index.html').and_return(true)
|
|
362
|
+
dev_instance.send(:open_browser, 'http://localhost:8080/src/index.html')
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
context 'when system call fails' do
|
|
366
|
+
before do
|
|
367
|
+
allow(dev_instance).to receive(:system).and_raise(StandardError.new('Command failed'))
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
it 'outputs fallback message' do
|
|
371
|
+
expect { dev_instance.send(:open_browser, 'http://localhost:8080/src/index.html') }.to output(
|
|
372
|
+
/Please open http:\/\/localhost:8080\/src\/index.html in your browser/
|
|
373
|
+
).to_stdout
|
|
374
|
+
end
|
|
375
|
+
end
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
context 'on Linux' do
|
|
379
|
+
before do
|
|
380
|
+
allow(RbConfig::CONFIG).to receive(:[]).with('host_os').and_return('linux')
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
it 'calls xdg-open command' do
|
|
384
|
+
expect(dev_instance).to receive(:system).with('xdg-open', 'http://localhost:8080/src/index.html').and_return(true)
|
|
385
|
+
dev_instance.send(:open_browser, 'http://localhost:8080/src/index.html')
|
|
386
|
+
end
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
context 'on Windows' do
|
|
390
|
+
before do
|
|
391
|
+
allow(RbConfig::CONFIG).to receive(:[]).with('host_os').and_return('mswin')
|
|
392
|
+
end
|
|
393
|
+
|
|
394
|
+
it 'calls start command' do
|
|
395
|
+
expect(dev_instance).to receive(:system).with('start', 'http://localhost:8080/src/index.html').and_return(true)
|
|
396
|
+
dev_instance.send(:open_browser, 'http://localhost:8080/src/index.html')
|
|
397
|
+
end
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
context 'on unknown OS' do
|
|
401
|
+
before do
|
|
402
|
+
allow(RbConfig::CONFIG).to receive(:[]).with('host_os').and_return('unknown')
|
|
403
|
+
end
|
|
404
|
+
|
|
405
|
+
it 'outputs manual instruction' do
|
|
406
|
+
expect { dev_instance.send(:open_browser, 'http://localhost:8080/src/index.html') }.to output(
|
|
407
|
+
/Please open http:\/\/localhost:8080\/src\/index.html in your browser/
|
|
408
|
+
).to_stdout
|
|
409
|
+
end
|
|
410
|
+
end
|
|
411
|
+
end
|
|
412
|
+
end
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
require 'fileutils'
|
|
5
|
+
require 'tmpdir'
|
|
6
|
+
|
|
7
|
+
RSpec.describe RubyWasmUi::Cli::Command::Pack do
|
|
8
|
+
let(:pack_instance) { described_class.new }
|
|
9
|
+
let(:temp_dir) { Dir.mktmpdir }
|
|
10
|
+
let(:original_dir) { Dir.pwd }
|
|
11
|
+
|
|
12
|
+
around do |example|
|
|
13
|
+
Dir.chdir(temp_dir) do
|
|
14
|
+
example.run
|
|
15
|
+
end
|
|
16
|
+
ensure
|
|
17
|
+
Dir.chdir(original_dir)
|
|
18
|
+
FileUtils.rm_rf(temp_dir) if Dir.exist?(temp_dir)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
describe '.description' do
|
|
22
|
+
it 'returns the description' do
|
|
23
|
+
expect(described_class.description).to eq('Pack WASM file by packing Ruby source files')
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
describe '#run' do
|
|
28
|
+
context 'when src directory does not exist' do
|
|
29
|
+
it 'outputs error message and exits' do
|
|
30
|
+
expect { pack_instance.run([]) }.to output(
|
|
31
|
+
/src directory not found. Please run 'ruby-wasm-ui setup' first./
|
|
32
|
+
).to_stdout.and raise_error(SystemExit)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it 'exits with status 1' do
|
|
36
|
+
expect { pack_instance.run([]) }.to raise_error(SystemExit) do |error|
|
|
37
|
+
expect(error.status).to eq(1)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
context 'when src directory exists but ruby.wasm does not exist' do
|
|
43
|
+
before do
|
|
44
|
+
FileUtils.mkdir_p('src')
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it 'outputs error message and exits' do
|
|
48
|
+
expect { pack_instance.run([]) }.to output(
|
|
49
|
+
/ruby.wasm not found. Please run 'ruby-wasm-ui setup' first./
|
|
50
|
+
).to_stdout.and raise_error(SystemExit)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it 'exits with status 1' do
|
|
54
|
+
expect { pack_instance.run([]) }.to raise_error(SystemExit) do |error|
|
|
55
|
+
expect(error.status).to eq(1)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
context 'when src directory and ruby.wasm exist' do
|
|
61
|
+
before do
|
|
62
|
+
FileUtils.mkdir_p('src')
|
|
63
|
+
FileUtils.touch('ruby.wasm')
|
|
64
|
+
allow(pack_instance).to receive(:pack)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
it 'outputs packing message' do
|
|
68
|
+
expect { pack_instance.run([]) }.to output(
|
|
69
|
+
/Packing WASM file/
|
|
70
|
+
).to_stdout
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it 'calls pack method' do
|
|
74
|
+
expect(pack_instance).to receive(:pack)
|
|
75
|
+
pack_instance.run([])
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
describe '#pack' do
|
|
81
|
+
before do
|
|
82
|
+
FileUtils.mkdir_p('src')
|
|
83
|
+
FileUtils.touch('ruby.wasm')
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
context 'when command succeeds' do
|
|
87
|
+
before do
|
|
88
|
+
allow(pack_instance).to receive(:run_command).and_return(true)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it 'executes rbwasm pack command via run_command' do
|
|
92
|
+
expect(pack_instance).to receive(:run_command).with(
|
|
93
|
+
'bundle exec rbwasm pack ruby.wasm --dir ./src::./src -o src.wasm'
|
|
94
|
+
)
|
|
95
|
+
pack_instance.send(:pack)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
it 'outputs pack message' do
|
|
99
|
+
expect { pack_instance.send(:pack) }.to output(
|
|
100
|
+
/Packing: bundle exec rbwasm pack/
|
|
101
|
+
).to_stdout
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
it 'outputs success message' do
|
|
105
|
+
expect { pack_instance.send(:pack) }.to output(
|
|
106
|
+
/Pack completed/
|
|
107
|
+
).to_stdout
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
context 'when command fails' do
|
|
112
|
+
before do
|
|
113
|
+
allow(pack_instance).to receive(:run_command).and_raise(SystemExit.new(1))
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
it 'outputs error message and exits' do
|
|
117
|
+
expect { pack_instance.send(:pack) }.to raise_error(SystemExit)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
it 'exits with status 1' do
|
|
121
|
+
expect { pack_instance.send(:pack) }.to raise_error(SystemExit) do |error|
|
|
122
|
+
expect(error.status).to eq(1)
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe RubyWasmUi::Cli::Command::Rebuild do
|
|
6
|
+
let(:rebuild_instance) { described_class.new }
|
|
7
|
+
|
|
8
|
+
describe '.description' do
|
|
9
|
+
it 'returns the description' do
|
|
10
|
+
expect(described_class.description).to eq('Rebuild Ruby WASM file (useful when gems are added)')
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
describe '#run' do
|
|
15
|
+
before do
|
|
16
|
+
allow(rebuild_instance).to receive(:check_ruby_version).and_return(RUBY_VERSION.split('.')[0..1].join('.'))
|
|
17
|
+
allow(rebuild_instance).to receive(:configure_excluded_gems)
|
|
18
|
+
allow(rebuild_instance).to receive(:build_ruby_wasm)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it 'outputs rebuild message' do
|
|
22
|
+
expect { rebuild_instance.run([]) }.to output(
|
|
23
|
+
/Rebuilding Ruby WASM/
|
|
24
|
+
).to_stdout
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it 'checks Ruby version' do
|
|
28
|
+
expect(rebuild_instance).to receive(:check_ruby_version)
|
|
29
|
+
rebuild_instance.run([])
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it 'configures excluded gems' do
|
|
33
|
+
expect(rebuild_instance).to receive(:configure_excluded_gems)
|
|
34
|
+
rebuild_instance.run([])
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it 'executes rbwasm build command' do
|
|
38
|
+
ruby_version = RUBY_VERSION.split('.')[0..1].join('.')
|
|
39
|
+
expect(rebuild_instance).to receive(:build_ruby_wasm).with(ruby_version)
|
|
40
|
+
rebuild_instance.run([])
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it 'outputs completion message' do
|
|
44
|
+
expect { rebuild_instance.run([]) }.to output(
|
|
45
|
+
/Rebuild completed successfully!/
|
|
46
|
+
).to_stdout
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it 'outputs progress messages' do
|
|
50
|
+
expect { rebuild_instance.run([]) }.to output(
|
|
51
|
+
/Configuring excluded gems/
|
|
52
|
+
).to_stdout
|
|
53
|
+
expect { rebuild_instance.run([]) }.to output(
|
|
54
|
+
/Building Ruby WASM/
|
|
55
|
+
).to_stdout
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it 'does not update .gitignore' do
|
|
59
|
+
expect(rebuild_instance).not_to respond_to(:update_gitignore)
|
|
60
|
+
rebuild_instance.run([])
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it 'does not create initial files' do
|
|
64
|
+
expect(rebuild_instance).not_to respond_to(:create_initial_files)
|
|
65
|
+
rebuild_instance.run([])
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
context 'when Ruby version check fails' do
|
|
69
|
+
before do
|
|
70
|
+
allow(rebuild_instance).to receive(:check_ruby_version).and_raise(SystemExit.new(1))
|
|
71
|
+
allow(Kernel).to receive(:exit)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it 'does not execute subsequent steps' do
|
|
75
|
+
expect(rebuild_instance).not_to receive(:configure_excluded_gems)
|
|
76
|
+
expect(rebuild_instance).not_to receive(:build_ruby_wasm)
|
|
77
|
+
expect { rebuild_instance.run([]) }.to raise_error(SystemExit)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
context 'when Ruby version is 3.2' do
|
|
82
|
+
before do
|
|
83
|
+
stub_const('RUBY_VERSION', '3.2.0')
|
|
84
|
+
allow(rebuild_instance).to receive(:check_ruby_version).and_return('3.2')
|
|
85
|
+
allow(rebuild_instance).to receive(:configure_excluded_gems)
|
|
86
|
+
allow(rebuild_instance).to receive(:build_ruby_wasm)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
it 'executes rbwasm build command with correct version' do
|
|
90
|
+
expect(rebuild_instance).to receive(:build_ruby_wasm).with('3.2')
|
|
91
|
+
rebuild_instance.run([])
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|