stimulus_reflex 3.4.1 → 3.5.0.pre3

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 (53) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +664 -495
  3. data/Gemfile.lock +99 -95
  4. data/LATEST +1 -0
  5. data/README.md +17 -16
  6. data/app/channels/stimulus_reflex/channel.rb +44 -75
  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/stimulus_reflex_generator.rb +5 -4
  10. data/lib/generators/stimulus_reflex/templates/app/reflexes/%file_name%_reflex.rb.tt +3 -2
  11. data/lib/generators/stimulus_reflex/templates/app/reflexes/application_reflex.rb.tt +11 -4
  12. data/lib/generators/stimulus_reflex/templates/config/initializers/stimulus_reflex.rb +21 -1
  13. data/lib/stimulus_reflex/broadcasters/broadcaster.rb +22 -18
  14. data/lib/stimulus_reflex/broadcasters/nothing_broadcaster.rb +6 -1
  15. data/lib/stimulus_reflex/broadcasters/page_broadcaster.rb +3 -5
  16. data/lib/stimulus_reflex/broadcasters/selector_broadcaster.rb +22 -16
  17. data/lib/stimulus_reflex/broadcasters/update.rb +23 -0
  18. data/lib/stimulus_reflex/cable_ready_channels.rb +10 -2
  19. data/lib/stimulus_reflex/callbacks.rb +55 -5
  20. data/lib/stimulus_reflex/concern_enhancer.rb +37 -0
  21. data/lib/stimulus_reflex/configuration.rb +4 -1
  22. data/lib/stimulus_reflex/dataset.rb +34 -0
  23. data/lib/stimulus_reflex/element.rb +20 -13
  24. data/lib/stimulus_reflex/policies/reflex_invocation_policy.rb +28 -0
  25. data/lib/stimulus_reflex/reflex.rb +41 -21
  26. data/lib/stimulus_reflex/reflex_data.rb +79 -0
  27. data/lib/stimulus_reflex/reflex_factory.rb +31 -0
  28. data/lib/stimulus_reflex/request_parameters.rb +19 -0
  29. data/lib/stimulus_reflex/utils/attribute_builder.rb +17 -0
  30. data/lib/stimulus_reflex/{logger.rb → utils/logger.rb} +6 -4
  31. data/lib/stimulus_reflex/utils/sanity_checker.rb +210 -0
  32. data/lib/stimulus_reflex/version.rb +1 -1
  33. data/lib/stimulus_reflex.rb +10 -2
  34. data/lib/tasks/stimulus_reflex/install.rake +54 -15
  35. data/test/broadcasters/broadcaster_test.rb +0 -1
  36. data/test/broadcasters/broadcaster_test_case.rb +25 -1
  37. data/test/broadcasters/nothing_broadcaster_test.rb +14 -20
  38. data/test/broadcasters/page_broadcaster_test.rb +31 -29
  39. data/test/broadcasters/selector_broadcaster_test.rb +165 -55
  40. data/test/callbacks_test.rb +652 -0
  41. data/test/concern_enhancer_test.rb +54 -0
  42. data/test/element_test.rb +254 -0
  43. data/test/generators/stimulus_reflex_generator_test.rb +8 -0
  44. data/test/reflex_test.rb +12 -1
  45. data/test/test_helper.rb +25 -1
  46. data/test/tmp/app/reflexes/application_reflex.rb +10 -3
  47. data/test/tmp/app/reflexes/{user_reflex.rb → demo_reflex.rb} +4 -12
  48. metadata +65 -36
  49. data/lib/stimulus_reflex/sanity_checker.rb +0 -154
  50. data/package.json +0 -57
  51. data/stimulus_reflex.gemspec +0 -42
  52. data/tags +0 -156
  53. data/yarn.lock +0 -4687
