window-helpers.ts 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. import { BaseWindow, BrowserWindow, webContents } from 'electron/main';
  2. import { expect } from 'chai';
  3. import { once } from 'node:events';
  4. async function ensureWindowIsClosed (window: BaseWindow | null) {
  5. if (window && !window.isDestroyed()) {
  6. if (window instanceof BrowserWindow && window.webContents && !window.webContents.isDestroyed()) {
  7. // If a window isn't destroyed already, and it has non-destroyed WebContents,
  8. // then calling destroy() won't immediately destroy it, as it may have
  9. // <webview> children which need to be destroyed first. In that case, we
  10. // await the 'closed' event which signals the complete shutdown of the
  11. // window.
  12. const isClosed = once(window, 'closed');
  13. window.destroy();
  14. await isClosed;
  15. } else {
  16. // If there's no WebContents or if the WebContents is already destroyed,
  17. // then the 'closed' event has already been emitted so there's nothing to
  18. // wait for.
  19. window.destroy();
  20. }
  21. }
  22. }
  23. export const closeWindow = async (
  24. window: BaseWindow | null = null,
  25. { assertNotWindows } = { assertNotWindows: true }
  26. ) => {
  27. await ensureWindowIsClosed(window);
  28. if (assertNotWindows) {
  29. let windows = BaseWindow.getAllWindows();
  30. if (windows.length > 0) {
  31. setTimeout(async () => {
  32. // Wait until next tick to assert that all windows have been closed.
  33. windows = BaseWindow.getAllWindows();
  34. try {
  35. expect(windows).to.have.lengthOf(0);
  36. } finally {
  37. for (const win of windows) {
  38. await ensureWindowIsClosed(win);
  39. }
  40. }
  41. });
  42. }
  43. }
  44. };
  45. export async function closeAllWindows (assertNotWindows = false) {
  46. let windowsClosed = 0;
  47. for (const w of BaseWindow.getAllWindows()) {
  48. await closeWindow(w, { assertNotWindows });
  49. windowsClosed++;
  50. }
  51. return windowsClosed;
  52. }
  53. export async function cleanupWebContents () {
  54. let webContentsDestroyed = 0;
  55. const existingWCS = webContents.getAllWebContents();
  56. for (const contents of existingWCS) {
  57. const isDestroyed = once(contents, 'destroyed');
  58. contents.destroy();
  59. await isDestroyed;
  60. webContentsDestroyed++;
  61. }
  62. return webContentsDestroyed;
  63. }