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,130 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "base"
|
|
4
|
+
|
|
5
|
+
module RubyWasmUi
|
|
6
|
+
module Cli
|
|
7
|
+
class Command
|
|
8
|
+
class Setup < Base
|
|
9
|
+
def self.description
|
|
10
|
+
"Set up the project for ruby-wasm-ui"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def run(_argv)
|
|
14
|
+
log_info("Setting up ruby-wasm-ui project...")
|
|
15
|
+
puts ""
|
|
16
|
+
|
|
17
|
+
# Check Ruby version
|
|
18
|
+
ruby_version_str = check_ruby_version
|
|
19
|
+
|
|
20
|
+
# Configure excluded gems for WASM build
|
|
21
|
+
log_info("Step 1/3: Configuring excluded gems...")
|
|
22
|
+
configure_excluded_gems
|
|
23
|
+
log_success("✓ Excluded gems configured")
|
|
24
|
+
|
|
25
|
+
# Build Ruby WASM
|
|
26
|
+
puts ""
|
|
27
|
+
log_info("Step 2/3: Building Ruby WASM...")
|
|
28
|
+
log_info("Running: rbwasm build --ruby-version #{ruby_version_str} -o ruby.wasm")
|
|
29
|
+
build_ruby_wasm(ruby_version_str)
|
|
30
|
+
log_success("✓ Ruby WASM build completed")
|
|
31
|
+
|
|
32
|
+
# Update .gitignore
|
|
33
|
+
puts ""
|
|
34
|
+
log_info("Step 3/4: Updating .gitignore...")
|
|
35
|
+
update_gitignore(["*.wasm", "/rubies", "/build"])
|
|
36
|
+
log_success("✓ .gitignore updated")
|
|
37
|
+
|
|
38
|
+
# Create initial files
|
|
39
|
+
puts ""
|
|
40
|
+
log_info("Step 4/4: Creating initial files...")
|
|
41
|
+
create_initial_files
|
|
42
|
+
|
|
43
|
+
puts ""
|
|
44
|
+
log_success("Setup completed successfully!")
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
def create_initial_files
|
|
50
|
+
# Skip if src directory exists
|
|
51
|
+
if Dir.exist?("src")
|
|
52
|
+
log_info("src directory already exists, skipping initial file creation")
|
|
53
|
+
return
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Skip if files already exist
|
|
57
|
+
if File.exist?("src/index.html")
|
|
58
|
+
log_info("src/index.html already exists, skipping initial file creation")
|
|
59
|
+
return
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
if File.exist?("src/index.rb")
|
|
63
|
+
log_info("src/index.rb already exists, skipping initial file creation")
|
|
64
|
+
return
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Create src directory
|
|
68
|
+
Dir.mkdir("src")
|
|
69
|
+
|
|
70
|
+
# Create index.html
|
|
71
|
+
File.write("src/index.html", <<~HTML)
|
|
72
|
+
<!DOCTYPE html>
|
|
73
|
+
<html lang="en">
|
|
74
|
+
<head>
|
|
75
|
+
<meta charset="UTF-8" />
|
|
76
|
+
<title>My App</title>
|
|
77
|
+
<script type="module">
|
|
78
|
+
import { DefaultRubyVM } from "https://cdn.jsdelivr.net/npm/@ruby/wasm-wasi@2.7.2/dist/browser/+esm";
|
|
79
|
+
const response = await fetch("../src.wasm");
|
|
80
|
+
const module = await WebAssembly.compileStreaming(response);
|
|
81
|
+
const { vm } = await DefaultRubyVM(module);
|
|
82
|
+
vm.evalAsync(`
|
|
83
|
+
require "ruby_wasm_ui"
|
|
84
|
+
require_relative './src/index.rb'
|
|
85
|
+
`);
|
|
86
|
+
</script>
|
|
87
|
+
</head>
|
|
88
|
+
<body>
|
|
89
|
+
<h1>My App</h1>
|
|
90
|
+
<div id="app"></div>
|
|
91
|
+
</body>
|
|
92
|
+
</html>
|
|
93
|
+
HTML
|
|
94
|
+
|
|
95
|
+
# Create index.rb
|
|
96
|
+
File.write("src/index.rb", <<~RUBY)
|
|
97
|
+
# Simple Hello World component
|
|
98
|
+
HelloComponent = RubyWasmUi.define_component(
|
|
99
|
+
state: ->(props) {
|
|
100
|
+
{ message: props[:message] || "Hello, Ruby WASM UI!" }
|
|
101
|
+
},
|
|
102
|
+
template: ->() {
|
|
103
|
+
RubyWasmUi::Template::Parser.parse_and_eval(<<~HTML, binding)
|
|
104
|
+
<div>
|
|
105
|
+
<h2>{state[:message]}</h2>
|
|
106
|
+
<button on="{ click: -> { update_message } }">
|
|
107
|
+
Click me!
|
|
108
|
+
</button>
|
|
109
|
+
</div>
|
|
110
|
+
HTML
|
|
111
|
+
},
|
|
112
|
+
methods: {
|
|
113
|
+
update_message: ->() {
|
|
114
|
+
update_state(message: "You clicked the button!")
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
# Create and mount the app
|
|
120
|
+
app = RubyWasmUi::App.create(HelloComponent, message: "Hello, Ruby WASM UI!")
|
|
121
|
+
app_element = JS.global[:document].getElementById("app")
|
|
122
|
+
app.mount(app_element)
|
|
123
|
+
RUBY
|
|
124
|
+
|
|
125
|
+
log_success("✓ Initial files created: src/index.html, src/index.rb")
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "command/setup"
|
|
4
|
+
require_relative "command/dev"
|
|
5
|
+
require_relative "command/pack"
|
|
6
|
+
require_relative "command/rebuild"
|
|
7
|
+
|
|
8
|
+
module RubyWasmUi
|
|
9
|
+
module Cli
|
|
10
|
+
class Command
|
|
11
|
+
COMMANDS = {
|
|
12
|
+
"setup" => Command::Setup,
|
|
13
|
+
"dev" => Command::Dev,
|
|
14
|
+
"pack" => Command::Pack,
|
|
15
|
+
"rebuild" => Command::Rebuild
|
|
16
|
+
}.freeze
|
|
17
|
+
|
|
18
|
+
def self.run(argv)
|
|
19
|
+
command_name = argv[0]
|
|
20
|
+
|
|
21
|
+
if command_name.nil?
|
|
22
|
+
show_usage
|
|
23
|
+
raise SystemExit.new(1)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
command_class = COMMANDS[command_name]
|
|
27
|
+
if command_class.nil?
|
|
28
|
+
puts "Unknown command: #{command_name}"
|
|
29
|
+
puts ""
|
|
30
|
+
show_usage
|
|
31
|
+
raise SystemExit.new(1)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
command_class.new.run(argv[1..-1])
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def self.show_usage
|
|
38
|
+
puts "Usage: ruby-wasm-ui <command>"
|
|
39
|
+
puts ""
|
|
40
|
+
puts "Commands:"
|
|
41
|
+
COMMANDS.each do |name, klass|
|
|
42
|
+
description = klass.description || ""
|
|
43
|
+
puts " #{name.ljust(12)}#{description}"
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
data/lib/ruby_wasm_ui/version.rb
CHANGED
data/lib/ruby_wasm_ui.rb
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative "ruby_wasm_ui/app"
|
|
4
|
-
require_relative "ruby_wasm_ui/component"
|
|
5
|
-
require_relative "ruby_wasm_ui/dispatcher"
|
|
6
|
-
require_relative "ruby_wasm_ui/dom"
|
|
7
|
-
require_relative "ruby_wasm_ui/nodes_equal"
|
|
8
|
-
require_relative "ruby_wasm_ui/template"
|
|
9
|
-
require_relative "ruby_wasm_ui/utils"
|
|
10
|
-
require_relative "ruby_wasm_ui/vdom"
|
|
3
|
+
require_relative "ruby_wasm_ui/runtime/app"
|
|
4
|
+
require_relative "ruby_wasm_ui/runtime/component"
|
|
5
|
+
require_relative "ruby_wasm_ui/runtime/dispatcher"
|
|
6
|
+
require_relative "ruby_wasm_ui/runtime/dom"
|
|
7
|
+
require_relative "ruby_wasm_ui/runtime/nodes_equal"
|
|
8
|
+
require_relative "ruby_wasm_ui/runtime/template"
|
|
9
|
+
require_relative "ruby_wasm_ui/runtime/utils"
|
|
10
|
+
require_relative "ruby_wasm_ui/runtime/vdom"
|
|
11
11
|
require_relative "ruby_wasm_ui/version"
|
|
12
12
|
|
|
13
13
|
module RubyWasmUi
|
data/package-lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ruby-wasm-ui-project",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "ruby-wasm-ui-project",
|
|
9
|
-
"version": "0.
|
|
9
|
+
"version": "0.9.0",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"workspaces": [
|
|
12
12
|
"packages/*"
|
data/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ruby-wasm-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "ruby-wasm-ui",
|
|
9
|
-
"version": "0.
|
|
9
|
+
"version": "0.9.0",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"devDependencies": {
|
|
12
12
|
"@rollup/plugin-replace": "^6.0.2",
|
|
@@ -18,7 +18,7 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
|
18
18
|
|
|
19
19
|
// Find all Ruby files in ruby_wasm_ui directory
|
|
20
20
|
const rubyFiles = glob
|
|
21
|
-
.sync("src/ruby_wasm_ui/**/*.rb")
|
|
21
|
+
.sync("src/ruby_wasm_ui/runtime/**/*.rb")
|
|
22
22
|
.map((file) => file.replace("src/", ""))
|
|
23
23
|
.sort((a, b) => {
|
|
24
24
|
// Files in root directory should be loaded first
|
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
require 'fileutils'
|
|
5
|
+
require 'tmpdir'
|
|
6
|
+
|
|
7
|
+
RSpec.describe RubyWasmUi::Cli::Command::Base do
|
|
8
|
+
let(:base_instance) { described_class.new }
|
|
9
|
+
|
|
10
|
+
describe '#run' do
|
|
11
|
+
it 'raises NotImplementedError' do
|
|
12
|
+
expect { base_instance.run([]) }.to raise_error(NotImplementedError, /Subclasses must implement #run/)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
describe '#update_gitignore' do
|
|
17
|
+
let(:temp_dir) { Dir.mktmpdir }
|
|
18
|
+
let(:original_dir) { Dir.pwd }
|
|
19
|
+
|
|
20
|
+
around do |example|
|
|
21
|
+
Dir.chdir(temp_dir) do
|
|
22
|
+
example.run
|
|
23
|
+
end
|
|
24
|
+
ensure
|
|
25
|
+
FileUtils.rm_rf(temp_dir) if Dir.exist?(temp_dir)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
context 'when .gitignore does not exist' do
|
|
29
|
+
it 'creates .gitignore with new entries' do
|
|
30
|
+
base_instance.send(:update_gitignore, ['*.wasm', '/rubies'])
|
|
31
|
+
content = File.read('.gitignore')
|
|
32
|
+
expect(content).to include('*.wasm')
|
|
33
|
+
expect(content).to include('/rubies')
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
context 'when .gitignore exists' do
|
|
38
|
+
before do
|
|
39
|
+
File.write('.gitignore', "node_modules/\n*.log\n")
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it 'adds new entries to existing .gitignore' do
|
|
43
|
+
base_instance.send(:update_gitignore, ['*.wasm', '/rubies'])
|
|
44
|
+
content = File.read('.gitignore')
|
|
45
|
+
expect(content).to include('node_modules/')
|
|
46
|
+
expect(content).to include('*.log')
|
|
47
|
+
expect(content).to include('*.wasm')
|
|
48
|
+
expect(content).to include('/rubies')
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it 'does not add duplicate entries' do
|
|
52
|
+
File.write('.gitignore', "*.wasm\n")
|
|
53
|
+
base_instance.send(:update_gitignore, ['*.wasm', '/rubies'])
|
|
54
|
+
content = File.read('.gitignore')
|
|
55
|
+
expect(content.scan(/^\*\.wasm$/).count).to eq(1)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it 'outputs message when entries are added' do
|
|
59
|
+
expect { base_instance.send(:update_gitignore, ['*.wasm']) }.to output(
|
|
60
|
+
/Added to .gitignore: \*\.wasm/
|
|
61
|
+
).to_stdout
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it 'outputs message when no entries are added' do
|
|
65
|
+
File.write('.gitignore', "*.wasm\n")
|
|
66
|
+
expect { base_instance.send(:update_gitignore, ['*.wasm']) }.to output(
|
|
67
|
+
/No new entries added to .gitignore/
|
|
68
|
+
).to_stdout
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
describe '#run_command' do
|
|
74
|
+
context 'when command succeeds' do
|
|
75
|
+
it 'executes the command and outputs stdout' do
|
|
76
|
+
expect { base_instance.send(:run_command, 'echo "test output"') }.to output(
|
|
77
|
+
/test output/
|
|
78
|
+
).to_stdout
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
it 'does not raise error' do
|
|
82
|
+
expect { base_instance.send(:run_command, 'echo "test"') }.not_to raise_error
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
it 'returns true' do
|
|
86
|
+
result = base_instance.send(:run_command, 'echo "test"')
|
|
87
|
+
expect(result).to be true
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
context 'when command fails' do
|
|
92
|
+
it 'outputs error message and exits by default' do
|
|
93
|
+
expect { base_instance.send(:run_command, 'false') }.to output(
|
|
94
|
+
/Command failed: false/
|
|
95
|
+
).to_stdout.and raise_error(SystemExit)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
it 'exits with correct status code' do
|
|
99
|
+
expect { base_instance.send(:run_command, 'false') }.to raise_error(SystemExit) do |error|
|
|
100
|
+
expect(error.status).to eq(1)
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
context 'when exit_on_error is false' do
|
|
105
|
+
it 'outputs error message but does not exit' do
|
|
106
|
+
expect { base_instance.send(:run_command, 'false', exit_on_error: false) }.to output(
|
|
107
|
+
/Command failed: false/
|
|
108
|
+
).to_stdout
|
|
109
|
+
expect { base_instance.send(:run_command, 'false', exit_on_error: false) }.not_to raise_error
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
it 'returns false' do
|
|
113
|
+
result = base_instance.send(:run_command, 'false', exit_on_error: false)
|
|
114
|
+
expect(result).to be false
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
describe '#ensure_src_directory' do
|
|
121
|
+
let(:temp_dir) { Dir.mktmpdir }
|
|
122
|
+
let(:original_dir) { Dir.pwd }
|
|
123
|
+
|
|
124
|
+
around do |example|
|
|
125
|
+
Dir.chdir(temp_dir) do
|
|
126
|
+
example.run
|
|
127
|
+
end
|
|
128
|
+
ensure
|
|
129
|
+
FileUtils.rm_rf(temp_dir) if Dir.exist?(temp_dir)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
context 'when src directory does not exist' do
|
|
133
|
+
it 'outputs error message and exits' do
|
|
134
|
+
expect { base_instance.send(:ensure_src_directory) }.to output(
|
|
135
|
+
/src directory not found. Please run 'ruby-wasm-ui setup' first./
|
|
136
|
+
).to_stdout.and raise_error(SystemExit)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
it 'exits with status 1' do
|
|
140
|
+
expect { base_instance.send(:ensure_src_directory) }.to raise_error(SystemExit) do |error|
|
|
141
|
+
expect(error.status).to eq(1)
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
context 'when src directory exists' do
|
|
147
|
+
before do
|
|
148
|
+
FileUtils.mkdir_p('src')
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
it 'does not raise error' do
|
|
152
|
+
expect { base_instance.send(:ensure_src_directory) }.not_to raise_error
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
it 'does not output error message' do
|
|
156
|
+
expect { base_instance.send(:ensure_src_directory) }.not_to output(
|
|
157
|
+
/src directory not found/
|
|
158
|
+
).to_stdout
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
describe '#ensure_ruby_wasm' do
|
|
164
|
+
let(:temp_dir) { Dir.mktmpdir }
|
|
165
|
+
let(:original_dir) { Dir.pwd }
|
|
166
|
+
|
|
167
|
+
around do |example|
|
|
168
|
+
Dir.chdir(temp_dir) do
|
|
169
|
+
example.run
|
|
170
|
+
end
|
|
171
|
+
ensure
|
|
172
|
+
FileUtils.rm_rf(temp_dir) if Dir.exist?(temp_dir)
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
context 'when ruby.wasm does not exist' do
|
|
176
|
+
it 'outputs error message and exits' do
|
|
177
|
+
expect { base_instance.send(:ensure_ruby_wasm) }.to output(
|
|
178
|
+
/ruby.wasm not found. Please run 'ruby-wasm-ui setup' first./
|
|
179
|
+
).to_stdout.and raise_error(SystemExit)
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
it 'exits with status 1' do
|
|
183
|
+
expect { base_instance.send(:ensure_ruby_wasm) }.to raise_error(SystemExit) do |error|
|
|
184
|
+
expect(error.status).to eq(1)
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
context 'when ruby.wasm exists' do
|
|
190
|
+
before do
|
|
191
|
+
FileUtils.touch('ruby.wasm')
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
it 'does not raise error' do
|
|
195
|
+
expect { base_instance.send(:ensure_ruby_wasm) }.not_to raise_error
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
it 'does not output error message' do
|
|
199
|
+
expect { base_instance.send(:ensure_ruby_wasm) }.not_to output(
|
|
200
|
+
/ruby.wasm not found/
|
|
201
|
+
).to_stdout
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
describe '#check_ruby_version' do
|
|
207
|
+
context 'when Ruby version is 3.2 or higher' do
|
|
208
|
+
before do
|
|
209
|
+
stub_const('RUBY_VERSION', '3.2.0')
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
it 'returns the version string' do
|
|
213
|
+
result = base_instance.send(:check_ruby_version)
|
|
214
|
+
expect(result).to eq('3.2')
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
it 'does not exit' do
|
|
218
|
+
expect { base_instance.send(:check_ruby_version) }.not_to raise_error
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
context 'when Ruby version is 3.4' do
|
|
223
|
+
before do
|
|
224
|
+
stub_const('RUBY_VERSION', '3.4.0')
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
it 'returns the version string' do
|
|
228
|
+
result = base_instance.send(:check_ruby_version)
|
|
229
|
+
expect(result).to eq('3.4')
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
context 'when Ruby version is less than 3.2' do
|
|
234
|
+
context 'when Ruby version is 3.1' do
|
|
235
|
+
before do
|
|
236
|
+
stub_const('RUBY_VERSION', '3.1.5')
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
it 'outputs error message and exits' do
|
|
240
|
+
expect { base_instance.send(:check_ruby_version) }.to output(
|
|
241
|
+
/\[ERROR\] Ruby WASM requires Ruby 3.2 or higher. Current version: 3.1.5/
|
|
242
|
+
).to_stdout.and raise_error(SystemExit) do |error|
|
|
243
|
+
expect(error.status).to eq(1)
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
context 'when Ruby version is 2.7' do
|
|
249
|
+
before do
|
|
250
|
+
stub_const('RUBY_VERSION', '2.7.8')
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
it 'outputs error message and exits' do
|
|
254
|
+
expect { base_instance.send(:check_ruby_version) }.to output(
|
|
255
|
+
/\[ERROR\] Ruby WASM requires Ruby 3.2 or higher. Current version: 2.7.8/
|
|
256
|
+
).to_stdout.and raise_error(SystemExit) do |error|
|
|
257
|
+
expect(error.status).to eq(1)
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
describe '#configure_excluded_gems' do
|
|
265
|
+
before do
|
|
266
|
+
# Clear EXCLUDED_GEMS before each test
|
|
267
|
+
RubyWasm::Packager::EXCLUDED_GEMS.clear if defined?(RubyWasm::Packager::EXCLUDED_GEMS)
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
it 'excludes rack, puma, nio4r, listen, and ffi gems' do
|
|
271
|
+
allow(Bundler).to receive(:definition).and_return(
|
|
272
|
+
double(
|
|
273
|
+
resolve: double(
|
|
274
|
+
materialize: [
|
|
275
|
+
double(name: 'rack'),
|
|
276
|
+
double(name: 'puma'),
|
|
277
|
+
double(name: 'nio4r'),
|
|
278
|
+
double(name: 'listen'),
|
|
279
|
+
double(name: 'ffi'),
|
|
280
|
+
double(name: 'js'),
|
|
281
|
+
double(name: 'ruby_wasm')
|
|
282
|
+
]
|
|
283
|
+
),
|
|
284
|
+
requested_dependencies: []
|
|
285
|
+
)
|
|
286
|
+
)
|
|
287
|
+
|
|
288
|
+
base_instance.send(:configure_excluded_gems)
|
|
289
|
+
|
|
290
|
+
expect(RubyWasm::Packager::EXCLUDED_GEMS).to include('rack', 'puma', 'nio4r', 'listen', 'ffi')
|
|
291
|
+
expect(RubyWasm::Packager::EXCLUDED_GEMS).not_to include('js', 'ruby_wasm')
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
it 'always excludes nio4r, puma, rack, listen, and ffi even if not in dependencies' do
|
|
295
|
+
allow(Bundler).to receive(:definition).and_return(
|
|
296
|
+
double(
|
|
297
|
+
resolve: double(
|
|
298
|
+
materialize: [
|
|
299
|
+
double(name: 'js'),
|
|
300
|
+
double(name: 'ruby_wasm')
|
|
301
|
+
]
|
|
302
|
+
),
|
|
303
|
+
requested_dependencies: []
|
|
304
|
+
)
|
|
305
|
+
)
|
|
306
|
+
|
|
307
|
+
base_instance.send(:configure_excluded_gems)
|
|
308
|
+
|
|
309
|
+
# Always excluded gems should be in the list even if not in dependencies
|
|
310
|
+
expect(RubyWasm::Packager::EXCLUDED_GEMS).to include('nio4r', 'puma', 'rack', 'listen', 'ffi')
|
|
311
|
+
expect(RubyWasm::Packager::EXCLUDED_GEMS).not_to include('js', 'ruby_wasm')
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
it 'excludes development/test gems' do
|
|
315
|
+
allow(Bundler).to receive(:definition).and_return(
|
|
316
|
+
double(
|
|
317
|
+
resolve: double(
|
|
318
|
+
materialize: [
|
|
319
|
+
double(name: 'rspec'),
|
|
320
|
+
double(name: 'rubocop'),
|
|
321
|
+
double(name: 'rake'),
|
|
322
|
+
double(name: 'js')
|
|
323
|
+
]
|
|
324
|
+
),
|
|
325
|
+
requested_dependencies: []
|
|
326
|
+
)
|
|
327
|
+
)
|
|
328
|
+
|
|
329
|
+
base_instance.send(:configure_excluded_gems)
|
|
330
|
+
|
|
331
|
+
expect(RubyWasm::Packager::EXCLUDED_GEMS).to include('rspec', 'rubocop', 'rake')
|
|
332
|
+
expect(RubyWasm::Packager::EXCLUDED_GEMS).not_to include('js')
|
|
333
|
+
end
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
describe '#build_ruby_wasm' do
|
|
337
|
+
let(:cli_instance) { instance_double(RubyWasm::CLI) }
|
|
338
|
+
|
|
339
|
+
before do
|
|
340
|
+
allow(RubyWasm::CLI).to receive(:new).and_return(cli_instance)
|
|
341
|
+
allow(cli_instance).to receive(:run)
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
it 'executes rbwasm build command with correct arguments' do
|
|
345
|
+
expect(RubyWasm::CLI).to receive(:new).with(stdout: $stdout, stderr: $stderr).and_return(cli_instance)
|
|
346
|
+
expect(cli_instance).to receive(:run).with(['build', '--ruby-version', '3.2', '-o', 'ruby.wasm'])
|
|
347
|
+
|
|
348
|
+
base_instance.send(:build_ruby_wasm, '3.2')
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
it 'executes rbwasm build command with different version' do
|
|
352
|
+
expect(RubyWasm::CLI).to receive(:new).with(stdout: $stdout, stderr: $stderr).and_return(cli_instance)
|
|
353
|
+
expect(cli_instance).to receive(:run).with(['build', '--ruby-version', '3.4', '-o', 'ruby.wasm'])
|
|
354
|
+
|
|
355
|
+
base_instance.send(:build_ruby_wasm, '3.4')
|
|
356
|
+
end
|
|
357
|
+
end
|
|
358
|
+
end
|