Як із Capybara перейти в нове вікно для посилань із цілями “_blank”?


77

Можливо, це насправді не проблема, з якою я стикаюся, але, схоже, коли я клацну посилання "посилання з цільовим =" _ пустим ", сесія фокусується на поточному вікні.

Тому я або хочу мати можливість перейти в нове вікно, або ігнорувати атрибут _blank - по суті, я просто хочу, щоб він фактично перейшов на сторінку, вказану за посиланням, щоб я міг переконатися, що це правильна сторінка.

Я використовую драйвери webkit та селен.


Я подав свої висновки до цього моменту. Більш грунтовна відповідь дуже цінується.

Крім того, це працює лише з селеном - це було б дуже вдячно для еквівалента драйвера webkit (або вказування, де я міг би сам це виявити).

Відповіді:


87

Capybara> = 2.3 включає новий API управління вікнами. Його можна використовувати, як:

new_window = window_opened_by { click_link 'Something' }
within_window new_window do
  # code
end

3
poltergeist 1.6 реалізує цей API, тому при написанні цього шляху слід піти з poltergeist.
Дейв Швайсгут,

54

Це рішення працює лише для драйвера Selenium

Всі відкриті вітрини - це магазини в Selenium's

response.driver.browser.window_handles

Що здається масивом. Останнім елементом завжди є вікно, яке було нещодавно відкрито, тобто ви можете зробити наступне, щоб перейти до нього.

У межах блоку:

new_window=page.driver.browser.window_handles.last 
page.within_window new_window do
  #code
end

Просто перефокусуйте поточну сесію:

session.driver.browser.switch_to.window(page.driver.browser.window_handles.last)

Посилання на сторінці випусків капібари: https://github.com/jnicklas/capybara/issues/173

Детальніше про можливості перемикання вікон у Selenium: http://qastuffs.blogspot.com/2010/10/testing-pop-up-windows-using-selenium.html


4
Це чудово, але другий приклад трохи вводить в оману. Немає різниці між sessionі page, тому session.driver.browserі page.driver.browserнасправді відносяться до одного і того ж. Це мене заплутало, намагаючись адаптувати це до іншого контексту, отримуючи доступ до Capybara через іншу бібліотеку і не використовуючи DSL. Мені довелося прочитати код DSL Capybara, щоб зрозуміти, що для доступу до "сторінки" мені просто потрібен доступ до сеансу.
Стів Йоргенсен

@glyphgryph boy Я люблю, коли рішення просто працюють із копіюванням та вставленням, позбавляючи всіх зайвих витрат.
nfriend21

3
Це не тільки для селену: within_window(page.driver.window_handles.last)працює для мене з capybara-webkit .
Тоні - Currentuser.io

2
Як уже згадувалося нижче, Capybara має новий синтаксис роботи з Windows: github.com/jnicklas/capybara#working-with-windows
Сара

1
Цей метод застарілий у капібаріDEPRECATION WARNING: Passing string argument to #within_window is deprecated.
Aravin

11