@@ -0,0 +1,79 @@
1
+ class StimulusReflex::ReflexData
2
+ attr_reader :data
3
+
4
+ def initialize(data)
5
+ @data = data
6
+ end
7
+
8
+ def reflex_name
9
+ reflex_name = target.split("#").first
10
+ reflex_name = reflex_name.camelize
11
+ reflex_name.end_with?("Reflex") ? reflex_name : "#{reflex_name}Reflex"
12
+ end
13
+
14
+ def selectors
15
+ selectors = (data["selectors"] || []).select(&:present?)
16
+ selectors = data["selectors"] = ["body"] if selectors.blank?
17
+ selectors
18
+ end
19
+
20
+ def target
21
+ data["target"].to_s
22
+ end
23
+
24
+ def method_name
25
+ target.split("#").second
26
+ end
27
+
28
+ def arguments
29
+ (data["args"] || []).map { |arg| object_with_indifferent_access arg } || []
30
+ end
31
+
32
+ def url
33
+ data["url"].to_s
34
+ end
35
+
36
+ def element
37
+ StimulusReflex::Element.new(data)
38
+ end
39
+
40
+ def permanent_attribute_name
41
+ data["permanentAttributeName"]
42
+ end
43
+
44
+ def form_data
45
+ Rack::Utils.parse_nested_query(data["formData"])
46
+ end
47
+
48
+ def form_params
49
+ form_data.deep_merge(data["params"] || {})
50
+ end
51
+
52
+ def reflex_id
53
+ data["reflexId"]
54
+ end
55
+
56
+ def tab_id
57
+ data["tabId"]
58
+ end
59
+
60
+ def xpath_controller
61
+ data["xpathController"]
62
+ end
63
+
64
+ def xpath_element
65
+ data["xpathElement"]
66
+ end
67
+
68
+ def reflex_controller
69
+ data["reflexController"]
70
+ end
71
+
72
+ private
73
+
74
+ def object_with_indifferent_access(object)
75
+ return object.with_indifferent_access if object.respond_to?(:with_indifferent_access)
76
+ object.map! { |obj| object_with_indifferent_access obj } if object.is_a?(Array)
77
+ object
78
+ end
79
+ end
@@ -0,0 +1,31 @@
1
+ class StimulusReflex::ReflexFactory
2
+ class << self
3
+ attr_reader :reflex_data
4
+
5
+ def create_reflex_from_data(channel, reflex_data)
6
+ @reflex_data = reflex_data
7
+ reflex_class.new(channel,
8
+ url: reflex_data.url,
9
+ element: reflex_data.element,
10
+ selectors: reflex_data.selectors,
11
+ method_name: reflex_data.method_name,
12
+ params: reflex_data.form_params,
13
+ client_attributes: {
14
+ reflex_id: reflex_data.reflex_id,
15
+ tab_id: reflex_data.tab_id,
16
+ xpath_controller: reflex_data.xpath_controller,
17
+ xpath_element: reflex_data.xpath_element,
18
+ reflex_controller: reflex_data.reflex_controller,
19
+ permanent_attribute_name: reflex_data.permanent_attribute_name
20
+ })
21
+ end
22
+
23
+ def reflex_class
24
+ reflex_data.reflex_name.constantize.tap { |klass| raise ArgumentError.new("#{reflex_name} is not a StimulusReflex::Reflex") unless is_reflex?(klass) }
25
+ end
26
+
27
+ def is_reflex?(klass)
28
+ klass.ancestors.include? StimulusReflex::Reflex
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,19 @@
1
+ module StimulusReflex
2
+ class RequestParameters
3
+ def initialize(params:, req:, url:)
4
+ @params = params
5
+ @req = req
6
+ @url = url
7
+ end
8
+
9
+ def apply!
10
+ path_params = Rails.application.routes.recognize_path_with_request(@req, @url, @req.env[:extras] || {})
11
+ path_params[:controller] = path_params[:controller].force_encoding("UTF-8")
12
+ path_params[:action] = path_params[:action].force_encoding("UTF-8")
13
+
14
+ @req.env.merge(ActionDispatch::Http::Parameters::PARAMETERS_KEY => path_params)
15
+ @req.env["action_dispatch.request.parameters"] = @req.parameters.merge(@params)
16
+ @req.tap { |r| r.session.send :load! }
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module StimulusReflex::AttributeBuilder
4
+ def build_data_attrs(dataset, dataset_all)
5
+ dataset_all.transform_keys! { |key| "data-#{key.delete_prefix("data-").pluralize}" }
6
+
7
+ dataset.each { |key, value| dataset_all[key]&.prepend(value) }
8
+
9
+ data_attrs = dataset.merge(dataset_all)
10
+
11
+ HashWithIndifferentAccess.new(data_attrs || {})
12
+ end
13
+
14
+ def build_underscored(attrs)
15
+ attrs.merge(attrs.transform_keys(&:underscore))
16
+ end
17
+ end
@@ -2,22 +2,24 @@
2
2
 
