Загрузка файла в определенную папку с использованием драйвера Capybara и Poltergeist
Я пишу свои приемочные тесты, используя драйверы Capybara и Poltergeist. Мне нужно проверить содержимое загруженного CSV-файла.
- Я пробовал различные способы рендеринга контента на самой странице, а не загружал его.
- Также попытался изменить типы пантомимы, но это не работает.
Наконец, я хочу выбрать вариант загрузки файла в определенную папку, а затем прочитать файл CSV, используя основные библиотеки ruby.
Чтобы добиться этого, когда драйвер poltergeist нажимает на ссылку для скачивания, я хочу, чтобы он обрабатывал всплывающее окно и загружал файл прямо в заданную папку.
В драйверах Selenium для Chrome и Firefox у меня есть опция настройки профилей для обработки всплывающих окон и настройки каталога загрузки.
Есть ли такая возможность с помощью полтергейста? Любая информация будет полезна.
4 ответа
С Poltergeist это невозможно, вы можете просто проверить заголовки.
step 'I should get zipped file' do
page.response_headers['Content-Disposition'].should include("filename=\"file.zip\"")
end
Но это возможно с драйвером Chrome, а также с последними версиями Firefox и Selenium Webdriver. К сожалению, он работает через Selenium - то есть не без головы... Смотрите эту статью: http://collectiveidea.com/blog/archives/2012/01/27/testing-file-downloads-with-capybara-and-chromedriver/
Мой подход - немного другой, так как я работаю со Spinach и Rubyzip:
Добавьте следующее в ваш Gemfile
group :test do
gem 'chromedriver-helper' # for Chrome <= 28
gem 'chromedriver2-helper' # for Chrome >= 29
gem 'selenium-webdriver'
end
features / support / capybara.rb - я использую Poltergeist для сценариев с @javascript
тег и Chrome для сценариев с @download
тег.
require 'spinach/capybara'
require 'capybara/poltergeist'
require 'selenium/webdriver'
# ChromeDriver 1.x, for Chrome <= 28
Capybara.register_driver :chrome do |app|
profile = Selenium::WebDriver::Chrome::Profile.new
profile['download.default_directory'] = DownloadHelper::PATH.to_s
args = ["--window-size=1024,768"]
Capybara::Selenium::Driver.new(app, browser: :chrome, profile: profile, args: args)
end
# ChromeDriver 2.x, for Chrome >= 29
Capybara.register_driver :chrome do |app|
prefs = {
download: {
prompt_for_download: false,
default_directory: DownloadHelper::PATH.to_s
}
}
args = ['--window-size=1024,768']
Capybara::Selenium::Driver.new(app, browser: :chrome, prefs: prefs, args: args)
end
# Tested with Firefox 27 and Selenium Webdriver 2.39
Capybara.register_driver :firefox do |app|
profile = Selenium::WebDriver::Firefox::Profile.new
profile['browser.download.dir'] = DownloadHelper::PATH.to_s
profile['browser.download.folderList'] = 2 # 2 - save to user defined location
profile['browser.helperApps.neverAsk.saveToDisk'] = 'application/zip'
Capybara::Selenium::Driver.new(app, browser: :firefox, profile: profile)
end
Capybara.javascript_driver = :poltergeist # :webkit :selenium :poltergeist :chrome
Spinach.hooks.on_tag("javascript") do
Capybara.current_driver = Capybara.javascript_driver
Capybara.default_wait_time = 5
end
Spinach.hooks.on_tag("download") do
Capybara.current_driver = :chrome # or :firefox
Capybara.default_wait_time = 50
end
Возможности / поддержка / downloads.rb
module DownloadHelper
TIMEOUT = 10
PATH = Rails.root.join("tmp/downloads")
extend self
def downloads
Dir[PATH.join("*")]
end
def download_path
wait_for_download
downloads.first
end
def download_content
wait_for_download
File.read(download_path)
end
def wait_for_download
Timeout.timeout(TIMEOUT) do
sleep 0.1 until downloaded?
end
end
def downloaded?
downloads.any? && !downloading?
end
def downloading?
downloads.grep(/\.crdownload$/).any?
end
def clear_downloads
FileUtils.rm_f(downloads)
end
end
Spinach.hooks.before_scenario do |scenario|
DownloadHelper.clear_downloads
end
Spinach.hooks.after_scenario do
DownloadHelper.clear_downloads
end
Возможности / file_download.feature
Feature: File download
As a user
I want to be able to download my files
Background:
Given I am logged in as a user
And I have uploaded files in the system
@download
Scenario: Successfull download
When I click on the download button
Then I should get zipped files
features / steps / file_download.rb - обратите внимание, что вы не можете использовать page.response_headers
так как он не поддерживается Selenium/ChromeDriver. Но вы можете проверить имя файла загруженного файла, используя File.basename()
,
class Spinach::Features::FileDownload < Spinach::FeatureSteps
include SharedAuthentication
step 'I click on the download button' do
click_link "Download"
end
step 'I should get zipped files' do
File.basename(DownloadHelper.download_path).should == 'file.zip'
Zip::ZipFile.open(DownloadHelper.download_path) do |zipfile|
zipfile.find_entry('myfile.txt').should_not be_nil
zipfile.find_entry('myphoto.jpg').should_not be_nil
end
end
end
Мне приходилось делать подобные вещи в моем приложении rails. Мое решение - использовать Javascript для создания XMLHttpRequest на URL, загрузить файл, вернуть содержимое файла обратно в Capybara и использовать ruby для сохранения файла где-нибудь на диске. Затем на другом этапе я проверяю содержимое загруженного файла CSV.
Вот определение шага для загрузки файла:
Then /^I download the csv file$/ do
page.execute_script("window.downloadCSVXHR = function(){ var url = window.location.protocol + '//' + window.location.host + '/file.csv'; return getFile(url); }")
page.execute_script("window.getFile = function(url) { var xhr = new XMLHttpRequest(); xhr.open('GET', url, false); xhr.send(null); return xhr.responseText; }")
data = page.evaluate_script("downloadCSVXHR()")
File.open(File.join(Rails.root, "tmp", "csv.data"), "w") { |f| f.write(data) }
end
Измените URL в коде Javascript на местоположение вашего CSV.
И, наконец, вот мое определение шага для проверки содержимого файла CSV:
And /^the contents of the downloaded csv should be:$/ do |contents|
file = File.open(File.join(Rails.root, "tmp", "csv.data"), "r")
file_contents = file.read
file_contents.chop!
file_contents.should == contents
end
Удачи. Надеюсь это поможет.
Это не возможно в настоящее время с Poltergeist.
Я думаю, вам лучше написать тест для этого CSV, который не использует Capybara. (Например, используя встроенные средства тестирования интеграции Rails и анализируя ответ как CSV.)
Есть билет для поддержки загрузки файлов в PhantomJS/Poltergeist, и есть одна или две вилки, которые утверждают, что они заставили его работать как-то. См. https://github.com/ariya/phantomjs/issues/10052