diff --git a/src/Api/Concerns/InteractsWithElements.php b/src/Api/Concerns/InteractsWithElements.php index 24566e7e..1d444ff3 100644 --- a/src/Api/Concerns/InteractsWithElements.php +++ b/src/Api/Concerns/InteractsWithElements.php @@ -176,9 +176,11 @@ public function uncheck(string $field, ?string $value = null): self } /** - * Attach the given file to the field. + * Attach the given files to the field. + * + * @param string|array $path */ - public function attach(string $field, string $path): self + public function attach(string $field, string|array $path): self { $this->guessLocator($field)->setInputFiles($path); diff --git a/src/Playwright/Locator.php b/src/Playwright/Locator.php index b628b61a..2279335d 100644 --- a/src/Playwright/Locator.php +++ b/src/Playwright/Locator.php @@ -651,10 +651,12 @@ public function tap(?array $options = null): void /** * Set input files for a file input element. + * + * @param string|array $path */ - public function setInputFiles(string $path): void + public function setInputFiles(string|array $path): void { - $params = ['localPaths' => [$path]]; + $params = ['localPaths' => is_array($path) ? $path : [$path]]; $response = $this->sendMessage('setInputFiles', $params); $this->processVoidResponse($response); diff --git a/tests/Browser/Webpage/AttachTest.php b/tests/Browser/Webpage/AttachTest.php index 580a20e5..bb65582c 100644 --- a/tests/Browser/Webpage/AttachTest.php +++ b/tests/Browser/Webpage/AttachTest.php @@ -47,3 +47,33 @@ // Clean up unlink($tempFile); }); + +it('may attach multiple files to a file input', function (): void { + Route::get('/', fn (): string => ' +
+ +
+ '); + + $page = visit('/'); + + // Create temporary files + $tempFiles = [ + tempnam(sys_get_temp_dir(), 'test'), + tempnam(sys_get_temp_dir(), 'test'), + ]; + file_put_contents($tempFiles[0], 'test content 1'); + file_put_contents($tempFiles[1], 'test content 2'); + + $page->attach('avatar', $tempFiles); + + // Check that the files are attached + $fileNames = array_map(fn ($file) => basename($file), $tempFiles); + expect($page->script('() => document.querySelector("input[name=avatar]").files.length'))->toBe(count($tempFiles)); + expect($page->script('() => document.querySelector("input[name=avatar]").files.map(file => file.name)'))->toBe($fileNames); + + // Clean up + foreach ($tempFiles as $tempFile) { + unlink($tempFile); + } +});