我正在通过剧作家的非输入HTML标签上传文件。
例如,您可以像这样使用setInputFiles
,这是有效的:
await page.setInputFiles('input[type="file"]', './headphone.png')
但显然setInputFiles
只适用于输入元素,像这样的东西将是错误的:
await page.setInputFiles('label.ImageUpload__label ', './headphone.png');
我正在处理的HTML是这样的:
<div id="ImageUpload" class="ImageUpload u-marginB10">
<label class="ImageUpload__label js-dragdrop-area" for="selectFileMultiple">
<span class="ImageUpload__hide">drag and drop or select files</span>
<span class="ImageUpload__text"><span class="js-dragdrop-num">10</span>up to</span>
</label>
</div>
那么,是否有可能将文件上传到这样的HTML元素与剧作家?
NodeJs: https://playwright.dev/docs/api/class-filechooser
page.on("filechooser", (fileChooser: FileChooser) => {
fileChooser.setFiles(["/path/to/a/file"]);
})
Python: https://playwright.dev/python/docs/api/class-filechooser/
with page.expect_file_chooser() as fc_info:
page.click("upload")
file_chooser = fc_info.value
file_chooser.set_files("/path/to/a/file")
Java: https://playwright.dev/java/docs/api/class-filechooser
FileChooser fileChooser = page.waitForFileChooser(() ->
page.click("upload"));
fileChooser.setFiles(Paths.get("myfile.pdf"));
使用setInputFiles(selector, files[, options])
函数上传文件。此方法接受输入元素的选择器和要上传的文件的路径。
"files
"参数可以是相对路径(相对于当前工作目录),也可以是绝对路径。我强烈建议您使用绝对路径来确保可预测的行为。
test("upload a file", async ({ page }) => {
console.log(resolve(__dirname, "bar.png"));
await page.goto("http://127.0.0.1:8080/upload-file/");
await page.locator('input[name="foo"]').click();
await page
.locator('input[name="foo"]')
.setInputFiles(resolve(__dirname, "bar.png"));
await page.click("input[type=submit]");
});
或者,您可以将文件读入Buffer并将drop
事件分派到具有DataTransfer
负载的目标元素上。这在测试拖放区域时非常有用:
const dataTransfer = await page.evaluateHandle(
async ({ fileHex, localFileName, localFileType }) => {
const dataTransfer = new DataTransfer();
dataTransfer.items.add(
new File([fileHex], localFileName, { type: localFileType })
);
return dataTransfer;
},
{
fileHex: (await readFile(resolve(__dirname, "bar.png"))).toString("hex"),
localFileName: fileName,
localFileType: fileType,
}
);
await page.dispatchEvent("#drop_zone", "drop", { dataTransfer });
await expect(page.locator("text=bar.png")).toBeVisible();
您可以使用createDataTransfer
实用程序从playwright-utilities
:
const dataTransfer = await createDataTransfer({
page,
filePath: resolve(__dirname, "bar.png"),
fileName: "bar.png",
fileType: "image/png",
});
await page.dispatchEvent("#drop_zone", "drop", { dataTransfer });
await expect(page.locator("text=bar.png")).toBeVisible();
通过克隆剧作家游乐场存储库在本地尝试这个例子:
git clone --branch test/upload-file https://punkpeye@github.com/punkpeye/playwright-playground.git
cd playwright-playground
npm install
npx playwright test tests/upload-file
在我的情况下找到了另一种上传方法。我们从内存中创建一个缓冲区,并将文件拖放到上传按钮上。
// Read your file into a buffer.
const buffer = readFileSync('file.pdf');
// Create the DataTransfer and File
const dataTransfer = await scope.page.evaluateHandle((data) => {
const dt = new DataTransfer();
// Convert the buffer to a hex array
const file = new File([data.toString('hex')], 'file.pdf', { type: 'application/pdf' });
dt.items.add(file);
return dt;
}, buffer);
// Now dispatch
await page.dispatchEvent('YOUR_TARGET_SELECTOR', 'drop', { dataTransfer });
如果使用typescript,将此添加到文件的顶部:
import {readFileSync} from 'fs';
Github issue: https://github.com/microsoft/playwright/issues/10667#issuecomment-998397241
我有同样的问题,所以我决定使用AutoIt
AutoIt v3是一种类似basic的免费脚本语言,用于自动执行Windows GUI和通用脚本。
我使用AutoIT来处理Windows文件上传对话框,这是使用剧作家无法处理的。
创建脚本
- 下载AutoIt: https://www.autoitscript.com/site/autoit/downloads/
- 打开SciTE脚本编辑器并输入以下内容:
WinWaitActive("Choose files")
Send("C:ChromeDrivertext.txt")
Send("{ENTER}")
如果不行,把选择文件改成上传对话框左上角的任意标题。
- 点击保存并命名为upload。 . au3并将其保存在测试的根目录中。
保存位置示例
- 右键单击新创建的文件并单击Compile Script
在测试中执行脚本
在node.js中创建子进程模块的execFile函数参考:https://nodejs.org/api/child_process.html child_process_child_process_execfile_file_args_options_callback
将其添加到.spec的顶部。测试文件:
var exec = require('child_process').execFile;
var upload_script = function(){
exec('upload.exe', function(err, data) {
console.log(err)
});
}
打开上传对话框,然后调用测试
中的函数// Click Browse
await page.locator('#browse').click();
// Execute Upload Script
upload_script();
你必须运行你的测试头,否则它将无法工作:
npx剧作家测试——head