stimulus_reflex 3.4.2 → 3.5.0.pre0

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.

Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +587 -495
  3. data/Gemfile.lock +120 -172
  4. data/LATEST +1 -0
  5. data/README.md +10 -10
  6. data/app/channels/stimulus_reflex/channel.rb +40 -62
  7. data/lib/generators/USAGE +1 -1
  8. data/lib/generators/stimulus_reflex/{config_generator.rb → initializer_generator.rb} +3 -3
  9. data/lib/generators/stimulus_reflex/templates/app/reflexes/%file_name%_reflex.rb.tt +3 -2
  10. data/lib/generators/stimulus_reflex/templates/app/reflexes/application_reflex.rb.tt +1 -1
  11. data/lib/generators/stimulus_reflex/templates/config/initializers/stimulus_reflex.rb +6 -1
  12. data/lib/stimulus_reflex/broadcasters/broadcaster.rb +7 -4
  13. data/lib/stimulus_reflex/broadcasters/page_broadcaster.rb +2 -2
  14. data/lib/stimulus_reflex/broadcasters/selector_broadcaster.rb +12 -5
  15. data/lib/stimulus_reflex/cable_ready_channels.rb +6 -2
  16. data/lib/stimulus_reflex/callbacks.rb +55 -5
  17. data/lib/stimulus_reflex/concern_enhancer.rb +37 -0
  18. data/lib/stimulus_reflex/configuration.rb +2 -1
  19. data/lib/stimulus_reflex/element.rb +31 -7
  20. data/lib/stimulus_reflex/policies/reflex_invocation_policy.rb +28 -0
  21. data/lib/stimulus_reflex/reflex.rb +35 -20
  22. data/lib/stimulus_reflex/reflex_data.rb +79 -0
  23. data/lib/stimulus_reflex/reflex_factory.rb +23 -54
  24. data/lib/stimulus_reflex/request_parameters.rb +19 -0
  25. data/lib/stimulus_reflex/{logger.rb → utils/logger.rb} +0 -2
  26. data/lib/stimulus_reflex/{sanity_checker.rb → utils/sanity_checker.rb} +58 -10
  27. data/lib/stimulus_reflex/version.rb +1 -1
  28. data/lib/stimulus_reflex.rb +8 -2
  29. data/lib/tasks/stimulus_reflex/install.rake +6 -4
  30. data/package.json +6 -5
  31. data/stimulus_reflex.gemspec +5 -5
  32. data/test/broadcasters/broadcaster_test_case.rb +1 -1
  33. data/test/broadcasters/nothing_broadcaster_test.rb +5 -3
  34. data/test/broadcasters/page_broadcaster_test.rb +8 -4
  35. data/test/broadcasters/selector_broadcaster_test.rb +171 -55
  36. data/test/callbacks_test.rb +652 -0
  37. data/test/concern_enhancer_test.rb +54 -0
  38. data/test/element_test.rb +181 -0
  39. data/test/reflex_test.rb +1 -1
  40. data/test/test_helper.rb +4 -34
  41. data/test/tmp/app/reflexes/application_reflex.rb +12 -0
  42. data/test/tmp/app/reflexes/user_reflex.rb +44 -0
  43. data/yarn.lock +1138 -919
  44. metadata +36 -23
  45. data/test/reflex_factory_test.rb +0 -79
