Repository: electron/electron
Pull request: test: fixup flaky session tests

#### Description of Change
- #44389 fixed some flaky tests in 32-x-y, mainly by migrating away from synchronous mocha functions to async ones.  It turns out that those flakes are present in newer versions as well, eg https://github.com/electron/electron/actions/runs/11645084310/job/32437831508?pr=44534, so we should apply the same fixes to newer versions.
- 
<!--
Thank you for your Pull Request. Please provide a description above and review
the requirements below.

Contributors guide: https://github.com/electron/electron/blob/main/CONTRIBUTING.md
-->

#### Checklist
<!-- Remove items that do not apply. For completed items, change [ ] to [x]. -->

- [x] PR description included and stakeholders cc'd
- [x] `npm test` passes
- [x] tests are [changed or added](https://github.com/electron/electron/blob/main/docs/development/testing.md)
- [x] [PR release notes](https://github.com/electron/clerk/blob/main/README.md) describe the change in a way relevant to app developers, and are [capitalized, punctuated, and past tense](https://github.com/electron/clerk/blob/main/README.md#examples).

#### Release Notes

Notes: <!-- Please add a one-line description for app developers to read in the release notes, or 'none' if no notes relevant to app developers. Examples and help on special cases: https://github.com/electron/clerk/blob/main/README.md#examples -->none


Changed files:
filename: spec/api-session-spec.ts
patch: @@ -12,7 +12,7 @@ import * as https from 'node:https';
 import * as path from 'node:path';
 import { setTimeout } from 'node:timers/promises';
 
-import { defer, listen } from './lib/spec-helpers';
+import { defer, ifit, listen } from './lib/spec-helpers';
 import { closeAllWindows } from './lib/window-helpers';
 
 describe('session module', () => {
@@ -841,19 +841,13 @@ describe('session module', () => {
     };
 
     describe('session.downloadURL', () => {
-      it('can perform a download', (done) => {
-        session.defaultSession.once('will-download', function (e, item) {
-          item.savePath = downloadFilePath;
-          item.on('done', function (e, state) {
-            try {
-              assertDownload(state, item);
-              done();
-            } catch (e) {
-              done(e);
-            }
-          });
-        });
+      it('can perform a download', async () => {
+        const willDownload = once(session.defaultSession, 'will-download');
         session.defaultSession.downloadURL(`${url}:${port}`);
+        const [, item] = await willDownload;
+        item.savePath = downloadFilePath;
+        const [, state] = await once(item, 'done');
+        assertDownload(state, item);
       });
 
       it('can perform a download with a valid auth header', async () => {
@@ -963,20 +957,14 @@ describe('session module', () => {
     });
 
     describe('webContents.downloadURL', () => {
-      it('can perform a download', (done) => {
+      it('can perform a download', async () => {
         const w = new BrowserWindow({ show: false });
-        w.webContents.session.once('will-download', function (e, item) {
-          item.savePath = downloadFilePath;
-          item.on('done', function (e, state) {
-            try {
-              assertDownload(state, item);
-              done();
-            } catch (e) {
-              done(e);
-            }
-          });
-        });
+        const willDownload = once(w.webContents.session, 'will-download');
         w.webContents.downloadURL(`${url}:${port}`);
+        const [, item] = await willDownload;
+        item.savePath = downloadFilePath;
+        const [, state] = await once(item, 'done');
+        assertDownload(state, item);
       });
 
       it('can perform a download with a valid auth header', async () => {
@@ -1079,73 +1067,51 @@ describe('session module', () => {
         expect(item.getTotalBytes()).to.equal(0);
       });
 
-      it('can download from custom protocols', (done) => {
+      it('can download from custom protocols', async () => {
         const protocol = session.defaultSession.protocol;
         const handler = (ignoredError: any, callback: Function) => {
           callback({ url: `${url}:${port}` });
         };
         protocol.registerHttpProtocol(protocolName, handler);
         const w = new BrowserWindow({ show: false });
-        w.webContents.session.once('will-download', function (e, item) {
-          item.savePath = downloadFilePath;
-          item.on('done', function (e, state) {
-            try {
-              assertDownload(state, item, true);
-              done();
-            } catch (e) {
-              done(e);
-            }
-          });
-        });
+        const willDownload = once(w.webContents.session, 'will-download');
         w.webContents.downloadURL(`${protocolName}://item`);
+        const [, item] = await willDownload;
+        item.savePath = downloadFilePath;
+        const [, state] = await once(item, 'done');
+        assertDownload(state, item, true);
       });
 
-      it('can cancel download', (done) => {
+      it('can cancel download', async () => {
         const w = new BrowserWindow({ show: false });
-        w.webContents.session.once('will-download', function (e, item) {
-          item.savePath = downloadFilePath;
-          item.on('done', function (e, state) {
-            try {
-              expect(state).to.equal('cancelled');
-              expect(item.getFilename()).to.equal('mock.pdf');
-              expect(item.getMimeType()).to.equal('application/pdf');
-              expect(item.getReceivedBytes()).to.equal(0);
-              expect(item.getTotalBytes()).to.equal(mockPDF.length);
-              expect(item.getContentDisposition()).to.equal(contentDisposition);
-              done();
-            } catch (e) {
-              done(e);
-            }
-          });
-          item.cancel();
-        });
+        const willDownload = once(w.webContents.session, 'will-download');
         w.webContents.downloadURL(`${url}:${port}/`);
+        const [, item] = await willDownload;
+        item.savePath = downloadFilePath;
+        const itemDone = once(item, 'done');
+        item.cancel();
+        const [, state] = await itemDone;
+        expect(state).to.equal('cancelled');
+        expect(item.getFilename()).to.equal('mock.pdf');
+        expect(item.getMimeType()).to.equal('application/pdf');
+        expect(item.getReceivedBytes()).to.equal(0);
+        expect(item.getTotalBytes()).to.equal(mockPDF.length);
+        expect(item.getContentDisposition()).to.equal(contentDisposition);
       });
 
-      it('can generate a default filename', function (done) {
-        if (process.env.APPVEYOR === 'True') {
-          // FIXME(alexeykuzmin): Skip the test.
-          // this.skip()
-          return done();
-        }
-
+      ifit(process.platform !== 'win32')('can generate a default filename', async () => {
         const w = new BrowserWindow({ show: false });
-        w.webContents.session.once('will-download', function (e, item) {
-          item.savePath = downloadFilePath;
-          item.on('done', function () {
-            try {
-              expect(item.getFilename()).to.equal('download.pdf');
-              done();
-            } catch (e) {
-              done(e);
-            }
-          });
-          item.cancel();
-        });
+        const willDownload = once(w.webContents.session, 'will-download');
         w.webContents.downloadURL(`${url}:${port}/?testFilename`);
+        const [, item] = await willDownload;
+        item.savePath = downloadFilePath;
+        const itemDone = once(item, 'done');
+        item.cancel();
+        await itemDone;
+        expect(item.getFilename()).to.equal('download.pdf');
       });
 
-      it('can set options for the save dialog', (done) => {
+      it('can set options for the save dialog', async () => {
         const filePath = path.join(__dirname, 'fixtures', 'mock.pdf');
         const options = {
           window: null,
@@ -1164,40 +1130,29 @@ describe('session module', () => {
         };
 
         const w = new BrowserWindow({ show: false });
-        w.webContents.session.once('will-download', function (e, item) {
-          item.setSavePath(filePath);
-          item.setSaveDialogOptions(options);
-          item.on('done', function () {
-            try {
-              expect(item.getSaveDialogOptions()).to.deep.equal(options);
-              done();
-            } catch (e) {
-              done(e);
-            }
-          });
-          item.cancel();
-        });
+        const willDownload = once(w.webContents.session, 'will-download');
         w.webContents.downloadURL(`${url}:${port}`);
+        const [, item] = await willDownload;
+        item.setSavePath(filePath);
+        item.setSaveDialogOptions(options);
+        const itemDone = once(item, 'done');
+        item.cancel();
+        await itemDone;
+        expect(item.getSaveDialogOptions()).to.deep.equal(options);
       });
 
       describe('when a save path is specified and the URL is unavailable', () => {
-        it('does not display a save dialog and reports the done state as interrupted', (done) => {
+        it('does not display a save dialog and reports the done state as interrupted', async () => {
           const w = new BrowserWindow({ show: false });
-          w.webContents.session.once('will-download', function (e, item) {
-            item.savePath = downloadFilePath;
-            if (item.getState() === 'interrupted') {
-              item.resume();
-            }
-            item.on('done', function (e, state) {
-              try {
-                expect(state).to.equal('interrupted');
-                done();
-              } catch (e) {
-                done(e);
-              }
-            });
-          });
+          const willDownload = once(w.webContents.session, 'will-download');
           w.webContents.downloadURL(`file://${path.join(__dirname, 'does-not-exist.txt')}`);
+          const [, item] = await willDownload;
+          item.savePath = downloadFilePath;
+          if (item.getState() === 'interrupted') {
+            item.resume();
+          }
+          const [, state] = await once(item, 'done');
+          expect(state).to.equal('interrupted');
         });
       });
     });