Skip to content

Commit

Permalink
Merge 4a7b558 into 8ba1525
Browse files Browse the repository at this point in the history
  • Loading branch information
romikoops committed Nov 4, 2016
2 parents 8ba1525 + 4a7b558 commit e373edb
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 3 deletions.
34 changes: 31 additions & 3 deletions lib/howitzer/web/page_dsl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ class PageScope

def initialize(page_klass, &block)
self.page_klass = page_klass
self.outer_context = eval('self', block.binding) if block.present?
instance_eval(&block)
end

Expand All @@ -20,10 +21,16 @@ def is_expected # rubocop:disable Style/PredicateName
expect(page_klass.given)
end

# Proxies all methods to page instance except methods with be_ and have_ prefixes
# Proxies all methods to a page instance.
#
# @note There are some exceptions:
# * Methods with `be_` and `have_` prefixes are excluded
# * `out` method extracts an instance variable from an original context it starts from @.
# Otherwise it executes a method from an original context

def method_missing(name, *args, &block)
return super if name =~ /\A(?:be|have)_/
return eval_in_out_context(*args, &block) if name == :out
page_klass.given.send(name, *args, &block)
end

Expand All @@ -36,7 +43,18 @@ def respond_to_missing?(name, include_private = false)

private

attr_accessor :page_klass
def eval_in_out_context(*args, &block)
return nil if args.size.zero?
name = args.shift
return get_outer_instance_variable(name) if name.to_s.start_with?('@')
outer_context.send(name, *args, &block)
end

def get_outer_instance_variable(name)
outer_context.instance_variable_get(name)
end

attr_accessor :page_klass, :outer_context
end

def self.included(base)
Expand All @@ -47,12 +65,22 @@ module ClassMethods
# Allows to execute page methods in context of the page.
# @note It additionally checks the page is really displayed
# on each method call, otherwise it raises error
# @example
# @example Standard case
# LoginPage.open
# LoginPage.on do
# fill_form(name: 'John', email: 'jkarpensky@gmail.com')
# submit_form
# end
# @example More complex case with outer context
# @name = 'John'
# def email(domain = 'gmail.com')
# "jkarpensky@#{domain}"
# end
# LoginPage.open
# LoginPage.on do
# fill_form(name: out(:@name), email: out(:email, 'yahoo.com'))
# submit_form
# end

def on(&block)
PageScope.new(self, &block)
Expand Down
22 changes: 22 additions & 0 deletions spec/unit/lib/web/page_dsl_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,28 @@
it { expect(subject.class).to eq(RSpec::Matchers::BuiltIn::Has) }
end

context 'when out' do
let(:outer_context) do
Class.new do
def initialize(klass)
@klass = klass
@a = 5
end

def scope
@klass.new(nil) { 1 }
end

def secret
'***'
end
end
end
let(:scope) { outer_context.new(described_class).scope }
it { expect(scope.out(:@a)).to eq(5) }
it { expect(scope.out(:secret)).to eq('***') }
end

context 'when starts other prefix' do
let(:scope) { described_class.new(page) { 1 } }
subject { scope.foo(1, 2, 3) }
Expand Down

0 comments on commit e373edb

Please sign in to comment.