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

Backport of #44545

See that PR for details.


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');
         });
       });
     });