fortitude 0.0.4-java → 0.0.5-java
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 +4 -4
- data/.travis.yml +19 -19
- data/CHANGES.md +31 -0
- data/Gemfile +1 -0
- data/README-erector.md +1 -1
- data/lib/fortitude/erector.rb +32 -0
- data/lib/fortitude/method_templates/tag_method_template.rb.smpl +6 -6
- data/lib/fortitude/method_templates/text_method_template.rb.smpl +3 -3
- data/lib/fortitude/rails/railtie.rb +6 -4
- data/lib/fortitude/rails/renderer.rb +7 -4
- data/lib/fortitude/rails/template_handler.rb +18 -3
- data/lib/fortitude/rendering_context.rb +20 -2
- data/lib/fortitude/tags/render_widget_placeholder.rb +19 -0
- data/lib/fortitude/tags/tag.rb +18 -4
- data/lib/fortitude/tags/tag_return_value.rb +1 -1
- data/lib/fortitude/tags/tag_store.rb +4 -0
- data/lib/fortitude/tilt/fortitude_template.rb +6 -128
- data/lib/fortitude/version.rb +1 -1
- data/lib/fortitude/widget.rb +2 -0
- data/lib/fortitude/widget/files.rb +162 -0
- data/lib/fortitude/widget/integration.rb +5 -3
- data/lib/fortitude/widget/modules_and_subclasses.rb +17 -0
- data/lib/fortitude/widget/rendering.rb +12 -5
- data/lib/fortitude/widget/start_and_end_comments.rb +4 -2
- data/lib/fortitude/widget/tags.rb +6 -1
- data/lib/fortitude/widget/widget_class_inheritable_attributes.rb +7 -0
- data/spec/helpers/rails_server.rb +4 -0
- data/spec/rails/basic_rails_system_spec.rb +4 -0
- data/spec/rails/erector_coexistence_system_spec.rb +33 -0
- data/spec/rails/rendering_context_system_spec.rb +19 -3
- data/spec/rails/rendering_system_spec.rb +6 -0
- data/spec/rails/templates/basic_rails_system_spec/app/controllers/basic_rails_system_spec_controller.rb +5 -0
- data/spec/rails/templates/basic_rails_system_spec/app/views/basic_rails_system_spec/double_render_one.rb +5 -0
- data/spec/rails/templates/basic_rails_system_spec/app/views/basic_rails_system_spec/double_render_three.rb +5 -0
- data/spec/rails/templates/basic_rails_system_spec/app/views/basic_rails_system_spec/double_render_two.rb +9 -0
- data/spec/rails/templates/erector_coexistence_system_spec/app/controllers/erector_coexistence_system_spec_controller.rb +19 -0
- data/spec/rails/templates/erector_coexistence_system_spec/app/v/views/erector_coexistence_system_spec/erector_widget_in_app_v_views.rb +7 -0
- data/spec/rails/templates/erector_coexistence_system_spec/app/v/views/erector_coexistence_system_spec/fortitude_widget_in_app_v_views.rb +7 -0
- data/spec/rails/templates/erector_coexistence_system_spec/app/views/erector_coexistence_system_spec/erector_widget_in_app_views.rb +7 -0
- data/spec/rails/templates/erector_coexistence_system_spec/app/views/erector_coexistence_system_spec/fortitude_widget_in_app_views.rb +7 -0
- data/spec/rails/templates/erector_coexistence_system_spec/config/application.rb +25 -0
- data/spec/rails/templates/rendering_context_system_spec/app/controllers/rendering_context_system_spec_controller.rb +2 -2
- data/spec/rails/templates/rendering_context_system_spec/app/views/rendering_context_system_spec/_current_element_nesting_intermediate.html.erb +3 -0
- data/spec/rails/templates/rendering_context_system_spec/app/views/rendering_context_system_spec/current_element_nesting_child.rb +13 -0
- data/spec/rails/templates/rendering_context_system_spec/app/views/rendering_context_system_spec/current_element_nesting_toplevel.rb +9 -0
- data/spec/rails/templates/rendering_context_system_spec/app/views/rendering_context_system_spec/start_end_widget_through_partials.rb +2 -2
- data/spec/system/convenience_methods_system_spec.rb +22 -0
- data/spec/system/inline_system_spec.rb +2 -2
- data/spec/system/record_tag_emission_system_spec.rb +71 -0
- data/spec/system/rendering_context_system_spec.rb +21 -0
- data/spec/system/setting_inheritance_system_spec.rb +52 -0
- data/spec/system/tag_return_value_system_spec.rb +7 -0
- data/spec/system/tilt_system_spec.rb +13 -18
- data/spec/system/widget_class_from_spec.rb +240 -0
- data/spec/system/widget_method_system_spec.rb +52 -0
- metadata +37 -2
| @@ -139,6 +139,30 @@ describe "Fortitude setting inheritance", :type => :system do | |
| 139 139 | 
             
              end
         | 
