require_relative "../spec_helper.rb" module WinGuiTest describe Window do before(:each) { @win = launch_test_app.main_window } after(:each){ close_test_app } context 'initializing' do it 'can be wrapped around any existing window' do any_handle = find_window(nil, nil) use{ Window.new any_handle } end end context 'manipulating' do it 'closes when asked nicely' do @win.close sleep SLEEP_DELAY # needed to ensure window had enough time to close down find_window(nil, WIN_TITLE).should == nil end it 'waits for window to disappear (NB: this happens before handle is released!)' do start = Time.now @win.close @win.wait_for_close (Time.now - start).should be <= CLOSE_TIMEOUT window_visible?(@win.handle).should be false window?(@win.handle).should be false end end context 'handle-related WinGui functions as instance methods' do it 'calls all WinGui functions as instance methods (with handle as implicit first argument)' do @win.window?.should == true @win.visible?.should == true @win.foreground?.should == true @win.maximized?.should == false @win.minimized?.should == false @win.child?(any_handle).should == false @win.window_rect.should be_an Array @win.window_thread_process_id.should be_an Array @win.enum_child_windows.should be_an Array end end context 'derived properties' do it 'has handle property equal to underlying window handle' do any = Window.new any_handle any.handle.should == any_handle end it 'has class_name and text/title properties (derived from WinGui function calls)' do @win.class_name.should == WIN_CLASS # text propery accessed by sending WM_GETTEXT directly to window (convenience method in WinGui) @win.text.should == WIN_TITLE # window_text propery accessed via GetWindowText @win.window_text.should == WIN_TITLE # title property is just an alias for window_text @win.title.should == WIN_TITLE end it 'has thread and process properties derived from get_window_thread_process_id' do thread = @win.thread process = @win.process [thread, process].should == get_window_thread_process_id(@win.handle) end it 'has id property that only makes sense for controls' do use{ @win.id } end end describe '::top_level' do it 'finds top-level window by title and wraps it in a Window object' do window = Window.top_level( title: WIN_TITLE, timeout: 1) window.handle.should == @win.handle end it 'finds top-level window by class and wraps it in a Window object' do window = Window.top_level( class: WIN_CLASS, timeout: 1) window.handle.should == @win.handle end it 'finds ANY top-level window without args and wraps it in a Window object' do use { @window = Window.top_level() } @window.should be_a Window end it 'returns nil immediately if top-level window with given title not found' do start = Time.now Window.top_level( title: IMPOSSIBLE).should == nil (Time.now - start).should be_close 0, 0.03 end it 'returns nil after timeout if top-level window with given title not found' do start = Time.now Window.top_level( title: IMPOSSIBLE, timeout: 0.3).should == nil (Time.now - start).should be_close 0.3, 0.03 end it 'raises exception if asked to' do expect{ Window.top_level( title: IMPOSSIBLE, raise: "Horror!")}.to raise_error "Horror!" end it 'uses .find as alias for .top_level' do use { @window = Window.find() } @window.should be_a Window end end # describe .top_level describe '#child' do spec { use { @child = @win.child(title: "Title", class: "Class", id: 0) }} it 'returns nil immediately if specific child not found' do start = Time.now @win.child( title: IMPOSSIBLE).should == nil (Time.now - start).should be_close 0, 0.03 end it 'returns nil after timeout if specific child not found' do start = Time.now @win.child( title: IMPOSSIBLE, timeout: 0.5).should == nil (Time.now - start).should be_close 0.5, 0.03 end it 'finds ANY child window without args' do use { @child = @win.child() } @child.should_not == nil @win.child?(@child.handle).should == true end it 'finds child window by class and returns it as a Window object (no timeout)' do child = @win.child( class: TEXTAREA_CLASS) child.should_not == nil @win.child?(child.handle).should == true end it 'finds child window by class and returns it as a Window object (with timeout)' do child = @win.child( class: TEXTAREA_CLASS, timeout: 0.5) child.should_not == nil @win.child?(child.handle).should == true child = @win.child( class: STATUSBAR_CLASS, timeout: 0.5) child.should_not == nil @win.child?(child.handle).should == true end it 'finds child with specific text and returns it as a Window object' do with_dialog(:save) do |dialog| child = dialog.child( title: "Cancel") child.should_not == nil dialog.child?(child.handle).should == true child.get_dlg_ctrl_id.should == IDCANCEL child = dialog.child( title: "&Save") child.should_not == nil dialog.child?(child.handle).should == true child.get_dlg_ctrl_id.should == IDOK end end it 'finds child control with a given ID and returns it as a Window object' do with_dialog(:save) do |dialog| child = dialog.child( id: IDCANCEL) child.should_not == nil dialog.child?(child.handle).should == true child.text.should == "Cancel" end end context 'indirect child' do it 'returns nil if specified child not found' do @win.child( title: IMPOSSIBLE, indirect: true).should == nil end it 'finds ANY child window without other args' do use { @child = @win.child(indirect: true) } @child.should_not == nil @win.child?(@child.handle).should == true end it 'finds child window by class' do child = @win.child( class: TEXTAREA_CLASS, indirect: true) child.should_not == nil @win.child?(child.handle).should == true end it 'finds child with specific text' do with_dialog(:save) do |dialog| child = dialog.child( title: "Cancel", indirect: true) child.should_not == nil dialog.child?(child.handle).should == true child.id.should == IDCANCEL child = dialog.child( title: "&Save", indirect: true) child.should_not == nil dialog.child?(child.handle).should == true child.id.should == IDOK end end it 'finds child control with a given ID ' do with_dialog(:save) do |dialog| child = dialog.child( id: IDCANCEL, indirect: true) child.should_not == nil dialog.child?(child.handle).should == true child.text.should == "Cancel" end end end # context indirect end # describe child describe '#children' do spec { use { children = @win.children }} it 'returns an array of Windows that are descendants (not only DIRECT children) of a given Window' do children = @win.children children.should be_a_kind_of Array children.should_not be_empty children.should have(2).elements children.each{|child| child?(@win.handle, child.handle).should == true } children.last.class_name.should == TEXTAREA_CLASS end end # describe #children describe '#click' do it 'emulates left click of the control identified by id, returns click coords' do with_dialog(:save) do |dialog| point = dialog.click(id: IDCANCEL) point.should be_an Array sleep 0.3 dialog.window?.should == false end end it 'emulates left click of the control identified by title, returns click coords' do with_dialog(:save) do |dialog| point = dialog.click(title: "Cancel") point.should be_an Array sleep 0.3 dialog.window?.should == false end end it 'emulates right click of the control identified by id, returns click coords' do with_dialog(:save) do |dialog| point = dialog.click(id: IDCANCEL, mouse_button: :right) point.should be_an Array sleep 0.3 dialog.window?.should == true end end it 'emulates right click of the control identified by title, returns click coords' do with_dialog(:save) do |dialog| point = dialog.click(title: "Cancel", mouse_button: :right) point.should be_an Array sleep 0.3 dialog.window?.should == true end end it 'returns nil if the specified control was not found' do with_dialog(:save) do |dialog| dialog.click(title: "Shpancel").should == nil dialog.click(id: 66).should == nil sleep 0.3 dialog.window?.should == true end end end # describe #click end end