# frozen_string_literal: true require 'watirspec_helper' module Watir describe Browser, exclude: {browser: :ie, reason: 'Cannot call #restore!'} do before do browser.goto WatirSpec.url_for('window_switching.html') browser.a(id: 'open').click browser.windows.wait_until(size: 2) end after do browser.windows.restore! end describe '#windows' do it 'returns a WindowCollection' do expect(browser.windows).to be_a(WindowCollection) end it 'stores Window instances' do expect(browser.windows(title: 'closeable window')).to all(be_a(Window)) end it 'filters windows to match the given selector' do expect(browser.windows(title: 'closeable window').size).to eq 1 end it 'raises ArgumentError if the selector is invalid' do expect { browser.windows(name: 'foo') }.to raise_error(ArgumentError) end it 'returns an empty array if no window matches the selector' do expect(browser.windows(title: 'noop')).to be_empty end end describe '#window' do it 'finds window by :url' do expect(browser.window(url: /closeable\.html/).use).to be_a(Window) end it 'finds window by :title' do expect(browser.window(title: 'closeable window').use).to be_a(Window) end it 'finds window by :element' do expect(browser.window(element: browser.a(id: 'close')).use).to be_a(Window) end it 'finds window by multiple values' do expect(browser.window(title: 'closeable window', url: /closeable\.html/).use).to be_a(Window) end it 'does not find incorrect handle' do expect(browser.window(handle: 'bar')).not_to be_present end it 'returns the current window if no argument is given' do expect(browser.window.url).to match(/window_switching\.html/) end it 'stores the reference to a window when no argument is given' do original_window = browser.window browser.window(title: 'closeable window').use expect(original_window.url).to match(/window_switching\.html/) end it 'executes the given block in the window', except: {browser: :safari, reason: 'Clicking an Element that Closes a Window is returning NoMatchingWindowFoundException'} do browser.window(title: 'closeable window') do link = browser.a(id: 'close') expect(link).to exist link.click end expect { browser.windows.wait_until(size: 1) }.not_to raise_error end it 'raises ArgumentError if the selector is invalid' do expect { browser.window(name: 'foo') }.to raise_error(ArgumentError) end it 'raises a NoMatchingWindowFoundException error if no window matches the selector' do expect { browser.window(title: 'noop').use }.to raise_no_matching_window_exception end it 'raises NoMatchingWindowFoundException error when attempting to use a window with an incorrect handle' do expect { browser.window(handle: 'bar').use }.to raise_no_matching_window_exception end end describe '#switch_window' do it 'stays on the same window when matches single window' do browser.switch_window browser.window.close browser.original_window.use title = browser.title expect { browser.window(title: title).use }.not_to raise_exception end it 'switches to second window' do original_window = browser.window browser.switch_window new_window = browser.window expect(original_window).not_to eq new_window expect(browser.windows).to include(original_window, new_window) end it 'returns an instance of Window' do expect(browser.switch_window).to be_a(Window) end it 'times out if there is no second window' do browser.windows.restore! message = /waiting for true condition on (.*) title="window switching">$/ expect { browser.switch_window }.to raise_timeout_exception(message) end it 'provides previous window value to #original_window' do browser.switch_window expect(browser.original_window).not_to be_nil end it 'waits for second window' do browser.windows.restore! expect { browser.a(id: 'delayed').click browser.switch_window }.to execute_when_satisfied(min: 1) end end end describe Window, exclude: {browser: :ie, reason: 'Cannot call #restore!'} do after do browser.windows.restore! end context 'when using multiple windows' do before do browser.goto WatirSpec.url_for('window_switching.html') browser.a(id: 'open').click browser.windows.wait_until(size: 2) end it 'allows actions on first window after opening second', except: {browser: :safari, reason: 'Focus is on newly opened window instead of the first'} do browser.a(id: 'open').click expect { browser.windows.wait_until(size: 3) }.not_to raise_timeout_exception end describe '#close' do it 'closes a window' do browser.window(title: 'window switching').use browser.a(id: 'open').click browser.windows.wait_until(size: 3) described_class.new(browser, title: 'closeable window').close expect { browser.windows.wait_until(size: 2) }.not_to raise_timeout_exception end it 'closes the current window', except: {browser: :safari}, reason: 'Focus is on newly opened window instead of the first' do browser.a(id: 'open').click browser.windows.wait_until(size: 3) described_class.new(browser, title: 'closeable window').use.close expect { browser.windows.wait_until(size: 2) }.not_to raise_timeout_exception end end describe '#use' do it 'switches to the window' do described_class.new(browser, title: 'closeable window').use expect(browser.title).to eq 'closeable window' end end describe '#current?' do it 'returns true if it is the current window' do expect(described_class.new(browser, title: browser.title)).to be_current end it 'returns false if it is not the current window' do expect(described_class.new(browser, title: 'closeable window')).not_to be_current end end describe '#title' do it 'returns the title of the window' do browser.wait_while { |b| b.window(title: /^$/).exists? } titles = browser.windows.map(&:title) expect(titles).to include 'window switching', 'closeable window' end end describe '#url' do it 'returns the url of the window' do urls = browser.windows.map(&:url) expect(urls).to(include(/window_switching\.html/, /closeable\.html$/)) end end describe '#eql?' do it 'knows when two windows are equal' do win1 = described_class.new browser, {} win2 = described_class.new browser, title: 'window switching' expect(win1).to eq win2 end it 'knows when two windows are not equal' do win1 = described_class.new browser, title: 'closeable window' win2 = described_class.new browser, title: 'window switching' expect(win1).not_to eq win2 end end describe '#handle' do it 'does not find if not matching' do expect(browser.window(title: 'noop').handle).to be_nil end it 'finds window by :url' do expect(browser.window(url: /closeable\.html/).handle).not_to be_nil end it 'finds window by :title' do expect(browser.window(title: 'closeable window').handle).not_to be_nil end it 'finds window by :element' do expect(browser.window(element: browser.a(id: 'close')).handle).not_to be_nil end it 'finds window by multiple values' do expect(browser.window(url: /closeable\.html/, title: 'closeable window').handle).not_to be_nil end end end context 'with a closed window', except: {browser: :safari, reason: 'Clicking an Element that Closes a Window is returning NoMatchingWindowFoundException'} do before do @original_window = browser.window browser.goto WatirSpec.url_for('window_switching.html') browser.a(id: 'open').click browser.windows.wait_until(size: 2) @handles = browser.driver.window_handles @closed_window = browser.window(title: 'closeable window').use browser.a(id: 'close').click browser.windows.wait_until(size: 1) end describe '#exists?' do it 'returns false if previously referenced window is closed' do expect(@closed_window).not_to be_present end it 'returns false if closed window is referenced' do expect(browser.window).not_to exist end end describe '#current?' do it 'returns false if the referenced window is closed' do expect(@original_window).not_to be_current end end describe '#eql?' do it 'returns false when checking equivalence to a closed window' do expect(browser.window).not_to eq @closed_widow end end describe '#use' do it 'raises NoMatchingWindowFoundException error when attempting to use a referenced window that is closed' do expect { @closed_window.use }.to raise_no_matching_window_exception end it 'raises NoMatchingWindowFoundException error when attempting to use the current window if it is closed' do expect { browser.window.use }.to raise_no_matching_window_exception end end it 'raises an exception when using an element on a closed window', exclude: {browser: :firefox, platform: :windows, reason: 'https://github.com/mozilla/geckodriver/issues/1847'} do msg = 'browser window was closed' expect { browser.a.text }.to raise_exception(Exception::NoMatchingWindowFoundException, msg) end it 'raises an exception when locating a closed window' do expect { browser.window(title: 'closeable window').use }.to raise_no_matching_window_exception end end context 'with a closed window on a delay' do it 'raises an exception when locating a window closed during lookup' do browser.goto WatirSpec.url_for('window_switching.html') browser.a(id: 'open').click browser.windows.wait_until(size: 2) browser.window(title: 'closeable window').use browser.a(id: 'close-delay').click allow(browser).to receive(:title).and_invoke(-> { sleep(0.5) && browser.wd.title }) expect { browser.window(title: 'closeable window').use }.to raise_no_matching_window_exception end end context 'with current window closed', except: {browser: :safari, reason: 'Clicking an Element that Closes a Window is returning NoMatchingWindowFoundException'} do before do browser.goto WatirSpec.url_for('window_switching.html') browser.a(id: 'open').click browser.windows.wait_until(size: 2) browser.window(title: 'closeable window').use browser.a(id: 'close').click browser.windows.wait_until(size: 1) end describe '#present?' do it 'finds window by url' do expect(browser.window(url: /window_switching\.html/)).to be_present end it 'finds window by title' do expect(browser.window(title: 'window switching')).to be_present end it 'finds window by element' do expect(browser.window(element: browser.link(id: 'open'))).to be_present end end describe '#use' do context 'when switching windows without blocks' do it 'by url' do browser.window(url: /window_switching\.html/).use expect(browser.title).to be == 'window switching' end it 'by title' do browser.window(title: 'window switching').use expect(browser.url).to match(/window_switching\.html/) end it 'by element' do browser.window(element: browser.link(id: 'open')).use expect(browser.url).to match(/window_switching\.html/) end end context 'when switching windows with blocks' do it 'by url' do browser.window(url: /window_switching\.html/).use { expect(browser.title).to be == 'window switching' } end it 'by title' do browser.window(title: 'window switching').use { expect(browser.url).to match(/window_switching\.html/) } end it 'by element' do element = browser.link(id: 'open') browser.window(element: element).use { expect(browser.url).to match(/window_switching\.html/) } end end end end context 'when manipulating size and position', except: {headless: true} do before(:all) do maximized_size = browser.window.size browser.window.resize_to( maximized_size.width - 100, maximized_size.height - 100 ) browser.wait_until { |b| b.window.size != maximized_size } current_position = browser.window.position browser.window.move_to( current_position.x + 40, current_position.y + 40 ) browser.wait_until { |b| b.window.position != current_position } @initial_size = browser.window.size @initial_position = browser.window.position end before do browser.goto WatirSpec.url_for('window_switching.html') end after do browser.window.resize_to @initial_size.width, @initial_size.height browser.window.move_to @initial_position.x, @initial_position.y end it 'gets the size of the current window' do expect(@initial_size.width).to eq browser.execute_script('return window.outerWidth;') expect(@initial_size.height).to eq browser.execute_script('return window.outerHeight;') end it 'gets the position of the current window' do expect(@initial_position.x).to eq browser.execute_script('return window.screenX;') expect(@initial_position.y).to eq browser.execute_script('return window.screenY;') end it 'resizes the window' do browser.window.resize_to( @initial_size.width - 20, @initial_size.height - 20 ) browser.wait_until { |b| b.window.size != @initial_size } new_size = browser.window.size expect(new_size.width).to eq @initial_size.width - 20 expect(new_size.height).to eq @initial_size.height - 20 end it 'moves the window' do browser.window.move_to( @initial_position.x + 5, @initial_position.y + 5 ) browser.wait_until { |b| b.window.position != @initial_position } new_position = browser.window.position expect(new_position.x).to eq @initial_position.x + 5 expect(new_position.y).to eq @initial_position.y + 5 end it 'maximizes the window' do browser.window.maximize browser.wait_until { |b| b.window.size != @initial_size } new_size = browser.window.size expect(new_size.width).to be >= @initial_size.width expect(new_size.height).to be > @initial_size.height end it 'makes the window full screen' do browser.window.full_screen browser.wait_until { |b| b.window.size != @initial_size } new_size = browser.window.size expect(new_size.width).to be >= @initial_size.width expect(new_size.height).to be > @initial_size.height end it 'minimizes the window' do expect(browser.execute_script('return document.visibilityState;')).to eq 'visible' browser.window.minimize browser.wait_until { |b| b.execute_script('return document.visibilityState;') != 'visible' } expect(browser.execute_script('return document.visibilityState;')).to eq 'hidden' browser.window.maximize end end end describe WindowCollection, exclude: {browser: :ie, reason: 'Cannot call #restore!'} do before do browser.goto WatirSpec.url_for('window_switching.html') browser.a(id: 'open').click browser.windows.wait_until(size: 2) end after do browser.windows.restore! end describe '#to_a' do it 'raises exception' do expect { described_class.new(browser).to_a }.to raise_exception(NoMethodError, 'indexing not reliable on WindowCollection') end end describe '#new' do it 'returns all windows by default' do windows = described_class.new(browser) expect(windows.size).to eq 2 end it 'filters available windows by url' do windows = described_class.new(browser, url: /closeable\.html/) expect(windows.size).to eq 1 end it 'filters available windows by title' do windows = described_class.new(browser, title: /closeable/) expect(windows.size).to eq 1 end it 'filters available windows by element' do windows = described_class.new(browser, element: browser.element(id: 'close')) expect(windows.size).to eq 1 end it 'raises ArgumentError if unrecognized locator' do expect { described_class.new(browser, foo: /closeable/) }.to raise_error(ArgumentError) end end describe '#size' do it 'counts the number of matching windows' do expect(described_class.new(browser).size).to eq 2 end end describe '#eq?' do it 'compares the equivalence of window handles' do windows1 = described_class.new(browser, title: //) windows2 = described_class.new(browser, url: //) expect(windows1).to eq windows2 end end describe '#reset!' do it 'clears window list' do wins = browser.windows expect(wins.size).to eq 2 wins.reset! expect(wins.instance_variable_get(:@window_list)).to be_nil end end describe '#restore!' do it 'when on other window', except: {browser: :safari, reason: 'Focus is on newly opened window instead of the first'} do browser.a(id: 'open').click browser.windows.wait_until(size: 3) browser.window(title: 'closeable window').use browser.windows.restore! expect(browser.windows.size).to eq 1 expect(browser.title).to eq 'window switching' end it 'when browser closed does not raise exception' do browser.close expect { browser.windows.restore! }.not_to raise_exception end end end end