@@ -0,0 +1,181 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "test_helper"
4
+
5
+ class StimulusReflex::ElementTest < ActiveSupport::TestCase
6
+ element = StimulusReflex::Element.new({
7
+ "attrs" => {
8
+ "user" => "First User",
9
+ "user-id" => "1"
10
+ },
11
+ "dataset" => {
12
+ "dataset" => {
13
+ "data-post" => "The Post",
14
+ "data-post-id" => "2"
15
+ },
16
+ "datasetAll" => {}
17
+ }
18
+ })
19
+
20
+ test "should be able to access attributes on element itself" do
21
+ assert_equal "First User", element.user
22
+ assert_equal "First User", element["user"]
23
+ assert_equal "First User", element[:user]
24
+
25
+ assert_equal "1", element.user_id
26
+ assert_equal "1", element["user_id"]
27
+ assert_equal "1", element["user-id"]
28
+ assert_equal "1", element[:user_id]
29
+
30
+ assert_equal "The Post", element.data_post
31
+ assert_equal "The Post", element["data_post"]
32
+ assert_equal "The Post", element["data-post"]
33
+ assert_equal "The Post", element[:data_post]
34
+
35
+ assert_equal "2", element.data_post_id
36
+ assert_equal "2", element["data_post_id"]
37
+ assert_equal "2", element["data-post-id"]
38
+ assert_equal "2", element[:data_post_id]
39
+ end
40
+
41
+ test "should be able to access attributes via attributes" do
42
+ assert_equal "First User", element.attributes.user
43
+ assert_equal "First User", element.attributes["user"]
44
+ assert_equal "First User", element.attributes[:user]
45
+
46
+ assert_equal "1", element.attributes.user_id
47
+ assert_equal "1", element.attributes["user_id"]
48
+ assert_equal "1", element.attributes["user-id"]
49
+ assert_equal "1", element.attributes[:user_id]
50
+ end
51
+
52
+ test "should be able to access attributes via dataset" do
53
+ assert_equal "The Post", element.dataset.post
54
+ assert_equal "The Post", element.dataset["post"]
55
+ assert_equal "The Post", element.dataset[:post]
56
+
57
+ assert_equal "2", element.dataset.post_id
58
+ assert_equal "2", element.dataset["post-id"]
59
+ assert_equal "2", element.dataset["post_id"]
60
+ assert_equal "2", element.dataset[:post_id]
61
+ end
62
+
63
+ test "should be able to access attributes via data_attributes" do
64
+ assert_equal "The Post", element.data_attributes.post
65
+ assert_equal "The Post", element.data_attributes["post"]
66
+ assert_equal "The Post", element.data_attributes[:post]
67
+
68
+ assert_equal "2", element.data_attributes.post_id
69
+ assert_equal "2", element.data_attributes["post-id"]
70
+ assert_equal "2", element.data_attributes["post_id"]
71
+ assert_equal "2", element.data_attributes[:post_id]
72
+ end
73
+
74
+ test "should pluralize keys from datasetAll" do
75
+ data = {
76
+ "dataset" => {
77
+ "dataset" => {
78
+ "data-reflex" => "click",
79
+ "data-sex" => "male"
80
+ },
81
+ "datasetAll" => {
82
+ "data-reflex" => ["click"],
83
+ "data-post-id" => ["1", "2", "3", "4"],
84
+ "data-name" => ["steve", "bill", "steve", "mike"]
85
+ }
86
+ }
87
+ }
88
+
89
+ dataset_all_element = StimulusReflex::Element.new(data)
90
+
91
+ assert_equal "click", dataset_all_element.dataset.reflex
92
+ assert_equal "male", dataset_all_element.dataset.sex
93
+
94
+ assert_equal ["steve", "bill", "steve", "mike"], dataset_all_element.dataset.names
95
+ assert_equal ["1", "2", "3", "4"], dataset_all_element.dataset.post_ids
96
+ assert_equal ["click"], dataset_all_element.dataset.reflexes
97
+ end
98
+
99
+ test "should pluralize irregular words from datasetAll" do
100
+ data = {
101
+ "dataset" => {
102
+ "dataset" => {},
103
+ "datasetAll" => {
104
+ "data-cat" => ["cat"],
105
+ "data-child" => ["child"],
106
+ "data-women" => ["woman"],
107
+ "data-man" => ["man"],
108
+ "data-wolf" => ["wolf"],
109
+ "data-library" => ["library"],
110
+ "data-mouse" => ["mouse"]
111
+ }
112
+ }
113
+ }
114
+
115
+ pluralize_element = StimulusReflex::Element.new(data)
116
+
117
+ assert_equal ["cat"], pluralize_element.dataset.cats
118
+ assert_equal ["child"], pluralize_element.dataset.children
119
+ assert_equal ["woman"], pluralize_element.dataset.women
120
+ assert_equal ["man"], pluralize_element.dataset.men
121
+ assert_equal ["wolf"], pluralize_element.dataset.wolves
122
+ assert_equal ["library"], pluralize_element.dataset.libraries
123
+ assert_equal ["mouse"], pluralize_element.dataset.mice
124
+ end
125
+
126
+ test "should not pluralize plural key" do
127
+ data = {
128
+ "dataset" => {
129
+ "datasetAll" => {
130
+ "data-ids" => ["1", "2"]
131
+ }
132
+ }
133
+ }
134
+
135
+ assert_equal ["1", "2"], StimulusReflex::Element.new(data).dataset.ids
136
+ assert_nil StimulusReflex::Element.new(data).dataset.idss
137
+ end
138
+
139
+ test "should not build array with pluralized key" do
140
+ data = {
141
+ "dataset" => {
142
+ "dataset" => {
143
+ "data-ids" => "1"
144
+ }
145
+ }
146
+ }
147
+
148
+ assert_equal "1", StimulusReflex::Element.new(data).dataset.ids
149
+ end
150
+
151
+ test "should handle overlapping singluar and plural key names" do
152
+ data = {
153
+ "dataset" => {
154
+ "dataset" => {
155
+ "data-id" => "1",
156
+ "data-ids" => "2",
157
+ "data-post-id" => "9",
158
+ "data-post-ids" => "10",
159
+ "data-duplicate-value" => "19",
160
+ "data-duplicate-values" => "20"
161
+ },
162
+ "datasetAll" => {
163
+ "data-id" => ["3", "4"],
164
+ "data-post-ids" => ["11", "12"],
165
+ "data-duplicate-value" => ["20", "21", "22"]
166
+ }
167
+ }
168
+ }
169
+
170
+ overlapping_keys_element = StimulusReflex::Element.new(data)
171
+
172
+ assert_equal "1", overlapping_keys_element.dataset.id
173
+ assert_equal ["2", "3", "4"], overlapping_keys_element.dataset.ids
174
+
175
+ assert_equal "9", overlapping_keys_element.dataset.post_id
176
+ assert_equal ["10", "11", "12"], overlapping_keys_element.dataset.post_ids
177
+
178
+ assert_equal "19", overlapping_keys_element.dataset.duplicate_value
179
+ assert_equal ["20", "20", "21", "22"], overlapping_keys_element.dataset.duplicate_values
180
+ end
181
+ end
data/test/reflex_test.rb CHANGED
@@ -10,7 +10,7 @@ class StimulusReflex::ReflexTest < ActionCable::Channel::TestCase
10
10
  def connection.env