3
3
  module StimulusReflex
4
4
  class Logger
5
+ attr_reader :logger
5
6
  attr_accessor :reflex, :current_operation
6
7
 
8
+ delegate :debug, :info, :warn, :error, :fatal, :unknown, to: :logger
9
+
7
10
  def initialize(reflex)
8
11
  @reflex = reflex
9
12
  @current_operation = 1
13
+ @logger = StimulusReflex.config.logger
10
14
  end
11
15
 
12
- def print
16
+ def log_all_operations
13
17
  return unless config_logging.instance_of?(Proc)
14
18
 
15
- puts
16
19
  reflex.broadcaster.operations.each do
17
- puts instance_eval(&config_logging) + "\e[0m"
20
+ logger.info instance_eval(&config_logging) + "\e[0m"
18
21
  @current_operation += 1
19
22
  end
20
- puts
21
23
  end
22
24
 
23
25
  private
@@ -0,0 +1,210 @@
1
+ # frozen_string_literal: true
2
+
3
+ class StimulusReflex::SanityChecker
4
+ LATEST_VERSION_FORMAT = /^(\d+\.\d+\.\d+)$/
5
+ NODE_VERSION_FORMAT = /(\d+\.\d+\.\d+.*):/
6
+ JSON_VERSION_FORMAT = /(\d+\.\d+\.\d+.*)"/
7
+
8
+ class << self
9
+ def check!
10
+ return if ENV["SKIP_SANITY_CHECK"]
11
+ return if StimulusReflex.config.on_failed_sanity_checks == :ignore
12
+ return if called_by_installer?
13
+ return if called_by_generate_config?
14
+ return if called_by_rake?
15
+
16
+ instance = new
17
+ instance.check_caching_enabled
18
+ instance.check_package_versions_match
19
+ # instance.check_default_url_config
20
+ instance.check_new_version_available
21
+ end
22
+
23
+ private
24
+
25
+ def called_by_installer?
26
+ Rake.application.top_level_tasks.include? "stimulus_reflex:install"
27
+ rescue
28
+ false
29
+ end
30
+
31
+ def called_by_generate_config?
32
+ ARGV.include? "stimulus_reflex:initializer"
33
+ end
34
+
35
+ def called_by_rake?
36
+ File.basename($PROGRAM_NAME) == "rake"
37
+ end
38
+ end
39
+
40
+ def check_caching_enabled
41
+ if caching_not_enabled?
42
+ warn_and_exit <<~WARN
43
+ 👉 StimulusReflex requires caching to be enabled. Caching allows the session to be modified during ActionCable requests.
44
+
45
+ To enable caching in development, run:
46
+
47
+ rails dev:cache
48
+ WARN
49
+ end
50
+
51
+ if using_null_store?
52
+ warn_and_exit <<~WARN
53
+ 👉 StimulusReflex requires caching to be enabled.
54
+
55
+ Caching allows the session to be modified during ActionCable requests. Your config.cache_store is set to :null_store, so it won't work.
56
+ WARN
57
+ end
58
+ end
59
+
60
+ def check_default_url_config
61
+ return if StimulusReflex.config.on_missing_default_urls == :ignore
62
+ if default_url_config_set? == false
63
+ puts <<~WARN
64
+ 👉 StimulusReflex strongly suggests that you set default_url_options in your environment files. Otherwise, ActionController #{"and ActionMailer " if defined?(ActionMailer)}will default to example.com when rendering route helpers.
65
+
66
+ You can set your URL options in config/environments/#{Rails.env}.rb
67
+
68
+ config.action_controller.default_url_options = {host: "localhost", port: 3000}
69
+ #{"config.action_mailer.default_url_options = {host: \"localhost\", port: 3000}\n" if defined?(ActionMailer)}
70
+ Please update every environment with the appropriate URL. Typically, no port is necessary in production.
71
+
72
+ WARN
73
+ end
74
+ end
75
+
76
+ def check_package_versions_match
77
+ if npm_version.nil?
78
+ warn_and_exit <<~WARN
79
+ 👉 Can't locate the stimulus_reflex npm package.
80
+
81
+ yarn add stimulus_reflex@#{gem_version}
82
+
83
+ Either add it to your package.json as a dependency or use "yarn link stimulus_reflex" if you are doing development.
84
+ WARN
85
+ end
86
+
87
+ if package_version_mismatch?
88
+ warn_and_exit <<~WARN
89
+ 👉 The stimulus_reflex npm package version (#{npm_version}) does not match the Rubygem version (#{gem_version}).
90
+
91
+ To update the stimulus_reflex npm package:
92
+
93
+ yarn upgrade stimulus_reflex@#{gem_version}
94
+ WARN
95
+ end
96
+ end
97
+
98
+ def check_new_version_available
99
+ return if StimulusReflex.config.on_new_version_available == :ignore
100
+ return if Rails.env.development? == false
101
+ return if using_preview_release?
102
+ begin
103
+ latest_version = URI.open("https://raw.githubusercontent.com/stimulusreflex/stimulus_reflex/master/LATEST", open_timeout: 1, read_timeout: 1).read.strip
104
+ if latest_version != StimulusReflex::VERSION
105
+ puts <<~WARN
106
+
107
+ 👉 There is a new version of StimulusReflex available!
108
+ Current: #{StimulusReflex::VERSION} Latest: #{latest_version}
109
+
110
+ If you upgrade, it is very important that you update BOTH Gemfile and package.json
111
+ Then, run `bundle install && yarn install` to update to #{latest_version}.
112
+
113
+ WARN
114
+ exit if StimulusReflex.config.on_new_version_available == :exit
115
+ end
116
+ rescue
117
+ puts "👉 StimulusReflex #{StimulusReflex::VERSION} update check skipped: connection timeout"
118
+ end
119
+ end
120
+
121
+ def caching_not_enabled?
122
+ Rails.application.config.action_controller.perform_caching == false
123
+ end
124
+
125
+ def using_null_store?
126
+ Rails.application.config.cache_store == :null_store
127
+ end
128
+
129
+ def default_url_config_set?
130
+ if defined?(ActionMailer)
131
+ Rails.application.config.action_controller.default_url_options.blank? && Rails.application.config.action_mailer.default_url_options.blank?
132
+ else
133
+ Rails.application.config.action_controller.default_url_options.blank?
134
+ end
135
+ end
136
+
137
+ def package_version_mismatch?
138
+ npm_version != gem_version
139
+ end
140
+
141
+ def using_preview_release?
142
+ preview = StimulusReflex::VERSION.match?(LATEST_VERSION_FORMAT) == false
143
+ puts "👉 StimulusReflex #{StimulusReflex::VERSION} update check skipped: pre-release build" if preview
144
+ preview
145
+ end
146
+
147
+ def gem_version
148
+ @_gem_version ||= StimulusReflex::VERSION.gsub(".pre", "-pre")
149
+ end
150
+
151
+ def npm_version
152
+ @_npm_version ||= find_npm_version
153
+ end
154
+
155
+ def find_npm_version
156
+ if (match = search_file(package_json_path, regex: /version/))
157
+ match[JSON_VERSION_FORMAT, 1]
158
+ elsif (match = search_file(yarn_lock_path, regex: /^stimulus_reflex/))
159
+ match[NODE_VERSION_FORMAT, 1]
160
+ end
161
+ end
162
+
163
+ def search_file(path, regex:)
164
+ return if File.exist?(path) == false
165
+ File.foreach(path).grep(regex).first
166
+ end
167
+
168
+ def package_json_path
169
+ Rails.root.join("node_modules", "stimulus_reflex", "package.json")
170
+ end
171
+
172
+ def yarn_lock_path
173
+ Rails.root.join("yarn.lock")
174
+ end
175
+
176
+ def initializer_missing?
177
+ File.exist?(Rails.root.join("config", "initializers", "stimulus_reflex.rb")) == false
178
+ end
179
+
180
+ def warn_and_exit(text)
181
+ puts
182
+ puts "Heads up! 🔥"
183
+ puts
184
+ puts text
185
+ puts
186
+ if StimulusReflex.config.on_failed_sanity_checks == :exit
187
+ puts <<~INFO
188
+ To ignore any warnings and start the application anyway, you can set the SKIP_SANITY_CHECK environment variable:
189
+
190
+ SKIP_SANITY_CHECK=true rails
191
+
192
+ To do this permanently, add the following directive to the StimulusReflex initializer:
193
+
194
+ StimulusReflex.configure do |config|
195
+ config.on_failed_sanity_checks = :warn
196
+ end
197
+
198
+ INFO
199
+ if initializer_missing?
200
+ puts <<~INFO
201
+ You can create a StimulusReflex initializer with the command:
202
+
203
+ bundle exec rails generate stimulus_reflex:initializer
204
+
205
+ INFO
206
+ end
207
+ exit false if Rails.env.test? == false
208
+ end
209
+ end
210
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module StimulusReflex
4
- VERSION = "3.4.1"
4
+ VERSION = "3.5.0.pre3"
5
5
  end
@@ -1,26 +1,34 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "uri"
4
+ require "open-uri"
4
5
  require "rack"
5
6
  require "rails/engine"
6
7
  require "active_support/all"
7
8
  require "action_dispatch"
8
9
  require "action_cable"
10
+ require "action_view"
9
11
  require "nokogiri"
10
12
  require "cable_ready"
11
13
  require "stimulus_reflex/version"
12
14
  require "stimulus_reflex/cable_ready_channels"
15
+ require "stimulus_reflex/concern_enhancer"
13
16
  require "stimulus_reflex/configuration"
14
17
  require "stimulus_reflex/callbacks"
18
+ require "stimulus_reflex/request_parameters"
15
19
  require "stimulus_reflex/reflex"
20
+ require "stimulus_reflex/reflex_data"
21
+ require "stimulus_reflex/reflex_factory"
16
22
  require "stimulus_reflex/element"
17
- require "stimulus_reflex/sanity_checker"
18
23
  require "stimulus_reflex/broadcasters/broadcaster"
19
24
  require "stimulus_reflex/broadcasters/nothing_broadcaster"
20
25
  require "stimulus_reflex/broadcasters/page_broadcaster"
21
26
  require "stimulus_reflex/broadcasters/selector_broadcaster"
27
+ require "stimulus_reflex/broadcasters/update"
28
+ require "stimulus_reflex/policies/reflex_invocation_policy"
22
29
  require "stimulus_reflex/utils/colorize"
23
- require "stimulus_reflex/logger"
30
+ require "stimulus_reflex/utils/logger"
31
+ require "stimulus_reflex/utils/sanity_checker"
24
32
 
25
33
  module StimulusReflex
26
34
  class Engine < Rails::Engine
@@ -4,7 +4,7 @@ require "fileutils"
4
4
  require "stimulus_reflex/version"
5
5
 
6
6
  namespace :stimulus_reflex do
7
- desc "Install StimulusReflex in this application"
7
+ desc "Install StimulusReflex in this application"
8
8
  task install: :environment do
9
9
  system "rails dev:cache" unless Rails.root.join("tmp", "caching-dev.txt").exist?
10
10
  gem_version = StimulusReflex::VERSION.gsub(".pre", "-pre")
@@ -25,8 +25,8 @@ namespace :stimulus_reflex do
25
25
  .map { |path| Rails.root.join(path) }
26
26
  .first
27
27
 
28
- puts "Updating #{filepath}"
29
- lines = File.open(filepath, "r") { |f| f.readlines }
28
+ puts "Updating #{filepath}"
29
+ lines = File.readlines(filepath)
30
30
 
31
31
  unless lines.find { |line| line.start_with?("import StimulusReflex") }
32
32
  matches = lines.select { |line| line =~ /\A(require|import)/ }
@@ -44,34 +44,73 @@ namespace :stimulus_reflex do
44
44
  end
45
45
 
46
46
  initialize_line = lines.find { |line| line.start_with?("StimulusReflex.initialize") }
47
- lines << "StimulusReflex.initialize(application, { consumer, controller, isolate: true })\n" unless initialize_line
47
+ lines << "application.consumer = consumer\n"
48
+ lines << "StimulusReflex.initialize(application, { controller, isolate: true })\n" unless initialize_line
48
49
  lines << "StimulusReflex.debug = process.env.RAILS_ENV === 'development'\n" unless initialize_line
49
- File.open(filepath, "w") { |f| f.write lines.join }
50
+ File.write(filepath, lines.join)
50
51
 
52
+ puts
53
+ puts "✨ Updating config/environments/development.rb"
51
54
  filepath = Rails.root.join("config/environments/development.rb")
52
- lines = File.open(filepath, "r") { |f| f.readlines }
55
+ lines = File.readlines(filepath)
53
56
  unless lines.find { |line| line.include?("config.session_store") }
54
- lines.insert 3, " config.session_store :cache_store\n\n"
55
- File.open(filepath, "w") { |f| f.write lines.join }
57
+ matches = lines.select { |line| line =~ /\A(Rails.application.configure do)/ }
58
+ lines.insert lines.index(matches.last).to_i + 1, " config.session_store :cache_store\n\n"
59
+ puts
60
+ puts "✨ Using :cache_store for session storage. We recommend switching to Redis for cache and session storage."
61
+ puts
62
+ puts "https://docs.stimulusreflex.com/appendices/deployment#use-redis-as-your-cache-store"
63
+ File.write(filepath, lines.join)
64
+ end
65
+
66
+ if defined?(ActionMailer)
67
+ lines = File.readlines(filepath)
68
+ unless lines.find { |line| line.include?("config.action_mailer.default_url_options") }
69
+ matches = lines.select { |line| line =~ /\A(Rails.application.configure do)/ }
70
+ lines.insert lines.index(matches.last).to_i + 1, " config.action_mailer.default_url_options = {host: \"localhost\", port: 3000}\n\n"
71
+ File.write(filepath, lines.join)
72
+ end
56
73
  end
57
74
 
75
+ lines = File.readlines(filepath)
76
+ unless lines.find { |line| line.include?("config.action_controller.default_url_options") }
77
+ matches = lines.select { |line| line =~ /\A(Rails.application.configure do)/ }
78
+ lines.insert lines.index(matches.last).to_i + 1, " config.action_controller.default_url_options = {host: \"localhost\", port: 3000}\n"
79
+ File.write(filepath, lines.join)
80
+ end
81
+
82
+ puts
83
+ puts "✨ Updating config/cable.yml to use Redis in development"
58
84
  filepath = Rails.root.join("config/cable.yml")
59
- lines = File.open(filepath, "r") { |f| f.readlines }
85
+ lines = File.readlines(filepath)
60
86
  if lines[1].include?("adapter: async")
61
87
  lines.delete_at 1
62
88
  lines.insert 1, " adapter: redis\n"
63
89
  lines.insert 2, " url: <%= ENV.fetch(\"REDIS_URL\") { \"redis://localhost:6379/1\" } %>\n"
64
- lines.insert 3, " channel_prefix: " + File.basename(Rails.root.to_s).underscore + "_development\n"
65
- File.open(filepath, "w") { |f| f.write lines.join }
90
+ lines.insert 3, " channel_prefix: " + File.basename(Rails.root.to_s).tr("\\", "").tr("-. ", "_").underscore + "_development\n"
91
+ File.write(filepath, lines.join)
66
92
  end
67
93
 
94
+ puts
95
+ puts "✨ Generating default StimulusReflex and CableReady configuration files"
96
+ puts
97
+ system "bundle exec rails generate stimulus_reflex:initializer"
98
+ system "bundle exec rails generate cable_ready:initializer"
99
+ system "bundle exec rails generate cable_ready:helpers"
100
+
101
+ puts
102
+ puts "✨ Generating ApplicationReflex class and Stimulus controllers, plus an example Reflex class and controller"
103
+ puts
68
104
  system "bundle exec rails generate stimulus_reflex example"
69
- puts "Generating default StimulusReflex configuration file into your application config/initializers directory"
70
- system "bundle exec rails generate stimulus_reflex:config"
71
105
 
72
106
  puts
73
- puts "StimulusReflex and CableReady have been successfully installed!"
74
- puts "Go to https://docs.stimulusreflex.com/quickstart if you need help getting started."
107
+ puts "🎉 StimulusReflex and CableReady have been successfully installed! 🎉"
108
+ puts
109
+ puts "https://docs.stimulusreflex.com/hello-world/quickstart"
110
+ puts
111
+ puts "😊 The fastest way to get support is to say hello on Discord:"
112
+ puts
113
+ puts "https://discord.gg/stimulus-reflex"
75
114
  puts
76
115
  end
77
116
  end
@@ -7,6 +7,5 @@ class StimulusReflex::BroadcasterTest < StimulusReflex::BroadcasterTestCase
7
7
  broadcaster = StimulusReflex::Broadcaster.new(@reflex)
8
8
 
9
9
  assert_raises(NotImplementedError) { broadcaster.broadcast }
10
- assert_raises(NotImplementedError) { broadcaster.broadcast_message(subject: "Test") }
11
10
  end
12
11
  end
@@ -5,11 +5,35 @@ require_relative "../test_helper"
5
5
  class StimulusReflex::BroadcasterTestCase < ActionCable::Channel::TestCase
6
6
  tests StimulusReflex::Channel
7
7
 
8
+ def assert_broadcast_on(stream, data, &block)
9
+ serialized_msg = ActiveSupport::JSON.decode(ActiveSupport::JSON.encode(data))
10
+
11
+ new_messages = broadcasts(stream)
12
+ if block
13
+ old_messages = new_messages
14
+ clear_messages(stream)
15
+
16
+ yield
17
+ new_messages = broadcasts(stream)
18
+ clear_messages(stream)
19
+
20
+ (old_messages + new_messages).each { |m| pubsub_adapter.broadcast(stream, m) }
21
+ end
22
+
23
+ message = new_messages.find { |msg| ActiveSupport::JSON.decode(msg) == serialized_msg }
24
+
25
+ unless message
26
+ puts "\n\n#{ActiveSupport::JSON.decode(new_messages.first)}\n#{data}\n\n"
27
+ end
28
+
29
+ assert message, "No messages sent with #{data} to #{stream}"
30
+ end
31
+
8
32
  setup do
9
33
  stub_connection(session_id: SecureRandom.uuid)
10
34
  def connection.env
11
35
  @env ||= {}
12
36
  end
13
- @reflex = StimulusReflex::Reflex.new(subscribe, url: "https://test.stimulusreflex.com")
37
+ @reflex = StimulusReflex::Reflex.new(subscribe, url: "https://test.stimulusreflex.com", client_attributes: {reflex_id: "666"})
14
38
  end
15
39
  end
@@ -3,33 +3,27 @@
3
3
  require_relative "broadcaster_test_case"
4
4
 
5
5
  class StimulusReflex::NothingBroadcasterTest < StimulusReflex::BroadcasterTestCase
6
- test "broadcasts a server message when called" do
6
+ test "broadcasts a nothing morph when called" do
7
7
  broadcaster = StimulusReflex::NothingBroadcaster.new(@reflex)
8
8
 
9
9
  expected = {
10
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
- }
11
+ "operations" => [
12
+ {
13
+ "name" => "stimulus-reflex:morph-nothing",
14
+ "payload" => {},
15
+ "stimulusReflex" => {
16
+ "some" => "data",
17
+ "morph" => "nothing"
18
+ },
19
+ "reflexId" => "666",
20
+ "operation" => "dispatchEvent"
21
+ }
22
+ ]
29
23
  }
30
24
 
31
25
  assert_broadcast_on @reflex.stream_name, expected do
32
- broadcaster.broadcast nil, some: :data
26
+ broadcaster.broadcast nil, {some: :data}
33
27
  end
34
28
  end
35
29
  end