require 'spec_helper' describe 'the React DSL', js: true do context "render macro" do it "can define the render method with the render macro with a html tag container" do mount 'Foo' do class Foo include React::Component render(:div, class: :foo) do "hello" end end end expect(page.body[-60..-19]).to include('
hello
') end it "can define the render method with the render macro without a container" do mount 'Foo' do class Foo include React::Component render do "hello" end end end expect(page.body[-60..-19]).to include('hello') end it "can define the render method with the render macro with a application defined container" do on_client do class Bar < React::Component::Base param :p1 render { "hello #{params.p1}" } end class Foo < React::Component::Base render Bar, p1: "fred" end end mount 'Foo' expect(page.body[-60..-19]).to include('hello fred') end end it "will turn the last string in a block into a element" do mount 'Foo' do class Foo include React::Component def render div { "hello" } end end end expect(page.body[-60..-19]).to include('
hello
') end it "in prerender will pass converted props through event handlers" do client_option render_on: :both mount 'Foo' do class Foo include React::Component def render INPUT(data: {foo: 12}).on(:change) {} end end end expect(page.body).to match(//) end it "will turn the last string in a block into a element" do mount 'Foo' do class Foo include React::Component def render DIV { "hello" } end end end expect(page.body[-60..-19]).to include('
hello
') end it "has a .span short hand String method" do mount 'Foo' do class Foo include React::Component def render div { "hello".span; "goodby".span } end end end expect(page.body[-70..-19]).to include('
hellogoodby
') end it "in prerendering has a .br short hand String method" do client_option render_on: :both client_option raise_on_js_errors: :off mount 'Foo' do class Foo include React::Component def render div { "hello".br } end end end expect(page.body[-80..-19]).to match(/(
hello<(br|br\/|br \/)><\/span><\/div>/) end it "has a .td short hand String method" do mount 'Foo' do class Foo include React::Component def render table { tbody { tr { "hello".td } } } end end end expect(page.body[-90..-19]).to include('
hello
') end it "has a .para short hand String method" do mount 'Foo' do class Foo include React::Component def render div { "hello".para } end end end expect(page.body[-60..-19]).to include('

hello

') end it 'can do a method call on a class name that is not a direct sibling' do # this test is failing because Comp() is not serialized/compiled to a method call, # but instead to a $scope.get("Comp"); which returns the Component Class Mod::Comp # instead it sould serialize/compile to a $scope.$Comp(); # this is a bug in unparser, workaround is to pass a argument to comp mount 'Mod::NestedMod::NestedComp' do module Mod class Comp include React::Component param :test def render "Mod::Comp" end end module NestedMod class NestedComp include React::Component def render Comp(test: 'string') end end end end end expect(page.body[-60..-19]).to include('Mod::Comp') end it 'raises a meaningful error if a Constant Name is not actually a component' do client_option raise_on_js_errors: :off mount 'Mod::NestedMod::NestedComp' do module Mod module NestedMod class NestedComp < React::Component::Base backtrace :none render do Comp(test: 'string') end end end class Comp; end end end expect(page.driver.browser.manage.logs.get(:browser).map { |m| m.message.gsub(/\\n/, "\n") }.to_a.join("\n")) .to match(/Comp does not appear to be a react component./) end it 'raises a method missing error' do client_option render_on: :both client_option raise_on_js_errors: :off expect_evaluate_ruby do class Foo < React::Component::Base backtrace :none render do _undefined_method end end begin React::Test::Utils.render_component_into_document(Foo) 'not raised' rescue NoMethodError 'raised for sure!' end end.to eq('raised for sure!') end it "will treat the component class name as a first class component name" do mount 'Foo' do module Mod class Bar include React::Component def render "a man walks into a bar" end end end class Foo < React::Component::Base def render Mod::Bar() end end end expect(page.body[-60..-19]).to include('a man walks into a bar') end it "can add class names by the haml .class notation" do mount 'Foo' do module Mod class Bar include React::Component collect_other_params_as :attributes def render "a man walks into a bar".span(params.attributes) end end end class Foo < React::Component::Base def render Mod::Bar().the_class.other_class end end end expect(page.body[-90..-19]).to include('a man walks into a bar') end it "can use the 'class' keyword for classes" do mount 'Foo' do class Foo include React::Component def render span(class: "the-class") { "hello" } end end end expect(page.body[-60..-19]).to include('hello') end it "can generate a unrendered node using the .as_node method" do # div { "hello" }.as_node mount 'Foo' do class Foo include React::Component def render span(data: {size: 12}) { "hello".span.as_node.class.name }.as_node.render end end end expect(page.body[-80..-19]).to include('React::Element') end it "can use the dangerously_set_inner_HTML param" do mount 'Foo' do class Foo include React::Component def render div(dangerously_set_inner_HTML: { __html: "Hello and Goodby" }) end end end expect(page.body[-60..-19]).to include('
Hello and Goodby
') end it 'should convert a hash param to hyphenated html attributes if in React::HASH_ATTRIBUTES' do mount 'Foo' do class Foo include React::Component def render div(data: { foo: :bar }, aria: { label: "title" }) end end end expect(page.body[-70..-19]).to include('
') end it 'should not convert a hash param to hyphenated html attributes if not in React::HASH_ATTRIBUTES' do mount 'Foo' do class Foo include React::Component def render div(title: { bar: :foo }) end end end expect(page.body[-80..-19]).to include('
') end it "will remove all elements passed as params from the rendering buffer" do mount 'Foo' do class X2 include React::Component param :ele def render div do params[:ele].render params[:ele].render end end end class Foo include React::Component def render X2(ele: b { "hello" }) end end end expect(page.body[-60..-19]).to include('
hellohello
') end end