Skip to content

Commit e9b6697

Browse files
committed
Fixes a gnarly test bug with server side rendering
Background: Running tests multiple times in a row could result in errors, and could result in complete passing. In other words, the order the tests ran in determined whether or not the tests would pass. Ruby Test::Unit uses a psuedorandom seed to randomize the order that tests are run in; you can specify a certain seed with TESTOPS="--seed=xyz", which fixes the seed and thus the order the tests will be run in. The main source of the bug was that many of the tests rely on replacing asset files and asserting that the results are as expected; however, the asset pipeline uses mtime to determine when files have been changed. *mtime's resolution is only 1 second, meaning that when a series of actions took less than a second to run, the mtime wouldn't actually change, and Rails asset pipeline wouldn't update the file list.* This commit adds a hook to force reset the internal concatinated react.js and components.js string. Another test requires a few calls to sleep(1), because it is specifically testing that the asset pipeline picks up changes to the file on disk correctly and renders them server side.
1 parent 75a3188 commit e9b6697

File tree

4 files changed

+25
-11
lines changed

4 files changed

+25
-11
lines changed

lib/react/rails/railtie.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ class Railtie < ::Rails::Railtie
6464

6565
do_setup = lambda do
6666
cfg = app.config.react
67-
React::Renderer.setup!( cfg.react_js.call, cfg.components_js.call,
67+
React::Renderer.setup!( cfg.react_js, cfg.components_js,
6868
{:size => cfg.size, :timeout => cfg.timeout})
6969
end
7070

lib/react/renderer.rb

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ def self.setup!(react_js, components_js, args={})
1010
@@react_js = react_js
1111
@@components_js = components_js
1212
@@pool.shutdown{} if @@pool
13-
@@combined_js = nil if defined? @@combined_js
13+
reset_combined_js!
1414
@@pool = ConnectionPool.new(:size => args[:size]||10, :timeout => args[:timeout]||20) { self.new }
1515
end
1616

@@ -20,8 +20,8 @@ def self.render(component, args={})
2020
end
2121
end
2222

23-
def self.combined_js
24-
@@combined_js ||= <<-CODE
23+
def self.setup_combined_js
24+
<<-CODE
2525
var global = global || this;
2626
2727
var console = global.console || {};
@@ -31,12 +31,20 @@ def self.combined_js
3131
}
3232
});
3333
34-
#{@@react_js};
34+
#{@@react_js.call};
3535
React = global.React;
36-
#{@@components_js};
36+
#{@@components_js.call};
3737
CODE
3838
end
3939

40+
def self.reset_combined_js!
41+
@@combined_js = setup_combined_js
42+
end
43+
44+
def self.combined_js
45+
@@combined_js
46+
end
47+
4048
def context
4149
@context ||= ExecJS.compile(self.class.combined_js)
4250
end

test/react_test.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ class ReactTest < ActionDispatch::IntegrationTest
3131

3232
assert_response :success
3333
assert_equal "'test_confirmation_token_react_content';\n", @response.body
34+
35+
React::Renderer.reset_combined_js!
3436
end
3537

3638
end

test/server_rendered_html_test.rb

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,34 @@
22
require 'fileutils'
33

44
class ServerRenderedHtmlTest < ActionDispatch::IntegrationTest
5+
# Rails' asset pipeline has trouble picking up changes to files if they happen too fast.
6+
# By sleeping for a little bit at certain points, we can make sure that rails notices the
7+
# change in the file mtime, and calls our renderer setup functions appropriately
8+
def wait_to_ensure_asset_pipeline_detects_changes
9+
sleep(1)
10+
end
11+
512
test 'react server rendering reloads jsx after changes to the jsx files' do
613
file_with_updates = File.expand_path('../helper_files/TodoListWithUpdates.js.jsx', __FILE__)
714
file_without_updates = File.expand_path('../helper_files/TodoListWithoutUpdates.js.jsx', __FILE__)
815
app_file = File.expand_path('../dummy/app/assets/javascripts/components/TodoList.js.jsx', __FILE__)
916

10-
sleep(1)
1117
FileUtils.cp app_file, file_without_updates
12-
# fixes inconsistent test runs; phantomjs doesn't always see that the file was
13-
# updated without manually calling #touch on it
1418
FileUtils.touch app_file
1519

1620
begin
1721
get '/server/1'
1822
refute_match 'Updated', response.body
1923

20-
sleep(1)
24+
wait_to_ensure_asset_pipeline_detects_changes
2125
FileUtils.cp file_with_updates, app_file
2226
FileUtils.touch app_file
2327

2428
get '/server/1'
2529
assert_match 'Updated', response.body
2630
ensure
2731
# if we have a test failure, we want to make sure that we revert the dummy file
28-
sleep(1)
32+
wait_to_ensure_asset_pipeline_detects_changes
2933
FileUtils.mv file_without_updates, app_file
3034
FileUtils.touch app_file
3135
end

0 commit comments

Comments
 (0)