stimulus_reflex 3.4.1 → 3.5.0.pre3

Sign up to get free protection for your applications and to get access to all the features.

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