hyper-react 0.10.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.
- checksums.yaml +7 -0
- data/.codeclimate.yml +27 -0
- data/.gitignore +36 -0
- data/.rubocop.yml +1159 -0
- data/.travis.yml +29 -0
- data/Appraisals +20 -0
- data/CHANGELOG.md +93 -0
- data/Gemfile +6 -0
- data/LICENSE +19 -0
- data/README.md +121 -0
- data/Rakefile +33 -0
- data/UPGRADING.md +24 -0
- data/component-name-lookup.md +145 -0
- data/config.ru +25 -0
- data/gemfiles/opal_0.8_react_13.gemfile +13 -0
- data/gemfiles/opal_0.8_react_14.gemfile +13 -0
- data/gemfiles/opal_0.8_react_15.gemfile +13 -0
- data/gemfiles/opal_0.9_react_13.gemfile +13 -0
- data/gemfiles/opal_0.9_react_14.gemfile +13 -0
- data/gemfiles/opal_0.9_react_15.gemfile +13 -0
- data/hyper-react.gemspec +43 -0
- data/lib/generators/reactive_ruby/test_app/templates/assets/javascripts/components.rb +4 -0
- data/lib/generators/reactive_ruby/test_app/templates/assets/javascripts/test_application.rb +2 -0
- data/lib/generators/reactive_ruby/test_app/templates/boot.rb.erb +6 -0
- data/lib/generators/reactive_ruby/test_app/templates/script/rails +5 -0
- data/lib/generators/reactive_ruby/test_app/templates/test_application.rb.erb +13 -0
- data/lib/generators/reactive_ruby/test_app/templates/views/components/hello_world.rb +11 -0
- data/lib/generators/reactive_ruby/test_app/templates/views/components/todo.rb +14 -0
- data/lib/generators/reactive_ruby/test_app/templates/views/layouts/test_layout.html.erb +0 -0
- data/lib/generators/reactive_ruby/test_app/test_app_generator.rb +109 -0
- data/lib/hyper-react.rb +52 -0
- data/lib/rails-helpers/top_level_rails_component.rb +54 -0
- data/lib/react-sources/react-server.js +2 -0
- data/lib/react/api.rb +162 -0
- data/lib/react/callbacks.rb +42 -0
- data/lib/react/children.rb +30 -0
- data/lib/react/component.rb +139 -0
- data/lib/react/component/api.rb +50 -0
- data/lib/react/component/base.rb +9 -0
- data/lib/react/component/class_methods.rb +214 -0
- data/lib/react/component/dsl_instance_methods.rb +27 -0
- data/lib/react/component/params.rb +6 -0
- data/lib/react/component/props_wrapper.rb +83 -0
- data/lib/react/component/should_component_update.rb +98 -0
- data/lib/react/component/tags.rb +144 -0
- data/lib/react/element.rb +168 -0
- data/lib/react/event.rb +76 -0
- data/lib/react/ext/hash.rb +9 -0
- data/lib/react/ext/string.rb +8 -0
- data/lib/react/hash.rb +13 -0
- data/lib/react/native_library.rb +92 -0
- data/lib/react/object.rb +15 -0
- data/lib/react/observable.rb +29 -0
- data/lib/react/react-source.rb +9 -0
- data/lib/react/rendering_context.rb +142 -0
- data/lib/react/state.rb +190 -0
- data/lib/react/test.rb +16 -0
- data/lib/react/test/dsl.rb +17 -0
- data/lib/react/test/matchers/render_html_matcher.rb +49 -0
- data/lib/react/test/rspec.rb +15 -0
- data/lib/react/test/session.rb +46 -0
- data/lib/react/top_level.rb +132 -0
- data/lib/react/validator.rb +136 -0
- data/lib/reactive-ruby/component_loader.rb +49 -0
- data/lib/reactive-ruby/isomorphic_helpers.rb +197 -0
- data/lib/reactive-ruby/rails.rb +7 -0
- data/lib/reactive-ruby/rails/component_mount.rb +46 -0
- data/lib/reactive-ruby/rails/controller_helper.rb +15 -0
- data/lib/reactive-ruby/rails/railtie.rb +14 -0
- data/lib/reactive-ruby/serializers.rb +15 -0
- data/lib/reactive-ruby/server_rendering/contextual_renderer.rb +42 -0
- data/lib/reactive-ruby/version.rb +3 -0
- data/lib/reactrb/auto-import.rb +32 -0
- data/lib/reactrb/deep-compare.rb +24 -0
- data/lib/reactrb/new-event-name-convention.rb +11 -0
- data/lib/sources/react-latest.js +21169 -0
- data/lib/sources/react-v13.js +21645 -0
- data/lib/sources/react-v14.js +20821 -0
- data/lib/sources/react-v15.js +21170 -0
- data/logo1.png +0 -0
- data/logo2.png +0 -0
- data/logo3.png +0 -0
- data/path_release_steps.md +9 -0
- data/spec/controller_helper_spec.rb +34 -0
- data/spec/index.html.erb +10 -0
- data/spec/react/callbacks_spec.rb +106 -0
- data/spec/react/children_spec.rb +76 -0
- data/spec/react/component/base_spec.rb +32 -0
- data/spec/react/component_spec.rb +872 -0
- data/spec/react/dsl_spec.rb +296 -0
- data/spec/react/element_spec.rb +136 -0
- data/spec/react/event_spec.rb +24 -0
- data/spec/react/native_library_spec.rb +344 -0
- data/spec/react/observable_spec.rb +7 -0
- data/spec/react/opal_jquery_extensions_spec.rb +66 -0
- data/spec/react/param_declaration_spec.rb +258 -0
- data/spec/react/react_spec.rb +209 -0
- data/spec/react/state_spec.rb +55 -0
- data/spec/react/test/dsl_spec.rb +43 -0
- data/spec/react/test/matchers/render_html_matcher_spec.rb +83 -0
- data/spec/react/test/rspec_spec.rb +62 -0
- data/spec/react/test/session_spec.rb +100 -0
- data/spec/react/test/utils_spec.rb +45 -0
- data/spec/react/top_level_component_spec.rb +96 -0
- data/spec/react/tutorial/tutorial_spec.rb +36 -0
- data/spec/react/validator_spec.rb +124 -0
- data/spec/reactive-ruby/component_loader_spec.rb +71 -0
- data/spec/reactive-ruby/isomorphic_helpers_spec.rb +155 -0
- data/spec/reactive-ruby/rails/asset_pipeline_spec.rb +10 -0
- data/spec/reactive-ruby/rails/component_mount_spec.rb +66 -0
- data/spec/reactive-ruby/server_rendering/contextual_renderer_spec.rb +35 -0
- data/spec/spec_helper.rb +115 -0
- data/spec/support/react/spec_helpers.rb +64 -0
- data/spec/vendor/es5-shim.min.js +6 -0
- data/spec/vendor/jquery-2.2.4.min.js +4 -0
- metadata +387 -0
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
RSpec.describe React::IsomorphicHelpers do
|
|
4
|
+
describe 'code execution context' do
|
|
5
|
+
let(:klass) { Class.send(:include, described_class) }
|
|
6
|
+
|
|
7
|
+
describe 'module class methods', :opal do
|
|
8
|
+
it { expect(described_class).to_not be_on_opal_server }
|
|
9
|
+
it { expect(described_class).to be_on_opal_client }
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
describe 'included class methods', :opal do
|
|
13
|
+
it { expect(klass).to_not be_on_opal_server }
|
|
14
|
+
it { expect(klass).to be_on_opal_client }
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
describe 'included instance methods', :opal do
|
|
18
|
+
it { expect(klass.new).to_not be_on_opal_server }
|
|
19
|
+
it { expect(klass.new).to be_on_opal_client }
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
describe 'module class methods', :ruby do
|
|
23
|
+
it { is_expected.to_not be_on_opal_server }
|
|
24
|
+
it { is_expected.to_not be_on_opal_client }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
describe 'included class methods', :ruby do
|
|
28
|
+
subject { klass }
|
|
29
|
+
it { is_expected.to_not be_on_opal_server }
|
|
30
|
+
it { is_expected.to_not be_on_opal_client }
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
describe 'included instance methods', :ruby do
|
|
34
|
+
subject { klass.new }
|
|
35
|
+
it { is_expected.to_not be_on_opal_server }
|
|
36
|
+
it { is_expected.to_not be_on_opal_client }
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
if ruby?
|
|
41
|
+
describe 'load_context', :ruby do
|
|
42
|
+
let(:v8_context) { TestV8Context.new }
|
|
43
|
+
let(:controller) { double('controller') }
|
|
44
|
+
let(:name) { double('name') }
|
|
45
|
+
|
|
46
|
+
it 'creates a context and sets a controller' do
|
|
47
|
+
context = described_class.load_context(v8_context, controller, name)
|
|
48
|
+
expect(context.controller).to eq(controller)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it 'creates a context and sets a unique_id' do
|
|
52
|
+
Timecop.freeze do
|
|
53
|
+
stamp = Time.now.to_i
|
|
54
|
+
context = described_class.load_context(v8_context, controller, name)
|
|
55
|
+
expect(context.unique_id).to eq("#{ controller.object_id }-#{ stamp }")
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
describe React::IsomorphicHelpers::Context do
|
|
61
|
+
class TestV8Context < Hash
|
|
62
|
+
def eval(args)
|
|
63
|
+
true
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Need to decouple/dry up this...
|
|
68
|
+
def test_context(files = nil)
|
|
69
|
+
js = ReactiveRuby::ServerRendering::ContextualRenderer::CONSOLE_POLYFILL.dup
|
|
70
|
+
js << Opal::Builder.build('opal').to_s
|
|
71
|
+
Array(files).each do |filename|
|
|
72
|
+
js << ::Rails.application.assets[filename].to_s
|
|
73
|
+
end
|
|
74
|
+
js = "#{React::ServerRendering::ExecJSRenderer::GLOBAL_WRAPPER}#{js}"
|
|
75
|
+
ctx = ExecJS.compile(js)
|
|
76
|
+
ctx = ReactiveRuby::ServerRendering.context_instance_for(ctx)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def react_context
|
|
80
|
+
test_context('components')
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
let(:v8_context) { TestV8Context.new }
|
|
84
|
+
let(:controller) { double('controller') }
|
|
85
|
+
let(:name) { double('name') }
|
|
86
|
+
before do
|
|
87
|
+
described_class.instance_variable_set :@before_first_mount_blocks, nil
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
describe '#initialize' do
|
|
91
|
+
it "sets the given V8 context's ServerSideIsomorphicMethods to itself" do
|
|
92
|
+
context = described_class.new('unique-id', v8_context, controller, name)
|
|
93
|
+
expect(v8_context['ServerSideIsomorphicMethods']).to eq(context)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
it 'calls before mount callbacks' do
|
|
97
|
+
string = instance_double(String)
|
|
98
|
+
described_class.register_before_first_mount_block do
|
|
99
|
+
string.inspect
|
|
100
|
+
end
|
|
101
|
+
expect(string).to receive(:inspect).once
|
|
102
|
+
context = described_class.new('unique-id', v8_context, controller, name)
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
describe '#eval' do
|
|
107
|
+
it 'delegates to given context' do
|
|
108
|
+
context = described_class.new('unique-id', v8_context, controller, name)
|
|
109
|
+
js = 'true;'
|
|
110
|
+
expect(v8_context).to receive(:eval).with(js).once
|
|
111
|
+
context.eval(js)
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
describe '#send_to_opal' do
|
|
116
|
+
let(:opal_code) { Opal::Builder.new.build_str(ruby_code, __FILE__) }
|
|
117
|
+
let(:ruby_code) { %Q[
|
|
118
|
+
module React::IsomorphicHelpers
|
|
119
|
+
def self.greet(name)
|
|
120
|
+
"Hello, #\{name}!"
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def self.valediction
|
|
124
|
+
'Goodbye'
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
]}
|
|
128
|
+
|
|
129
|
+
it 'raises an error when react cannot be loaded' do
|
|
130
|
+
context = described_class.new('unique-id', v8_context, controller, name)
|
|
131
|
+
context.instance_variable_set(:@ctx, test_context)
|
|
132
|
+
expect {
|
|
133
|
+
context.send_to_opal(:foo)
|
|
134
|
+
}.to raise_error(/No react.rb components found/)
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
it 'executes method with args inside opal rubyracer context' do
|
|
138
|
+
ctx = react_context
|
|
139
|
+
context = described_class.new('unique-id', ctx, controller, name)
|
|
140
|
+
ctx.eval(opal_code)
|
|
141
|
+
result = context.send_to_opal(:greet, 'world')
|
|
142
|
+
expect(result).to eq('Hello, world!')
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
it 'executes the method inside opal rubyracer context' do
|
|
146
|
+
ctx = react_context
|
|
147
|
+
context = described_class.new('unique-id', ctx, controller, name)
|
|
148
|
+
ctx.eval(opal_code)
|
|
149
|
+
result = context.send_to_opal(:valediction)
|
|
150
|
+
expect(result).to eq('Goodbye')
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
if ruby?
|
|
4
|
+
RSpec.describe 'test_app generator' do
|
|
5
|
+
it "does not interfer with asset precompilation" do
|
|
6
|
+
cmd = "cd spec/test_app; BUNDLE_GEMFILE=#{ENV['REAL_BUNDLE_GEMFILE']} bundle exec rake assets:precompile"
|
|
7
|
+
expect(system(cmd)).to be_truthy
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
if ruby?
|
|
4
|
+
RSpec.describe ReactiveRuby::Rails::ComponentMount do
|
|
5
|
+
let(:helper) { described_class.new }
|
|
6
|
+
|
|
7
|
+
before do
|
|
8
|
+
helper.setup(ActionView::TestCase::TestController.new)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
describe '#react_component' do
|
|
12
|
+
it 'renders a div' do
|
|
13
|
+
html = helper.react_component('Components::HelloWorld')
|
|
14
|
+
expect(html).to match(/<div.*><\/div>/)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it 'accepts a pre-render option' do
|
|
18
|
+
html = helper.react_component('Components::HelloWorld', {}, prerender: true)
|
|
19
|
+
expect(html).to match(/<div.*><span.*>Hello, World!<\/span><\/div>/)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it 'sets data-react-class to React.TopLevelRailsComponent' do
|
|
23
|
+
html = helper.react_component('Components::HelloWorld')
|
|
24
|
+
top_level_class = 'React.TopLevelRailsComponent'
|
|
25
|
+
expect(attr_value(html, 'data-react-class')).to eq(top_level_class)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it 'sets component_name in data-react-props hash' do
|
|
29
|
+
html = helper.react_component('Components::HelloWorld')
|
|
30
|
+
props = react_props_for(html)
|
|
31
|
+
|
|
32
|
+
expect(props['component_name']).to eq('Components::HelloWorld')
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it 'sets render_params in data-react-props hash' do
|
|
36
|
+
html = helper.react_component('Components::HelloWorld', {'foo' => 'bar'})
|
|
37
|
+
props = react_props_for(html)
|
|
38
|
+
|
|
39
|
+
expect(props['render_params']).to include({ 'foo' => 'bar' })
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it 'sets controller in data-react-props hash' do
|
|
43
|
+
html = helper.react_component('Components::HelloWorld')
|
|
44
|
+
props = react_props_for(html)
|
|
45
|
+
|
|
46
|
+
expect(props['controller']).to eq('ActionView::TestCase::Test')
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it 'passes additional options through as html attributes' do
|
|
50
|
+
html = helper.react_component('Components::HelloWorld', {},
|
|
51
|
+
{ 'foo-bar' => 'biz-baz' })
|
|
52
|
+
|
|
53
|
+
expect(attr_value(html, 'foo-bar')).to eq('biz-baz')
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def attr_value(html, attr)
|
|
58
|
+
matches = html.match(/#{attr}=["']((?:.(?!["']\s+(?:\S+)=|[>"']))+.)["']?/)
|
|
59
|
+
matches.captures.first
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def react_props_for(html)
|
|
63
|
+
JSON.parse(CGI.unescapeHTML("#{attr_value(html, 'data-react-props')}"))
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
if ruby?
|
|
4
|
+
RSpec.describe ReactiveRuby::ServerRendering::ContextualRenderer do
|
|
5
|
+
let(:renderer) { described_class.new({}) }
|
|
6
|
+
let(:init) { Proc.new {} }
|
|
7
|
+
let(:options) { { context_initializer: init } }
|
|
8
|
+
|
|
9
|
+
describe '#render' do
|
|
10
|
+
it 'pre-renders HTML' do
|
|
11
|
+
result = renderer.render('Components.Todo',
|
|
12
|
+
{ todo: 'finish reactive-ruby' },
|
|
13
|
+
options)
|
|
14
|
+
expect(result).to match(/<li.*>finish reactive-ruby<\/li>/)
|
|
15
|
+
expect(result).to match(/data-react-checksum/)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it 'accepts props as a string' do
|
|
19
|
+
result = renderer.render('Components.Todo',
|
|
20
|
+
{ todo: 'finish reactive-ruby' }.to_json,
|
|
21
|
+
options)
|
|
22
|
+
expect(result).to match(/<li.*>finish reactive-ruby<\/li>/)
|
|
23
|
+
expect(result).to match(/data-react-checksum/)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it 'pre-renders static content' do
|
|
27
|
+
result = renderer.render('Components.Todo',
|
|
28
|
+
{ todo: 'finish reactive-ruby' },
|
|
29
|
+
:static)
|
|
30
|
+
expect(result).to match(/<li.*>finish reactive-ruby<\/li>/)
|
|
31
|
+
expect(result).to_not match(/data-react-checksum/)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
ENV["RAILS_ENV"] ||= 'test'
|
|
2
|
+
|
|
3
|
+
require 'opal'
|
|
4
|
+
require 'opal-rspec'
|
|
5
|
+
require 'opal-jquery'
|
|
6
|
+
|
|
7
|
+
def opal?
|
|
8
|
+
RUBY_ENGINE == 'opal'
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def ruby?
|
|
12
|
+
!opal?
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
if RUBY_ENGINE == 'opal'
|
|
17
|
+
require File.expand_path('../vendor/jquery-2.2.4.min', __FILE__)
|
|
18
|
+
require 'react/react-source'
|
|
19
|
+
require 'hyper-react'
|
|
20
|
+
require 'react/test/rspec'
|
|
21
|
+
|
|
22
|
+
require File.expand_path('../support/react/spec_helpers', __FILE__)
|
|
23
|
+
|
|
24
|
+
module Opal
|
|
25
|
+
module RSpec
|
|
26
|
+
module AsyncHelpers
|
|
27
|
+
module ClassMethods
|
|
28
|
+
def rendering(title, &block)
|
|
29
|
+
klass = Class.new do
|
|
30
|
+
include React::Component
|
|
31
|
+
|
|
32
|
+
def self.block
|
|
33
|
+
@block
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def self.name
|
|
37
|
+
"dummy class"
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def render
|
|
41
|
+
instance_eval &self.class.block
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def self.should_generate(opts={}, &block)
|
|
45
|
+
sself = self
|
|
46
|
+
@self.async(@title, opts) do
|
|
47
|
+
expect_component_to_eventually(sself, &block)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def self.should_immediately_generate(opts={}, &block)
|
|
52
|
+
sself = self
|
|
53
|
+
@self.it(@title, opts) do
|
|
54
|
+
element = build_element sself, {}
|
|
55
|
+
context = block.arity > 0 ? self : element
|
|
56
|
+
expect((element and context.instance_exec(element, &block))).to be(true)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
end
|
|
61
|
+
klass.instance_variable_set("@block", block)
|
|
62
|
+
klass.instance_variable_set("@self", self)
|
|
63
|
+
klass.instance_variable_set("@title", "it can render #{title}")
|
|
64
|
+
klass
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
RSpec.configure do |config|
|
|
73
|
+
config.include React::SpecHelpers
|
|
74
|
+
config.filter_run_excluding :ruby
|
|
75
|
+
if `(React.version.search(/^0\.13/) === -1)`
|
|
76
|
+
config.filter_run_excluding :v13_only
|
|
77
|
+
else
|
|
78
|
+
config.filter_run_excluding :v13_exclude
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
if RUBY_ENGINE != 'opal'
|
|
84
|
+
begin
|
|
85
|
+
require File.expand_path('../test_app/config/environment', __FILE__)
|
|
86
|
+
rescue LoadError
|
|
87
|
+
puts 'Could not load test application. Please ensure you have run `bundle exec rake test_app`'
|
|
88
|
+
end
|
|
89
|
+
require 'rspec/rails'
|
|
90
|
+
require 'timecop'
|
|
91
|
+
|
|
92
|
+
Dir["./spec/support/**/*.rb"].sort.each { |f| require f }
|
|
93
|
+
|
|
94
|
+
RSpec.configure do |config|
|
|
95
|
+
config.color = true
|
|
96
|
+
config.fail_fast = ENV['FAIL_FAST'] || false
|
|
97
|
+
config.fixture_path = File.join(File.expand_path(File.dirname(__FILE__)), "fixtures")
|
|
98
|
+
config.infer_spec_type_from_file_location!
|
|
99
|
+
config.mock_with :rspec
|
|
100
|
+
config.raise_errors_for_deprecations!
|
|
101
|
+
|
|
102
|
+
# If you're not using ActiveRecord, or you'd prefer not to run each of your
|
|
103
|
+
# examples within a transaction, comment the following line or assign false
|
|
104
|
+
# instead of true.
|
|
105
|
+
config.use_transactional_fixtures = true
|
|
106
|
+
|
|
107
|
+
config.before :each do
|
|
108
|
+
Rails.cache.clear
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
config.filter_run_including focus: true
|
|
112
|
+
config.filter_run_excluding opal: true
|
|
113
|
+
config.run_all_when_everything_filtered = true
|
|
114
|
+
end
|
|
115
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
if opal?
|
|
2
|
+
module React
|
|
3
|
+
module SpecHelpers
|
|
4
|
+
`var ReactTestUtils = React.addons.TestUtils`
|
|
5
|
+
|
|
6
|
+
def render_to_html(type, options = {})
|
|
7
|
+
element = React.create_element(type, options)
|
|
8
|
+
React.render_to_static_markup(element)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def renderToDocument(type, options = {})
|
|
12
|
+
element = React.create_element(type, options)
|
|
13
|
+
renderElementToDocument(element)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def renderElementToDocument(element)
|
|
17
|
+
instance = Native(`ReactTestUtils.renderIntoDocument(#{element.to_n})`)
|
|
18
|
+
instance.class.include(React::Component::API)
|
|
19
|
+
instance
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def simulateEvent(event, element, params = {})
|
|
23
|
+
simulator = Native(`ReactTestUtils.Simulate`)
|
|
24
|
+
simulator[event.to_s].call(element.dom_node, params)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def isElementOfType(element, type)
|
|
28
|
+
`React.addons.TestUtils.isElementOfType(#{element.to_n}, #{type.cached_component_class})`
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def build_element(type, options)
|
|
32
|
+
component = React.create_element(type, options)
|
|
33
|
+
element = `ReactTestUtils.renderIntoDocument(#{component.to_n})`
|
|
34
|
+
if `typeof React.findDOMNode === 'undefined'`
|
|
35
|
+
`$(element.getDOMNode())` # v0.12
|
|
36
|
+
else
|
|
37
|
+
`$(React.findDOMNode(element))` # v0.13
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def expect_component_to_eventually(component_class, opts = {}, &block)
|
|
42
|
+
# Calls block after each update of a component until it returns true.
|
|
43
|
+
# When it does set the expectation to true. Uses the after_update
|
|
44
|
+
# callback of the component_class, then instantiates an element of that
|
|
45
|
+
# class The call back is only called on updates, so the call back is
|
|
46
|
+
# manually called right after the element is created. Because React.rb
|
|
47
|
+
# runs the callback inside the components context, we have to setup a
|
|
48
|
+
# lambda to get back to correct context before executing run_async.
|
|
49
|
+
# Because run_async can only be run once it is protected by clearing
|
|
50
|
+
# element once the test passes.
|
|
51
|
+
element = nil
|
|
52
|
+
check_block = lambda do
|
|
53
|
+
context = block.arity > 0 ? self : element
|
|
54
|
+
run_async do
|
|
55
|
+
element = nil; expect(true).to be(true)
|
|
56
|
+
end if element and context.instance_exec(element, &block)
|
|
57
|
+
end
|
|
58
|
+
component_class.after_update { check_block.call }
|
|
59
|
+
element = build_element component_class, opts
|
|
60
|
+
check_block.call
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|