Функция playwright's set_input_files() не работает должным образом в python
Я пишу тесты для своего Django-проекта, используя playwright и StaticLiveServerTestCase. В одном тесте мне нужно выбрать два файла с помощью поля input[type=file] и отправить их на сервер.
file_input = page.locator('input[type="file"]')
file_input.set_input_files(["Input1.xlsx", "Input2.xlsx"])
Но Playwright отправляет только первый файл, и мой тест не удается. Я пытался посмотреть, имеет ли поле ввода только один файл, но после выбора
оно имеет оба файла.file_info = page.evaluate("""
element => {
const files = Array.from(element.files);
return files.map(file => ({
name: file.name,
size: file.size,
type: file.type
}));
}
""", file_input.element_handle())
print("Files that JS sees:", file_info)
Вот вывод:
Files that JS sees: [{'name': 'Input1.xlsx', 'size': 5853, 'type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'}, {'name': 'Input2.xlsx', 'size': 5851, 'type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'}]
А Драматург выводит только первого:
input_value = file_input.input_value()
print("Playwright's version:", input_value)
Playwright's version: C:\fakepath\Input1.xlsx
Если вы спросите меня, я пробовал абсолютный путь для файлов и пытался изменить браузеры.
Django версии 5.1.6 Playwright версии 1.51.0
Первое, что нужно сказать, это то, что вам нужно сравнить яблоки с яблоками. В вашем page.evaluate
вы получаете доступ к свойству files
, но в file_input.input_value()
вы получаете доступ к свойству value
.
Это разные свойства элемента HTMLInputElement
Итак, вместо file_input.input_value()
вам нужно что-то вроде file_input.get_property('files')
, но, к сожалению, этого нет в API Playground (AFAIK).
Единственный способ, которым я мог это сделать, - использовать устаревший element handle API, вот мой тест на Javascript (извините, я давно не использовал python).
Я использую страницу, предоставленную MDN, для запуска своего теста.
Метод evaluate()
ограничен возвратом простых значений, но свойство input.files
возвращает объект FileList, который не может быть возвращен неповрежденным, поэтому мы необходимо извлечь данные, которые нам нужны для утверждения в функции evaluate.
test('file upload', async ({ page }) => {
await page.goto('https://mdn.github.io/learning-area/html/forms/file-examples/simple-file.html');
const fileInput = page.locator('input[type="file"]');
await fileInput.setInputFiles(['./fixtures/Input1.xlsx', './fixtures/Input2.xlsx']);
// for reference, this is the input value
await expect(fileInput).toHaveValue('C:\\fakepath\\Input1.xlsx');
// evaluate the input files property
const inputHandle = await page.waitForSelector('input[type="file"]');
const file0 = await inputHandle.evaluate(input => {
return (input as HTMLInputElement).files!.item(0)!.name;
});
expect(file0).toBe('Input1.xlsx');
const file1 = await inputHandle.evaluate(input => {
return (input as HTMLInputElement).files!.item(1)!.name;
});
expect(file1).toBe('Input2.xlsx')
})
Этот тест выполнен успешно, что означает, что к файлу действительно прикреплены два файла. <input>
.
Проблема была на стороне сервера. Я забыл создать пользователя для тестирования, потому что тестовая система создает пустую базу данных, поэтому в хранилище у меня был только один файл.