win_gui 0.2.16 → 0.2.17
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.
- data/HISTORY +4 -0
- data/VERSION +1 -1
- data/lib/win_gui/app.rb +1 -1
- data/lib/win_gui/window.rb +1 -1
- data/lib/win_gui.rb +3 -2
- data/spec/extension_spec.rb +49 -52
- data/spec/spec_helper.rb +65 -67
- data/spec/win_gui/app_spec.rb +88 -91
- data/spec/win_gui/convenience_spec.rb +53 -56
- data/spec/win_gui/window_spec.rb +213 -216
- data/tasks/spec.rake +3 -7
- metadata +5 -31
- data/spec/spec.opts +0 -2
    
        data/HISTORY
    CHANGED
    
    
    
        data/VERSION
    CHANGED
    
    | @@ -1 +1 @@ | |
| 1 | 
            -
            0.2. | 
| 1 | 
            +
            0.2.17
         | 
    
        data/lib/win_gui/app.rb
    CHANGED
    
    
    
        data/lib/win_gui/window.rb
    CHANGED
    
    
    
        data/lib/win_gui.rb
    CHANGED
    
    
    
        data/spec/extension_spec.rb
    CHANGED
    
    | @@ -1,68 +1,65 @@ | |
| 1 1 | 
             
            # encoding: UTF-8
         | 
| 2 | 
            -
             | 
| 2 | 
            +
            require "spec_helper.rb"
         | 
| 3 3 |  | 
| 4 | 
            -
             | 
| 5 | 
            -
             | 
| 6 | 
            -
             | 
| 7 | 
            -
             | 
| 8 | 
            -
             | 
| 9 | 
            -
                    ('0'..'9').each {|char| char.to_key.should == char.unpack('C')}
         | 
| 10 | 
            -
                  end
         | 
| 11 | 
            -
             | 
| 12 | 
            -
                  it 'transforms uppercase letters into [shift, equivalent key code]' do
         | 
| 13 | 
            -
                    ('A'..'Z').each {|char| char.to_key.should == [0x10, *char.unpack('C')]}
         | 
| 14 | 
            -
                  end
         | 
| 4 | 
            +
            describe String do
         | 
| 5 | 
            +
              describe '#to_key' do
         | 
| 6 | 
            +
                it 'transforms number char into [equivalent key code]' do
         | 
| 7 | 
            +
                  ('0'..'9').each { |char| char.to_key.should == char.unpack('C') }
         | 
| 8 | 
            +
                end
         | 
| 15 9 |  | 
| 16 | 
            -
             | 
| 17 | 
            -
             | 
| 18 | 
            -
             | 
| 10 | 
            +
                it 'transforms uppercase letters into [shift, equivalent key code]' do
         | 
| 11 | 
            +
                  ('A'..'Z').each { |char| char.to_key.should == [0x10, *char.unpack('C')] }
         | 
| 12 | 
            +
                end
         | 
| 19 13 |  | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 14 | 
            +
                it 'transforms lowercase letters into [(upcase) key code]' do
         | 
| 15 | 
            +
                  ('a'..'z').each { |char| char.to_key.should == char.upcase.unpack('C') }
         | 
| 16 | 
            +
                end
         | 
| 23 17 |  | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
             | 
| 18 | 
            +
                it 'transforms space into [equivalent key code]' do
         | 
| 19 | 
            +
                  ' '.to_key.should == " ".unpack('C')
         | 
| 20 | 
            +
                end
         | 
| 27 21 |  | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 30 | 
            -
             | 
| 31 | 
            -
                    ':'.to_key.should == [VK_SHIFT, VK_OEM_1]
         | 
| 32 | 
            -
                    ';'.to_key.should == [VK_OEM_1]
         | 
| 33 | 
            -
                    "\\".to_key.should == [VK_OEM_102]
         | 
| 34 | 
            -
                  end
         | 
| 22 | 
            +
                it 'transforms \n into [VK_RETURN]' do
         | 
| 23 | 
            +
                  "\n".to_key.should == [VK_RETURN]
         | 
| 24 | 
            +
                end
         | 
| 35 25 |  | 
| 36 | 
            -
             | 
| 37 | 
            -
             | 
| 38 | 
            -
             | 
| 39 | 
            -
             | 
| 40 | 
            -
             | 
| 41 | 
            -
                   | 
| 26 | 
            +
                it 'transforms .,:;\\ into [equivalent key code]' do
         | 
| 27 | 
            +
                  ','.to_key.should == [VK_OEM_COMMA]
         | 
| 28 | 
            +
                  '.'.to_key.should == [VK_OEM_PERIOD]
         | 
| 29 | 
            +
                  ':'.to_key.should == [VK_SHIFT, VK_OEM_1]
         | 
| 30 | 
            +
                  ';'.to_key.should == [VK_OEM_1]
         | 
| 31 | 
            +
                  "\\".to_key.should == [VK_OEM_102]
         | 
| 32 | 
            +
                end
         | 
| 42 33 |  | 
| 43 | 
            -
             | 
| 44 | 
            -
             | 
| 45 | 
            -
             | 
| 46 | 
            -
                   | 
| 34 | 
            +
                it 'raises error if char is not implemented punctuation' do
         | 
| 35 | 
            +
                  ('!'..'+').each { |char| lambda { char.to_key }.should raise_error ERROR_CONVERSION }
         | 
| 36 | 
            +
                  (']'..'`').each { |char| lambda { char.to_key }.should raise_error ERROR_CONVERSION }
         | 
| 37 | 
            +
                  ('{'..'~').each { |char| lambda { char.to_key }.should raise_error ERROR_CONVERSION }
         | 
| 38 | 
            +
                  ['-', '/', '['].each { |char| lambda { char.to_key }.should raise_error ERROR_CONVERSION }
         | 
| 39 | 
            +
                end
         | 
| 47 40 |  | 
| 48 | 
            -
             | 
| 49 | 
            -
             | 
| 50 | 
            -
             | 
| 51 | 
            -
                  end
         | 
| 41 | 
            +
                it 'raises error if char is non-printable or non-ascii' do
         | 
| 42 | 
            +
                  lambda { 1.chr.to_key }.should raise_error ERROR_CONVERSION
         | 
| 43 | 
            +
                  lambda { 230.chr.to_key }.should raise_error ERROR_CONVERSION
         | 
| 52 44 | 
             
                end
         | 
| 53 45 |  | 
| 54 | 
            -
                 | 
| 55 | 
            -
                   | 
| 56 | 
            -
             | 
| 57 | 
            -
             | 
| 58 | 
            -
             | 
| 59 | 
            -
                    win_string_thought_utf8 = win_string.force_encoding('utf-8')
         | 
| 60 | 
            -
                    win_string_thought_dos = win_string.force_encoding('cp866')
         | 
| 46 | 
            +
                it 'raises error if string is multi-char' do
         | 
| 47 | 
            +
                  lambda { 'hello'.to_key }.should raise_error ERROR_CONVERSION
         | 
| 48 | 
            +
                  lambda { '23'.to_key }.should raise_error ERROR_CONVERSION
         | 
| 49 | 
            +
                end
         | 
| 50 | 
            +
              end
         | 
| 61 51 |  | 
| 62 | 
            -
             | 
| 63 | 
            -
             | 
| 64 | 
            -
                   | 
| 52 | 
            +
              describe '#to_print' do
         | 
| 53 | 
            +
                it 'converts String from (implied) WinCyrillic (CP1251) to default output encoding' do
         | 
| 54 | 
            +
                  string                  = "Широкая электрификация южных губерний даст мощный толчок подъёму сельского хозяйства"
         | 
| 55 | 
            +
                  win_string              = string.encode('cp1251')
         | 
| 56 | 
            +
                  print_string            = win_string.encode(Encoding.default_external, :undef => :replace)
         | 
| 57 | 
            +
                  win_string_thought_utf8 = win_string.force_encoding('utf-8')
         | 
| 58 | 
            +
                  win_string_thought_dos  = win_string.force_encoding('cp866')
         | 
| 65 59 |  | 
| 60 | 
            +
                  win_string_thought_utf8.to_print.should == print_string
         | 
| 61 | 
            +
                  win_string_thought_dos.to_print.should == print_string
         | 
| 66 62 | 
             
                end
         | 
| 63 | 
            +
             | 
| 67 64 | 
             
              end
         | 
| 68 65 | 
             
            end
         | 
    
        data/spec/spec_helper.rb
    CHANGED
    
    | @@ -1,5 +1,4 @@ | |
| 1 | 
            -
            require ' | 
| 2 | 
            -
            require 'spec/autorun'
         | 
| 1 | 
            +
            require 'rspec'
         | 
| 3 2 | 
             
            require 'win_gui'
         | 
| 4 3 |  | 
| 5 4 | 
             
            # Customize RSpec with my own extensions
         | 
