Skip to content

feat: cache file uploads so the upload button is not re-resolved every run - #84

Open
Agam00 wants to merge 1 commit into
mainfrom
agam/cache-file-uploads
Open

feat: cache file uploads so the upload button is not re-resolved every run#84
Agam00 wants to merge 1 commit into
mainfrom
agam/cache-file-uploads

Conversation

@Agam00

@Agam00 Agam00 commented Sep 12, 2026

Copy link
Copy Markdown
Member

Why

browser_upload_file is the only tool that doesn't write a cache entry. click, fill, hover and selectOption all call prepareCacheData, uploads never did.

So every run asks the model to find the upload button again. Usually it finds it. When it doesn't, the step uses up its full 3 minute timeout and fails a test that had nothing to do with uploading. That happened to us three times in one week, in three different suites.

What

This caches the button that opens the file chooser, and replays both steps against it on later runs.

The upload itself is unchanged. Still waitForEvent('filechooser') then click then setFiles. The only thing that goes away is asking the model where the button is.

Nothing to configure. Existing browser_upload_file steps get this automatically.

I did look at using locator.setInputFiles() to make it a single action, but that only works when the button is a label wrapped around the input, and the file chooser flow is closer to what a real user does. So I left that part alone.

Worth a look

const input = step.data?.value || value isn't safe for uploads. step.data.value is just a filename, while the cached value already has the folder on the front. Since step.data wins, using input directly would add the folder twice and give you ./uploads/./uploads/file.pdf. That only breaks on the second run, so I moved the logic into resolveCachedUploadPaths and added a test for exactly that case.

Also worth knowing if you try this out: caching only happens for steps that resolve to a single tool call. A step written as several actions, like "click the drop area, find the input, attach the file", never gets cached no matter what this PR does.

Testing

Build is clean, 171 tests pass (5 new), and lint has no new errors.

I also ran it against a real suite. First run resolved the button through the model and saved it, second run replayed it with no model call:

Executing Cached Step: Upload value using the "browse documents" control...
const fileChooserPromise = page.waitForEvent('filechooser');
await page.getByRole('button', { name: 'Drag and drop or browse' }).click({ timeout: 5000 });
const fileChooser = await fileChooserPromise;
await fileChooser.setFiles(["./uploads/David_Thompson_Client_Case_File.pdf"]);

I didn't run format:check. The globs in that script don't expand on Windows, and the checked in tree isn't prettier clean anyway (42 files come up, including ones I didn't touch). I checked my own lines against the config separately and they're fine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant