vapir-ie 1.7.2 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,56 @@
1
+ require 'vapir-ie/browser.rb'
2
+
3
+ module Vapir
4
+ class IE
5
+ module ClearTracks
6
+ History = 1 << 0
7
+ Cookies = 1 << 1
8
+ # ?? = 1 << 2
9
+ TemporaryFiles = 1 << 3
10
+ FormData = 1 << 4
11
+ StoredPasswords = 1 << 5
12
+ # ?? = 1 << 6
13
+ # ?? = 1 << 7
14
+ All = (1 << 8)-1 # this is called 'All' by such references as exist, despite higher bits being meaningful too.
15
+ FilesAndSettingsStoredByAddOns = 1 << 12 # don't know what happened to any of bits 6 through 11. also this only seems to be documented anywhere as 4351 = 1000011111111 (= All | FilesAndSettingsStoredByAddOns)
16
+ # apparently 1 << 13 is also meaningful, but I have no idea what it is. I have seen ClearMyTracksByProcess called with the argument 8651 = 10000111001011 (so bits 0, 1, 3, 6, 7, 8, 13)
17
+
18
+ # Clears tracks according to the given argument, which should be one of the constants of
19
+ # this module, or any number of those constants bitwise-OR'd together.
20
+ #
21
+ # ClearTracks.clear_tracks(ClearTracks::FormData)
22
+ # ClearTracks.clear_tracks(ClearTracks::History | ClearTracks::StoredPasswords)
23
+ def self.clear_tracks(what)
24
+ unless const_defined?('InetCpl')
25
+ require 'ffi'
26
+ define_const('InetCpl', Module.new)
27
+ InetCpl.extend(FFI::Library)
28
+ InetCpl.ffi_lib 'InetCpl.cpl'
29
+ InetCpl.ffi_convention :stdcall
30
+ InetCpl.attach_function :ClearMyTracksByProcess, :ClearMyTracksByProcessW, [:int], :void
31
+ end
32
+ InetCpl.ClearMyTracksByProcess(what)
33
+ end
34
+ end
35
+ module ClearTracksMethods
36
+ # Clear the history of sites that have been visited from the browser
37
+ def clear_history
38
+ ClearTracks.clear_tracks(ClearTracks::History)
39
+ end
40
+ # Clear all cookies from the browser
41
+ def clear_cookies
42
+ ClearTracks.clear_tracks(ClearTracks::Cookies)
43
+ end
44
+ # Clear temporary copies of web pages, images, and media that are saved
45
+ def clear_temporary_files
46
+ ClearTracks.clear_tracks(ClearTracks::TemporaryFiles)
47
+ end
48
+ # Clear all history, cookies, temporary files, form data, and passwords from the browser
49
+ def clear_all_tracks
50
+ ClearTracks.clear_tracks(ClearTracks::All)
51
+ end
52
+ end
53
+ include ClearTracksMethods
54
+ extend ClearTracksMethods
55
+ end
56
+ end
@@ -1,4 +1,4 @@
1
- require 'vapir-ie/ie-class'
1
+ require 'vapir-ie/browser'
2
2
 
3
3
  module Vapir
4
4
  class IE
@@ -0,0 +1,22 @@
1
+ require 'vapir-common/config'
2
+ require 'vapir-ie' # need the class to be set first
3
+
4
+ module Vapir
5
+ # if vapir-ie is required before any other browser-specific library, then set the default browser to ie
6
+ @base_configuration.default_browser = :ie unless @base_configuration.locally_defined_key?(:default_browser)
7
+
8
+ # add ie-specific stuff to base, and then bring them in from env and yaml
9
+ @base_configuration.create_update(:ie_launch_new_process, false, :validator => :boolean)
10
+ @base_configuration.create_update(:browser_visible, true, :validator => :boolean)
11
+ if defined?($HIDE_IE)
12
+ if config.warn_deprecated
13
+ Kernel.warn "WARNING: The $HIDE_IE global is gone. Please use the new config framework, and unset that global to silence this warning."
14
+ end
15
+ Vapir.config.browser_visible=false
16
+ end
17
+ @configurations.update_from_source
18
+ class IE
19
+ @configuration_parent = Vapir.config
20
+ extend Configurable
21
+ end
22
+ end
@@ -23,41 +23,19 @@ module Vapir
23
23
 
24
24
  public
25
25
  # see documentation for the common Vapir::Container#handling_existence_failure
26
- def handling_existence_failure(options={})
27
- options=handle_options(options, :handle => :ignore)
26
+ def handling_existence_failure(options={}, &block)
28
27
  begin
29
- yield
28
+ base_handling_existence_failure(options, &block)
30
29
  rescue WIN32OLERuntimeError, RuntimeError, NoMethodError, Vapir::Exception::ExistenceFailureException
