From 565bb4aab413887d225a94d034d0905c9fb4078b Mon Sep 17 00:00:00 2001 From: yunlei Date: Wed, 17 Sep 2014 22:46:55 -0700 Subject: [PATCH] fix change_to bug --- lib/ae_page_objects/document_loader.rb | 10 +---- lib/ae_page_objects/document_proxy.rb | 31 ++++++-------- lib/ae_page_objects/document_query.rb | 8 ++++ lib/ae_page_objects/exceptions.rb | 2 + .../multiple_windows/browser.rb | 5 ++- .../cross_window_loader_strategy.rb | 4 +- .../same_window_loader_strategy.rb | 4 +- lib/ae_page_objects/single_window/window.rb | 3 +- test/test_apps/shared/db/schema.rb | 38 +++++++++++++++++ .../selenium/page_object_integration_test.rb | 28 +++++++++++-- test/unit/document_proxy_test.rb | 20 ++++----- test/unit/document_query_test.rb | 42 ++++++++++++++++++- test/unit/multiple_windows/browser_test.rb | 4 +- .../cross_window_loader_strategy_test.rb | 8 ++-- test/unit/page_loader_test.rb | 35 +++------------- .../same_window_loader_strategy_test.rb | 6 +-- 16 files changed, 159 insertions(+), 89 deletions(-) create mode 100644 test/test_apps/shared/db/schema.rb diff --git a/lib/ae_page_objects/document_loader.rb b/lib/ae_page_objects/document_loader.rb index 791c40a5..229b579e 100644 --- a/lib/ae_page_objects/document_loader.rb +++ b/lib/ae_page_objects/document_loader.rb @@ -5,14 +5,6 @@ def initialize(query, strategy) @strategy = strategy end - def default_document_class - @default_document_class ||= @query.conditions.first.document_class - end - - def permitted_types_dump - @permitted_types_dump ||= @query.conditions.map(&:document_class).map(&:name).inspect - end - def load Waiter.wait_for do @query.conditions.each do |document_condition| @@ -24,7 +16,7 @@ def load nil end - raise @strategy.document_not_loaded_error(self) + raise DocumentLoadError, @strategy.document_not_loaded_error_message(@query) end end end diff --git a/lib/ae_page_objects/document_proxy.rb b/lib/ae_page_objects/document_proxy.rb index f1fb31cf..0c182d87 100644 --- a/lib/ae_page_objects/document_proxy.rb +++ b/lib/ae_page_objects/document_proxy.rb @@ -1,21 +1,16 @@ module AePageObjects class DocumentProxy - - # Remove all instance methods so even things like class() - # get handled by method_missing(). instance_methods.each do |m| - unless m.to_s =~ /^(?:nil\?|send|object_id|to_a|tap)$|^__|^respond_to|is_a?|instance_variable_get/ - undef_method m - end + undef_method(m) if m.to_s !~ /(?:^__|^nil?$|^send$|^object_id$|instance_variable_get)/ end - def initialize(loaded_page, document_loader) - @loaded_page = loaded_page - @document_loader = document_loader + def initialize(loaded_page, query) + @loaded_page = loaded_page + @query = query end def is_a?(document_class) - super || @loaded_page.is_a?(document_class) + super || @loaded_page.is_a?(document_class) end def as_a(document_class) @@ -23,25 +18,25 @@ def as_a(document_class) return @loaded_page end - raise DocumentLoadError, "#{document_class.name} not expected. Allowed types: #{@document_loader.permitted_types_dump}" + raise CastError, "Loaded page is not a #{document_class.name}. Allowed pages: #{@query.permitted_types_dump}" end private def implicit_document - @implicit_document ||= as_a(implicit_document_class) - end - - def implicit_document_class - @implicit_document_class ||= @document_loader.default_document_class + if @loaded_page.is_a? @query.default_document_class + @loaded_page + else + raise CastError, "#{@query.default_document_class} expected, but #{@loaded_page.class} loaded" + end end def method_missing(name, *args, &block) implicit_document.__send__(name, *args, &block) end - def respond_to?(*args) - super || implicit_document_class.allocate.respond_to?(*args) + def respond_to_missing?(*args) + super || implicit_document.respond_to?(*args) end end end diff --git a/lib/ae_page_objects/document_query.rb b/lib/ae_page_objects/document_query.rb index f8db5c46..b5190dbe 100644 --- a/lib/ae_page_objects/document_query.rb +++ b/lib/ae_page_objects/document_query.rb @@ -64,5 +64,13 @@ def initialize(*document_classes, &block) def matches(document_class, conditions = {}, &block_condition) @conditions << Condition.new(document_class, conditions, &block_condition) end + + def default_document_class + @default_document_class ||= conditions.first.document_class + end + + def permitted_types_dump + @permitted_types_dump ||= conditions.map(&:document_class).map(&:name).inspect + end end end diff --git a/lib/ae_page_objects/exceptions.rb b/lib/ae_page_objects/exceptions.rb index 57ed3c5f..1d8bb05d 100644 --- a/lib/ae_page_objects/exceptions.rb +++ b/lib/ae_page_objects/exceptions.rb @@ -18,4 +18,6 @@ class PathNotResolvable < Error class DocumentLoadError < Error end + class CastError < Error + end end diff --git a/lib/ae_page_objects/multiple_windows/browser.rb b/lib/ae_page_objects/multiple_windows/browser.rb index d3b59891..7c8781b5 100644 --- a/lib/ae_page_objects/multiple_windows/browser.rb +++ b/lib/ae_page_objects/multiple_windows/browser.rb @@ -14,9 +14,10 @@ def current_window def find_document(*document_classes, &block) query = DocumentQuery.new(*document_classes, &block) document_loader = DocumentLoader.new(query, CrossWindowLoaderStrategy.new(@windows)) + loaded_page = document_loader.load - DocumentProxy.new(document_loader.load, document_loader) + DocumentProxy.new(loaded_page, query) end end end -end \ No newline at end of file +end diff --git a/lib/ae_page_objects/multiple_windows/cross_window_loader_strategy.rb b/lib/ae_page_objects/multiple_windows/cross_window_loader_strategy.rb index 6be3be99..52e34d43 100644 --- a/lib/ae_page_objects/multiple_windows/cross_window_loader_strategy.rb +++ b/lib/ae_page_objects/multiple_windows/cross_window_loader_strategy.rb @@ -36,13 +36,13 @@ def load_document_with_condition(condition) nil end - def document_not_loaded_error(document_loader) + def document_not_loaded_error_message(query) all_windows = @window_list.opened.map do |window| name = window.current_document && window.current_document.to_s || "" {:window_handle => window.handle, :document => name } end - DocumentLoadError.new("Couldn't find document with type in #{document_loader.permitted_types_dump} in any of the open windows: #{all_windows.inspect}") + "Couldn't find document with type in #{query.permitted_types_dump} in any of the open windows: #{all_windows.inspect}" end end end diff --git a/lib/ae_page_objects/single_window/same_window_loader_strategy.rb b/lib/ae_page_objects/single_window/same_window_loader_strategy.rb index 5f67e959..bc32ef0c 100644 --- a/lib/ae_page_objects/single_window/same_window_loader_strategy.rb +++ b/lib/ae_page_objects/single_window/same_window_loader_strategy.rb @@ -11,8 +11,8 @@ def load_document_with_condition(condition) end end - def document_not_loaded_error(document_loader) - DocumentLoadError.new("Current window does not contain document with type in #{document_loader.permitted_types_dump}.") + def document_not_loaded_error_message(query) + "Current window does not contain document with type in #{query.permitted_types_dump}." end private diff --git a/lib/ae_page_objects/single_window/window.rb b/lib/ae_page_objects/single_window/window.rb index 77649001..816ec526 100644 --- a/lib/ae_page_objects/single_window/window.rb +++ b/lib/ae_page_objects/single_window/window.rb @@ -15,8 +15,9 @@ def current_document=(document) def change_to(*document_classes, &block) query = DocumentQuery.new(*document_classes, &block) document_loader = DocumentLoader.new(query, SameWindowLoaderStrategy.new) + loaded_page = document_loader.load - DocumentProxy.new(document_loader.load, document_loader) + DocumentProxy.new(loaded_page, query) end end end diff --git a/test/test_apps/shared/db/schema.rb b/test/test_apps/shared/db/schema.rb new file mode 100644 index 00000000..2b1e288b --- /dev/null +++ b/test/test_apps/shared/db/schema.rb @@ -0,0 +1,38 @@ +# encoding: UTF-8 +# This file is auto-generated from the current state of the database. Instead +# of editing this file, please use the migrations feature of Active Record to +# incrementally modify your database, and then regenerate this schema definition. +# +# Note that this schema.rb definition is the authoritative source for your +# database schema. If you need to create the application database on another +# system, you should be using db:schema:load, not running all the migrations +# from scratch. The latter is a flawed and unsustainable approach (the more migrations +# you'll amass, the slower it'll run and the greater likelihood for issues). +# +# It's strongly recommended to check this file into your version control system. + +ActiveRecord::Schema.define(:version => 1) do + + create_table "authors", :force => true do |t| + t.integer "lock_version" + t.string "first_name" + t.string "last_name" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "books", :force => true do |t| + t.integer "lock_version" + t.integer "author_id" + t.string "title" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "indices", :force => true do |t| + t.integer "lock_version" + t.integer "pages" + t.integer "book_id" + end + +end diff --git a/test/test_apps/shared/test/selenium/page_object_integration_test.rb b/test/test_apps/shared/test/selenium/page_object_integration_test.rb index 930243f5..bdfbbe5c 100644 --- a/test/test_apps/shared/test/selenium/page_object_integration_test.rb +++ b/test/test_apps/shared/test/selenium/page_object_integration_test.rb @@ -76,7 +76,7 @@ def test_document_proxy new_page.index.pages.set "132" result_page = new_page.save! - assert_equal true, result_page.is_a?(AePageObjects::DocumentProxy) + assert_equal false, result_page.is_a?(AePageObjects::DocumentProxy) assert_equal true, result_page.is_a?(PageObjects::Books::NewPage) assert_equal false, result_page.is_a?(PageObjects::Authors::NewPage) @@ -96,16 +96,36 @@ def test_document_proxy result_page = edit_page.save! - assert_raises AePageObjects::DocumentLoadError do + assert_raises AePageObjects::CastError do result_page.as_a(PageObjects::Authors::NewPage) end # test an incorrect cast - assert_raises AePageObjects::DocumentLoadError do + assert_raises AePageObjects::CastError do result_page.as_a(PageObjects::Books::EditPage) end end - + + def test_window_change_to + visit("/books/new") + + result_page = AePageObjects.browser.current_window.change_to(PageObjects::Authors::NewPage, + PageObjects::Books::NewPage) + + assert_equal true, result_page.is_a?(PageObjects::Books::NewPage) + + # implicit access attempts to use default document class + raised = assert_raises AePageObjects::CastError do + result_page.rating + end + + assert_equal "PageObjects::Authors::NewPage expected, but PageObjects::Books::NewPage loaded", raised.message + + books_new_page = result_page.as_a(PageObjects::Books::NewPage) + + assert_equal PageObjects::Books::NewPage, books_new_page.class + end + def test_element_proxy author = PageObjects::Authors::NewPage.visit diff --git a/test/unit/document_proxy_test.rb b/test/unit/document_proxy_test.rb index 3a5527a3..1148c357 100644 --- a/test/unit/document_proxy_test.rb +++ b/test/unit/document_proxy_test.rb @@ -1,5 +1,4 @@ require 'unit_helper' - module AePageObjects class DocumentProxyTest < Test::Unit::TestCase @@ -35,24 +34,23 @@ def test_as_a__error proxy = DocumentProxy.new(loaded_page, page_loader) - raised = assert_raise DocumentLoadError do + raised = assert_raise CastError do proxy.as_a(DocumentClass2) end - assert_equal "AePageObjects::DocumentProxyTest::DocumentClass2 not expected. Allowed types: permitted_types_dump", raised.message + assert_equal "Loaded page is not a AePageObjects::DocumentProxyTest::DocumentClass2. Allowed pages: permitted_types_dump", raised.message end def test_methods_are_forwarded - loaded_page = Class.new(DocumentClass) do - def hello_kitty - :meow - end - end.new + loaded_page = DocumentClass.new + def loaded_page.hello_kitty + :meow + end - page_loader = mock - page_loader.expects(:default_document_class).returns(DocumentClass) + query = mock + query.expects(:default_document_class).times(3).returns(DocumentClass) - proxy = DocumentProxy.new(loaded_page, page_loader) + proxy = DocumentProxy.new(loaded_page, query) assert_equal :meow, proxy.hello_kitty # memoized diff --git a/test/unit/document_query_test.rb b/test/unit/document_query_test.rb index 4384df44..0af323d3 100644 --- a/test/unit/document_query_test.rb +++ b/test/unit/document_query_test.rb @@ -1,8 +1,46 @@ require 'unit_helper' - module AePageObjects class DocumentQueryTest < Test::Unit::TestCase + + def test_default_document_class + hello_class = ::AePageObjects::Document.new_subclass + kitty_class = ::AePageObjects::Document.new_subclass + + + document_query = DocumentQuery.new do |query| + query.matches(hello_class) + query.matches(kitty_class) + end + + assert_equal hello_class, document_query.default_document_class + end + + def test_permitted_types_dump + + hello_class = ::AePageObjects::Document.new_subclass do + def self.name + "hello" + end + end + + kitty_class = ::AePageObjects::Document.new_subclass do + def self.name + "kitty" + end + end + + document_query = DocumentQuery.new do |query| + query.matches(hello_class) + query.matches(kitty_class) + end + + assert_equal ["hello", "kitty"].inspect, document_query.permitted_types_dump + + # it's memoized + #assert_equal ["AePageObjects::DocumentLoaderTest::DocumentClass1", "AePageObjects::DocumentLoaderTest::DocumentClass2"].inspect, loader.permitted_types_dump + end + def test_query_conditions block_condition = proc do |page| page.is_starbucks? @@ -97,4 +135,4 @@ def setup_page_for_conditions(options = {}) stub(:current_url => options[:current_url], :is_starbucks? => options[:is_starbucks?]) end end -end \ No newline at end of file +end diff --git a/test/unit/multiple_windows/browser_test.rb b/test/unit/multiple_windows/browser_test.rb index 01808fd2..c18acf89 100644 --- a/test/unit/multiple_windows/browser_test.rb +++ b/test/unit/multiple_windows/browser_test.rb @@ -28,7 +28,7 @@ def test_find_document proxy = browser.find_document(document_class, :ignore_current => true, &the_block) assert_equal true, proxy.is_a?(DocumentProxy) - assert_equal document_loader, proxy.instance_variable_get(:@document_loader) + assert_equal :loaded_page, proxy.instance_variable_get(:@loaded_page) query_conditions = query.conditions assert_equal 1, query_conditions.size @@ -45,4 +45,4 @@ def test_find_document end end end -end \ No newline at end of file +end diff --git a/test/unit/multiple_windows/cross_window_loader_strategy_test.rb b/test/unit/multiple_windows/cross_window_loader_strategy_test.rb index 138f7c72..a53e4827 100644 --- a/test/unit/multiple_windows/cross_window_loader_strategy_test.rb +++ b/test/unit/multiple_windows/cross_window_loader_strategy_test.rb @@ -119,9 +119,9 @@ def test_document_not_loaded_error ) loader = CrossWindowLoaderStrategy.new(window_list) - page_loader = mock(:permitted_types_dump => "permitted_types_dump") + query = mock(:permitted_types_dump => "permitted_types_dump") - error = loader.document_not_loaded_error(page_loader) + error = loader.document_not_loaded_error_message(query) all_windows_dump = [ {:window_handle => "window1", :document => "Document1"}, @@ -129,8 +129,8 @@ def test_document_not_loaded_error {:window_handle => "window3", :document => "Document3"}, ] - assert_equal "Couldn't find document with type in permitted_types_dump in any of the open windows: #{all_windows_dump.inspect}", error.message + assert_equal "Couldn't find document with type in permitted_types_dump in any of the open windows: #{all_windows_dump.inspect}", error end end end -end \ No newline at end of file +end diff --git a/test/unit/page_loader_test.rb b/test/unit/page_loader_test.rb index 299aa2de..3714d9ea 100644 --- a/test/unit/page_loader_test.rb +++ b/test/unit/page_loader_test.rb @@ -1,5 +1,4 @@ require 'unit_helper' - module AePageObjects class DocumentLoaderTest < Test::Unit::TestCase @@ -20,28 +19,6 @@ class DocumentClass1; end class DocumentClass2; end class DocumentClass3; end - def test_default_document_class - query = mock(:conditions => [mock(:document_class => DocumentClass1), stub(:document_class => DocumentClass2)]) - strategy = mock - - loader = DocumentLoader.new(query, strategy) - assert_equal DocumentClass1, loader.default_document_class - - # it's memoized - assert_equal DocumentClass1, loader.default_document_class - end - - def test_permitted_types_dump - query = mock(:conditions => [mock(:document_class => DocumentClass1), mock(:document_class => DocumentClass2)]) - strategy = mock - - loader = DocumentLoader.new(query, strategy) - assert_equal ["AePageObjects::DocumentLoaderTest::DocumentClass1", "AePageObjects::DocumentLoaderTest::DocumentClass2"].inspect, loader.permitted_types_dump - - # it's memoized - assert_equal ["AePageObjects::DocumentLoaderTest::DocumentClass1", "AePageObjects::DocumentLoaderTest::DocumentClass2"].inspect, loader.permitted_types_dump - end - def test_load_page query = stub(:conditions => [ stub(:document_class => DocumentClass1), @@ -77,14 +54,14 @@ def test_load_page__document_not_loaded_error strategy.expects(:load_document_with_condition).in_sequence(sequence).with(query.conditions[1]).returns(nil) strategy.expects(:load_document_with_condition).in_sequence(sequence).with(query.conditions[2]).returns(nil) - error = RuntimeError.new("Hello") - strategy.expects(:document_not_loaded_error).with(loader).returns(error) + error = DocumentLoadError.new('hello') + strategy.expects(:document_not_loaded_error_message).with(query).returns("hello") raised = assert_raise error.class do loader.load end - assert_equal error, raised + assert_equal error.message, raised.message end def test_load_page__timeout @@ -105,14 +82,14 @@ def test_load_page__timeout strategy.expects(:load_document_with_condition).in_sequence(sequence).with(query.conditions.first).returns(nil) strategy.expects(:load_document_with_condition).in_sequence(sequence).with(query.conditions.last).returns(nil) - error = RuntimeError.new("") - strategy.expects(:document_not_loaded_error).with(loader).returns(error) + error = DocumentLoadError.new("hello") + strategy.expects(:document_not_loaded_error_message).with(query).returns(error) raised = assert_raise error.class do loader.load end - assert_equal error, raised + assert_equal error.message, raised.message end end end diff --git a/test/unit/single_window/same_window_loader_strategy_test.rb b/test/unit/single_window/same_window_loader_strategy_test.rb index 14a946fb..29ba6f80 100644 --- a/test/unit/single_window/same_window_loader_strategy_test.rb +++ b/test/unit/single_window/same_window_loader_strategy_test.rb @@ -41,11 +41,11 @@ def test_load_page_with_condition__loading_failed def test_document_not_loaded_error loader = SameWindowLoaderStrategy.new - page_loader = mock(:permitted_types_dump => "permitted_types_dump") + query = mock(:permitted_types_dump => "permitted_types_dump") - error = loader.document_not_loaded_error(page_loader) + error = loader.document_not_loaded_error_message(query) - assert_equal "Current window does not contain document with type in permitted_types_dump.", error.message + assert_equal "Current window does not contain document with type in permitted_types_dump.", error end end end