Как вы тестируете загрузку файла с помощью Capybara и Dropzone.js?
Я перешел на использование плагина Dropzone.js для загрузки файлов с перетаскиванием. Как я могу написать тест Capybara, чтобы эта функция продолжала работать?
Раньше у меня был шаблон с элементом входного файла:
<input type="file" name="attachments">
И тест был прост:
When(/^I upload "([^"]*)"$/) do |filename|
attach_file("attachments", File.expand_path(filename))
# add assertion here
end
Однако это больше не работает, потому что Dropzone не имеет видимого входного файла.
Ответы
Ответ 1
Чтобы решить эту проблему, смоделируйте событие сброса, чтобы инициировать сброс вложения в Dropzone. Сначала добавьте эту функцию в определение шага:
# Upload a file to Dropzone.js
def drop_in_dropzone(file_path)
# Generate a fake input selector
page.execute_script <<-JS
fakeFileInput = window.$('<input/>').attr(
{id: 'fakeFileInput', type:'file'}
).appendTo('body');
JS
# Attach the file to the fake input selector
attach_file("fakeFileInput", file_path)
# Add the file to a fileList array
page.execute_script("var fileList = [fakeFileInput.get(0).files[0]]")
# Trigger the fake drop event
page.execute_script <<-JS
var e = jQuery.Event('drop', { dataTransfer : { files : [fakeFileInput.get(0).files[0]] } });
$('.dropzone')[0].dropzone.listeners[0].events.drop(e);
JS
end
Затем проверьте с помощью:
When(/^I upload "([^"]*)"$/) do |filename|
drop_in_dropzone File.expand_path(filename)
# add assertion here
end
ПРИМЕЧАНИЕ. Вам необходимо загрузить jQuery, а элемент Dropzone требует класса dropzone.
Ответ 2
Построение ответа @deepwell, который мне не совсем помог, вот решение, использующее vanilla JS для событий и диспетчеризацию событий, и нейтральный селектор для dropzone:
def drop_in_dropzone(file_path, zone_selector)
# Generate a fake input selector
page.execute_script <<-JS
fakeFileInput = window.$('<input/>').attr(
{id: 'fakeFileInput', type:'file'}
).appendTo('body');
JS
# Attach the file to the fake input selector
attach_file("fakeFileInput", file_path)
# Add the file to a fileList array
page.execute_script("fileList = [fakeFileInput.get(0).files[0]]")
# Trigger the fake drop event
page.execute_script <<-JS
dataTransfer = new DataTransfer()
dataTransfer.items.add(fakeFileInput.get(0).files[0])
testEvent = new DragEvent('drop', {bubbles:true, dataTransfer: dataTransfer })
$('#{zone_selector}')[0].dispatchEvent(testEvent)
JS
end
специально использует глобальные переменные, так что я могу тестировать в консоли js, но не стесняйтесь использовать их.
Ответ 3
В случае, если кто-то заинтересован, я портировал функцию @deepwell на javascript, чтобы использовать его с салатом javascript с ароматом:
this.dropInDropzone = function(filePath) {
var script = "fakeFileInput = $('#fakeFileInput'); if (fakeFileInput.length === 0) fakeFileInput = window.$('<input/>').attr({id: 'fakeFileInput', type:'file'}).appendTo('body');";
// Generate a fake input selector
return driver.executeScript(script).then(function() {
// Attach the file to the fake input selector
return driver.findElement(webdriver.By.css('#fakeFileInput')).sendKeys(filePath);
}).then(function() {
// Add the file to a fileList array
return driver.executeScript("var fileList = [fakeFileInput.get(0).files[0]]");
}).then(function() {
// Trigger the fake drop event
script = "var e = jQuery.Event('drop', { dataTransfer : { files : [fakeFileInput.get(0).files[0]] } }); $('.dropzone')[0].dropzone.listeners[0].events.drop(e);"
return driver.executeScript(script);
});
};