playwright
playwright copied to clipboard
[BUG][Electron] filechooser event not emitted when dialog.show(Open|Save)Dialog is called
Duplicate of #5013. Full details and repro steps available there.
Opening new issue as requested by maintainers on original issue.
This is definitely a blocker for our integration tests as we need to test open and save functionality in our app and we're not able to select the files in the dialogs.
I'm also having trouble with showOpenDialogSync and showSaveDialogSync because the test stopped.
Is there any workaround?
I have create a test repo to trying to mock electron dialog like spectron-fake-dialog
does, but failed.
Does not work, but returned mocked
is true.
https://github.com/wsw0108/electron-playwright-test/blob/master/test/test.js#L74-L81
This console.log
does not write to file.
https://github.com/wsw0108/electron-playwright-test/blob/master/test/preload.js#L37
Does anyone may have time to help to find out why?
I am also having this issue and have been looking for a solution.
@wsw0108 I am quite new to JS testing, but I will have a look into your code if I get some time. Please report back!
@Daveiano I have found the fail cause, it's the async thing of electron ipc. The mock works actually.
Based on spectron-fake-dialog, I wrote a little library to fake electron dialog for playwright/electron, https://github.com/wsw0108/playwright-fake-dialog
Based on spectron-fake-dialog, I wrote a little library to fake electron dialog for playwright/electron, https://github.com/wsw0108/playwright-fake-dialog
Awesome! Can actually simplify this and just do:
const electronApp = await playwright._electron.launch({ args: ['./main.js']});
// ...
// in test:
electronApp.evaluate(
async({ dialog }, filePaths) => {
dialog.showOpenDialog = () => Promise.resolve({ canceled: false, filePaths });
},
['file.txt']
);
@MikeJerred Elegant solution.
Can I use your idea to update my repo?
@MikeJerred Elegant solution.
Can I use your idea to update my repo?
Yep of course
@wsw0108 I am getting this error when using playwright-fake-dialog
page.evaluate: ReferenceError: require is not defined
at eval (eval at evaluate (:3:2389), <anonymous>:2:31)
at t.default.evaluate (<anonymous>:3:2412)
at t.default.<anonymous> (<anonymous>:1:44)
at ipcRendererSendSyncAsync (/var/www/weather-data-center-electron-forge/node_modules/playwright-fake-dialog/index.js:12:15)
at mock (/var/www/weather-data-center-electron-forge/node_modules/playwright-fake-dialog/index.js:22:10)
at /var/www/weather-data-center-electron-forge/src/main/renderer-empty.test.ts:93:13
at fulfilled (/var/www/weather-data-center-electron-forge/src/main/renderer-empty.test.ts:5:58)
Setup is the following:
import { _electron as electron } from "playwright-core";
const { launch, mock } = require('playwright-fake-dialog')
...
beforeAll(async () => {
// Launch Electron app.
electronApp = await launch(electron, {
args: [
'.'
],
env: {
...process.env
},
});
// Get the first window that the app opens, wait if necessary.
page = await electronApp.firstWindow();
// Wait for frame actually loaded.
await page.waitForSelector('main');
// Direct Electron console to Node terminal.
page.on('console', console.log);
});
...
it('should import new data', async () => {
await mock(page, [
{
method: 'showOpenDialog',
value: {
filePaths: [`${__dirname.replace('src/main', '')}tests/data/upload-data-start-16-08-21-30-09-21-1196-records.csv`]
}
}
]);
await page.click('button#import');
});
Any help and suggestions would be very appreciated!
https://github.com/wsw0108/electron-playwright-test/blob/e3c6ff53d9d71360270ddd37305b188b8273d2c5/app/main/index.js#L43
using 0.1.0 needs above lines in your electron main.js.
If you use html input, just use filechooser from playwright.
Ah, got you, thank you!
I got it working now with the snippet from @MikeJerred, many thanks for that!
H, i need some help to use the playwright-fake-dialog, do i need any code from "test/preload.js"?(https://github.com/wsw0108/electron-playwright-test/blob/master/test/preload.js).
This is my code
await mock(electronApp, [
{
method: 'showOpenDialog',
value: {
filePaths: [join(__dirname, 'minimal.pdf')]
}
}
])
await newPage.click('[e2e-id="action-bar-create"]');
And i get this ERROR in our Log-File: "fs.api.selectFilesWithOpenDialog (id 46189c0c) - failed due to error: n.a.dialog.showOpenDialog is not a function"
Our Application uses Electron 9, could that be a problem?
Based on spectron-fake-dialog, I wrote a little library to fake electron dialog for playwright/electron, https://github.com/wsw0108/playwright-fake-dialog
Awesome! Can actually simplify this and just do:
const electronApp = await playwright._electron.launch({ args: ['./main.js']}); // ... // in test: electronApp.evaluate( async({ dialog }, filePaths) => { dialog.showOpenDialog = () => Promise.resolve({ canceled: false, filePaths }); }, ['file.txt'] );
best method, you can also control dialogs like so:
const dialogControlHandler = electronApp.evaluateHandler(() => {
let resolve;
const promise = new Promise(res => { resolve = res; });
return {promise, resolve};
});
const dialogOptions = await electronApp.evaluate(
async({ dialog },{ dialogControlHandler }) => {
return new Promise(res => {
dialog.showMessageBox = (options) => {
res(options);
return dialogControlHandler.promise;
};
});
},
{ dialogControlHandler }
);
//Now you have the dialog options avaliable at `dialogOptions` (eg: dialogOptions.title)
//Choose how to resolve the dialog:
dialogControlHandler.evaluate( ({ resolve }) => resolve({response: 1, checkboxchecked: false}) );
Investigation:
- Upstream Electron method ShowOpenDialog calls immediately OS APIs
- When dealing with normal file pickers, upstream its a noop when intercepted like here in this cp
- Probably a new event should be introduced so Electron can wait for it and return the value once emitted. Since Electron API would be different. event -> path[] all the time. It's never a file content etc.
- Similar / different request is about setInputFiles should set path property. There we should extend 'DOM.setFileInputFiles' so it sets the path. https://github.com/microsoft/playwright/issues/10527
Hello everyone, do we have any updates on this ^^^?
I am new to Playwright and I need help with a file upload in my Electron app. My app doesn't have an input element with type="file", so I have to use a FileChooser instead.
Here's the scenario: there's a "Browse Files" button in the app. When I click it, a file manager dialog opens. I then select a file and click the "Upload" button in the file manager dialog to upload the file.
In my script, it successfully clicks the "Browse Files" button, and the file manager dialog opens. However, it doesn't select a file or upload it, and the script times out with an error.
Error: page.waitForEvent: Target page, context or browser has been closed =========================== logs =========================== waiting for event "filechooser" ====================================
Versions: "@playwright/test": "^1.45.3", "electron-playwright-helpers": "^1.7.1", "electron": "29.1.0",
Here is my test script:
const browseFilesBtn = await page.locator('button[aria-label="browse files"]')
try {
const fileChooserPromise = page.waitForEvent('filechooser');
await page.click(browseFilesBtn);
const fileChooser = await fileChooserPromise;
await fileChooser.setFiles(filepath);
} catch (e) {
console.log(e.message);
}
});
I have tried this one as well:
const [fileChooser] = await Promise.all([
page.waitForEvent('filechooser'),
page.click('button[aria-label="browse files"]'),
]);
console.log("File chooser event triggered.");
await fileChooser.setFiles(filePath);
console.log("File selected.");
Thank you all in advance!!