31
- raise if $!.class==RuntimeError && $!.message !~ /HRESULT/ # sometimes WIN32OLE raises a RuntimeError instead of a WIN32OLERuntimeError. only catch a RuntimeError if it's from WIN32OLE, indicated by HRESULT in the error message.
30
+ if [WIN32OLERuntimeError, RuntimeError, NoMethodError].any?{|klass| $!.is_a?(klass) } && $!.message !~ Vapir::IE::ExistenceFailureCodesRE
31
+ raise
32
+ end
32
33
  handle_existence_failure($!, options)
33
34
  end
34
35
  end
35
- public
36
- # Note: @container is the container of this object, i.e. the container
37
- # of this container.
38
- # In other words, for ie.table().this_thing().text_field().set,
39
- # container of this_thing is the table.
40
-
41
- # This is used to change the typing speed when entering text on a page.
42
- attr_accessor :typingspeed
43
- attr_accessor :type_keys
44
-
45
- def copy_test_config(container) # only used by form and frame
46
- @typingspeed = container.typingspeed
47
- @type_keys = container.type_keys
48
- end
49
- private :copy_test_config
50
-
51
36
  # Write the specified string to the log.
52
37
  def log(what)
53
38
  @container.logger.debug(what) if @logger
54
39
  end
55
-
56
- # def set_container container
57
- # @container = container
58
- # @page_container = container.page_container
59
- # end
60
-
61
- private
62
40
  end # module
63
41
  end
@@ -41,15 +41,33 @@ module Vapir
41
41
  # Return the outer html of the object - see http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/outerhtml.asp?frame=true
42
42
  dom_attr :outerHTML => :outer_html
43
43
 
44
- # return the text before the element
45
- def before_text
46
- element_object.getAdjacentText("afterEnd")
47
- end
48
-
49
- # return the text after the element
50
- def after_text
44
+ # text immediately before this element
45
+ #
46
+ # http://msdn.microsoft.com/en-us/library/ms536427(VS.85).aspx
47
+ def text_before_begin
51
48
  element_object.getAdjacentText("beforeBegin")
52
49
  end
50
+ # text after the start of the element but before all other content in the element
51
+ #
52
+ # http://msdn.microsoft.com/en-us/library/ms536427(VS.85).aspx
53
+ def text_after_begin
54
+ element_object.getAdjacentText("afterBegin")
55
+ end
56
+ # text immediately before the end of the element but after all other content in the element
57
+ #
58
+ # http://msdn.microsoft.com/en-us/library/ms536427(VS.85).aspx
59
+ def text_before_end
60
+ element_object.getAdjacentText("beforeEnd")
61
+ end
62
+ # text immediately before this element
63
+ #
64
+ # http://msdn.microsoft.com/en-us/library/ms536427(VS.85).aspx
65
+ def text_after_end
66
+ element_object.getAdjacentText("afterEnd")
67
+ end
68
+ # strange, counterintuitive aliases from watir
69
+ alias before_text text_after_end
70
+ alias after_text text_before_begin
53
71
 
54
72
  # Returns the text content of the element.
55
73
  dom_attr :innerText => :text
@@ -71,13 +89,6 @@ module Vapir
71
89
  source_index > other.source_index
72
90
  end
73
91
 
74
- def typingspeed
75
- @container.typingspeed
76
- end
77
- def type_keys
78
- @type_keys || @container.type_keys
79
- end
80
-
81
92
  private
82
93
  # for use with events' button property
83
94
  MouseButtonCodes=
@@ -111,7 +122,7 @@ module Vapir
111
122
  :shiftLeft => false,
112
123
  }
113
124
 
114
- if %w(onclick onmousedown onmouseup ondblclick onmouseover onmouseout).include?(event_type)
125
+ if %w(onclick onmousedown onmouseup ondblclick onmouseover onmouseout onmousemove).include?(event_type)
115
126
  client_center=self.client_center
116
127
 
117
128
  button_code=options[:button_code] ||
@@ -181,7 +192,6 @@ module Vapir
181
192
  actions.each do |action|
182
193
  # javascript stuff responding to previous events can cause self to stop existing, so check at every subsequent step
183
194
  handling_existence_failure(:handle => proc{ return result }) do
184
- assert_exists :force => true
185
195
  result=action.call
186
196
  end
187
197
  end
@@ -1,5 +1,4 @@
1
- require 'win32/process'
2
- require 'vapir-ie/ie-class'
1
+ require 'vapir-ie/browser'
3
2
 
4
3
  module Vapir
5
4
  class IE
