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.
@@ -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
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.0
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.0
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
@@ -1,5 +0,0 @@
1
- class MyOpalController < StimulusController
2
- def connect
3
- puts "'#{self.class.name}' connected!"
4
- end
5
- end
@@ -1,4 +0,0 @@
1
- # This file is automatically generated by `bin/opal`.
2
- # If you want to update this file, please run: `bin/opal --update-requires`.
3
-
4
- require 'controllers/my_opal_controller'
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