Skip to content

Commit

Permalink
Contains work
Browse files Browse the repository at this point in the history
  • Loading branch information
joshuaclayton committed Aug 2, 2023
1 parent 9c8e1d4 commit 0604c00
Show file tree
Hide file tree
Showing 2 changed files with 249 additions and 0 deletions.
15 changes: 15 additions & 0 deletions lib/page_ez/page.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,21 @@ def self.base_selector(value)
self.container_base_selector = value
end

def self.contains(page_object, only: nil)
delegation_target = :"__page_object_#{page_object.object_id}__"

has_one(delegation_target, page_object)

if only
methods_delegated_that_do_not_exist = only - page_object.instance_methods(false)
if methods_delegated_that_do_not_exist.any?
raise NoMethodError, "Attempting to delegate non-existent method(s) to #{page_object}: #{methods_delegated_that_do_not_exist.join(", ")}"
end
end

delegate(*(only || page_object.instance_methods(false)), to: delegation_target)
end

def initialize(container = nil)
@container = container || Class.new do
include Capybara::DSL
Expand Down
234 changes: 234 additions & 0 deletions spec/features/contains_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
require "spec_helper"

RSpec.describe "contains" do
it "pulls in everything from the corresponding PageEz::Page" do
page = build_page(<<-HTML)
<heading data-role="primary">
<h1>Application Title</h1>
</heading>
<main>
<h2>Awesome Site</h2>
</main>
<footer data-role="primary">
<p data-role=copyright>Copyright 2023 Company Name</p>
</footer>
HTML

heading = Class.new(PageEz::Page) do
base_selector "heading[data-role=primary]"

has_one :application_title, "h1"
end

footer = Class.new(PageEz::Page) do
base_selector "footer[data-role=primary]"

has_one :copyright, "p[data-role=copyright]"

def awesome?
true
end
end

test_page = Class.new(PageEz::Page) do
contains heading
contains footer

has_one :main do
has_one :heading, "h2"
end
end.new(page)

page.visit "/"

expect(test_page.application_title).to have_text("Application Title")
expect(test_page).to have_application_title(text: "Application Title")

expect(test_page.main).to have_heading(text: "Awesome Site")
expect(test_page).to have_copyright(text: "Copyright 2023 Company Name")
expect(test_page).to be_awesome
end

it "allows for delegating only a subset of methods" do
page = build_page(<<-HTML)
<heading data-role="primary">
<h1>Application Title</h1>
</heading>
<main>
<h2>Awesome Site</h2>
</main>
<footer data-role="primary">
<p data-role=copyright>Copyright 2023 Company Name</p>
</footer>
HTML

footer = Class.new(PageEz::Page) do
base_selector "footer[data-role=primary]"

has_one :copyright, "p[data-role=copyright]"

def awesome?
true
end
end

test_page = Class.new(PageEz::Page) do
contains footer, only: %i[has_copyright?]

def awesome?
false
end
end.new(page)

page.visit "/"

expect(test_page).to have_copyright(text: "Copyright 2023 Company Name")
expect(test_page).not_to be_awesome
end

it "applies base selectors to contained pages" do
page = build_page(<<-HTML)
<ul data-role="complete-todos">
<li data-role="todo">
<span data-role="name">Buy milk</span>
<button data-role="toggle-complete">Mark Incomplete</button>
</li>
</ul>
<ul data-role="incomplete-todos">
<li data-role="todo">
<span data-role="name">Buy eggs</span>
<button data-role="toggle-complete">Mark Complete</button>
</li>
</ul>
HTML

todo_list = Class.new(PageEz::Page) do
has_many_ordered :items, "li[data-role=todo]" do
has_one :name, "span[data-role=name]"
has_one :toggle_complete_button, "[data-role=toggle-complete]"
end
end

complete_todos = Class.new(PageEz::Page) do
base_selector "ul[data-role=complete-todos]"

contains todo_list
end.new(page)

incomplete_todos = Class.new(PageEz::Page) do
base_selector "ul[data-role=incomplete-todos]"

contains todo_list
end.new(page)

page.visit "/"

expect(complete_todos.item_at(0)).to have_name(text: "Buy milk")
expect(complete_todos.item_at(0)).to have_toggle_complete_button(text: "Mark Incomplete")

expect(incomplete_todos.item_at(0)).to have_name(text: "Buy eggs")
expect(incomplete_todos.item_at(0)).to have_toggle_complete_button(text: "Mark Complete")
end

it "raises when macros collide" do
nav = Class.new(PageEz::Page) do
has_many :links, "a"
end

expect do
Class.new(PageEz::Page) do
contains nav

has_many :links, "li a"
end
end.to raise_error(PageEz::DuplicateElementDeclarationError)

expect do
Class.new(PageEz::Page) do
has_many :links, "li a"

contains nav
end
end.to raise_error(PageEz::DuplicateElementDeclarationError)
end

it "raises when instance methods collide" do
nav = Class.new(PageEz::Page) do
def awesome?
true
end
end

expect do
Class.new(PageEz::Page) do
contains nav

def awesome?
false
end
end
end.to raise_error(PageEz::DuplicateElementDeclarationError)

expect do
Class.new(PageEz::Page) do
def awesome?
false
end

contains nav
end
end.to raise_error(PageEz::DuplicateElementDeclarationError)
end

it "raises when instance methods collide with element names" do
nav = Class.new(PageEz::Page) do
has_many :links, "a"
end

expect do
Class.new(PageEz::Page) do
contains nav

def links
"whoops"
end
end
end.to raise_error(PageEz::DuplicateElementDeclarationError)

expect do
Class.new(PageEz::Page) do
def links
"whoops"
end

contains nav
end
end.to raise_error(PageEz::DuplicateElementDeclarationError)
end

it "does not raise when instance methods collide with element names in nested pages" do
nav = Class.new(PageEz::Page) do
has_many :links, "a"
end

expect do
Class.new(PageEz::Page) do
contains nav

has_one :header do
has_many :links, "a"
end
end
end.not_to raise_error
end

it "raises NoMethodError when attempting to contains->delegate a method that does not exist" do
footer = Class.new(PageEz::Page)

expect do
Class.new(PageEz::Page) do
contains footer, only: %i[bogus]
end
end.to raise_error(NoMethodError, /Attempting to delegate.*to #{footer}: bogus/)
end
end

0 comments on commit 0604c00

Please sign in to comment.