lib/bauxite/core/context.rb in bauxite-0.4.2 vs lib/bauxite/core/context.rb in bauxite-0.4.3

- old
+ new

@@ -37,10 +37,54 @@ # Bauxite Namespace module Bauxite # The Main test context. This class includes state and helper functions # used by clients execute tests and by actions and selectors to interact # with the test engine (i.e. Selenium WebDriver). + # + # === Context variables + # Context variables are a key/value pairs scoped to the a test context. + # + # Variables can be set using different actions. For example: + # - Action#set sets a variable to a literal string. + # - Action#store sets a variable to the value of an element in the page. + # - Action#exec sets a variable to the output of an external command + # (i.e. stdout). + # - Action#js sets a variable to the result of Javascript command. + # - Action#replace sets a variable to the result of doing a + # find-and-replace operation on a literal. + # + # Variables can be expanded in every Action argument (e.g. selectors, + # texts, expressions, etc.). To obtain the value of a variable through + # variable expansion the following syntax must be used: + # ${var_name} + # + # For example: + # set field "greeting" + # set name "John" + # write "${field}_textbox" "Hi, my name is ${name}!" + # click "${field}_button" + # + # === Variable scope + # When the main test starts (via the #start method), the test is bound + # to the global scope. The variables defined in the global scope are + # available to every test Action. + # + # The global scope can have nested variable scopes created by special + # actions. The variables defined in a scope +A+ are only available to that + # scope and scopes nested within +A+. + # + # Every time an Action loads a file, a new nested scope is created. + # File-loading actions include: + # - Action#load + # - Action#tryload + # - Action#ruby + # - Action#test + # + # A nested scope can bubble variables to its parent scope with the special + # action: + # - Action#return_action + # class Context # Test engine driver instance (Selenium WebDriver). attr_reader :driver # Logger instance. @@ -68,12 +112,13 @@ # def initialize(options) @options = options @driver_name = (options[:driver] || :firefox).to_sym @variables = { - '__TIMEOUT__' => (options[:timeout] || 10).to_i, - '__DEBUG__' => false + '__TIMEOUT__' => (options[:timeout] || 10).to_i, + '__DEBUG__' => false, + '__SELECTOR__' => options[:selector] || 'sid' } @aliases = {} @tests = [] _load_extensions(options[:extensions] || []) @@ -162,11 +207,11 @@ # ctx.find('frame=|myframe|css=.my_button').click # # => error, cannot click .my_button (no longer in myframe scope) # def find(selector, &block) # yields: element with_timeout Selenium::WebDriver::Error::NoSuchElementError do - Selector.new(self).find(selector, &block) + Selector.new(self, @variables['__SELECTOR__']).find(selector, &block) end end # Breaks into the debug console. # @@ -297,10 +342,32 @@ @logger.progress(rem.round) sleep(1.0/10.0) if (t - stime).to_i < 1 retry end + + # Executes the given block using the specified driver +timeout+. + # + # Note that the driver +timeout+ is the time (in seconds) Selenium + # will wait for a specific element to appear in the page (using any + # of the available Selector strategies). + # + # For example + # ctx.with_driver_timeout 0.5 do + # ctx.find ('find_me_quickly') do |e| + # # do something with e + # end + # end + # + def with_driver_timeout(timeout) + current = @driver_timeout + @driver.manage.timeouts.implicit_wait = timeout + yield + ensure + @driver_timeout = current + @driver.manage.timeouts.implicit_wait = current + end # Prompts the user to press ENTER before resuming execution. # # For example: # Context::wait @@ -501,9 +568,10 @@ end def _load_driver @driver = Selenium::WebDriver.for(@driver_name, @options[:driver_opt]) @driver.manage.timeouts.implicit_wait = 1 + @driver_timeout = 1 end def _load_extensions(dirs) dirs.each do |d| d = File.join(Dir.pwd, d) unless Dir.exists? d \ No newline at end of file