require 'howitzer/web/capybara_context_holder'
module Howitzer
module Web
# This module combines iframe dsl methods
module IframeDsl
include CapybaraContextHolder
def self.included(base) #:nodoc:
base.extend(ClassMethods)
end
private
def iframe_element_selector(args, params)
args = convert_iframe_arguments(args, params)
case args[0]
when String, Hash
[:frame, *args]
when Integer
idx = args.shift
["iframe:nth-of-type(#{idx + 1})", *args]
else
args
end
end
def convert_iframe_arguments(args, params)
new_args = args.deep_dup
hash = new_args.pop.merge(params) if new_args.last.is_a?(Hash)
new_args << hash if hash.present?
new_args
end
# This module holds frame dsl class methods
module ClassMethods
protected
# Creates a group of methods to interact with described HTML frame on page
# @note This method generates following dynamic methods:
#
# frame_name_iframe - equals capybara #within_frame(...) method
#
# has_frame_name_iframe? - equals capybara #has_selector(...) method
#
# has_no_frame_name_iframe? - equals capybara #has_no_selector(...) method
# @param name [Symbol, String] an unique iframe name
# @param args [Array] original Capybara arguments. For details, see `Capybara::Session#within_frame`.
# @example Using in a page class
# class FbPage < Howitzer::Web::Page
# element :like, :xpath, ".//*[text()='Like']"
# def like
# like_element.click
# end
#
# def liked?
# #some code here
# end
# end
#
# class HomePage < Howitzer::Web::Page
# iframe :fb, 1
# end
#
# HomePage.on do
# fb_iframe do |frame|
# frame.like
# expect(frame).to be_liked
# end
# end
# HomePage.on { is_expected.to have_fb_iframe }
# @!visibility public
def iframe(name, *args)
raise ArgumentError, 'iframe selector arguments must be specified' if args.blank?
klass = "#{name}_page".classify.constantize
define_iframe(klass, name, args)
define_has_iframe(name, args)
define_has_no_iframe(name, args)
end
private
def define_iframe(klass, name, args)
define_method "#{name}_iframe" do |**params, &block|
capybara_context.within_frame(*convert_iframe_arguments(args, params)) do
klass.displayed?
block.call klass.instance
end
end
end
def define_has_iframe(name, args)
define_method("has_#{name}_iframe?") do |**params|
capybara_context.has_selector?(*iframe_element_selector(args, params))
end
end
def define_has_no_iframe(name, args)
define_method("has_no_#{name}_iframe?") do |**params|
capybara_context.has_no_selector?(*iframe_element_selector(args, params))
end
end
end
end
end
end