2017-01-19 11 views
1

Я пытаюсь запустить некоторые тесты rspec, используя смесь Capybara, Selenium, Capybara/webkit и Poltergeist. Мне нужно, чтобы он работал без головок в определенных случаях и предпочел бы не использовать xvfb для работы webkit. Я в порядке, используя селен или полтергейст в качестве драйвера для фантомов. Проблема, с которой я столкнулась, заключается в том, что мои тесты отлично работают с селеном и firefox или хром, но когда я пытаюсь использовать phantomjs, элементы всегда показывают, что их не найдено. Изучив его некоторое время и используя page.save_screenshot в capybara, я узнал, что браузер phantomjs не был загружен, когда водитель сказал ему найти элементы, чтобы он ничего не возвращал. Я был в состоянии взломать исправление к этому в редактировании полтергейста источника в <gem_path> /capybara/poltergeist/driver.rb следующийpoltergeist, похоже, не дождался загрузки phantomjs в capybara

def visit(url) 
    if @started 
    sleep_time = 0 
    else 
    sleep_time = 2 
    end 
    @started = true 
    browser.visit(url) 
    sleep sleep_time 
end 

Это, очевидно, не является идеальным решением проблемы, и это Безразлично» t работать с селеном в качестве драйвера для фантомов. Есть ли в любом случае, я могу сказать водителю ждать, пока призрак будет готов?

UPDATE:

я смог его запустить, изменив где я включил водосвинка :: DSL. Я добавил его в блок RSpec.configure, как показано ниже.

RSpec.configure do |config| 
    config.include Capybara::DSL 

Затем я передал объект страницы всем классам, которые я создал для взаимодействия с веб-страницей ui.

Пример класса будет выглядеть так, как этот модуль веб-страницы

module LoginUI 
    require_relative 'webpage' 

    class LoginPage < WebPages::Pages 
    def initialize(page, values = {}) 
     super(page) 
    end 

    def visit 
     browser.visit(login_url) 
    end 

    def login(username, password) 
     set_username(username) 
     set_password(password) 
     sign_in_button 
    end 

    def set_username(username) 
     edit = browser.find_element(@selectors[:login_edit]) 
     edit.send_keys(username) 
    end 

    def set_password(password) 
     edit = browser.find_element(@selectors[:password_edit]) 
     edit.send_keys(password) 
    end 

    def sign_in_button 
     browser.find_element(@selectors[:sign_in_button]).click 
    end 
    end 
end 

выглядит следующим образом

module WebPages 
    require_relative 'browser' 
    class Pages 
    def initialize(page) 
     @page = page 
     @browser = Browser::Browser.new 
    end 

    def browser 
     @browser 
    end 

    def sign_out 
     browser.visit(sign_out_url) 
    end 
    end 
end 

Модуль браузера выглядит как этот

module Browser 
    class Browser 
    include Capybara::DSL 
    def refresh_page 
     page.evaluate_script("window.location.reload()") 
    end 

    def submit(locator) 
     find_element(locator).click 
    end 

    def find_element(hash) 
     page.find(hash.keys.first, hash.values.first) 
    end 

    def find_elements(hash) 
     page.find(hash.keys.first, hash.values.first, match: :first) 
     page.all(hash.keys.first, hash.values.first) 
    end 

    def current_url 
     return page.current_url 
    end 
    end 
end 

В то время как это работает я не» t нужно включить Capybara :: DSL внутри RSpec или включить объект страницы в классы. У этих классов были некоторые вещи, удаленные для примера, но отображающие общую структуру. В идеале я хотел бы, чтобы модуль Browser включал Capybara :: DSL и мог обрабатывать все взаимодействия с Capybara.

ответ

1

Ваше обновление полностью меняет вопрос, поэтому я добавляю второй ответ. Нет необходимости включать Capybara :: DSL в конфигурацию RSpec, если вы не вызываете какие-либо методы Capybara из-за пределов вашего браузера, так же как нет необходимости передавать «страницу» всем вашим классам страниц, если вы ограничиваете все Capybara для вашего браузера.Следует отметить, что метод page, предоставляемый Capybara :: DSL, является просто псевдонимом для Capybara.current_session, поэтому технически вы всегда можете это назвать.

В вашем коде не указано, как вы обрабатываете какие-либо утверждения/ожидания в содержании страницы, поэтому в зависимости от того, как вы это делаете, вам может понадобиться включить Capybara::RSpecMatchers в конфигурацию RSpec и/или ваши веб-страницы :: Класс страниц.

Ваш пример кода имеет несколько вопросов, которые сразу выскочить, во-первых, ваш Browser#find_elements (при условии, что я читаю ваши намерения за то, что find первый правильно), вероятно, следует просто быть

def find_elements(hash) 
    page.all(hash.keys.first, hash.values.first, minimum: 1) 
end 

Во-вторых, ваш метод LoginPage#login должен иметь утверждение/ожидание на визуальном изменении, которое указывает, что логин завершился как окончательная строка (проверьте, что какое-либо сообщение отображается/зарегистрировано в меню существует/и т. д.), чтобы браузер не получал файлы cookie и т. д. до того, как тесты будут продолжены. То, что эта строка выглядит, зависит от того, как вы строите свои ожидания.

Если это не ответит на ваш вопрос, укажите конкретный пример того, что именно не работает для вас, поскольку ни один из кода, который вы показываете, не указывает на необходимость использования Capybara :: DSL в любом из места, которые вы говорите, вы не хотите.

+0

Большое вам спасибо. Я добавил метод страницы, который возвращает Capybara.current_session и удаляется, включая Capybara :: DSL. Теперь все работает отлично. Кроме того, спасибо за минимум: 1. Я не знал об этом. Я все еще очень новичок в рубине, rspec и capybara, поэтому ответ очень высоко оценен. – alphamonkey

0

Capybara не зависит от завершения посещения, вместо этого поисковики и помощники будут повторять попытку до определенного периода времени, пока они не добьются успеха. Вы можете увеличить это количество времени, увеличив значение Capybara.default_max_wait_time. Единственные методы, которые не ждать по умолчанию являются first и all, но можно подождать/повторить попытку, указав любой из вариантов подсчета

first('.some_class', minimum: 1) # will wait up to Capybara.default_max_wait_time seconds for the element to exist on the page. 

хотя вы всегда должны отдавать предпочтение find над первой/все по возможности

Если увеличение максимального времени ожидания не решит проблему, добавьте пример теста, который не отвечает на ваш вопрос.

+0

Благодарим вас за ответ. Я установил default_max_wait_time 10, 30, 120 и 300 для тестирования этого. По-видимому, это не повлияло на результаты. Я собираюсь опубликовать немного больше информации в исходном контексте и попытаться получить пример в какой-то момент. – alphamonkey