Зараз це працює з Полтергейстом. Хоча window_handlesце все ще не реалізовано (вам потрібно ім'я вікна, тобто через спливаюче вікно JavaScript):

within_window 'other_window' do
  current_url.should match /example.com/
end

Редагувати: За коментарем нижче, Poltergeist тепер впроваджує window_handlesз версії 1.4.0 .


3
Я щойно спробував, page.within_window page.driver.browser.window_handles.last do ... і, здається, це працює, як очікувалось у Poltergeist. Не потрібно давати назву вікна. Тож цю відповідь, можливо, доведеться оновити.
thom_nic

1
Capybara 2.3 припиняє виклик within_windowрядком: DEPRECATION WARNING: Passing string argument to #within_window is deprecated. Pass window object or lambda.Метод, задокументований Андрієм Боталовим, виправляє це припинення.
Дейв Швайсгут,

9

Capybara пропонує кілька методів для полегшення пошуку та перемикання між вікнами:

facebook_window = window_opened_by do
  click_button 'Like'
end
within_window facebook_window do
  find('#login_email').set('a@example.com')
  find('#login_password').set('qwerty')
  click_button 'Submit'
end

Детальніше тут: Документація Capybara


8

Я знаю, що це старий пост, але для чого він вартий у капібарі 2.4.4

within_window(switch_to_window(windows.last)) do 
    # in my case assert redirected url from a prior click action
    expect(current_url).to eq(redirect['url'])
end

7

Здається, зараз це неможливо з capybara-webkit: https://github.com/thoughtbot/capybara-webkit/issues/271

:-(

У той же час https://github.com/thoughtbot/capybara-webkit/issues/129 заявляє, що можна перемикати вікна за допомогою within_window.

Також https://github.com/thoughtbot/capybara-webkit/issues/47 припускає, що це page.driver.browser.switch_to().window(page.driver.browser.window_handles.last)працює. Ну добре, щодо читання коду.

У коді на https://github.com/thoughtbot/capybara-webkit/blob/master/lib/capybara/webkit/browser.rb є принаймні деякі посилання, які свідчать про те, що API, який працює для webdriver / firefox, також працює веб-комплект.


1
Дивіться мій коментар щодо прийнятої відповіді: within_window(page.driver.window_handles.last)працює для мене з capybara-webkit.
Тоні - Currentuser.io


6

Станом на травень 2014 року на capybara-webkit працює наступний код

 within_window(page.driver.browser.window_handles.last) do
   expect(current_url).to eq('http://www.example.com/')
 end

page.driver.brower.window_handles.lasзараз застаріла. Використовуйте windows.last. Дивіться github.com/thoughtbot/capybara-webkit/issues/650
smcgregor

4

Це працює для мене в capybara-webkit:

within_window(windows.last) do
  # code here
end

(Я використовую capybara 2.4.1 та capybara-webkit 1.3.0)


4

Ви також можете передати ім'я , URL-адресу чи заголовок вікна (але тепер це роздруковано)

  let(:product) { create :product }

  it 'tests' do
    visit products_path
    click_link(product.id)

    within_window(product_path(product)) do
      expect(page).to have_content(product.title)
    end
  end

Ви можете передати labda або процедурний також

within_window(->{ page.title == 'Page title' }) do
  click_button 'Submit'
end

бажаю, щоб це поширювало використання методу на більш чітке розуміння


4

Щоб явно змінити вікно, ви використовуєте switch_to_window

  def terms_of_use
    terms_window = window_opened_by do
      click_link(@terms_link)
    end
    switch_to_window(terms_window)
  end

Після цього браузер методів буде працювати на новій сторінці, замість того, щоб обертати все в блоці Within_window


3

У мене виникла ця проблема при відкритті посилань у вікні gmail: я виправив це так:

Given /^(?:|I )click the "([^"]*)" link in email message$/ do |field|

  # var alllinks = document.getElementsByTagName("a");
  # for (alllinksi=0; alllinksi<alllinks.length; alllinksi++) {
  #   alllinks[alllinksi].removeAttribute("target");
  # }

  page.execute_script('var alllinks = document.getElementsByTagName("a"); for (alllinksi=0; alllinksi<alllinks.length; alllinksi++) { alllinks[alllinksi].removeAttribute("target"); }')

  within(:css, "div.msg") do
    click_link link_text
  end

end

До речі, замість коментарів ви можете використовувати синтаксис heredoc: page.execute_script <<-JS var alllinks = document.getElementsByTagName("a"); for (alllinksi=0; alllinksi<alllinks.length; alllinksi++) { alllinks[alllinksi].removeAttribute("target"); } JS Коментарі дозволять лише вбудований код, тому переконайтеся, що є розриви рядків до та після "JS", але ви зрозуміли ідею. таким чином, вам не потрібно керувати кодом у двох місцях, і більшість редакторів все одно виділять їх.
Девід

3

Найкраща ідея - оновити capybara до останньої версії (2.4.1) і просто використовувати, windows.last оскільки page.driver.browser.window_handlesвона застаріла.


0

Основна реалізація ( window_opened_by) викликає для мене помилку:

*** Capybara::WindowError Exception: block passed to #window_opened_by opened 0 windows instead of 1

Отже, я вирішую це за допомогою такого рішення:

new_window = open_new_window

within_window new_window do
  visit(click_link 'Something')
end

page.driver.browser.window_handles
# => ["CDwindow-F7EF6D3C12B68D6B6A3DFC69C2790718", "CDwindow-9A026DEC65C3C031AF7D2BA12F28ADC7"]

0

Мені особисто подобається наступний підхід, оскільки він працює правильно, незалежно від того, включений JS чи ні.

Моя специфікація:

  it "shows as expected" do
    visit my_path

    # ...test my non-JS stuff in the current tab

    switch_to_new_tab

    # ...test my non-JS stuff in the new tab
    
    # ...keep switching to new tabs as much as necessary
  end 

  # OR

  it "shows as expected", js: true do
    visit my_path

    # ...test my non-JS stuff in the current tab
    # ...also test my JS stuff in the current tab

    switch_to_new_tab

    # ...test my non-JS stuff in the new tab
    # ...also test my JS stuff in the new tab

    # ...keep switching to new tabs as much as necessary
  end 

Помічники тесту:

  def switch_to_new_tab
    current_browser = page.driver.browser

    if js_enabled?
      current_browser.switch_to.window(current_browser.window_handles.last)
    else
      visit current_browser.last_request.fullpath
    end
  end

  def js_enabled?
    Capybara.current_driver == Capybara.javascript_driver
  end
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.