| 140 140 |  | 
| 141 141 |  | 
| 142 | 
            +
              def record_tag_emission_should_be(expected_result, *klasses)
         | 
| 143 | 
            +
                klasses.each do |klass|
         | 
| 144 | 
            +
                  expect(klass.record_tag_emission).to eq(expected_result)
         | 
| 145 | 
            +
                  send("record_tag_emission_should_be_#{expected_result}", klass)
         | 
| 146 | 
            +
                end
         | 
| 147 | 
            +
              end
         | 
| 148 | 
            +
             | 
| 149 | 
            +
              def record_tag_emission_should_be_true(klass)
         | 
| 150 | 
            +
                instance = klass.new
         | 
| 151 | 
            +
                expect(render(instance)).to eq("<p><div></div></p>")
         | 
| 152 | 
            +
                nesting = instance.inner_element_nesting
         | 
| 153 | 
            +
                expect(nesting.shift).to be(instance)
         | 
| 154 | 
            +
                expect(nesting.map(&:name)).to eq([ :p, :div ])
         | 
| 155 | 
            +
              end
         | 
| 156 | 
            +
             | 
| 157 | 
            +
              def record_tag_emission_should_be_false(klass)
         | 
| 158 | 
            +
                instance = klass.new
         | 
| 159 | 
            +
                expect(render(instance)).to eq("<p><div></div></p>")
         | 
| 160 | 
            +
                nesting = instance.inner_element_nesting
         | 
| 161 | 
            +
                expect(nesting.shift).to be(instance)
         | 
| 162 | 
            +
                expect(nesting).to eq([ ])
         | 
| 163 | 
            +
              end
         | 
| 164 | 
            +
             | 
| 165 | 
            +
             | 
| 142 166 | 
             
              def format_output_should_be(expected_result, *klasses)
         | 
| 143 167 | 
             
                klasses.each do |klass|
         | 
| 144 168 | 
             
                  expect(klass.format_output).to eq(expected_result)
         | 
| @@ -405,6 +429,34 @@ describe "Fortitude setting inheritance", :type => :system do | |
| 405 429 | 
             
                enforce_element_nesting_rules_should_be(true, @parent1, @child11, @child12)
         | 
| 406 430 | 
             
              end
         | 
| 407 431 |  | 
| 432 | 
            +
              it "should properly inherit record_tag_emission" do
         | 
| 433 | 
            +
                @grandparent.class_eval do
         | 
| 434 | 
            +
                  attr_reader :inner_element_nesting
         | 
| 435 | 
            +
             | 
| 436 | 
            +
                  def content
         | 
| 437 | 
            +
                    p { div { @inner_element_nesting = rendering_context.current_element_nesting.dup } }
         | 
| 438 | 
            +
                  end
         | 
| 439 | 
            +
                end
         | 
| 440 | 
            +
             | 
| 441 | 
            +
                record_tag_emission_should_be(false, @grandparent, @parent1, @child11, @child12, @parent2, @child21, @child22)
         | 
| 442 | 
            +
             | 
| 443 | 
            +
                @parent1.record_tag_emission true
         | 
| 444 | 
            +
                record_tag_emission_should_be(false, @grandparent, @parent2, @child21, @child22)
         | 
| 445 | 
            +
                record_tag_emission_should_be(true, @parent1, @child11, @child12)
         | 
| 446 | 
            +
             | 
| 447 | 
            +
                @parent2.record_tag_emission false
         | 
| 448 | 
            +
                record_tag_emission_should_be(false, @grandparent, @parent2, @child21, @child22)
         | 
| 449 | 
            +
                record_tag_emission_should_be(true, @parent1, @child11, @child12)
         | 
| 450 | 
            +
             | 
| 451 | 
            +
                @grandparent.record_tag_emission true
         | 
| 452 | 
            +
                record_tag_emission_should_be(false, @parent2, @child21, @child22)
         | 
| 453 | 
            +
                record_tag_emission_should_be(true, @grandparent, @parent1, @child11, @child12)
         | 
| 454 | 
            +
             | 
| 455 | 
            +
                @grandparent.record_tag_emission false
         | 
| 456 | 
            +
                record_tag_emission_should_be(false, @grandparent, @parent2, @child21, @child22)
         | 
| 457 | 
            +
                record_tag_emission_should_be(true, @parent1, @child11, @child12)
         | 
| 458 | 
            +
              end
         | 
| 459 | 
            +
             | 
| 408 460 | 
             
              it "should properly inherit translation_base" do
         | 
| 409 461 | 
             
                @grandparent.class_eval do
         | 
| 410 462 | 
             
                  def content
         | 
| @@ -38,4 +38,11 @@ describe "Fortitude tag return values", :type => :system do | |
| 38 38 | 
             
                  expect_nrv(:foo) { p("foo", :foo => :bar) { text "whatever" }.foo }
         | 
