Skip to content

Commit

Permalink
fix change_to bug
Browse files Browse the repository at this point in the history
  • Loading branch information
yunlei committed Sep 23, 2014
1 parent 0ed0c32 commit 565bb4a
Show file tree
Hide file tree
Showing 16 changed files with 159 additions and 89 deletions.
10 changes: 1 addition & 9 deletions lib/ae_page_objects/document_loader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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|
Expand All @@ -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
31 changes: 13 additions & 18 deletions lib/ae_page_objects/document_proxy.rb
Original file line number Diff line number Diff line change
@@ -1,47 +1,42 @@
module AePageObjects
class DocumentProxy

# Remove all instance methods so even things like class()
# get handled by method_missing(). <lifted from activerecord>
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)
if @loaded_page.is_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
8 changes: 8 additions & 0 deletions lib/ae_page_objects/document_query.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 2 additions & 0 deletions lib/ae_page_objects/exceptions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,6 @@ class PathNotResolvable < Error

class DocumentLoadError < Error
end
class CastError < Error
end
end
5 changes: 3 additions & 2 deletions lib/ae_page_objects/multiple_windows/browser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
end
Original file line number Diff line number Diff line change
Expand Up @@ -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 || "<none>"
{: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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion lib/ae_page_objects/single_window/window.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
38 changes: 38 additions & 0 deletions test/test_apps/shared/db/schema.rb
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -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

Expand Down
20 changes: 9 additions & 11 deletions test/unit/document_proxy_test.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
require 'unit_helper'

module AePageObjects
class DocumentProxyTest < Test::Unit::TestCase

Expand Down Expand Up @@ -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
Expand Down
42 changes: 40 additions & 2 deletions test/unit/document_query_test.rb
Original file line number Diff line number Diff line change
@@ -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?
Expand Down Expand Up @@ -97,4 +135,4 @@ def setup_page_for_conditions(options = {})
stub(:current_url => options[:current_url], :is_starbucks? => options[:is_starbucks?])
end
end
end
end
4 changes: 2 additions & 2 deletions test/unit/multiple_windows/browser_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -45,4 +45,4 @@ def test_find_document
end
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -119,18 +119,18 @@ 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"},
{:window_handle => "window2", :document => "<none>"},
{: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
end
Loading

0 comments on commit 565bb4a

Please sign in to comment.