Подтвердить что ты не робот

"Отказаться от подключения" с помощью ChromeDriver, Capybara & Docker Compose

Я пытаюсь сделать переход от PhantomJS к Chrome Headless и немного запутался. Для локального тестирования я использую Docker Compose для запуска всех зависимых сервисов. Чтобы предоставить Google Chrome, я использую изображение, которое объединяет и его, и ChromeDriver вместе, обслуживая его на порту 4444. Затем я свяжу его с контейнером для приложения следующим образом в этом упрощенном файле docker-compose.yml:

web:
    image: web/chrome-headless
    command: [js-specs]
    stdin_open: true
    tty: true
    environment:
        - RACK_ENV=test
        - RAILS_ENV=test
    links:
        - "chromedriver:chromedriver"

chromedriver:
    image: robcherry/docker-chromedriver:latest
    ports: 
        - "4444"
    cap_add: 
        - SYS_ADMIN
    environment:
        CHROMEDRIVER_WHITELISTED_IPS: ""

Затем у меня есть файл spec/spec_helper.rb, который загружает тестовую среду и связанные с ней инструменты. Я определяю драйвер :headless_chrome и указываю его на локальную привязку ChromeDriver; http://chromedriver:4444. Я уверен, что верно следующее:

Capybara.javascript_driver = :headless_chrome

Capybara.register_driver :chrome do |app|
    Capybara::Selenium::Driver.new(app, browser: :chrome)
end

Capybara.register_driver :headless_chrome do |app|
    capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(
    chromeOptions: { args: %w[headless disable-gpu window-size=1440,900] },
)

Capybara::Selenium::Driver.new app,
    browser: :chrome,
    url: "http://chromedriver:4444/",
    desired_capabilities: capabilities
end

Мы также используем видеомагнитофон, но я настроил его, чтобы игнорировать любые подключения к порту, используемому ChromeDriver:

VCR.configure do |c|
    c.cassette_library_dir = 'spec/vcr_cassettes'
    c.default_cassette_options = { record: :new_episodes }
    c.ignore_localhost = true
    c.allow_http_connections_when_no_cassette = false
    c.configure_rspec_metadata!
    c.ignore_hosts 'codeclimate.com'
    c.hook_into :webmock, :excon

    c.ignore_request do |request|
        URI(request.uri).port == 4444
    end
end

Я запускаю службы с помощью Docker Compose, который запускает тестовый бегун. Команда в значительной степени такова:

$ bundle exec rspec --format progress --profile --tag 'broken' --tag 'js' --tag '~quarantined'

После небольшого ожидания я столкнулся с первым неудавшимся тестом:

  1) Beta parents code redemption:  redeeming a code on the dashboard when the parent has reached the code redemption limit does not display an error message for cart codes
     Failure/Error: fill_in "code", with: "BOOK-CODE"

     Capybara::ElementNotFound:
       Unable to find field "code"
     # ./spec/features/beta_parents_code_redemption_spec.rb:104:in `block (4 levels) in <top (required)>'

Все спецификации имеют одинаковую ошибку. Итак, я запускаю в контейнер, чтобы запускать тесты самостоятельно и захватывать HTML, на котором он тестирует. Я сохраняю его локально и открываю его в своем браузере, чтобы его приветствовали на следующей странице ошибок Chrome. Казалось бы, ChromeDriver не оценивает спецификацию HTML, потому что он не может ее достичь, поэтому он пытается запустить тесты с этой страницы ошибок.

Учитывая приведенную выше информацию, что я делаю неправильно здесь? Я ценю любую помощь, поскольку уход от PhantomJS разрешит нам столько головных болей.

Большое вам спасибо заранее. Пожалуйста, дайте мне знать, если вам нужна дополнительная информация.

введите описание изображения здесь

4b9b3361

Ответ 1

Проблема, с которой вы сталкиваетесь, заключается в том, что Capybara по умолчанию запускает привязку AUT до 127.0.0.1, а затем сообщает драйверу, что запрос браузера совпадает с этим. В вашем случае, однако, 127.0.0.1 не там, где приложение работает (с точки зрения браузеров), поскольку оно находится в другом контейнере, чем в браузере. Чтобы исправить это, вам нужно установить Capybara.server_host на любой внешний интерфейс "веб-контейнера" (который доступен из контейнера "хромированная решетка" ). Это заставит Capybara привязать AUT к этому интерфейсу и сообщить драйверу, чтобы браузер запрашивал его.

В вашем случае это, вероятно, означает, что вы можете указать 'web'

Capybara.server_host = 'web'