| 39 39 | 
             
                end
         | 
| 40 40 | 
             
              end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
              context "should not blow up when calling" do
         | 
| 43 | 
            +
                it "#is_a?" do
         | 
| 44 | 
            +
                  wc = widget_class_with_content { text("value: #{p.is_a?(String).inspect}") }
         | 
| 45 | 
            +
                  expect(render(wc)).to eq("<p></p>value: false")
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
              end
         | 
| 41 48 | 
             
            end
         | 
| @@ -308,14 +308,14 @@ EOS | |
| 308 308 | 
             
              end
         | 
| 309 309 |  | 
| 310 310 | 
             
              it "should fail with a nice message if it can't figure out which class to render" do
         | 
| 311 | 
            -
                e = capture_exception(Fortitude:: | 
| 311 | 
            +
                e = capture_exception(Fortitude::Widget::Files::CannotDetermineWidgetClassNameError) do
         | 
| 312 312 | 
             
                  render_text_with_tilt("random_#{rand(1_000_000)}.rb", impossible_to_find_class_name_text(5), context_object, { })
         | 
| 313 313 | 
             
                end
         | 
| 314 314 |  | 
| 315 315 | 
             
                expect(e).to be
         | 
| 316 316 | 
             
                expect(e.tried_class_names).to eq([ ])
         | 
| 317 | 
            -
                expect(e.message).to match( | 
| 318 | 
            -
                expect(e.message).to match(/: | 
| 317 | 
            +
                expect(e.message).to match(/fortitude_tilt_class/)
         | 
| 318 | 
            +
                expect(e.message).to match(/:class_names_to_try/)
         | 
| 319 319 | 
             
              end
         | 
| 320 320 |  | 
| 321 321 | 
             
              it "should allow overriding the class that's defined in the module explicitly with an option" do
         | 
| @@ -325,32 +325,29 @@ EOS | |
| 325 325 | 
             
              end
         | 
| 326 326 |  | 
| 327 327 | 
             
              it "should fail with a nice message if you tell it to use something that doesn't exist, using an option" do
         | 
| 328 | 
            -
                e = capture_exception(Fortitude:: | 
| 328 | 
            +
                e = capture_exception(Fortitude::Widget::Files::CannotDetermineWidgetClassNameError) do
         | 
| 329 329 | 
             
                  render_text_with_tilt("random_#{rand(1_000_000)}.rb", impossible_to_find_class_name_text(7), context_object, { },
         | 
| 330 330 | 
             
                    { :fortitude_class => "NonExistent" })
         | 
| 331 331 | 
             
                end
         | 
| 332 | 
            -
                expect(e. | 
| 333 | 
            -
                expect(e.actual_object).to be_nil
         | 
| 332 | 
            +
                expect(e.tried_class_names).to be_include("NonExistent")
         | 
| 334 333 | 
             
                expect(e.message).to match(/NonExistent/)
         | 
| 335 334 | 
             
              end
         | 
| 336 335 |  | 
| 337 336 | 
             
              it "should fail with a nice message if you tell it to use something that isn't a class, using an option" do
         | 
| 338 | 
            -
                e = capture_exception(Fortitude:: | 
| 337 | 
            +
                e = capture_exception(Fortitude::Widget::Files::CannotDetermineWidgetClassNameError) do
         | 
| 339 338 | 
             
                  render_text_with_tilt("random_#{rand(1_000_000)}.rb", impossible_to_find_class_name_text(8), context_object, { },
         | 
| 340 339 | 
             
                    { :fortitude_class => 12345 })
         | 
| 341 340 | 
             
                end
         | 
| 342 | 
            -
                expect(e. | 
| 343 | 
            -
                expect(e.actual_object).to eq(12345)
         | 
| 341 | 
            +
                expect(e.tried_class_names).to be_include(12345)
         | 
| 344 342 | 
             
                expect(e.message).to match(/12345/)
         | 
| 345 343 | 
             
              end
         | 
| 346 344 |  | 
| 347 345 | 
             
              it "should fail with a nice message if you tell it to use something that isn't a widget class, using an option" do
         | 
| 348 | 
            -
                e = capture_exception(Fortitude:: | 
| 346 | 
            +
                e = capture_exception(Fortitude::Widget::Files::CannotDetermineWidgetClassNameError) do
         | 
| 349 347 | 
             
                  render_text_with_tilt("random_#{rand(1_000_000)}.rb", impossible_to_find_class_name_text(9), context_object, { },
         | 
| 350 348 | 
             
                    { :fortitude_class => "String" })
         | 
| 351 349 | 
             
                end
         | 
| 352 | 
            -
                expect(e. | 
| 353 | 
            -
                expect(e.actual_object).to eq(String)
         | 
| 350 | 
            +
                expect(e.tried_class_names).to be_include("String")
         | 
| 354 351 | 
             
                expect(e.message).to match(/String/)
         | 
| 355 352 | 
             
              end
         | 
| 356 353 |  | 
| @@ -361,22 +358,20 @@ EOS | |
| 361 358 | 
             
              end
         | 
| 362 359 |  | 
| 363 360 | 
             
              it "should fail with a nice message if you tell it to use something that isn't a class, using a comment in the template" do
         | 
| 364 | 
            -
                e = capture_exception(Fortitude:: | 
| 361 | 
            +
                e = capture_exception(Fortitude::Widget::Files::CannotDetermineWidgetClassNameError) do
         | 
| 365 362 | 
             
                  render_text_with_tilt("random_#{rand(1_000_000)}.rb",
         | 
| 366 363 | 
             
                    impossible_to_find_class_name_text(11, "#!fortitude_tilt_class: 12345"), context_object, { })
         | 
| 367 364 | 
             
                end
         | 
| 368 | 
            -
                expect(e. | 
| 369 | 
            -
                expect(e.actual_object).to be_nil
         | 
| 365 | 
            +
                expect(e.tried_class_names).to be_include("12345")
         | 
| 370 366 | 
             
                expect(e.message).to match(/12345/)
         | 
| 371 367 | 
             
              end
         | 
| 372 368 |  | 
| 373 369 | 
             
              it "should fail with a nice message if you tell it to use something that isn't a widget class, using a comment in the template" do
         | 
| 374 | 
            -
                e = capture_exception(Fortitude:: | 
| 370 | 
            +
                e = capture_exception(Fortitude::Widget::Files::CannotDetermineWidgetClassNameError) do
         | 
| 375 371 | 
             
                  render_text_with_tilt("random_#{rand(1_000_000)}.rb",
         | 
| 376 372 | 
             
                    impossible_to_find_class_name_text(12, "#!fortitude_tilt_class: String"), context_object, { })
         | 
| 377 373 | 
             
                end
         | 
| 378 | 
            -
                expect(e. | 
| 379 | 
            -
                expect(e.actual_object).to eq(String)
         | 
| 374 | 
            +
                expect(e.tried_class_names).to be_include("String")
         | 
| 380 375 | 
             
                expect(e.message).to match(/String/)
         | 
| 381 376 | 
             
              end
         | 
| 382 377 | 
             
            end
         | 
| @@ -0,0 +1,240 @@ | |
| 1 | 
            +
            require 'fileutils'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe "Fortitude widget-class-from-(file|source) support", :type => :system do
         | 
| 4 | 
            +
              def tempdir
         | 
| 5 | 
            +
                @tempdir ||= begin
         | 
| 6 | 
            +
                  out = File.join(File.dirname(File.dirname(File.dirname(__FILE__))), 'tmp', 'spec', 'widget_class_from_spec')
         | 
| 7 | 
            +
                  FileUtils.rm_rf(out)
         | 
| 8 | 
            +
                  FileUtils.mkdir_p(out)
         | 
| 9 | 
            +
                  out
         | 
| 10 | 
            +
                end
         | 
| 11 | 
            +
              end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              def splat!(filename, text)
         | 
| 14 | 
            +
                full_path = File.join(tempdir, filename)
         | 
| 15 | 
            +
                FileUtils.mkdir_p(File.dirname(full_path))
         | 
| 16 | 
            +
                File.open(full_path, 'w') { |f| f << text }
         | 
| 17 | 
            +
                full_path
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
              def wcfs(*args)
         | 
| 21 | 
            +
                ::Fortitude::Widget.widget_class_from_source(*args)
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
              def wcff(filename, *args)
         | 
| 25 | 
            +
                filename = File.join(tempdir, filename)
         | 
| 26 | 
            +
                ::Fortitude::Widget.widget_class_from_file(filename, *args)
         | 
| 27 | 
            +
              end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
              context "with no hints" do
         | 
| 30 | 
            +
                it "should return a widget subclass that's already been evaluated" do
         | 
| 31 | 
            +
                  text = "class WidgetFromClass1 < Fortitude::Widget; end"
         | 
| 32 | 
            +
                  ::Object.class_eval(text)
         | 
| 33 | 
            +
                  expect(wcfs(text)).to eq(::WidgetFromClass1)
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                it "should automatically evaluate the source, if needed" do
         | 
| 37 | 
            +
                  text = "class WidgetFromClass2 < Fortitude::Widget; end"
         | 
| 38 | 
            +
                  expect(wcfs(text)).to eq(::WidgetFromClass2)
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                it "should fail if given source code it can't guess the class name from" do
         | 
| 42 | 
            +
                  expect do
         | 
| 43 | 
            +
                    wcfs("cname = 'WidgetFromCla' + 'ss3'; eval('class ' + cname + ' < ::Fortitude::Widget; end')")
         | 
| 44 | 
            +
                  end.to raise_error(::Fortitude::Widget::Files::CannotDetermineWidgetClassNameError)
         | 
| 45 | 
            +
                end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                it "should fail if the source code contains something that isn't a widget class" do
         | 
| 48 | 
            +
                  cdne = capture_exception(::Fortitude::Widget::Files::CannotDetermineWidgetClassNameError) do
         | 
| 49 | 
            +
                    wcfs("class WidgetFromClass11; end")
         | 
| 50 | 
            +
                  end
         | 
| 51 | 
            +
                  expect(cdne.tried_class_names).to be_include("WidgetFromClass11")
         | 
| 52 | 
            +
                end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                it "should work if given something that's a grandchild of Fortitude::Widget, not a direct child" do
         | 
| 55 | 
            +
                  ::Object.class_eval("class WidgetFromClass12Parent < ::Fortitude::Widget; end")
         | 
| 56 | 
            +
                  expect(wcfs("class WidgetFromClass12 < WidgetFromClass12Parent; end")).to eq(WidgetFromClass12)
         | 
| 57 | 
            +
                end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                it "should be able to guess the class name of a class namespaced in a module" do
         | 
| 60 | 
            +
                  module ::Wcfs1; end
         | 
| 61 | 
            +
                  expect(wcfs("class Wcfs1::WidgetFromClass6 < ::Fortitude::Widget; end")).to eq(Wcfs1::WidgetFromClass6)
         | 
| 62 | 
            +
                end
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                it "should be able to guess the class name of a class nested in a module" do
         | 
| 65 | 
            +
                  expect(wcfs("module Wcfs2; class WidgetFromClass7 < ::Fortitude::Widget; end; end")).to eq(Wcfs2::WidgetFromClass7)
         | 
| 66 | 
            +
                end
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                it "should be able to guess the class name of a class nested in a module several levels deep" do
         | 
| 69 | 
            +
                  expect(wcfs("module Wcfs3; module Wcfs4; class WidgetFromClass8 < ::Fortitude::Widget; end; end; end")).to eq(Wcfs3::Wcfs4::WidgetFromClass8)
         | 
| 70 | 
            +
                end
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                it "should be able to guess the class name of a class nested in a module several levels deep, using newlines" do
         | 
| 73 | 
            +
                  expect(wcfs(%{module Wcfs5
         | 
| 74 | 
            +
              module Wcfs6
         | 
| 75 | 
            +
                class WidgetFromClass9 < ::Fortitude::Widget
         | 
| 76 | 
            +
                end
         | 
| 77 | 
            +
              end
         | 
| 78 | 
            +
            end})).to eq(Wcfs5::Wcfs6::WidgetFromClass9)
         | 
| 79 | 
            +
                end
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                it "should be able to guess the class name of a class with both nesting and namespacing" do
         | 
| 82 | 
            +
                  ::Object.class_eval %{module Wcfs7; module Wcfs8; module Wcfs9; end; end; end}
         | 
| 83 | 
            +
             | 
| 84 | 
            +
                  expect(wcfs(%{module Wcfs7
         | 
| 85 | 
            +
              module Wcfs8
         | 
| 86 | 
            +
                class Wcfs9::WidgetFromClass10 < ::Fortitude::Widget
         | 
| 87 | 
            +
                end
         | 
| 88 | 
            +
              end
         | 
| 89 | 
            +
            end})).to eq(Wcfs7::Wcfs8::Wcfs9::WidgetFromClass10)
         | 
| 90 | 
            +
                end
         | 
| 91 | 
            +
              end
         | 
| 92 | 
            +
             | 
| 93 | 
            +
              context "with an explicit class name provided" do
         | 
| 94 | 
            +
                it "should be able to get a widget class, even if it can't get it by parsing the source code" do
         | 
| 95 | 
            +
                  result = wcfs("cname = 'WidgetFromCla' + 'ss4'; eval('class ' + cname + ' < ::Fortitude::Widget; end')",
         | 
| 96 | 
            +
                    :class_names_to_try => [ 'WidgetFromClass4' ])
         | 
| 97 | 
            +
                  expect(result).to eq(WidgetFromClass4)
         | 
| 98 | 
            +
                end
         | 
| 99 | 
            +
             | 
| 100 | 
            +
                it "should be able to get a widget class, even if it can't get it by parsing the source code, if passed in among a bunch of other crap" do
         | 
| 101 | 
            +
                  result = wcfs("cname = 'WidgetFromCla' + 'ss5'; eval('class ' + cname + ' < ::Fortitude::Widget; end')",
         | 
| 102 | 
            +
                    :class_names_to_try => [ 'String', 'Integer', 'Foo::Bar::Baz', 'WidgetFromClass5', 'Baz::Quux' ])
         | 
| 103 | 
            +
                  expect(result).to eq(WidgetFromClass5)
         | 
| 104 | 
            +
                end
         | 
| 105 | 
            +
              end
         | 
| 106 | 
            +
             | 
| 107 | 
            +
              context "with a magic comment provided" do
         | 
| 108 | 
            +
                it "should be able to get a widget class, even if it can't get it by parsing the source code" do
         | 
| 109 | 
            +
                  result = wcfs(%{#!fortitude_class: WidgetFromClass13
         | 
| 110 | 
            +
                    cname = 'WidgetFromCla' + 'ss13'; eval('class ' + cname + ' < ::Fortitude::Widget; end')})
         | 
| 111 | 
            +
                  expect(result).to eq(WidgetFromClass13)
         | 
| 112 | 
            +
                end
         | 
| 113 | 
            +
             | 
| 114 | 
            +
                it "should be able to get a widget class, even if it can't get it by parsing the source code, using an alternate magic comment text" do
         | 
| 115 | 
            +
                  result = wcfs(%{#!foo_bar_baz: WidgetFromClass14
         | 
| 116 | 
            +
                    cname = 'WidgetFromCla' + 'ss14'; eval('class ' + cname + ' < ::Fortitude::Widget; end')},
         | 
| 117 | 
            +
                    :magic_comment_text => %w{bar_baz_quux foo_bar_baz foo_Bar})
         | 
| 118 | 
            +
                  expect(result).to eq(WidgetFromClass14)
         | 
| 119 | 
            +
                end
         | 
| 120 | 
            +
             | 
| 121 | 
            +
                it "should be able to get a widget class, even if it can't get it by parsing the source code, using a standard magic comment text, even if an alternate is provided" do
         | 
| 122 | 
            +
                  result = wcfs(%{#!fortitude_class: WidgetFromClass20
         | 
| 123 | 
            +
                    cname = 'WidgetFromCla' + 'ss20'; eval('class ' + cname + ' < ::Fortitude::Widget; end')},
         | 
| 124 | 
            +
                    :magic_comment_text => %w{bar_baz_quux foo_bar_baz foo_Bar})
         | 
| 125 | 
            +
                  expect(result).to eq(WidgetFromClass20)
         | 
| 126 | 
            +
                end
         | 
| 127 | 
            +
             | 
| 128 | 
            +
                it "should be able to get a widget class, even if it can't get it by parsing the source code, even at the end" do
         | 
| 129 | 
            +
                  result = wcfs(%{
         | 
| 130 | 
            +
                    cname = 'WidgetFromCla' + 'ss15'; eval('class ' + cname + ' < ::Fortitude::Widget; end')
         | 
| 131 | 
            +
            #!fortitude_class: WidgetFromClass15})
         | 
| 132 | 
            +
                  expect(result).to eq(WidgetFromClass15)
         | 
| 133 | 
            +
                end
         | 
| 134 | 
            +
             | 
| 135 | 
            +
                it "should not fail if it's wrong (something that doesn't exist)" do
         | 
| 136 | 
            +
                  text = %{#!fortitude_class: Whatever
         | 
| 137 | 
            +
            class WidgetFromClass16 < Fortitude::Widget; end}
         | 
| 138 | 
            +
                  expect(wcfs(text)).to eq(::WidgetFromClass16)
         | 
| 139 | 
            +
                end
         | 
| 140 | 
            +
             | 
| 141 | 
            +
                it "should not fail if it's wrong (something that isn't a widget class)" do
         | 
| 142 | 
            +
                  text = %{#!fortitude_class: String
         | 
| 143 | 
            +
            class WidgetFromClass17 < Fortitude::Widget; end}
         | 
| 144 | 
            +
                  expect(wcfs(text)).to eq(::WidgetFromClass17)
         | 
| 145 | 
            +
                end
         | 
| 146 | 
            +
             | 
| 147 | 
            +
                it "should tell you the magic comment texts it was looking for in the error if it can't find a class" do
         | 
| 148 | 
            +
                  cdne = capture_exception(::Fortitude::Widget::Files::CannotDetermineWidgetClassNameError) do
         | 
| 149 | 
            +
                    wcfs(%{class WidgetFromClass18; end})
         | 
| 150 | 
            +
                  end
         | 
| 151 | 
            +
                  expect(cdne.magic_comment_texts).to eq(%w{fortitude_class})
         | 
| 152 | 
            +
                end
         | 
| 153 | 
            +
             | 
| 154 | 
            +
                it "should tell you the magic comment texts it was looking for in the error if it can't find a class and custom magic texts were provided" do
         | 
| 155 | 
            +
                  cdne = capture_exception(::Fortitude::Widget::Files::CannotDetermineWidgetClassNameError) do
         | 
| 156 | 
            +
                    wcfs(%{class WidgetFromClass19; end}, :magic_comment_text => %w{foo_bar bar_baz})
         | 
| 157 | 
            +
                  end
         | 
| 158 | 
            +
                  expect(cdne.magic_comment_texts).to be_include('fortitude_class')
         | 
| 159 | 
            +
                  expect(cdne.magic_comment_texts).to be_include('foo_bar')
         | 
| 160 | 
            +
                  expect(cdne.magic_comment_texts).to be_include('bar_baz')
         | 
| 161 | 
            +
                end
         | 
| 162 | 
            +
              end
         | 
| 163 | 
            +
             | 
| 164 | 
            +
              context "when given a file" do
         | 
| 165 | 
            +
                it "should still be able to guess the class name correctly" do
         | 
| 166 | 
            +
                  splat!('widget_from_file_1.rb', %{class WidgetFromClass21 < Fortitude::Widget; end})
         | 
| 167 | 
            +
                  expect(wcff('widget_from_file_1.rb')).to eq(WidgetFromClass21)
         | 
| 168 | 
            +
                end
         | 
| 169 | 
            +
             | 
| 170 | 
            +
                it "should still be able to use magic comments" do
         | 
| 171 | 
            +
                  splat!('widget_from_file_2.rb', %{#!fortitude_class: WidgetFromClass22\ncname = 'WidgetFromCla' + 'ss22'; eval('class ' + cname + ' < ::Fortitude::Widget; end')})
         | 
| 172 | 
            +
                  expect(wcff('widget_from_file_2.rb')).to eq(WidgetFromClass22)
         | 
| 173 | 
            +
                end
         | 
| 174 | 
            +
             | 
| 175 | 
            +
                it "should be able to use a root directory to infer a class name" do
         | 
| 176 | 
            +
                  ::Object.class_eval("module Wcfs10; module Wcfs11; end; end")
         | 
| 177 | 
            +
                  splat!('wcfs10/wcfs_11/widget_from_class_23.rb', %{cname = 'WidgetFromCla' + 'ss23'; eval('class Wcfs10::Wcfs11::' + cname + ' < ::Fortitude::Widget; end')})
         | 
| 178 | 
            +
                  expect(wcff('wcfs10/wcfs_11/widget_from_class_23.rb', :root_dirs => tempdir)).to eq(Wcfs10::Wcfs11::WidgetFromClass23)
         | 
| 179 | 
            +
                end
         | 
| 180 | 
            +
             | 
| 181 | 
            +
                it "should be able to use an array of root directories to infer a class name, and find the right one" do
         | 
| 182 | 
            +
                  ::Object.class_eval("module Wcfs10; module Wcfs11; end; end")
         | 
| 183 | 
            +
                  splat!('bar/wcfs10/wcfs_11/widget_from_class_23.rb', %{cname = 'WidgetFromCla' + 'ss23'; eval('class Wcfs10::Wcfs11::' + cname + ' < ::Fortitude::Widget; end')})
         | 
| 184 | 
            +
                  expect(wcff('bar/wcfs10/wcfs_11/widget_from_class_23.rb', :root_dirs => [ "#{tempdir}/foo", "#{tempdir}/bar" ])).to eq(Wcfs10::Wcfs11::WidgetFromClass23)
         | 
| 185 | 
            +
                end
         | 
| 186 | 
            +
              end
         | 
| 187 | 
            +
             | 
| 188 | 
            +
              it "should prioritize a magic comment above class names you told it to try or directory-based names or scanned source text" do
         | 
| 189 | 
            +
                splat!('widget_baz.rb', %{
         | 
| 190 | 
            +
            #!fortitude_class: WidgetFoo
         | 
| 191 | 
            +
             | 
| 192 | 
            +
            eval('class WidgetB' +
         | 
| 193 | 
            +
            'az < Fortitud' +
         | 
| 194 | 
            +
            'e::Widget; end')
         | 
| 195 | 
            +
            eval('class WidgetB' +
         | 
| 196 | 
            +
            'ar < Fortitud' +
         | 
| 197 | 
            +
            'e::Widget; end')
         | 
| 198 | 
            +
            class WidgetQuux < Fortitude::Widget; end
         | 
| 199 | 
            +
            eval('class WidgetF' +
         | 
| 200 | 
            +
            'oo < Fortitud' +
         | 
| 201 | 
            +
            'e::Widget; end')
         | 
| 202 | 
            +
                })
         | 
| 203 | 
            +
             | 
| 204 | 
            +
                expect(wcff('widget_baz.rb', :root_dirs => tempdir, :class_names_to_try => %w{WidgetBar})).to eq(WidgetFoo)
         | 
| 205 | 
            +
              end
         | 
| 206 | 
            +
             | 
| 207 | 
            +
              it "should prioritize class names you told it to try above directory-based names or scanned source text" do
         | 
| 208 | 
            +
                splat!('widget_baz.rb', %{
         | 
| 209 | 
            +
            eval('class WidgetB' +
         | 
| 210 | 
            +
            'az < Fortitud' +
         | 
| 211 | 
            +
            'e::Widget; end')
         | 
| 212 | 
            +
            eval('class WidgetB' +
         | 
| 213 | 
            +
            'ar < Fortitud' +
         | 
| 214 | 
            +
            'e::Widget; end')
         | 
| 215 | 
            +
            class WidgetQuux < Fortitude::Widget; end
         | 
| 216 | 
            +
            eval('class WidgetF' +
         | 
| 217 | 
            +
            'oo < Fortitud' +
         | 
| 218 | 
            +
            'e::Widget; end')
         | 
| 219 | 
            +
                })
         | 
| 220 | 
            +
             | 
| 221 | 
            +
                expect(wcff('widget_baz.rb', :root_dirs => tempdir, :class_names_to_try => %w{WidgetBar})).to eq(WidgetBar)
         | 
| 222 | 
            +
              end
         | 
| 223 | 
            +
             | 
| 224 | 
            +
              it "should prioritize directory-based names above scanned source text" do
         | 
| 225 | 
            +
                splat!('widget_baz.rb', %{
         | 
| 226 | 
            +
            eval('class WidgetB' +
         | 
| 227 | 
            +
            'az < Fortitud' +
         | 
| 228 | 
            +
            'e::Widget; end')
         | 
| 229 | 
            +
            eval('class WidgetB' +
         | 
| 230 | 
            +
            'ar < Fortitud' +
         | 
| 231 | 
            +
            'e::Widget; end')
         | 
| 232 | 
            +
            class WidgetQuux < Fortitude::Widget; end
         | 
| 233 | 
            +
            eval('class WidgetF' +
         | 
| 234 | 
            +
            'oo < Fortitud' +
         | 
| 235 | 
            +
            'e::Widget; end')
         | 
| 236 | 
            +
                })
         | 
| 237 | 
            +
             | 
| 238 | 
            +
                expect(wcff('widget_baz.rb', :root_dirs => tempdir)).to eq(WidgetBaz)
         | 
| 239 | 
            +
              end
         | 
| 240 | 
            +
            end
         | 
| @@ -0,0 +1,52 @@ | |
| 1 | 
            +
            describe "Fortitude::Widget#widget method", :type => :system do
         | 
| 2 | 
            +
              let(:child_widget_class) do
         | 
| 3 | 
            +
                widget_class do
         | 
| 4 | 
            +
                  needs :value => nil
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                  def content
         | 
| 7 | 
            +
                    p "child widget: #{value.inspect}"
         | 
| 8 | 
            +
                  end
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
              end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              def parent_widget_class(&block)
         | 
| 13 | 
            +
                out = widget_class do
         | 
| 14 | 
            +
                  class << self
         | 
| 15 | 
            +
                    attr_accessor :child_widget_class
         | 
| 16 | 
            +
                  end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                  def child_widget_class
         | 
| 19 | 
            +
                    self.class.child_widget_class
         | 
| 20 | 
            +
                  end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                  define_method(:content, &block)
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                out.child_widget_class = child_widget_class
         | 
| 26 | 
            +
                out
         | 
| 27 | 
            +
              end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
              it "should let you render one widget from another by specifying it as an instance" do
         | 
| 30 | 
            +
                expect(render(parent_widget_class { text "before"; widget child_widget_class.new; text "after" })).to eq(
         | 
| 31 | 
            +
                  "before<p>child widget: nil</p>after")
         | 
| 32 | 
            +
              end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
              it "should let you render one widget from another by specifying it as an instance, passing parameters" do
         | 
| 35 | 
            +
                expect(render(parent_widget_class { text "before"; widget child_widget_class.new(:value => 123); text "after" })).to eq(
         | 
| 36 | 
            +
                  "before<p>child widget: 123</p>after")
         | 
| 37 | 
            +
              end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
              it "should let you render one widget from another by specifying it as just a class" do
         | 
| 40 | 
            +
                expect(render(parent_widget_class { text "before"; widget child_widget_class; text "after" })).to eq(
         | 
| 41 | 
            +
                  "before<p>child widget: nil</p>after")
         | 
| 42 | 
            +
              end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
              it "should let you render one widget from another by specifying it as a class, and a hash of parameters" do
         | 
| 45 | 
            +
                expect(render(parent_widget_class { text "before"; widget child_widget_class, :value => 123; text "after" })).to eq(
         | 
| 46 | 
            +
                  "before<p>child widget: 123</p>after")
         | 
| 47 | 
            +
              end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
              it "should not let you specify anything but a Hash as the second parameter" do
         | 
| 50 | 
            +
                expect { render(parent_widget_class { text "before"; widget child_widget_class, 123; text "after" }) }.to raise_error
         | 
| 51 | 
            +
              end
         | 
| 52 | 
            +
            end
         |