opal_stimulus 0.1.4 → 0.1.5
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/.rspec-opal +2 -0
- data/CHANGELOG.md +13 -7
- data/README.md +12 -2
- data/Rakefile +12 -1
- data/lib/generators/USAGE +14 -0
- data/lib/generators/opal_stimulus_generator.rb +9 -0
- data/lib/generators/templates/controller.rb.tt +14 -0
- data/lib/install/Procfile.dev +1 -1
- data/lib/install/application.rb +2 -7
- data/lib/install/install_opal_stimulus.rb +2 -13
- data/lib/opal_stimulus/stimulus_controller.rb +22 -13
- data/lib/opal_stimulus/version.rb +1 -1
- data/lib/tasks/build.rake +53 -0
- data/lib/tasks/install.rake +1 -1
- data/shared_fixtures/stimulus@3.2.2.umd.js +2588 -0
- data/spec-opal/spec_helper.rb +24 -0
- data/spec-opal/stimulus_controller_spec.rb +215 -0
- metadata +11 -6
- data/lib/install/controllers/my_opal_controller.rb +0 -5
- data/lib/install/controllers_requires.rb +0 -4
- data/lib/install/opal +0 -74
@@ -0,0 +1,24 @@
|
|
1
|
+
# backtick_javascript: true
|
2
|
+
|
3
|
+
require "opal"
|
4
|
+
require "stimulus@3.2.2.umd.js"
|
5
|
+
%x{
|
6
|
+
window.Stimulus = Stimulus
|
7
|
+
window.Controller = Stimulus.Controller
|
8
|
+
window.application = Stimulus.Application.start()
|
9
|
+
}
|
10
|
+
require "opal_stimulus/stimulus_controller"
|
11
|
+
|
12
|
+
RSpec.configure do |config|
|
13
|
+
# Run specs in random order to surface order dependencies. If you find an
|
14
|
+
# order dependency and want to debug it, you can fix the order by providing
|
15
|
+
# the seed, which is printed after each run.
|
16
|
+
# --seed 1234
|
17
|
+
config.order = :random
|
18
|
+
|
19
|
+
# Seed global randomization in this process using the `--seed` CLI option.
|
20
|
+
# Setting this allows you to use `--seed` to deterministically reproduce
|
21
|
+
# test failures related to randomization by passing the same `--seed` value
|
22
|
+
# as the one that triggered the failure.
|
23
|
+
Kernel.srand config.seed
|
24
|
+
end
|
@@ -0,0 +1,215 @@
|
|
1
|
+
# backtick_javascript: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
RSpec.describe StimulusController do
|
6
|
+
describe ".inherited" do
|
7
|
+
class MyController < described_class; end
|
8
|
+
|
9
|
+
it "bridges inherited class to Opal" do
|
10
|
+
expect {
|
11
|
+
Opal.bridge(described_class, MyController)
|
12
|
+
}.to raise_error("already bridged")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe ".stimulus_controller" do
|
17
|
+
class MyController < described_class; end
|
18
|
+
|
19
|
+
it "sets `stimulus_controller` with a basic Controller" do
|
20
|
+
expect(`Object.getPrototypeOf(#{MyController.stimulus_controller})`).to eq(`Controller`)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe ".stimulus_name" do
|
25
|
+
context "when is one word" do
|
26
|
+
class MyController < described_class; end
|
27
|
+
|
28
|
+
it "it returns it downcased" do
|
29
|
+
expect(MyController.stimulus_name).to eq("my")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context "when is multiple words" do
|
34
|
+
class MyBestController < described_class; end
|
35
|
+
|
36
|
+
it "it returns them separated by `-`" do
|
37
|
+
expect(MyBestController.stimulus_name).to eq("my-best")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context "when has namespaces" do
|
42
|
+
module My; end
|
43
|
+
class My::VeryBestController < described_class; end
|
44
|
+
|
45
|
+
it "it returns them separated by `--`" do
|
46
|
+
expect(My::VeryBestController.stimulus_name).to eq("my--very-best")
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe ".method_added" do
|
52
|
+
it "returns the same bridged class method result" do
|
53
|
+
class MyController < described_class
|
54
|
+
def hello_world
|
55
|
+
"Hello world!"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
expect(MyController.new.hello_world).to eq(`#{MyController.stimulus_controller}.prototype["hello_world"]()`)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe ".to_ruby_name" do
|
64
|
+
it "converts camelCase to snake_case" do
|
65
|
+
expect(described_class.to_ruby_name("myMethod")).to eq("my_method")
|
66
|
+
expect(described_class.to_ruby_name("anotherExample")).to eq("another_example")
|
67
|
+
expect(described_class.to_ruby_name("YetAnotherTest")).to eq("yet_another_test")
|
68
|
+
end
|
69
|
+
|
70
|
+
it "does not change already snake_case names" do
|
71
|
+
expect(described_class.to_ruby_name("already_snake_case")).to eq("already_snake_case")
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe ".register_all!" do
|
76
|
+
class MyController < described_class; end
|
77
|
+
StimulusController.register_all!
|
78
|
+
|
79
|
+
it "should register controller" do
|
80
|
+
expect(`application.router.modules[0].definition.identifier`).to eq("my")
|
81
|
+
end
|
82
|
+
|
83
|
+
it "sould respond to `dummy` method" do
|
84
|
+
expect(MyController.new).to respond_to(:dummy)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
describe ".targets=" do
|
89
|
+
class MyController < described_class
|
90
|
+
self.targets = ["container"]
|
91
|
+
|
92
|
+
def container_target_connected = "Container Target connected!"
|
93
|
+
def container_target_disconnected = "Container Target disconnected!"
|
94
|
+
end
|
95
|
+
|
96
|
+
it "defines all target methods and maps callbacks" do
|
97
|
+
my_controller = MyController.new
|
98
|
+
expect(my_controller).to respond_to(:container_target)
|
99
|
+
expect(my_controller).to respond_to(:container_targets)
|
100
|
+
expect(my_controller).to respond_to(:has_container_target)
|
101
|
+
expect(MyController.new.container_target_connected)
|
102
|
+
.to eq(`#{MyController.stimulus_controller}.prototype["containerTargetConnected"]()`)
|
103
|
+
expect(MyController.new.container_target_disconnected)
|
104
|
+
.to eq(`#{MyController.stimulus_controller}.prototype["containerTargetDisconnected"]()`)
|
105
|
+
end
|
106
|
+
|
107
|
+
it "returns a `JS::Proxy` instance whe `container_target` is called" do
|
108
|
+
my_controller = MyController.new
|
109
|
+
expect(my_controller.container_target).to be_a(JS::Proxy)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
describe ".outlets=" do
|
114
|
+
class MyController < described_class
|
115
|
+
self.outlets = ["container"]
|
116
|
+
|
117
|
+
def container_outlet_connected = "Container Outlet connected!"
|
118
|
+
def container_outlet_disconnected = "Container Outlet disconnected!"
|
119
|
+
end
|
120
|
+
|
121
|
+
it "defines all outlet methods and maps callbacks" do
|
122
|
+
my_controller = MyController.new
|
123
|
+
expect(my_controller).to respond_to(:container_outlet)
|
124
|
+
expect(my_controller).to respond_to(:container_outlets)
|
125
|
+
expect(my_controller).to respond_to(:has_container_outlet)
|
126
|
+
expect(MyController.new.container_outlet_connected)
|
127
|
+
.to eq(`#{MyController.stimulus_controller}.prototype["containerOutletConnected"]()`)
|
128
|
+
expect(MyController.new.container_outlet_disconnected)
|
129
|
+
.to eq(`#{MyController.stimulus_controller}.prototype["containerOutletDisconnected"]()`)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
describe ".values=" do
|
134
|
+
it "sets bridged class `values`" do
|
135
|
+
class MyController < described_class
|
136
|
+
self.values = {
|
137
|
+
name: :string,
|
138
|
+
age: :number,
|
139
|
+
alive: :boolean,
|
140
|
+
cars: :array,
|
141
|
+
notes: :object
|
142
|
+
}
|
143
|
+
end
|
144
|
+
|
145
|
+
expect(`#{MyController}.stimulus_controller.values.name === String`).to be_truthy
|
146
|
+
expect(`#{MyController}.stimulus_controller.values.age === Number`).to be_truthy
|
147
|
+
expect(`#{MyController}.stimulus_controller.values.alive === Boolean`).to be_truthy
|
148
|
+
expect(`#{MyController}.stimulus_controller.values.cars === Array`).to be_truthy
|
149
|
+
expect(`#{MyController}.stimulus_controller.values.notes === Object`).to be_truthy
|
150
|
+
end
|
151
|
+
|
152
|
+
it "defines all values methods" do
|
153
|
+
class MyController < described_class
|
154
|
+
self.values = {
|
155
|
+
name: :string
|
156
|
+
}
|
157
|
+
|
158
|
+
def name_value_changed(value, previous_value)
|
159
|
+
"Name value changed from #{previous_value} to #{value}!"
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
my_controller = MyController.new
|
164
|
+
expect(my_controller).to respond_to(:name_value)
|
165
|
+
expect(my_controller).to respond_to(:name_value=)
|
166
|
+
expect(my_controller).to respond_to(:has_name)
|
167
|
+
expect(MyController.new.name_value_changed(:new, :prev))
|
168
|
+
.to eq(`#{MyController.stimulus_controller}.prototype["nameValueChanged"]("new", "prev")`)
|
169
|
+
end
|
170
|
+
|
171
|
+
context "when unsupported type is passed" do
|
172
|
+
it "raises `ArgumentError`" do
|
173
|
+
expect {
|
174
|
+
class MyController < described_class
|
175
|
+
self.values = { age: :parsec }
|
176
|
+
end
|
177
|
+
}.to raise_error("Unsupported value type: parsec, please use :string, :number, :boolean, :array, or :object")
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
describe ".classes" do
|
183
|
+
it "defines all classes methods" do
|
184
|
+
class MyController < described_class
|
185
|
+
self.classes = ["active"]
|
186
|
+
end
|
187
|
+
|
188
|
+
my_controller = MyController.new
|
189
|
+
expect(my_controller).to respond_to(:active_class)
|
190
|
+
expect(my_controller).to respond_to(:active_classes)
|
191
|
+
expect(my_controller).to respond_to(:has_active_class)
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
describe "#element" do
|
196
|
+
it "has been tested with selenium" do
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
describe "#window" do
|
201
|
+
it "returns a `JS::Proxy`" do |example|
|
202
|
+
class MyController < described_class; end
|
203
|
+
|
204
|
+
expect(MyController.new.window).to be_a(JS::Proxy)
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
describe "#document" do
|
209
|
+
it "returns a `JS::Proxy`" do
|
210
|
+
class MyController < described_class; end
|
211
|
+
|
212
|
+
expect(MyController.new.document).to be_a(JS::Proxy)
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: opal_stimulus
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joseph Schito
|
@@ -43,14 +43,14 @@ dependencies:
|
|
43
43
|
requirements:
|
44
44
|
- - "~>"
|
45
45
|
- !ruby/object:Gem::Version
|
46
|
-
version: 0.1.
|
46
|
+
version: 0.1.1
|
47
47
|
type: :runtime
|
48
48
|
prerelease: false
|
49
49
|
version_requirements: !ruby/object:Gem::Requirement
|
50
50
|
requirements:
|
51
51
|
- - "~>"
|
52
52
|
- !ruby/object:Gem::Version
|
53
|
-
version: 0.1.
|
53
|
+
version: 0.1.1
|
54
54
|
description: Opal Stimulus provides a way to write Stimulus controllers in Ruby, leveraging
|
55
55
|
the Opal compiler to convert Ruby code into JavaScript. This allows developers familiar
|
56
56
|
with Ruby to use the Stimulus framework without needing to write JavaScript directly.
|
@@ -60,22 +60,27 @@ executables: []
|
|
60
60
|
extensions: []
|
61
61
|
extra_rdoc_files: []
|
62
62
|
files:
|
63
|
+
- ".rspec-opal"
|
63
64
|
- ".rubocop.yml"
|
64
65
|
- CHANGELOG.md
|
65
66
|
- LICENSE.txt
|
66
67
|
- README.md
|
67
68
|
- Rakefile
|
69
|
+
- lib/generators/USAGE
|
70
|
+
- lib/generators/opal_stimulus_generator.rb
|
71
|
+
- lib/generators/templates/controller.rb.tt
|
68
72
|
- lib/install/Procfile.dev
|
69
73
|
- lib/install/application.rb
|
70
|
-
- lib/install/controllers/my_opal_controller.rb
|
71
|
-
- lib/install/controllers_requires.rb
|
72
74
|
- lib/install/dev
|
73
75
|
- lib/install/install_opal_stimulus.rb
|
74
|
-
- lib/install/opal
|
75
76
|
- lib/opal_stimulus.rb
|
76
77
|
- lib/opal_stimulus/stimulus_controller.rb
|
77
78
|
- lib/opal_stimulus/version.rb
|
79
|
+
- lib/tasks/build.rake
|
78
80
|
- lib/tasks/install.rake
|
81
|
+
- shared_fixtures/stimulus@3.2.2.umd.js
|
82
|
+
- spec-opal/spec_helper.rb
|
83
|
+
- spec-opal/stimulus_controller_spec.rb
|
79
84
|
homepage: https://github.com/josephschito/opal_stimulus
|
80
85
|
licenses:
|
81
86
|
- MIT
|
data/lib/install/opal
DELETED
@@ -1,74 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
require "bundler/setup"
|
5
|
-
require "listen"
|
6
|
-
require "opal"
|
7
|
-
|
8
|
-
GEMS = ["opal_proxy", "opal_stimulus"]
|
9
|
-
|
10
|
-
GEMS.each do |gem_name|
|
11
|
-
Opal.use_gem(gem_name) rescue Opal.append_path(File.expand_path("lib", Bundler.rubygems.find_name(gem_name).first.full_gem_path))
|
12
|
-
end
|
13
|
-
|
14
|
-
Opal.append_path("app/opal")
|
15
|
-
|
16
|
-
build = -> {
|
17
|
-
puts "🔨 Compiling Opal..."
|
18
|
-
|
19
|
-
builder = Opal::Builder.new
|
20
|
-
|
21
|
-
result = builder.build("application")
|
22
|
-
|
23
|
-
output_path = "app/assets/builds/opal.js"
|
24
|
-
sourcemap_path = "#{output_path}.map"
|
25
|
-
|
26
|
-
js_code = result.to_s
|
27
|
-
source_map_json = result.source_map.to_json
|
28
|
-
|
29
|
-
File.write(output_path, js_code + "\n//# sourceMappingURL=/assets/opal.js.map")
|
30
|
-
File.write(sourcemap_path, source_map_json)
|
31
|
-
|
32
|
-
puts "✅ Compiled to #{output_path}"
|
33
|
-
}
|
34
|
-
|
35
|
-
update_opal_controllers_requires = -> {
|
36
|
-
file_path = "app/opal/controllers_requires.rb"
|
37
|
-
|
38
|
-
requires = Dir["app/opal/controllers/**/*.rb"].sort.map do |file|
|
39
|
-
"require '#{file.sub("app/opal/", "").sub(".rb", "")}'"
|
40
|
-
end
|
41
|
-
|
42
|
-
File.open(file_path, "w") do |f|
|
43
|
-
f.puts "# This file is automatically generated by `bin/opal`."
|
44
|
-
f.puts "# If you want to update this file, please run: `bin/opal --update-requires`."
|
45
|
-
f.puts
|
46
|
-
f.puts requires.join("\n")
|
47
|
-
end
|
48
|
-
|
49
|
-
puts "✅ Updated #{file_path} 🎉"
|
50
|
-
}
|
51
|
-
|
52
|
-
if ARGV.include?("--update-requires")
|
53
|
-
update_opal_controllers_requires.()
|
54
|
-
exit
|
55
|
-
end
|
56
|
-
|
57
|
-
update_opal_controllers_requires.()
|
58
|
-
build.call
|
59
|
-
|
60
|
-
exit unless ARGV.include?("--watch")
|
61
|
-
|
62
|
-
listen = Listen.to("app/opal") do |modified, added, removed|
|
63
|
-
if added.any? || removed.any?
|
64
|
-
puts "🔄 Updating opal controllers requires..."
|
65
|
-
update_opal_controllers_requires.()
|
66
|
-
end
|
67
|
-
|
68
|
-
build.call
|
69
|
-
end
|
70
|
-
|
71
|
-
puts "👀 Watching app/opal for changes..."
|
72
|
-
listen.start
|
73
|
-
Signal.trap("INT") { listen.stop }
|
74
|
-
sleep
|