11
11
  @env ||= {}
12
12
  end
13
- @reflex = StimulusReflex::Reflex.new(subscribe, url: "https://test.stimulusreflex.com")
13
+ @reflex = StimulusReflex::Reflex.new(subscribe, url: "https://test.stimulusreflex.com", client_attributes: {reflex_id: "666"})
14
14
  @reflex.controller_class.view_paths << Rails.root.join("test/views")
15
15
  end
16
16
 
data/test/test_helper.rb CHANGED
@@ -5,6 +5,7 @@ ENV["RAILS_ENV"] ||= "test"
5
5
  require "minitest/mock"
6
6
  require "rails"
7
7
  require "active_model"
8
+ require "active_record"
8
9
  require "action_controller"
9
10
  require "pry"
10
11
  require_relative "../lib/stimulus_reflex"
@@ -29,40 +30,6 @@ class SessionMock
29
30
  end
30
31
  end
31
32
 
32
- class ApplicationReflex < StimulusReflex::Reflex
33
- def application_reflex
34
- end
35
-
36
- private
37
-
38
- def private_application_reflex
39
- end
40
- end
41
-
42
- class PostReflex < ApplicationReflex
43
- def post_reflex
44
- end
45
-
46
- private
47
-
48
- def private_post_reflex
49
- end
50
- end
51
-
52
- class NoReflex
53
- def no_reflex
54
- end
55
- end
56
-
57
- module CounterConcern
58
- def increment
59
- end
60
- end
61
-
62
- class CounterReflex < ApplicationReflex
63
- include CounterConcern
64
- end
65
-
66
33
  class ActionDispatch::Request
67
34
  def session
68
35
  @session ||= SessionMock.new
@@ -72,6 +39,9 @@ end
72
39
  class TestModel
73
40
  include ActiveModel::Model
74
41
  attr_accessor :id
42
+ def is_a?(klass)
43
+ klass == ActiveRecord::Base
44
+ end
75
45
  end
76
46
 
77
47
  StimulusReflex.configuration.parent_channel = "ActionCable::Channel::Base"
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ApplicationReflex < StimulusReflex::Reflex
4
+ # Put application-wide Reflex behavior and callbacks in this file.
5
+ #
6
+ # Example:
7
+ #
8
+ # # If your ActionCable connection is: `identified_by :current_user`
9
+ # delegate :current_user, to: :connection
10
+ #
11
+ # Learn more at: https://docs.stimulusreflex.com/rtfm/reflex-classes
12
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UserReflex < ApplicationReflex
4
+ # Add Reflex methods in this file.
5
+ #
6
+ # All Reflex instances include CableReady::Broadcaster and expose the following properties:
7
+ #
8
+ # - connection - the ActionCable connection
9
+ # - channel - the ActionCable channel
10
+ # - request - an ActionDispatch::Request proxy for the socket connection
11
+ # - session - the ActionDispatch::Session store for the current visitor
12
+ # - flash - the ActionDispatch::Flash::FlashHash for the current request
13
+ # - url - the URL of the page that triggered the reflex
14
+ # - params - parameters from the element's closest form (if any)
15
+ # - element - a Hash like object that represents the HTML element that triggered the reflex
16
+ # - signed - use a signed Global ID to map dataset attribute to a model eg. element.signed[:foo]
17
+ # - unsigned - use an unsigned Global ID to map dataset attribute to a model eg. element.unsigned[:foo]
18
+ # - cable_ready - a special cable_ready that can broadcast to the current visitor (no brackets needed)
19
+ # - reflex_id - a UUIDv4 that uniquely identies each Reflex
20
+ # - tab_id - a UUIDv4 that uniquely identifies the browser tab
21
+ #
22
+ # Example:
23
+ #
24
+ # before_reflex do
25
+ # # throw :abort # this will prevent the Reflex from continuing
26
+ # # learn more about callbacks at https://docs.stimulusreflex.com/rtfm/lifecycle
27
+ # end
28
+ #
29
+ # def example(argument=true)
30
+ # # Your logic here...
31
+ # # Any declared instance variables will be made available to the Rails controller and view.
32
+ # end
33
+ #
34
+ # Learn more at: https://docs.stimulusreflex.com/rtfm/reflex-classes
35
+
36
+ def update
37
+ end
38
+
39
+ def do_stuff
40
+ end
41
+
42
+ def do_more_stuff
43
+ end
44
+ end