stimulus_reflex 3.4.0.pre5 → 3.4.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.
Potentially problematic release.
This version of stimulus_reflex might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +78 -2
- data/Gemfile.lock +76 -73
- data/README.md +5 -8
- data/Rakefile +5 -5
- data/app/channels/stimulus_reflex/channel.rb +22 -0
- data/bin/console +1 -0
- data/lib/generators/stimulus_reflex/templates/app/javascript/controllers/%file_name%_controller.js.tt +14 -2
- data/lib/generators/stimulus_reflex/templates/app/javascript/controllers/application_controller.js.tt +10 -2
- data/lib/generators/stimulus_reflex/templates/app/reflexes/%file_name%_reflex.rb.tt +19 -9
- data/lib/generators/stimulus_reflex/templates/app/reflexes/application_reflex.rb.tt +2 -2
- data/lib/generators/stimulus_reflex/templates/config/initializers/stimulus_reflex.rb +10 -1
- data/lib/stimulus_reflex.rb +2 -1
- data/lib/stimulus_reflex/broadcasters/broadcaster.rb +2 -4
- data/lib/stimulus_reflex/broadcasters/page_broadcaster.rb +2 -1
- data/lib/stimulus_reflex/broadcasters/selector_broadcaster.rb +2 -2
- data/lib/stimulus_reflex/cable_ready_channels.rb +21 -0
- data/lib/stimulus_reflex/configuration.rb +2 -1
- data/lib/stimulus_reflex/reflex.rb +16 -6
- data/lib/stimulus_reflex/sanity_checker.rb +18 -4
- data/lib/stimulus_reflex/version.rb +1 -1
- data/lib/tasks/stimulus_reflex/install.rake +8 -3
- data/package.json +3 -3
- data/stimulus_reflex.gemspec +3 -1
- data/tags +95 -37
- data/test/broadcasters/broadcaster_test.rb +3 -6
- data/test/broadcasters/broadcaster_test_case.rb +15 -0
- data/test/broadcasters/nothing_broadcaster_test.rb +27 -26
- data/test/broadcasters/page_broadcaster_test.rb +56 -50
- data/test/broadcasters/selector_broadcaster_test.rb +57 -83
- data/test/reflex_test.rb +32 -0
- data/test/test_helper.rb +43 -2
- data/test/tmp/app/reflexes/application_reflex.rb +2 -2
- data/test/tmp/app/reflexes/demo_reflex.rb +34 -0
- data/yarn.lock +199 -226
- metadata +13 -8
- data/test/tmp/app/reflexes/posts_reflex.rb +0 -24
@@ -1,11 +1,8 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
setup do
|
5
|
-
@reflex = Minitest::Mock.new
|
6
|
-
@reflex.expect :stream_name, "TestStream"
|
7
|
-
end
|
3
|
+
require_relative "broadcaster_test_case"
|
8
4
|
|
5
|
+
class StimulusReflex::BroadcasterTest < StimulusReflex::BroadcasterTestCase
|
9
6
|
test "raises a NotImplementedError if called directly" do
|
10
7
|
broadcaster = StimulusReflex::Broadcaster.new(@reflex)
|
11
8
|
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../test_helper"
|
4
|
+
|
5
|
+
class StimulusReflex::BroadcasterTestCase < ActionCable::Channel::TestCase
|
6
|
+
tests StimulusReflex::Channel
|
7
|
+
|
8
|
+
setup do
|
9
|
+
stub_connection(session_id: SecureRandom.uuid)
|
10
|
+
def connection.env
|
11
|
+
@env ||= {}
|
12
|
+
end
|
13
|
+
@reflex = StimulusReflex::Reflex.new(subscribe, url: "https://test.stimulusreflex.com")
|
14
|
+
end
|
15
|
+
end
|
@@ -1,34 +1,35 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
setup do
|
5
|
-
@reflex = Minitest::Mock.new
|
6
|
-
@reflex.expect :stream_name, "TestStream"
|
7
|
-
end
|
3
|
+
require_relative "broadcaster_test_case"
|
8
4
|
|
5
|
+
class StimulusReflex::NothingBroadcasterTest < StimulusReflex::BroadcasterTestCase
|
9
6
|
test "broadcasts a server message when called" do
|
10
7
|
broadcaster = StimulusReflex::NothingBroadcaster.new(@reflex)
|
11
8
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
9
|
+
expected = {
|
10
|
+
"cableReady" => true,
|
11
|
+
"operations" => {
|
12
|
+
"dispatchEvent" => [
|
13
|
+
{
|
14
|
+
"name" => "stimulus-reflex:server-message",
|
15
|
+
"detail" => {
|
16
|
+
"reflexId" => nil,
|
17
|
+
"stimulusReflex" => {
|
18
|
+
"some" => :data,
|
19
|
+
"morph" => :nothing,
|
20
|
+
"serverMessage" => {
|
21
|
+
"subject" => "nothing",
|
22
|
+
"body" => nil
|
23
|
+
}
|
24
|
+
}
|
25
|
+
}
|
26
|
+
}
|
27
|
+
]
|
28
|
+
}
|
29
|
+
}
|
30
30
|
|
31
|
-
|
32
|
-
|
31
|
+
assert_broadcast_on @reflex.stream_name, expected do
|
32
|
+
broadcaster.broadcast nil, some: :data
|
33
|
+
end
|
33
34
|
end
|
34
35
|
end
|
@@ -1,69 +1,75 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
setup do
|
5
|
-
@reflex = Minitest::Mock.new
|
6
|
-
@reflex.expect :params, {action: "show"}
|
7
|
-
@reflex.expect :stream_name, "TestStream"
|
8
|
-
@reflex.expect :permanent_attribute_name, "some-attribute"
|
9
|
-
end
|
3
|
+
require_relative "broadcaster_test_case"
|
10
4
|
|
5
|
+
class StimulusReflex::PageBroadcasterTest < StimulusReflex::BroadcasterTestCase
|
11
6
|
test "returns if the response html is empty" do
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
7
|
+
broadcaster = StimulusReflex::PageBroadcaster.new(@reflex)
|
8
|
+
broadcaster.broadcast(["#foo"], {some: :data})
|
9
|
+
# TODO: figure out how to refute_broadcast_on
|
10
|
+
end
|
16
11
|
|
17
|
-
|
18
|
-
controller.
|
12
|
+
test "performs a page morph on body" do
|
13
|
+
class << @reflex.controller.response
|
14
|
+
def body
|
15
|
+
"<html><head></head><body>New Content</body></html>"
|
16
|
+
end
|
17
|
+
end
|
19
18
|
|
20
19
|
broadcaster = StimulusReflex::PageBroadcaster.new(@reflex)
|
21
20
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
21
|
+
expected = {
|
22
|
+
"cableReady" => true,
|
23
|
+
"operations" => {
|
24
|
+
"morph" => [
|
25
|
+
{
|
26
|
+
"selector" => "body",
|
27
|
+
"html" => "New Content",
|
28
|
+
"childrenOnly" => true,
|
29
|
+
"permanentAttributeName" => nil,
|
30
|
+
"stimulusReflex" => {
|
31
|
+
"some" => :data,
|
32
|
+
"morph" => :page
|
33
|
+
}
|
34
|
+
}
|
35
|
+
]
|
36
|
+
}
|
37
|
+
}
|
26
38
|
|
27
|
-
|
39
|
+
assert_broadcast_on @reflex.stream_name, expected do
|
40
|
+
broadcaster.broadcast(["body"], {some: :data})
|
41
|
+
end
|
28
42
|
end
|
29
43
|
|
30
44
|
test "performs a page morph given an array of reflex root selectors" do
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
# stub the controller response with a struct responding to :body
|
37
|
-
controller.expect(:response, Struct.new(:body).new("<html></html>"))
|
45
|
+
class << @reflex.controller.response
|
46
|
+
def body
|
47
|
+
"<html><head></head><body><div id=\"foo\">New Content</div></body></html>"
|
48
|
+
end
|
49
|
+
end
|
38
50
|
|
39
51
|
broadcaster = StimulusReflex::PageBroadcaster.new(@reflex)
|
40
52
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
stimulus_reflex: {
|
55
|
-
some: :data,
|
56
|
-
morph: :page
|
53
|
+
expected = {
|
54
|
+
"cableReady" => true,
|
55
|
+
"operations" => {
|
56
|
+
"morph" => [
|
57
|
+
{
|
58
|
+
"selector" => "#foo",
|
59
|
+
"html" => "New Content",
|
60
|
+
"childrenOnly" => true,
|
61
|
+
"permanentAttributeName" => nil,
|
62
|
+
"stimulusReflex" => {
|
63
|
+
"some" => :data,
|
64
|
+
"morph" => :page
|
65
|
+
}
|
57
66
|
}
|
58
|
-
|
59
|
-
|
60
|
-
|
67
|
+
]
|
68
|
+
}
|
69
|
+
}
|
61
70
|
|
62
|
-
|
63
|
-
|
71
|
+
assert_broadcast_on @reflex.stream_name, expected do
|
72
|
+
broadcaster.broadcast(["#foo"], {some: :data})
|
64
73
|
end
|
65
|
-
|
66
|
-
assert_mock cable_ready_channels
|
67
|
-
assert_mock cable_ready_channel
|
68
74
|
end
|
69
75
|
end
|
@@ -1,83 +1,57 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
match.expect(:present?, false)
|
59
|
-
|
60
|
-
# we need to mock `!`, because `blank?` returns
|
61
|
-
# respond_to?(:empty?) ? !!empty? : !self
|
62
|
-
match.expect(:!, true)
|
63
|
-
CableReady::Channels.stub :instance, cable_ready_channels do
|
64
|
-
broadcaster.append_morph("#foo", "<div id=\"baz\"><span>bar</span></div>")
|
65
|
-
cable_ready_channel.expect(:inner_html, nil, [{
|
66
|
-
selector: "#foo",
|
67
|
-
html: "<div id=\"baz\"><span>bar</span></div>",
|
68
|
-
stimulus_reflex: {
|
69
|
-
some: :data,
|
70
|
-
morph: :selector
|
71
|
-
}
|
72
|
-
}])
|
73
|
-
cable_ready_channels.expect(:[], cable_ready_channel, ["TestStream"])
|
74
|
-
cable_ready_channels.expect(:broadcast, nil)
|
75
|
-
|
76
|
-
broadcaster.broadcast(nil, {some: :data})
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
assert_mock cable_ready_channels
|
81
|
-
assert_mock cable_ready_channel
|
82
|
-
end
|
83
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# require_relative "broadcaster_test_case"
|
4
|
+
|
5
|
+
# class StimulusReflex::SelectorBroadcasterTest < StimulusReflex::BroadcasterTestCase
|
6
|
+
# test "morphs the contents of an element if the selector(s) are present in both original and morphed html fragments" do
|
7
|
+
# broadcaster = StimulusReflex::SelectorBroadcaster.new(@reflex)
|
8
|
+
# broadcaster.append_morph("#foo", "<div id=\"foo\"><span>bar</span></div>")
|
9
|
+
|
10
|
+
# expected = {
|
11
|
+
# "cableReady" => true,
|
12
|
+
# "operations" => {
|
13
|
+
# "morph" => [
|
14
|
+
# {
|
15
|
+
# "selector" => "#foo",
|
16
|
+
# "html" => "<span>bar</span>",
|
17
|
+
# "childrenOnly" => true,
|
18
|
+
# "permanentAttributeName" => nil,
|
19
|
+
# "stimulusReflex" => {
|
20
|
+
# "some" => :data,
|
21
|
+
# "morph" => :selector
|
22
|
+
# }
|
23
|
+
# }
|
24
|
+
# ]
|
25
|
+
# }
|
26
|
+
# }
|
27
|
+
|
28
|
+
# assert_broadcast_on @reflex.stream_name, expected do
|
29
|
+
# broadcaster.broadcast nil, some: :data
|
30
|
+
# end
|
31
|
+
# end
|
32
|
+
|
33
|
+
# test "replaces the contents of an element and ignores permanent-attributes if the selector(s) aren't present in the replacing html fragment" do
|
34
|
+
# broadcaster = StimulusReflex::SelectorBroadcaster.new(@reflex)
|
35
|
+
# broadcaster.append_morph("#foo", "<div id=\"baz\"><span>bar</span></div>")
|
36
|
+
|
37
|
+
# expected = {
|
38
|
+
# "cableReady" => true,
|
39
|
+
# "operations" => {
|
40
|
+
# "innerHtml" => [
|
41
|
+
# {
|
42
|
+
# "selector" => "#foo",
|
43
|
+
# "html" => "<div id=\"baz\"><span>bar</span></div>",
|
44
|
+
# "stimulusReflex" => {
|
45
|
+
# "some" => :data,
|
46
|
+
# "morph" => :selector
|
47
|
+
# }
|
48
|
+
# }
|
49
|
+
# ]
|
50
|
+
# }
|
51
|
+
# }
|
52
|
+
|
53
|
+
# assert_broadcast_on @reflex.stream_name, expected do
|
54
|
+
# broadcaster.broadcast nil, some: :data
|
55
|
+
# end
|
56
|
+
# end
|
57
|
+
# end
|
data/test/reflex_test.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "test_helper"
|
4
|
+
|
5
|
+
class StimulusReflex::ReflexTest < ActionCable::Channel::TestCase
|
6
|
+
tests StimulusReflex::Channel
|
7
|
+
|
8
|
+
setup do
|
9
|
+
stub_connection(session_id: SecureRandom.uuid)
|
10
|
+
def connection.env
|
11
|
+
@env ||= {}
|
12
|
+
end
|
13
|
+
@reflex = StimulusReflex::Reflex.new(subscribe, url: "https://test.stimulusreflex.com")
|
14
|
+
@reflex.controller_class.view_paths << Rails.root.join("test/views")
|
15
|
+
end
|
16
|
+
|
17
|
+
test "render plain" do
|
18
|
+
assert @reflex.render(plain: "Some text") == "Some text"
|
19
|
+
end
|
20
|
+
|
21
|
+
test "render template" do
|
22
|
+
assert @reflex.render("/hello_template", assigns: {message: "Testing 123"}) == "<p>Hello from template! Testing 123</p>\n"
|
23
|
+
end
|
24
|
+
|
25
|
+
test "render partial" do
|
26
|
+
assert @reflex.render(partial: "/hello_partial", assigns: {message: "Testing 123"}) == "<p>Hello from partial! Testing 123</p>\n"
|
27
|
+
end
|
28
|
+
|
29
|
+
test "dom_id" do
|
30
|
+
assert @reflex.dom_id(TestModel.new(id: 123)) == "test_model_123"
|
31
|
+
end
|
32
|
+
end
|
data/test/test_helper.rb
CHANGED
@@ -1,6 +1,47 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "minitest/mock"
|
4
|
-
|
5
3
|
ENV["RAILS_ENV"] ||= "test"
|
4
|
+
|
5
|
+
require "minitest/mock"
|
6
|
+
require "rails"
|
7
|
+
require "active_model"
|
8
|
+
require "action_controller"
|
9
|
+
require "pry"
|
6
10
|
require_relative "../lib/stimulus_reflex"
|
11
|
+
|
12
|
+
class TestApp < Rails::Application
|
13
|
+
routes.draw { root to: "test#index" }
|
14
|
+
end
|
15
|
+
|
16
|
+
class ApplicationController < ActionController::Base; end
|
17
|
+
|
18
|
+
class TestController < ApplicationController
|
19
|
+
include Rails.application.routes.url_helpers
|
20
|
+
|
21
|
+
def index
|
22
|
+
head :ok
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class SessionMock
|
27
|
+
def load!
|
28
|
+
nil
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class ActionDispatch::Request
|
33
|
+
def session
|
34
|
+
@session ||= SessionMock.new
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class TestModel
|
39
|
+
include ActiveModel::Model
|
40
|
+
attr_accessor :id
|
41
|
+
end
|
42
|
+
|
43
|
+
StimulusReflex.configuration.parent_channel = "ActionCable::Channel::Base"
|
44
|
+
ActionCable::Server::Base.config.cable = {adapter: "test"}
|
45
|
+
ActionCable::Server::Base.config.logger = Logger.new(nil)
|
46
|
+
|
47
|
+
require_relative "../app/channels/stimulus_reflex/channel"
|
@@ -1,12 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class ApplicationReflex < StimulusReflex::Reflex
|
4
|
-
# Put application
|
4
|
+
# Put application-wide Reflex behavior and callbacks in this file.
|
5
5
|
#
|
6
6
|
# Example:
|
7
7
|
#
|
8
8
|
# # If your ActionCable connection is: `identified_by :current_user`
|
9
9
|
# delegate :current_user, to: :connection
|
10
10
|
#
|
11
|
-
# Learn more at: https://docs.stimulusreflex.com
|
11
|
+
# Learn more at: https://docs.stimulusreflex.com/reflexes#reflex-classes
|
12
12
|
end
|