@@ -18,10 +17,9 @@ module Vapir
18
17
  @@ie_version_parts ||= IE.version.split('.').map{|part| part.to_i }
19
18
  end
20
19
  class Process
21
- # Vapir::IE::Process.start is called by Vapir::IE.new_process and does not start a new process correctly in IE8.
22
- # Calling IE8 with the -nomerge option correctly starts a new process, so call Process.create with this option if
23
- # IE's version is 8
20
+ # start a new IE process and return a new Vapir::IE::Process object representing it.
24
21
  def self.start
22
+ require 'win32/process'
25
23
  program_files = ENV['ProgramFiles'] || "c:\\Program Files"
26
24
  startup_command = "#{program_files}\\Internet Explorer\\iexplore.exe"
27
25
  startup_command << " -nomerge" if ::Vapir::IE.version_parts.first==8
@@ -31,30 +29,22 @@ module Vapir
31
29
  new process_id
32
30
  end
33
31
 
32
+ # takes a process id
34
33
  def initialize process_id
35
34
  @process_id = process_id
36
35
  end
37
36
  attr_reader :process_id
38
37
 
39
- def window
40
- Waiter.wait_until do
41
- IE.each do | ie |
42
- window = ie.ie
43
- hwnd = ie.hwnd
44
- process_id = Process.process_id_from_hwnd hwnd
45
- return window if process_id == @process_id
38
+ # returns the browser object corresponding to the process id
39
+ def browser_object(options={})
40
+ options=handle_options(options, :timeout => 32)
41
+ Vapir.require_winwindow
42
+ ::Waiter.try_for(options[:timeout], :exception => RuntimeError.new("Could not find a browser for process #{self.inspect}")) do
43
+ Vapir::IE.browser_objects.detect do |browser_object|
44
+ @process_id == WinWindow.new(Vapir::IE.fix_win32ole_hwnd(browser_object.hwnd)).process_id
46
45
  end
47
46
  end
48
47
  end
49
-
50
- # Returns the process id for the specifed hWnd.
51
- def self.process_id_from_hwnd hwnd
52
- pid_info = ' ' * 32
53
- Win32API.new('user32', 'GetWindowThreadProcessId', 'ip', 'i').
54
- call(hwnd, pid_info)
55
- process_id = pid_info.unpack("L")[0]
56
- end
57
-
58
48
  end
59
49
  end
60
50
  end
@@ -87,15 +87,6 @@ module Vapir
87
87
  end
88
88
  end
89
89
  alias_deprecated :dragContentsTo, :drag_contents_to
90
-
91
- def requires_typing
92
- @type_keys = true
93
- self
94
- end
95
- def abhors_typing
96
- @type_keys = false
97
- self
98
- end
99
90
  end
100
91
 
101
92
  # this class can be used to access hidden field objects
@@ -122,7 +113,7 @@ module Vapir
122
113
  # of this browser, this process will handle the former, and we'll spawn another to do the
123
114
  # latter.
124
115
  require 'win32/process'
125
- require 'vapir-common/win_window'
116
+ Vapir.require_winwindow
126
117
  rubyw_exe= File.join(Config::CONFIG['bindir'], 'rubyw')
127
118
  error_file_name=File.expand_path(File.join(File.dirname(__FILE__), 'scripts', 'select_file_error_status.marshal_dump'))
128
119
  select_file_script=File.expand_path(File.join(File.dirname(__FILE__), 'scripts', 'select_file.rb'))
@@ -1,7 +1,5 @@
1
- require 'vapir-common/win_window'
2
1
  require 'vapir-common/modal_dialog'
3
2
  require 'vapir-ie/page_container'
4
- require 'Win32API'
5
3
 
6
4
  module Vapir
7
5
  class IE::ModalDialog
@@ -61,6 +59,7 @@ module Vapir
61
59
  @@iedialog_file = (File.expand_path(File.dirname(__FILE__) + '/..') + "/vapir-ie/IEDialog/Release/IEDialog.dll").gsub('/', '\\')
62
60
 
63
61
  def get_unknown(*args)
62
+ require 'Win32API'
64
63
  @@get_unknown ||= Win32API.new(@@iedialog_file, 'GetUnknown', ['l', 'p'], 'v')
65
64
  @@get_unknown.call(*args)
66
65
  end
@@ -104,120 +103,3 @@ module Vapir
104
103
  end
105
104
  end
106
105
  end
