Функция 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

The first thing to say is, you need to compare apples to apples. In your page.evaluate you are accessing the files property but in file_input.input_value() you are accessing the value property.

These are different properties of the HTMLInputElement

So, instead of file_input.input_value() you need something like file_input.get_property('files'), but unfortunately that's missing from the Playwright API (AFAIK).

The only way I could do it was to use the deprecated element handle API, here is my test in Javascript (sorry I haven't used python for a long time).

I'm using the page provided by MDN to run my test.

The evaluate() method is limited to returning simple values, but the input.files property returns a FileList object that can't be returned intact, so we must extract the data we need to assert within the evaluate function.

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')

}) 

This test succeeds, which means there are actually two files attached to the <input>.

enter image description here

The problem was on the server side. I forgot to create user for testing 'cause test system creates empty database, that's why I had only one file in the storage.

Вернуться на верх