| @@ -14,86 +13,85 @@ module SpecMacros | |
| 14 13 | 
             
              # reads description line from source file and drops external brackets (like its{}, use{}
         | 
| 15 14 | 
             
              def description_from(file, line)
         | 
| 16 15 | 
             
                File.open(file) do |f|
         | 
| 17 | 
            -
                  f.lines.to_a[line-1].gsub( | 
| 16 | 
            +
                  f.lines.to_a[line-1].gsub(/(spec.*?{)|(use.*?{)|}/, '').strip
         | 
| 18 17 | 
             
                end
         | 
| 19 18 | 
             
              end
         | 
| 20 19 | 
             
            end
         | 
| 21 20 |  | 
| 22 | 
            -
             | 
| 21 | 
            +
            RSpec.configure { |config|
         | 
| 22 | 
            +
              config.include Win::Gui # This is a namespace from win gem.
         | 
| 23 | 
            +
              config.include WinGui # This is our own main namespace. TODO: looks confusing... better names?
         | 
| 24 | 
            +
              config.extend SpecMacros }
         | 
| 23 25 |  | 
| 24 | 
            -
            module WinGuiTest
         | 
| 25 | 
            -
              include Win::Gui  # This is a namespace from win gem.
         | 
| 26 | 
            -
              include WinGui    # This is our own main namespace. TODO: looks confusing... better names?
         | 
| 27 26 |  | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 30 | 
            -
             | 
| 31 | 
            -
             | 
| 32 | 
            -
             | 
| 33 | 
            -
             | 
| 34 | 
            -
             | 
| 35 | 
            -
             | 
| 36 | 
            -
             | 
| 37 | 
            -
               | 
| 38 | 
            -
             | 
| 39 | 
            -
             | 
| 27 | 
            +
            # Test related Constants:
         | 
| 28 | 
            +
            TIMEOUT          = 0.001
         | 
| 29 | 
            +
            KEY_DELAY        = 0.001
         | 
| 30 | 
            +
            SLEEP_DELAY      = 0.01
         | 
| 31 | 
            +
            APP_PATH         = File.join(File.dirname(__FILE__), "../misc/locknote/LockNote.exe")
         | 
| 32 | 
            +
            DIALOG_TITLE     = "Save As"
         | 
| 33 | 
            +
            WIN_TITLE        = 'LockNote - Steganos LockNote'
         | 
| 34 | 
            +
            WIN_CLASS        = 'ATL:00434098'
         | 
| 35 | 
            +
            TEXTAREA_CLASS   = 'ATL:00434310'
         | 
| 36 | 
            +
            STATUSBAR_CLASS  = 'msctls_statusbar32'
         | 
| 37 | 
            +
            IMPOSSIBLE       = 'Impossible'
         | 
| 38 | 
            +
            ERROR_CONVERSION = /Can.t convert/
         | 
| 40 39 |  | 
| 41 | 
            -
             | 
| 42 | 
            -
             | 
| 43 | 
            -
             | 
| 44 | 
            -
             | 
| 40 | 
            +
            # Helper methods:
         | 
| 41 | 
            +
            def use
         | 
| 42 | 
            +
              lambda { yield }.should_not raise_error
         | 
| 43 | 
            +
            end
         | 
| 45 44 |  | 
| 46 | 
            -
             | 
| 47 | 
            -
             | 
| 48 | 
            -
             | 
| 45 | 
            +
            def any_handle
         | 
| 46 | 
            +
              find_window(nil, nil)
         | 
| 47 | 
            +
            end
         | 
| 49 48 |  | 
| 50 | 
            -
             | 
| 51 | 
            -
             | 
| 52 | 
            -
             | 
| 49 | 
            +
            def not_a_handle
         | 
| 50 | 
            +
              123
         | 
| 51 | 
            +
            end
         | 
| 53 52 |  | 
| 54 | 
            -
             | 
| 55 | 
            -
             | 
| 56 | 
            -
             | 
| 53 | 
            +
            def any_block
         | 
| 54 | 
            +
              lambda { |*args| args }
         | 
| 55 | 
            +
            end
         | 
| 57 56 |  | 
| 58 | 
            -
             | 
| 59 | 
            -
             | 
| 60 | 
            -
             | 
| 61 | 
            -
             | 
| 57 | 
            +
            def launch_test_app
         | 
| 58 | 
            +
              #system APP_START
         | 
| 59 | 
            +
              @test_app = App.launch(path: APP_PATH, title: WIN_TITLE, timeout: 1)
         | 
| 60 | 
            +
            end
         | 
| 62 61 |  | 
| 63 | 
            -
             | 
| 64 | 
            -
             | 
| 65 | 
            -
             | 
| 66 | 
            -
             | 
| 67 | 
            -
             | 
| 68 | 
            -
             | 
| 69 | 
            -
             | 
| 70 | 
            -
                  end
         | 
| 62 | 
            +
            def close_test_app
         | 
| 63 | 
            +
              while @test_app && @test_app.main_window.window?
         | 
| 64 | 
            +
                @test_app.close
         | 
| 65 | 
            +
                # Dealing with closing confirmation modal dialog
         | 
| 66 | 
            +
                if dialog = dialog(title: "Steganos Locknote", timeout: SLEEP_DELAY)
         | 
| 67 | 
            +
                  dialog.set_foreground_window
         | 
| 68 | 
            +
                  keystroke("N")
         | 
| 71 69 | 
             
                end
         | 
| 72 | 
            -
                @test_app = nil
         | 
| 73 70 | 
             
              end
         | 
| 71 | 
            +
              @test_app = nil
         | 
| 72 | 
            +
            end
         | 
| 74 73 |  | 
| 75 | 
            -
             | 
| 76 | 
            -
             | 
| 77 | 
            -
             | 
| 78 | 
            -
             | 
| 79 | 
            -
             | 
| 74 | 
            +
            # Creates test app object and yields it back to the block
         | 
| 75 | 
            +
            def test_app
         | 
| 76 | 
            +
              yield launch_test_app
         | 
| 77 | 
            +
              close_test_app
         | 
| 78 | 
            +
            end
         | 
| 80 79 |  | 
| 81 | 
            -
             | 
| 82 | 
            -
             | 
| 83 | 
            -
             | 
| 84 | 
            -
             | 
| 85 | 
            -
             | 
| 86 | 
            -
             | 
| 87 | 
            -
             | 
| 88 | 
            -
             | 
| 89 | 
            -
             | 
| 90 | 
            -
             | 
| 91 | 
            -
             | 
| 92 | 
            -
             | 
| 93 | 
            -
             | 
| 94 | 
            -
             | 
| 95 | 
            -
             | 
| 96 | 
            -
             | 
| 97 | 
            -
                end
         | 
| 80 | 
            +
            def with_dialog(type=:close)
         | 
| 81 | 
            +
              case type
         | 
| 82 | 
            +
                when :close
         | 
| 83 | 
            +
                  keystroke('A')
         | 
| 84 | 
            +
                  @app.close
         | 
| 85 | 
            +
                  title, key = "Steganos Locknote", "N"
         | 
| 86 | 
            +
                when :save
         | 
| 87 | 
            +
                  keystroke(VK_ALT, 'F', 'A')
         | 
| 88 | 
            +
                  title, key = "Save As", VK_ESCAPE
         | 
| 89 | 
            +
              end
         | 
| 90 | 
            +
              sleep 0.01 until dialog = Window.top_level(title: title)
         | 
| 91 | 
            +
              yield dialog
         | 
| 92 | 
            +
              while dialog.window?
         | 
| 93 | 
            +
                dialog.set_foreground_window
         | 
| 94 | 
            +
                keystroke(key)
         | 
| 95 | 
            +
                sleep 0.01
         | 
| 98 96 | 
             
              end
         | 
| 99 97 | 
             
            end
         | 
    
        data/spec/win_gui/app_spec.rb
    CHANGED
    
    | @@ -1,120 +1,117 @@ | |
| 1 | 
            -
             | 
| 1 | 
            +
            require "spec_helper.rb"
         | 
| 2 2 |  | 
| 3 | 
            -
             | 
| 4 | 
            -
             | 
| 5 | 
            -
             | 
| 6 | 
            -
                 | 
| 7 | 
            -
             | 
| 8 | 
            -
                  app.exit(timeout=10) if app
         | 
| 9 | 
            -
                end
         | 
| 10 | 
            -
             | 
| 11 | 
            -
                context 'initializing' do
         | 
| 12 | 
            -
                  context '::new' do
         | 
| 13 | 
            -
                    before(:each) { launch_test_app }
         | 
| 14 | 
            -
                    after(:each) { close_test_app }
         | 
| 15 | 
            -
             | 
| 16 | 
            -
                    it 'wraps new App around existing Window' do
         | 
| 17 | 
            -
                      window = Window.top_level(title: WIN_TITLE)
         | 
| 18 | 
            -
                      @app = App.new(window)
         | 
| 19 | 
            -
                      @app.should be_an App
         | 
| 20 | 
            -
                      @app.main_window.should == window
         | 
| 21 | 
            -
                    end
         | 
| 3 | 
            +
            describe WinGui::App do
         | 
| 4 | 
            +
              after(:each) do # Reliably closes launched app window (without calling close_test_app)
         | 
| 5 | 
            +
                app = App.find(title: WIN_TITLE)
         | 
| 6 | 
            +
                app.exit(timeout=10) if app
         | 
| 7 | 
            +
              end
         | 
| 22 8 |  | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
             | 
| 27 | 
            -
                      @app.main_window.handle.should == window.handle
         | 
| 28 | 
            -
                    end
         | 
| 9 | 
            +
              context 'initializing' do
         | 
| 10 | 
            +
                context '::new' do
         | 
| 11 | 
            +
                  before(:each) { launch_test_app }
         | 
| 12 | 
            +
                  after(:each) { close_test_app }
         | 
| 29 13 |  | 
| 30 | 
            -
             | 
| 31 | 
            -
             | 
| 32 | 
            -
             | 
| 33 | 
            -
             | 
| 34 | 
            -
             | 
| 35 | 
            -
                    end
         | 
| 14 | 
            +
                  it 'wraps new App around existing Window' do
         | 
| 15 | 
            +
                    window = Window.top_level(title: WIN_TITLE)
         | 
| 16 | 
            +
                    @app   = App.new(window)
         | 
| 17 | 
            +
                    @app.should be_an App
         | 
| 18 | 
            +
                    @app.main_window.should == window
         | 
| 36 19 | 
             
                  end
         | 
| 37 20 |  | 
| 38 | 
            -
                   | 
| 39 | 
            -
                     | 
| 40 | 
            -
                     | 
| 21 | 
            +
                  it 'wraps new App around active window handle (of top-level Window)' do
         | 
| 22 | 
            +
                    window = Window.top_level(title: WIN_TITLE)
         | 
| 23 | 
            +
                    @app   = App.new(window.handle)
         | 
| 24 | 
            +
                    @app.should be_an App
         | 
| 25 | 
            +
                    @app.main_window.handle.should == window.handle
         | 
| 26 | 
            +
                  end
         | 
| 41 27 |  | 
| 42 | 
            -
             | 
| 43 | 
            -
             | 
| 44 | 
            -
             | 
| 28 | 
            +
                  it 'raises error trying to create App with wrong init args' do
         | 
| 29 | 
            +
                    expect { App.new() }.to raise_error ArgumentError, /wrong number of arguments/
         | 
| 30 | 
            +
                    [[nil], 1.2, {title: WIN_TITLE}].each do |args|
         | 
| 31 | 
            +
                      expect { App.new(*args) }.to raise_error WinGui::Errors::InitError
         | 
| 45 32 | 
             
                    end
         | 
| 33 | 
            +
                  end
         | 
| 34 | 
            +
                end
         | 
| 46 35 |  | 
| 47 | 
            -
             | 
| 48 | 
            -
             | 
| 49 | 
            -
             | 
| 36 | 
            +
                context '::find' do
         | 
| 37 | 
            +
                  before(:each) { launch_test_app }
         | 
| 38 | 
            +
                  after(:each) { close_test_app }
         | 
| 50 39 |  | 
| 51 | 
            -
             | 
| 52 | 
            -
             | 
| 53 | 
            -
             | 
| 54 | 
            -
                    end
         | 
| 40 | 
            +
                  it 'finds already launched App given valid Window info' do
         | 
| 41 | 
            +
                    use { @app = App.find(title: WIN_TITLE) }
         | 
| 42 | 
            +
                    @app.should be_an App
         | 
| 55 43 | 
             
                  end
         | 
| 56 44 |  | 
| 57 | 
            -
                   | 
| 58 | 
            -
                     | 
| 59 | 
            -
             | 
| 60 | 
            -
                      @app.should be_an App
         | 
| 61 | 
            -
                    end
         | 
| 45 | 
            +
                  it 'returns nil if asked to find App with invalid Window info' do
         | 
| 46 | 
            +
                    App.find(title: IMPOSSIBLE).should == nil
         | 
| 47 | 
            +
                  end
         | 
| 62 48 |  | 
| 63 | 
            -
             | 
| 64 | 
            -
             | 
| 65 | 
            -
             | 
| 66 | 
            -
             | 
| 49 | 
            +
                  it 'raises error only if asked to find App with invalid Window info and :raise option is set' do
         | 
| 50 | 
            +
                    expect { App.find(title: IMPOSSIBLE, raise: WinGui::Errors::InitError) }.
         | 
| 51 | 
            +
                        to raise_error WinGui::Errors::InitError
         | 
| 52 | 
            +
                  end
         | 
| 53 | 
            +
                end
         | 
| 67 54 |  | 
| 68 | 
            -
             | 
| 69 | 
            -
             | 
| 70 | 
            -
             | 
| 71 | 
            -
                     | 
| 55 | 
            +
                context '::launch' do
         | 
| 56 | 
            +
                  it 'launches new App given valid path and Window info' do
         | 
| 57 | 
            +
                    use { @app = App.launch(path: APP_PATH, title: WIN_TITLE) }
         | 
| 58 | 
            +
                    @app.should be_an App
         | 
| 59 | 
            +
                  end
         | 
| 72 60 |  | 
| 73 | 
            -
             | 
| 74 | 
            -
             | 
| 75 | 
            -
             | 
| 76 | 
            -
             | 
| 61 | 
            +
                  it 'raises error if asked to launch App with invalid path' do
         | 
| 62 | 
            +
                    expect { App.launch(path: IMPOSSIBLE, title: WIN_TITLE) }.
         | 
| 63 | 
            +
                        to raise_error WinGui::Errors::InitError, /Unable to launch "Impossible"/
         | 
| 64 | 
            +
                  end
         | 
| 77 65 |  | 
| 78 | 
            -
             | 
| 79 | 
            -
             | 
| 80 | 
            -
             | 
| 81 | 
            -
                    end
         | 
| 66 | 
            +
                  it 'raises error if asked to launch App with invalid Window info' do
         | 
| 67 | 
            +
                    expect { App.launch(path: APP_PATH, title: IMPOSSIBLE) }.
         | 
| 68 | 
            +
                        to raise_error WinGui::Errors::InitError, /Unable to launch App with .*?:title=>"Impossible"/
         | 
| 82 69 | 
             
                  end
         | 
| 83 70 |  | 
| 84 | 
            -
                   | 
| 85 | 
            -
                     | 
| 86 | 
            -
                     | 
| 71 | 
            +
                  it 'changes to given valid directory before launch' do
         | 
| 72 | 
            +
                    use { @app = App.launch(dir: APP_PATH.sub(/LockNote.exe/, ''), path: 'Locknote.exe', title: WIN_TITLE) }
         | 
| 73 | 
            +
                    @app.should be_an App
         | 
| 74 | 
            +
                  end
         | 
| 87 75 |  | 
| 88 | 
            -
             | 
| 89 | 
            -
             | 
| 90 | 
            -
             | 
| 91 | 
            -
                    end
         | 
| 76 | 
            +
                  it 'raises error if given invalid directory to change' do
         | 
| 77 | 
            +
                    expect { @app = App.launch(dir: APP_PATH, path: APP_PATH, title: WIN_TITLE) }.
         | 
| 78 | 
            +
                        to raise_error WinGui::Errors::InitError, /Unable to change to ".*LockNote.exe"/
         | 
| 92 79 | 
             
                  end
         | 
| 93 80 | 
             
                end
         | 
| 94 81 |  | 
| 95 | 
            -
                context ' | 
| 82 | 
            +
                context 'properties:' do
         | 
| 96 83 | 
             
                  before(:each) { @app = App.launch(path: APP_PATH, title: WIN_TITLE) }
         | 
| 84 | 
            +
                  after(:each) { @app.close }
         | 
| 97 85 |  | 
| 98 | 
            -
                  it ' | 
| 99 | 
            -
                    @app. | 
| 100 | 
            -
                     | 
| 101 | 
            -
                    @app.main_window.visible?.should == false
         | 
| 102 | 
            -
                    @app.main_window.window?.should == false
         | 
| 86 | 
            +
                  it 'main_window' do
         | 
| 87 | 
            +
                    @app.main_window.should be_a Window
         | 
| 88 | 
            +
                    @app.main_window.title.should == WIN_TITLE
         | 
| 103 89 | 
             
                  end
         | 
| 90 | 
            +
                end
         | 
| 91 | 
            +
              end
         | 
| 104 92 |  | 
| 105 | 
            -
             | 
| 106 | 
            -
             | 
| 107 | 
            -
                    sleep SLEEP_DELAY # needed to ensure window had enough time to close down
         | 
| 108 | 
            -
                    @app.main_window.visible?.should == false
         | 
| 109 | 
            -
                    @app.main_window.window?.should == false
         | 
| 110 | 
            -
                  end
         | 
| 93 | 
            +
              context 'manipulating' do
         | 
| 94 | 
            +
                before(:each) { @app = App.launch(path: APP_PATH, title: WIN_TITLE) }
         | 
| 111 95 |  | 
| 112 | 
            -
             | 
| 113 | 
            -
             | 
| 114 | 
            -
             | 
| 115 | 
            -
             | 
| 116 | 
            -
             | 
| 117 | 
            -
             | 
| 96 | 
            +
                it 'exits App gracefully' do
         | 
| 97 | 
            +
                  @app.exit
         | 
| 98 | 
            +
                  sleep SLEEP_DELAY # needed to ensure window had enough time to close down
         | 
| 99 | 
            +
                  @app.main_window.visible?.should == false
         | 
| 100 | 
            +
                  @app.main_window.window?.should == false
         | 
| 101 | 
            +
                end
         | 
| 102 | 
            +
             | 
| 103 | 
            +
                it 'closes App gracefully' do
         | 
| 104 | 
            +
                  @app.close
         | 
| 105 | 
            +
                  sleep SLEEP_DELAY # needed to ensure window had enough time to close down
         | 
| 106 | 
            +
                  @app.main_window.visible?.should == false
         | 
| 107 | 
            +
                  @app.main_window.window?.should == false
         | 
| 108 | 
            +
                end
         | 
| 109 | 
            +
             | 
| 110 | 
            +
                it 'exits App with timeout' do
         | 
| 111 | 
            +
                  @app.exit(1)
         | 
| 112 | 
            +
                  # No sleep SLEEP_DELAY needed!
         | 
| 113 | 
            +
                  @app.main_window.visible?.should == false
         | 
| 114 | 
            +
                  @app.main_window.window?.should == false
         | 
| 118 115 | 
             
                end
         | 
| 119 116 | 
             
              end
         | 
| 120 117 | 
             
            end
         | 
| @@ -1,75 +1,72 @@ | |
| 1 | 
            -
             | 
| 1 | 
            +
            require "spec_helper.rb"
         | 
| 2 2 |  | 
| 3 | 
            -
             | 
| 3 | 
            +
            describe WinGui, 'Convenience methods' do
         | 
| 4 | 
            +
              before(:each) { @win = launch_test_app.main_window }
         | 
| 5 | 
            +
              after(:each) { close_test_app }
         | 
| 4 6 |  | 
| 5 | 
            -
              describe ' | 
| 6 | 
            -
                 | 
| 7 | 
            -
             | 
| 7 | 
            +
              describe '#dialog' do
         | 
| 8 | 
            +
                it 'returns top-level dialog window with given title if no block attached' do
         | 
| 9 | 
            +
                  with_dialog(:save) do
         | 
| 10 | 
            +
                    dialog_window = dialog(title: DIALOG_TITLE, timeout: 0.1)
         | 
| 11 | 
            +
                    dialog_window.should_not == nil
         | 
| 12 | 
            +
                    dialog_window.should be_a Window
         | 
| 13 | 
            +
                    dialog_window.text.should == DIALOG_TITLE
         | 
| 14 | 
            +
                  end
         | 
| 15 | 
            +
                end
         | 
| 8 16 |  | 
| 9 | 
            -
                 | 
| 10 | 
            -
                   | 
| 11 | 
            -
                     | 
| 12 | 
            -
                      dialog_window = dialog(title: DIALOG_TITLE, timeout: 0.1)
         | 
| 17 | 
            +
                it 'yields found dialog window to block if block is attached' do
         | 
| 18 | 
            +
                  with_dialog(:save) do
         | 
| 19 | 
            +
                    dialog(title: DIALOG_TITLE) do |dialog_window|
         | 
| 13 20 | 
             
                      dialog_window.should_not == nil
         | 
| 14 21 | 
             
                      dialog_window.should be_a Window
         | 
| 15 22 | 
             
                      dialog_window.text.should == DIALOG_TITLE
         | 
| 16 23 | 
             
                    end
         | 
| 17 24 | 
             
                  end
         | 
| 25 | 
            +
                end
         | 
| 18 26 |  | 
| 19 | 
            -
             | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 22 | 
            -
                        dialog_window.should_not == nil
         | 
| 23 | 
            -
                        dialog_window.should be_a Window
         | 
| 24 | 
            -
                        dialog_window.text.should == DIALOG_TITLE
         | 
| 25 | 
            -
                      end
         | 
| 26 | 
            -
                    end
         | 
| 27 | 
            -
                  end
         | 
| 28 | 
            -
             | 
| 29 | 
            -
                  it 'returns nil if there is no dialog with given title' do
         | 
| 30 | 
            -
                    with_dialog(:save) do
         | 
| 31 | 
            -
                      dialog(title: IMPOSSIBLE, timeout: 0.1).should == nil
         | 
| 32 | 
            -
                    end
         | 
| 27 | 
            +
                it 'returns nil if there is no dialog with given title' do
         | 
| 28 | 
            +
                  with_dialog(:save) do
         | 
| 29 | 
            +
                    dialog(title: IMPOSSIBLE, timeout: 0.1).should == nil
         | 
| 33 30 | 
             
                  end
         | 
| 31 | 
            +
                end
         | 
| 34 32 |  | 
| 35 | 
            -
             | 
| 36 | 
            -
             | 
| 37 | 
            -
             | 
| 38 | 
            -
             | 
| 39 | 
            -
                      end
         | 
| 33 | 
            +
                it 'yields nil to attached block if no dialog found' do
         | 
| 34 | 
            +
                  with_dialog(:save) do
         | 
| 35 | 
            +
                    dialog(title: IMPOSSIBLE, timeout: 0.1) do |dialog_window|
         | 
| 36 | 
            +
                      dialog_window.should == nil
         | 
| 40 37 | 
             
                    end
         | 
| 41 38 | 
             
                  end
         | 
| 39 | 
            +
                end
         | 
| 42 40 |  | 
| 43 | 
            -
             | 
| 44 | 
            -
             | 
| 45 | 
            -
             | 
| 46 | 
            -
                    end
         | 
| 41 | 
            +
                it 'considers all arguments optional' do
         | 
| 42 | 
            +
                  with_dialog(:save) do
         | 
| 43 | 
            +
                    use { dialog_window = dialog() }
         | 
| 47 44 | 
             
                  end
         | 
| 48 | 
            -
                end | 
| 45 | 
            +
                end
         | 
| 46 | 
            +
              end # describe dialog
         | 
| 49 47 |  | 
| 50 | 
            -
             | 
| 51 | 
            -
             | 
| 52 | 
            -
             | 
| 48 | 
            +
              describe 'convenience input methods on top of Windows API' do
         | 
| 49 | 
            +
                describe '#keystroke' do
         | 
| 50 | 
            +
                  spec { use { keystroke(vkey = 30, char = 'Z') } }
         | 
| 53 51 |  | 
| 54 | 
            -
             | 
| 55 | 
            -
             | 
| 56 | 
            -
             | 
| 57 | 
            -
             | 
| 58 | 
            -
             | 
| 59 | 
            -
             | 
| 60 | 
            -
             | 
| 61 | 
            -
             | 
| 62 | 
            -
             | 
| 52 | 
            +
                  it 'emulates combinations of keys pressed (Ctrl+Alt+P+M, etc)' do
         | 
| 53 | 
            +
                    keystroke(VK_CONTROL, 'A')
         | 
| 54 | 
            +
                    keystroke(VK_SPACE)
         | 
| 55 | 
            +
                    textarea = @win.child(class: TEXTAREA_CLASS)
         | 
| 56 | 
            +
                    textarea.text.should.should == ' '
         | 
| 57 | 
            +
                    keystroke('1', '2', 'A', 'B'.ord)
         | 
| 58 | 
            +
                    textarea.text.should.should == ' 12ab'
         | 
| 59 | 
            +
                  end
         | 
| 60 | 
            +
                end # describe '#keystroke'
         | 
| 63 61 |  | 
| 64 | 
            -
             | 
| 65 | 
            -
             | 
| 66 | 
            -
             | 
| 67 | 
            -
             | 
| 68 | 
            -
             | 
| 69 | 
            -
             | 
| 70 | 
            -
             | 
| 71 | 
            -
             | 
| 62 | 
            +
                describe '#type_in' do
         | 
| 63 | 
            +
                  it 'types text message into the window holding the focus' do
         | 
| 64 | 
            +
                    text = '1234 abcdefg'
         | 
| 65 | 
            +
                    type_in(text)
         | 
| 66 | 
            +
                    textarea = @win.child(class: TEXTAREA_CLASS)
         | 
| 67 | 
            +
                    textarea.text.should =~ Regexp.new(text)
         | 
| 68 | 
            +
                  end
         | 
| 69 | 
            +
                end # describe '#type_in'
         | 
| 72 70 |  | 
| 73 | 
            -
             | 
| 74 | 
            -
             | 
| 75 | 
            -
            end
         | 
| 71 | 
            +
              end # Input methods
         | 
| 72 | 
            +
            end # Convenience methods
         | 
    
        data/spec/win_gui/window_spec.rb
    CHANGED
    
    | @@ -1,275 +1,272 @@ | |
| 1 | 
            -
             | 
| 1 | 
            +
            require "spec_helper.rb"
         | 
| 2 2 |  | 
| 3 | 
            -
             | 
| 3 | 
            +
            describe WinGui::Window do
         | 
| 4 | 
            +
              before(:each) { @win = launch_test_app.main_window }
         | 
| 5 | 
            +
              after(:each) { close_test_app }
         | 
| 4 6 |  | 
| 5 | 
            -
               | 
| 6 | 
            -
                 | 
| 7 | 
            -
             | 
| 7 | 
            +
              context 'initializing' do
         | 
| 8 | 
            +
                it 'can be wrapped around any existing window' do
         | 
| 9 | 
            +
                  any_handle = find_window(nil, nil)
         | 
| 10 | 
            +
                  use { Window.new any_handle }
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
              end
         | 
| 8 13 |  | 
| 9 | 
            -
             | 
| 10 | 
            -
             | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 13 | 
            -
                   | 
| 14 | 
            +
              context 'manipulating' do
         | 
| 15 | 
            +
                it 'closes when asked nicely' do
         | 
| 16 | 
            +
                  @win.close
         | 
| 17 | 
            +
                  sleep SLEEP_DELAY # needed to ensure window had enough time to close down
         | 
| 18 | 
            +
                  find_window(nil, WIN_TITLE).should == nil
         | 
| 14 19 | 
             
                end
         | 
| 15 20 |  | 
| 16 | 
            -
                 | 
| 17 | 
            -
                   | 
| 18 | 
            -
             | 
| 19 | 
            -
             | 
| 20 | 
            -
             | 
| 21 | 
            -
                   | 
| 21 | 
            +
                it 'waits for window to disappear (NB: this happens before handle is released!)' do
         | 
| 22 | 
            +
                  start = Time.now
         | 
| 23 | 
            +
                  @win.close
         | 
| 24 | 
            +
                  @win.wait_for_close
         | 
| 25 | 
            +
                  (Time.now - start).should be <= CLOSE_TIMEOUT
         | 
| 26 | 
            +
                  window_visible?(@win.handle).should be false
         | 
| 27 | 
            +
                  window?(@win.handle).should be false
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
              end
         | 
| 22 30 |  | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
             | 
| 27 | 
            -
             | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 30 | 
            -
                   | 
| 31 | 
            +
              context 'handle-related WinGui functions as instance methods' do
         | 
| 32 | 
            +
                it 'calls all WinGui functions as instance methods (with handle as implicit first argument)' do
         | 
| 33 | 
            +
                  @win.window?.should == true
         | 
| 34 | 
            +
                  @win.visible?.should == true
         | 
| 35 | 
            +
                  @win.foreground?.should == true
         | 
| 36 | 
            +
                  @win.maximized?.should == false
         | 
| 37 | 
            +
                  @win.minimized?.should == false
         | 
| 38 | 
            +
                  @win.child?(any_handle).should == false
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                  @win.window_rect.should be_an Array
         | 
| 41 | 
            +
                  @win.window_thread_process_id.should be_an Array
         | 
| 42 | 
            +
                  @win.enum_child_windows.should be_an Array
         | 
| 31 43 | 
             
                end
         | 
| 44 | 
            +
              end
         | 
| 32 45 |  | 
| 33 | 
            -
             | 
| 34 | 
            -
             | 
| 35 | 
            -
             | 
| 36 | 
            -
             | 
| 37 | 
            -
             | 
| 38 | 
            -
                    @win.maximized?.should == false
         | 
| 39 | 
            -
                    @win.minimized?.should == false
         | 
| 40 | 
            -
                    @win.child?(any_handle).should == false
         | 
| 41 | 
            -
             | 
| 42 | 
            -
                    @win.window_rect.should be_an Array
         | 
| 43 | 
            -
                    @win.window_thread_process_id.should be_an Array
         | 
| 44 | 
            -
                    @win.enum_child_windows.should be_an Array
         | 
| 45 | 
            -
                  end
         | 
| 46 | 
            -
               end
         | 
| 46 | 
            +
              context 'derived properties' do
         | 
| 47 | 
            +
                it 'has handle property equal to underlying window handle' do
         | 
| 48 | 
            +
                  any = Window.new any_handle
         | 
| 49 | 
            +
                  any.handle.should == any_handle
         | 
| 50 | 
            +
                end
         | 
| 47 51 |  | 
| 48 | 
            -
                 | 
| 49 | 
            -
                   | 
| 50 | 
            -
             | 
| 51 | 
            -
             | 
| 52 | 
            -
                   | 
| 52 | 
            +
                it 'has class_name and text/title properties (derived from WinGui function calls)' do
         | 
| 53 | 
            +
                  @win.class_name.should == WIN_CLASS
         | 
| 54 | 
            +
                  # text propery accessed by sending WM_GETTEXT directly to window (convenience method in WinGui)
         | 
| 55 | 
            +
                  @win.text.should == WIN_TITLE
         | 
| 56 | 
            +
                  # window_text propery accessed via GetWindowText
         | 
| 57 | 
            +
                  @win.window_text.should == WIN_TITLE
         | 
| 58 | 
            +
                  # title property is just an alias for window_text
         | 
| 59 | 
            +
                  @win.title.should == WIN_TITLE
         | 
| 60 | 
            +
                end
         | 
| 53 61 |  | 
| 54 | 
            -
             | 
| 55 | 
            -
             | 
| 56 | 
            -
             | 
| 57 | 
            -
             | 
| 58 | 
            -
             | 
| 59 | 
            -
                    @win.window_text.should == WIN_TITLE
         | 
| 60 | 
            -
                    # title property is just an alias for window_text
         | 
| 61 | 
            -
                    @win.title.should == WIN_TITLE
         | 
| 62 | 
            -
                  end
         | 
| 62 | 
            +
                it 'has thread and process properties derived from get_window_thread_process_id' do
         | 
| 63 | 
            +
                  thread  = @win.thread
         | 
| 64 | 
            +
                  process = @win.process
         | 
| 65 | 
            +
                  [thread, process].should == get_window_thread_process_id(@win.handle)
         | 
| 66 | 
            +
                end
         | 
| 63 67 |  | 
| 64 | 
            -
             | 
| 65 | 
            -
             | 
| 66 | 
            -
             | 
| 67 | 
            -
             | 
| 68 | 
            -
                  end
         | 
| 68 | 
            +
                it 'has id property that only makes sense for controls' do
         | 
| 69 | 
            +
                  use { @win.id }
         | 
| 70 | 
            +
                end
         | 
| 71 | 
            +
              end
         | 
| 69 72 |  | 
| 70 | 
            -
             | 
| 71 | 
            -
             | 
| 72 | 
            -
                   | 
| 73 | 
            +
              describe '::top_level' do
         | 
| 74 | 
            +
                it 'finds top-level window by title and wraps it in a Window object' do
         | 
| 75 | 
            +
                  window = Window.top_level(title: WIN_TITLE, timeout: 1)
         | 
| 76 | 
            +
                  window.handle.should == @win.handle
         | 
| 73 77 | 
             
                end
         | 
| 74 78 |  | 
| 75 | 
            -
                 | 
| 76 | 
            -
                   | 
| 77 | 
            -
             | 
| 78 | 
            -
             | 
| 79 | 
            -
                  end
         | 
| 79 | 
            +
                it 'finds top-level window by class and wraps it in a Window object' do
         | 
| 80 | 
            +
                  window = Window.top_level(class: WIN_CLASS, timeout: 1)
         | 
| 81 | 
            +
                  window.handle.should == @win.handle
         | 
| 82 | 
            +
                end
         | 
| 80 83 |  | 
| 81 | 
            -
             | 
| 82 | 
            -
             | 
| 83 | 
            -
             | 
| 84 | 
            -
             | 
| 84 | 
            +
                it 'finds ANY top-level window without args and wraps it in a Window object' do
         | 
| 85 | 
            +
                  use { @window = Window.top_level() }
         | 
| 86 | 
            +
                  @window.should be_a Window
         | 
| 87 | 
            +
                end
         | 
| 85 88 |  | 
| 86 | 
            -
             | 
| 87 | 
            -
             | 
| 88 | 
            -
             | 
| 89 | 
            -
                   | 
| 89 | 
            +
                it 'returns nil immediately if top-level window with given title not found' do
         | 
| 90 | 
            +
                  start = Time.now
         | 
| 91 | 
            +
                  Window.top_level(title: IMPOSSIBLE).should == nil
         | 
| 92 | 
            +
                  (Time.now - start).should be_within(0.03).of 0
         | 
| 93 | 
            +
                end
         | 
| 90 94 |  | 
| 91 | 
            -
             | 
| 92 | 
            -
             | 
| 93 | 
            -
             | 
| 94 | 
            -
             | 
| 95 | 
            -
             | 
| 95 | 
            +
                it 'returns nil after timeout if top-level window with given title not found' do
         | 
| 96 | 
            +
                  start = Time.now
         | 
| 97 | 
            +
                  Window.top_level(title: IMPOSSIBLE, timeout: 0.3).should == nil
         | 
| 98 | 
            +
                  (Time.now - start).should be_within(0.03).of 0.3
         | 
| 99 | 
            +
                end
         | 
| 96 100 |  | 
| 97 | 
            -
             | 
| 98 | 
            -
             | 
| 99 | 
            -
             | 
| 100 | 
            -
                    (Time.now - start).should be_close 0.3, 0.03
         | 
| 101 | 
            -
                  end
         | 
| 101 | 
            +
                it 'raises exception if asked to' do
         | 
| 102 | 
            +
                  expect { Window.top_level(title: IMPOSSIBLE, raise: "Horror!") }.to raise_error "Horror!"
         | 
| 103 | 
            +
                end
         | 
| 102 104 |  | 
| 103 | 
            -
             | 
| 104 | 
            -
             | 
| 105 | 
            -
                   | 
| 105 | 
            +
                it 'uses .find as alias for .top_level' do
         | 
| 106 | 
            +
                  use { @window = Window.find() }
         | 
| 107 | 
            +
                  @window.should be_a Window
         | 
| 108 | 
            +
                end
         | 
| 109 | 
            +
              end # describe .top_level
         | 
| 106 110 |  | 
| 107 | 
            -
             | 
| 108 | 
            -
             | 
| 109 | 
            -
                    @window.should be_a Window
         | 
| 110 | 
            -
                  end
         | 
| 111 | 
            -
                end # describe .top_level
         | 
| 111 | 
            +
              describe '#child' do
         | 
| 112 | 
            +
                spec { use { @child = @win.child(title: "Title", class: "Class", id: 0) } }
         | 
| 112 113 |  | 
| 113 | 
            -
                 | 
| 114 | 
            -
                   | 
| 114 | 
            +
                it 'returns nil immediately if specific child not found' do
         | 
| 115 | 
            +
                  start = Time.now
         | 
| 116 | 
            +
                  @win.child(title: IMPOSSIBLE).should == nil
         | 
| 117 | 
            +
                  (Time.now - start).should be_within(0.03).of 0
         | 
| 118 | 
            +
                end
         | 
| 115 119 |  | 
| 116 | 
            -
             | 
| 117 | 
            -
             | 
| 118 | 
            -
             | 
| 119 | 
            -
             | 
| 120 | 
            -
             | 
| 120 | 
            +
                it 'returns nil after timeout if specific child not found' do
         | 
| 121 | 
            +
                  start = Time.now
         | 
| 122 | 
            +
                  @win.child(title: IMPOSSIBLE, timeout: 0.5).should == nil
         | 
| 123 | 
            +
                  (Time.now - start).should be_within(0.03).of 0.5
         | 
| 124 | 
            +
                end
         | 
| 121 125 |  | 
| 122 | 
            -
             | 
| 123 | 
            -
             | 
| 124 | 
            -
             | 
| 125 | 
            -
             | 
| 126 | 
            -
             | 
| 126 | 
            +
                it 'finds ANY child window without args' do
         | 
| 127 | 
            +
                  use { @child = @win.child() }
         | 
| 128 | 
            +
                  @child.should_not == nil
         | 
| 129 | 
            +
                  @win.child?(@child.handle).should == true
         | 
| 130 | 
            +
                end
         | 
| 127 131 |  | 
| 128 | 
            -
             | 
| 129 | 
            -
             | 
| 130 | 
            -
             | 
| 131 | 
            -
             | 
| 132 | 
            -
             | 
| 132 | 
            +
                it 'finds child window by class and returns it as a Window object (no timeout)' do
         | 
| 133 | 
            +
                  child = @win.child(class: TEXTAREA_CLASS)
         | 
| 134 | 
            +
                  child.should_not == nil
         | 
| 135 | 
            +
                  @win.child?(child.handle).should == true
         | 
| 136 | 
            +
                end
         | 
| 137 | 
            +
             | 
| 138 | 
            +
                it 'finds child window by class and returns it as a Window object (with timeout)' do
         | 
| 139 | 
            +
                  child = @win.child(class: TEXTAREA_CLASS, timeout: 0.5)
         | 
| 140 | 
            +
                  child.should_not == nil
         | 
| 141 | 
            +
             | 
| 142 | 
            +
                  @win.child?(child.handle).should == true
         | 
| 143 | 
            +
                  child = @win.child(class: STATUSBAR_CLASS, timeout: 0.5)
         | 
| 144 | 
            +
                  child.should_not == nil
         | 
| 145 | 
            +
                  @win.child?(child.handle).should == true
         | 
| 146 | 
            +
                end
         | 
| 133 147 |  | 
| 134 | 
            -
             | 
| 135 | 
            -
             | 
| 148 | 
            +
                it 'finds child with specific text and returns it as a Window object' do
         | 
| 149 | 
            +
                  with_dialog(:save) do |dialog|
         | 
| 150 | 
            +
                    child = dialog.child(title: "Cancel")
         | 
| 136 151 | 
             
                    child.should_not == nil
         | 
| 137 | 
            -
                     | 
| 152 | 
            +
                    dialog.child?(child.handle).should == true
         | 
| 153 | 
            +
                    child.get_dlg_ctrl_id.should == IDCANCEL
         | 
| 154 | 
            +
             | 
| 155 | 
            +
                    child = dialog.child(title: "&Save")
         | 
| 156 | 
            +
                    child.should_not == nil
         | 
| 157 | 
            +
                    dialog.child?(child.handle).should == true
         | 
| 158 | 
            +
                    child.get_dlg_ctrl_id.should == IDOK
         | 
| 138 159 | 
             
                  end
         | 
| 160 | 
            +
                end
         | 
| 139 161 |  | 
| 140 | 
            -
             | 
| 141 | 
            -
             | 
| 162 | 
            +
                it 'finds child control with a given ID and returns it as a Window object' do
         | 
| 163 | 
            +
                  with_dialog(:save) do |dialog|
         | 
| 164 | 
            +
                    child = dialog.child(id: IDCANCEL)
         | 
| 142 165 | 
             
                    child.should_not == nil
         | 
| 166 | 
            +
                    dialog.child?(child.handle).should == true
         | 
| 167 | 
            +
                    child.text.should == "Cancel"
         | 
| 168 | 
            +
                  end
         | 
| 169 | 
            +
                end
         | 
| 143 170 |  | 
| 144 | 
            -
             | 
| 145 | 
            -
             | 
| 171 | 
            +
                context 'indirect child' do
         | 
| 172 | 
            +
                  it 'returns nil if specified child not found' do
         | 
| 173 | 
            +
                    @win.child(title: IMPOSSIBLE, indirect: true).should == nil
         | 
| 174 | 
            +
                  end
         | 
| 175 | 
            +
             | 
| 176 | 
            +
                  it 'finds ANY child window without other args' do
         | 
| 177 | 
            +
                    use { @child = @win.child(indirect: true) }
         | 
| 178 | 
            +
                    @child.should_not == nil
         | 
| 179 | 
            +
                    @win.child?(@child.handle).should == true
         | 
| 180 | 
            +
                  end
         | 
| 181 | 
            +
             | 
| 182 | 
            +
                  it 'finds child window by class' do
         | 
| 183 | 
            +
                    child = @win.child(class: TEXTAREA_CLASS, indirect: true)
         | 
| 146 184 | 
             
                    child.should_not == nil
         | 
| 147 185 | 
             
                    @win.child?(child.handle).should == true
         | 
| 148 186 | 
             
                  end
         | 
| 149 187 |  | 
| 150 | 
            -
                  it 'finds child with specific text | 
| 188 | 
            +
                  it 'finds child with specific text' do
         | 
| 151 189 | 
             
                    with_dialog(:save) do |dialog|
         | 
| 152 | 
            -
                      child = dialog.child( | 
| 190 | 
            +
                      child = dialog.child(title: "Cancel", indirect: true)
         | 
| 153 191 | 
             
                      child.should_not == nil
         | 
| 154 192 | 
             
                      dialog.child?(child.handle).should == true
         | 
| 155 | 
            -
                      child. | 
| 193 | 
            +
                      child.id.should == IDCANCEL
         | 
| 156 194 |  | 
| 157 | 
            -
                      child = dialog.child( | 
| 195 | 
            +
                      child = dialog.child(title: "&Save", indirect: true)
         | 
| 158 196 | 
             
                      child.should_not == nil
         | 
| 159 197 | 
             
                      dialog.child?(child.handle).should == true
         | 
| 160 | 
            -
                      child. | 
| 198 | 
            +
                      child.id.should == IDOK
         | 
| 161 199 | 
             
                    end
         | 
| 162 200 | 
             
                  end
         | 
| 163 201 |  | 
| 164 | 
            -
                  it 'finds child control with a given ID  | 
| 202 | 
            +
                  it 'finds child control with a given ID ' do
         | 
| 165 203 | 
             
                    with_dialog(:save) do |dialog|
         | 
| 166 | 
            -
                      child = dialog.child( | 
| 204 | 
            +
                      child = dialog.child(id: IDCANCEL, indirect: true)
         | 
| 167 205 | 
             
                      child.should_not == nil
         | 
| 168 206 | 
             
                      dialog.child?(child.handle).should == true
         | 
| 169 207 | 
             
                      child.text.should == "Cancel"
         | 
| 170 208 | 
             
                    end
         | 
| 171 209 | 
             
                  end
         | 
| 172 | 
            -
             | 
| 173 | 
            -
             | 
| 174 | 
            -
             | 
| 175 | 
            -
             | 
| 176 | 
            -
             | 
| 177 | 
            -
             | 
| 178 | 
            -
             | 
| 179 | 
            -
             | 
| 180 | 
            -
             | 
| 181 | 
            -
             | 
| 182 | 
            -
             | 
| 183 | 
            -
             | 
| 184 | 
            -
             | 
| 185 | 
            -
             | 
| 186 | 
            -
             | 
| 187 | 
            -
             | 
| 188 | 
            -
             | 
| 189 | 
            -
             | 
| 190 | 
            -
             | 
| 191 | 
            -
             | 
| 192 | 
            -
             | 
| 193 | 
            -
             | 
| 194 | 
            -
             | 
| 195 | 
            -
                        child.id.should == IDCANCEL
         | 
| 196 | 
            -
             | 
| 197 | 
            -
                        child = dialog.child( title: "&Save", indirect: true)
         | 
| 198 | 
            -
                        child.should_not == nil
         | 
| 199 | 
            -
                        dialog.child?(child.handle).should == true
         | 
| 200 | 
            -
                        child.id.should == IDOK
         | 
| 201 | 
            -
                      end
         | 
| 202 | 
            -
                    end
         | 
| 203 | 
            -
             | 
| 204 | 
            -
                    it 'finds child control with a given ID ' do
         | 
| 205 | 
            -
                      with_dialog(:save) do |dialog|
         | 
| 206 | 
            -
                        child = dialog.child( id: IDCANCEL, indirect: true)
         | 
| 207 | 
            -
                        child.should_not == nil
         | 
| 208 | 
            -
                        dialog.child?(child.handle).should == true
         | 
| 209 | 
            -
                        child.text.should == "Cancel"
         | 
| 210 | 
            -
                      end
         | 
| 211 | 
            -
                    end
         | 
| 212 | 
            -
                  end # context indirect
         | 
| 213 | 
            -
                end # describe child
         | 
| 214 | 
            -
             | 
| 215 | 
            -
                describe '#children' do
         | 
| 216 | 
            -
                  spec { use { children = @win.children  }}
         | 
| 217 | 
            -
             | 
| 218 | 
            -
                  it 'returns an array of Windows that are descendants (not only DIRECT children) of a given Window' do
         | 
| 219 | 
            -
                    children = @win.children
         | 
| 220 | 
            -
                    children.should be_a_kind_of Array
         | 
| 221 | 
            -
                    children.should_not be_empty
         | 
| 222 | 
            -
                    children.should have(2).elements
         | 
| 223 | 
            -
                    children.each{|child| child?(@win.handle, child.handle).should == true }
         | 
| 224 | 
            -
                    children.last.class_name.should == TEXTAREA_CLASS
         | 
| 210 | 
            +
                end # context indirect
         | 
| 211 | 
            +
              end # describe child
         | 
| 212 | 
            +
             | 
| 213 | 
            +
              describe '#children' do
         | 
| 214 | 
            +
                spec { use { children = @win.children } }
         | 
| 215 | 
            +
             | 
| 216 | 
            +
                it 'returns an array of Windows that are descendants (not only DIRECT children) of a given Window' do
         | 
| 217 | 
            +
                  children = @win.children
         | 
| 218 | 
            +
                  children.should be_a_kind_of Array
         | 
| 219 | 
            +
                  children.should_not be_empty
         | 
| 220 | 
            +
                  children.should have(2).elements
         | 
| 221 | 
            +
                  children.each { |child| child?(@win.handle, child.handle).should == true }
         | 
| 222 | 
            +
                  children.last.class_name.should == TEXTAREA_CLASS
         | 
| 223 | 
            +
                end
         | 
| 224 | 
            +
              end # describe #children
         | 
| 225 | 
            +
             | 
| 226 | 
            +
              describe '#click' do
         | 
| 227 | 
            +
                it 'emulates left click of the control identified by id, returns click coords' do
         | 
| 228 | 
            +
                  with_dialog(:save) do |dialog|
         | 
| 229 | 
            +
                    point = dialog.click(id: IDCANCEL)
         | 
| 230 | 
            +
                    point.should be_an Array
         | 
| 231 | 
            +
                    sleep 0.3
         | 
| 232 | 
            +
                    dialog.window?.should == false
         | 
| 225 233 | 
             
                  end
         | 
| 226 | 
            -
                end | 
| 234 | 
            +
                end
         | 
| 227 235 |  | 
| 228 | 
            -
                 | 
| 229 | 
            -
                   | 
| 230 | 
            -
                     | 
| 231 | 
            -
             | 
| 232 | 
            -
             | 
| 233 | 
            -
             | 
| 234 | 
            -
                      dialog.window?.should == false
         | 
| 235 | 
            -
                    end
         | 
| 236 | 
            +
                it 'emulates left click of the control identified by title, returns click coords' do
         | 
| 237 | 
            +
                  with_dialog(:save) do |dialog|
         | 
| 238 | 
            +
                    point = dialog.click(title: "Cancel")
         | 
| 239 | 
            +
                    point.should be_an Array
         | 
| 240 | 
            +
                    sleep 0.3
         | 
| 241 | 
            +
                    dialog.window?.should == false
         | 
| 236 242 | 
             
                  end
         | 
| 243 | 
            +
                end
         | 
| 237 244 |  | 
| 238 | 
            -
             | 
| 239 | 
            -
             | 
| 240 | 
            -
             | 
| 241 | 
            -
             | 
| 242 | 
            -
             | 
| 243 | 
            -
             | 
| 244 | 
            -
                    end
         | 
| 245 | 
            -
                  end
         | 
| 246 | 
            -
             | 
| 247 | 
            -
                  it 'emulates right click of the control identified by id, returns click coords' do
         | 
| 248 | 
            -
                    with_dialog(:save) do |dialog|
         | 
| 249 | 
            -
                      point = dialog.click(id: IDCANCEL, mouse_button: :right)
         | 
| 250 | 
            -
                      point.should be_an Array
         | 
| 251 | 
            -
                      sleep 0.3
         | 
| 252 | 
            -
                      dialog.window?.should == true
         | 
| 253 | 
            -
                    end
         | 
| 245 | 
            +
                it 'emulates right click of the control identified by id, returns click coords' do
         | 
| 246 | 
            +
                  with_dialog(:save) do |dialog|
         | 
| 247 | 
            +
                    point = dialog.click(id: IDCANCEL, mouse_button: :right)
         | 
| 248 | 
            +
                    point.should be_an Array
         | 
| 249 | 
            +
                    sleep 0.3
         | 
| 250 | 
            +
                    dialog.window?.should == true
         | 
| 254 251 | 
             
                  end
         | 
| 252 | 
            +
                end
         | 
| 255 253 |  | 
| 256 | 
            -
             | 
| 257 | 
            -
             | 
| 258 | 
            -
             | 
| 259 | 
            -
             | 
| 260 | 
            -
             | 
| 261 | 
            -
             | 
| 262 | 
            -
                    end
         | 
| 254 | 
            +
                it 'emulates right click of the control identified by title, returns click coords' do
         | 
| 255 | 
            +
                  with_dialog(:save) do |dialog|
         | 
| 256 | 
            +
                    point = dialog.click(title: "Cancel", mouse_button: :right)
         | 
| 257 | 
            +
                    point.should be_an Array
         | 
| 258 | 
            +
                    sleep 0.3
         | 
| 259 | 
            +
                    dialog.window?.should == true
         | 
| 263 260 | 
             
                  end
         | 
| 261 | 
            +
                end
         | 
| 264 262 |  | 
| 265 | 
            -
             | 
| 266 | 
            -
             | 
| 267 | 
            -
             | 
| 268 | 
            -
             | 
| 269 | 
            -
             | 
| 270 | 
            -
             | 
| 271 | 
            -
                    end
         | 
| 263 | 
            +
                it 'returns nil if the specified control was not found' do
         | 
| 264 | 
            +
                  with_dialog(:save) do |dialog|
         | 
| 265 | 
            +
                    dialog.click(title: "Shpancel").should == nil
         | 
| 266 | 
            +
                    dialog.click(id: 66).should == nil
         | 
| 267 | 
            +
                    sleep 0.3
         | 
| 268 | 
            +
                    dialog.window?.should == true
         | 
| 272 269 | 
             
                  end
         | 
| 273 | 
            -
                end | 
| 274 | 
            -
              end
         | 
| 270 | 
            +
                end
         | 
| 271 | 
            +
              end # describe #click
         | 
| 275 272 | 
             
            end
         | 
    
        data/tasks/spec.rake
    CHANGED
    
    | @@ -2,17 +2,13 @@ desc 'Alias to spec:spec' | |
| 2 2 | 
             
            task :spec => 'spec:spec'
         | 
| 3 3 |  | 
| 4 4 | 
             
            namespace :spec do
         | 
| 5 | 
            -
              require ' | 
| 5 | 
            +
              require 'rspec/core/rake_task'
         | 
| 6 6 |  | 
| 7 7 | 
             
              desc "Run all specs"
         | 
| 8 | 
            -
               | 
| 9 | 
            -
                t.spec_opts = ['--options', %Q{"#{BASE_PATH}/spec/spec.opts"}]
         | 
| 10 | 
            -
                t.spec_files = FileList['spec/**/*_spec.rb']
         | 
| 11 | 
            -
              end
         | 
| 8 | 
            +
              RSpec::Core::RakeTask.new(:spec){|task|}
         | 
| 12 9 |  | 
| 13 10 | 
             
              desc "Run specs with RCov"
         | 
| 14 | 
            -
               | 
| 15 | 
            -
                t.spec_files = FileList['spec/**/*_spec.rb']
         | 
| 11 | 
            +
              RSpec::Core::RakeTask.new(:rcov) do |t|
         | 
| 16 12 | 
             
                t.rcov = true
         | 
| 17 13 | 
             
                t.rcov_opts = ['--exclude', 'spec']
         | 
| 18 14 | 
             
              end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,13 +1,8 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification 
         | 
| 2 2 | 
             
            name: win_gui
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version 
         | 
| 4 | 
            -
               | 
| 5 | 
            -
               | 
| 6 | 
            -
              segments: 
         | 
| 7 | 
            -
              - 0
         | 
| 8 | 
            -
              - 2
         | 
| 9 | 
            -
              - 16
         | 
| 10 | 
            -
              version: 0.2.16
         | 
| 4 | 
            +
              prerelease: 
         | 
| 5 | 
            +
              version: 0.2.17
         | 
| 11 6 | 
             
            platform: ruby
         | 
| 12 7 | 
             
            authors: 
         | 
| 13 8 | 
             
            - arvicco
         | 
| @@ -15,7 +10,7 @@ autorequire: | |
| 15 10 | 
             
            bindir: bin
         | 
| 16 11 | 
             
            cert_chain: []
         | 
| 17 12 |  | 
| 18 | 
            -
            date:  | 
| 13 | 
            +
            date: 2011-02-16 00:00:00 +03:00
         | 
| 19 14 | 
             
            default_executable: 
         | 
| 20 15 | 
             
            dependencies: 
         | 
| 21 16 | 
             
            - !ruby/object:Gem::Dependency 
         | 
| @@ -26,11 +21,6 @@ dependencies: | |
| 26 21 | 
             
                requirements: 
         | 
| 27 22 | 
             
                - - ">="
         | 
| 28 23 | 
             
                  - !ruby/object:Gem::Version 
         | 
| 29 | 
            -
                    hash: 13
         | 
| 30 | 
            -
                    segments: 
         | 
| 31 | 
            -
                    - 1
         | 
| 32 | 
            -
                    - 2
         | 
| 33 | 
            -
                    - 9
         | 
| 34 24 | 
             
                    version: 1.2.9
         | 
| 35 25 | 
             
              type: :development
         | 
| 36 26 | 
             
              version_requirements: *id001
         | 
| @@ -42,9 +32,6 @@ dependencies: | |
| 42 32 | 
             
                requirements: 
         | 
| 43 33 | 
             
                - - ">="
         | 
| 44 34 | 
             
                  - !ruby/object:Gem::Version 
         | 
| 45 | 
            -
                    hash: 3
         | 
| 46 | 
            -
                    segments: 
         | 
| 47 | 
            -
                    - 0
         | 
| 48 35 | 
             
                    version: "0"
         | 
| 49 36 | 
             
              type: :development
         | 
| 50 37 | 
             
              version_requirements: *id002
         | 
| @@ -56,11 +43,6 @@ dependencies: | |
| 56 43 | 
             
                requirements: 
         | 
| 57 44 | 
             
                - - ">="
         | 
| 58 45 | 
             
                  - !ruby/object:Gem::Version 
         | 
| 59 | 
            -
                    hash: 17
         | 
| 60 | 
            -
                    segments: 
         | 
| 61 | 
            -
                    - 0
         | 
| 62 | 
            -
                    - 3
         | 
| 63 | 
            -
                    - 1
         | 
| 64 46 | 
             
                    version: 0.3.1
         | 
| 65 47 | 
             
              type: :runtime
         | 
| 66 48 | 
             
              version_requirements: *id003
         | 
| @@ -82,7 +64,6 @@ files: | |
| 82 64 | 
             
            - lib/win_gui/window.rb
         | 
| 83 65 | 
             
            - lib/win_gui.rb
         | 
| 84 66 | 
             
            - spec/extension_spec.rb
         | 
| 85 | 
            -
            - spec/spec.opts
         | 
| 86 67 | 
             
            - spec/spec_helper.rb
         | 
| 87 68 | 
             
            - spec/win_gui/app_spec.rb
         | 
| 88 69 | 
             
            - spec/win_gui/convenience_spec.rb
         | 
| @@ -121,29 +102,22 @@ required_ruby_version: !ruby/object:Gem::Requirement | |
| 121 102 | 
             
              requirements: 
         | 
| 122 103 | 
             
              - - ">="
         | 
| 123 104 | 
             
                - !ruby/object:Gem::Version 
         | 
| 124 | 
            -
                  hash: 3
         | 
| 125 | 
            -
                  segments: 
         | 
| 126 | 
            -
                  - 0
         | 
| 127 105 | 
             
                  version: "0"
         | 
| 128 106 | 
             
            required_rubygems_version: !ruby/object:Gem::Requirement 
         | 
| 129 107 | 
             
              none: false
         | 
| 130 108 | 
             
              requirements: 
         | 
| 131 109 | 
             
              - - ">="
         | 
| 132 110 | 
             
                - !ruby/object:Gem::Version 
         | 
| 133 | 
            -
                  hash: 3
         | 
| 134 | 
            -
                  segments: 
         | 
| 135 | 
            -
                  - 0
         | 
| 136 111 | 
             
                  version: "0"
         | 
| 137 112 | 
             
            requirements: []
         | 
| 138 113 |  | 
| 139 | 
            -
            rubyforge_project:  | 
| 140 | 
            -
            rubygems_version: 1. | 
| 114 | 
            +
            rubyforge_project: 
         | 
| 115 | 
            +
            rubygems_version: 1.5.0
         | 
| 141 116 | 
             
            signing_key: 
         | 
| 142 117 | 
             
            specification_version: 3
         | 
| 143 118 | 
             
            summary: Abstractions/wrappers around GUI-related Win32 API functions
         | 
| 144 119 | 
             
            test_files: 
         | 
| 145 120 | 
             
            - spec/extension_spec.rb
         | 
| 146 | 
            -
            - spec/spec.opts
         | 
| 147 121 | 
             
            - spec/spec_helper.rb
         | 
| 148 122 | 
             
            - spec/win_gui/app_spec.rb
         | 
| 149 123 | 
             
            - spec/win_gui/convenience_spec.rb
         | 
    
        data/spec/spec.opts
    DELETED