107
- =begin
108
- module Watir
109
- class IE::ModalDialog
110
- include IE::Container
111
- include IE::PageContainer
112
- include Win32
113
-
114
- # Return the current window handle
115
- attr_reader :hwnd
116
-
117
- def find_modal_from_window
118
- # Use handle of our parent window to see if we have any currently
119
- # enabled popup.
120
- hwnd = @container.hwnd
121
- hwnd_modal = 0
122
- begin
123
- Watir::until_with_timeout do
124
- hwnd_modal, arr = GetWindow.call(hwnd, GW_ENABLEDPOPUP) # GW_ENABLEDPOPUP = 6
125
- hwnd_modal > 0
126
- end
127
- rescue TimeOutException
128
- return nil
129
- end
130
- if hwnd_modal == hwnd || hwnd_modal == 0
131
- hwnd_modal = nil
132
- end
133
- @hwnd = hwnd_modal
134
- end
135
- private :find_modal_from_window
136
-
137
- def locate
138
- how = @how
139
- what = @what
140
-
141
- case how
142
- when nil
143
- unless find_modal_from_window
144
- raise NoMatchingWindowFoundException,
145
- "Modal Dialog not found. Timeout = #{Watir::IE.attach_timeout}"
146
- end
147
- when :title
148
- case what.class.to_s
149
- # TODO: re-write like WET's so we can select on regular expressions too.
150
- when "String"
151
- begin
152
- Watir::until_with_timeout do
153
- title = "#{what} -- Web Page Dialog"
154
- @hwnd, arr = FindWindowEx.call(0, 0, nil, title)
155
- @hwnd > 0
156
- end
157
- rescue TimeOutException
158
- raise NoMatchingWindowFoundException,
159
- "Modal Dialog with title #{what} not found. Timeout = #{Watir::IE.attach_timeout}"
160
- end
161
- else
162
- raise ArgumentError, "Title value must be String"
163
- end
164
- else
165
- raise ArgumentError, "Only null and :title methods are supported"
166
- end
167
-
168
- intUnknown = 0
169
- begin
170
- Watir::until_with_timeout do
171
- intPointer = " " * 4 # will contain the int value of the IUnknown*
172
- GetUnknown.call(@hwnd, intPointer)
173
- intArray = intPointer.unpack('L')
174
- intUnknown = intArray.first
175
- intUnknown > 0
176
- end
177
- rescue TimeOutException => e
178
- raise NoMatchingWindowFoundException,
179
- "Unable to attach to Modal Window #{what.inspect} after #{e.duration} seconds."
180
- end
181
-
182
- copy_test_config @parent_container
183
- @document = WIN32OLE.connect_unknown(intUnknown)
184
- end
185
-
186
- def initialize(container, how, what=nil)
187
- set_container container
188
- @how = how
189
- @what = what
190
- @parent_container = container
191
- # locate our modal dialog's Document object and save it
192
- begin
193
- locate
194
- rescue NoMethodError => e
195
- message =
196
- "IE#modal_dialog not supported with the current version of Ruby (#{RUBY_VERSION}).\n" +
197
- "See http://jira.openqa.org/browse/WTR-2 for details.\n" +
198
- e.message
199
- raise NoMethodError.new(message)
200
- end
201
- end
202
-
203
- def document
204
- @document
205
- end
206
-
207
- # Return the title of the document
208
- def title
209
- document.title
210
- end
211
-
212
- def wait(options={})
213
- end
214
-
215
- # Return true if the modal exists. Mostly this is useful for testing whether
216
- # a modal has closed.
217
- def exists?
218
- Watir::Win32::window_exists? @hwnd
219
- end
220
- alias :exist? :exists?
221
- end
222
- end
223
- =end
@@ -101,11 +101,13 @@ module Vapir
101
101
  if respond_to?(:browser_object)
102
102
  ::Waiter.try_for(options[:timeout]-(Time.now-start_load_time), :interval => options[:interval], :exception => "The browser was still busy after #{options[:timeout]} seconds") do
103
103
  return unless exists?
104
- !browser_object.busy
104
+ handling_existence_failure(:handle => proc { false }) { !browser_object.busy }
105
105
  end
106
106
  ::Waiter.try_for(options[:timeout]-(Time.now-start_load_time), :interval => options[:interval], :exception => "The browser's readyState was still not ready for interaction after #{options[:timeout]} seconds") do
107
107
  return unless exists?
108
- [WebBrowserReadyState::Interactive, WebBrowserReadyState::Complete].include?(browser_object.readyState)
108
+ handling_existence_failure(:handle => proc { false }) do
109
+ [WebBrowserReadyState::Interactive, WebBrowserReadyState::Complete].include?(browser_object.readyState)
110
+ end
109
111
  end
110
112
  end
111
113
  # if the document object is gone, then we want to just return.
@@ -1,4 +1,4 @@
1
- require 'vapir-ie/ie-class'
1
+ require 'vapir-ie/browser'
2
2
 
3
3
  module Vapir
4
4
  module Process