Repository: electron/electron
File: spec/api-utility-process-spec.ts (TypeScript)

Code before:
      const child = utilityProcess.fork(path.join(fixturesPath, 'exception.mjs'));
      const [code] = await once(child, 'exit');
      expect(code).to.equal(1);
    });

    it('emits \'exit\' when process.exit is called', async () => {
      const exitCode = 2;
      const child = utilityProcess.fork(path.join(fixturesPath, 'custom-exit.js'), [`--exitCode=${exitCode}`]);
      const [code] = await once(child, 'exit');
      expect(code).to.equal(exitCode);
    });

    it('does not run JS after process.exit is called', async () => {
      const file = path.join(os.tmpdir(), `no-js-after-exit-log-${Math.random()}`);
      const child = utilityProcess.fork(path.join(fixturesPath, 'no-js-after-exit.js'), [`--testPath=${file}`]);
      const [code] = await once(child, 'exit');
      expect(code).to.equal(1);
      let handle = null;
      try {
        handle = await fs.open(file);
        for await (const line of handle.readLines()) {
          expect(line).to.not.contain('after exit');
        }
      } finally {
        await handle?.close();
      }
    });

    // 32-bit system will not have V8 Sandbox enabled.
    // WoA testing does not have VS toolchain configured to build native addons.
    ifit(process.arch !== 'ia32' && process.arch !== 'arm' && !isWindowsOnArm)('emits \'error\' when fatal error is triggered from V8', async () => {
      const child = utilityProcess.fork(path.join(fixturesPath, 'external-ab-test.js'));
      const [type, location, report] = await once(child, 'error');
      const [code] = await once(child, 'exit');
      expect(type).to.equal('FatalError');
      expect(location).to.equal('v8_ArrayBuffer_NewBackingStore');
      const reportJSON = JSON.parse(report);
      expect(reportJSON.header.trigger).to.equal('v8_ArrayBuffer_NewBackingStore');
      const addonPath = path.join(require.resolve('@electron-ci/external-ab'), '..', '..', 'build', 'Release', 'external_ab.node');
      expect(reportJSON.sharedObjects).to.include(path.toNamespacedPath(addonPath));
      expect(code).to.not.equal(0);
    });
  });

  describe('app \'child-process-gone\' event', () => {
    const waitForCrash = (name: string) => {
      return new Promise<Electron.Details>((resolve) => {
        app.on('child-process-gone', function onCrash (_event, details) {
          if (details.name === name) {
            app.off('child-process-gone', onCrash);
            resolve(details);

Review comment (refactor):
```suggestion
      const lines = [];
      try {
        handle = await fs.open(file);
        for await (const line of handle.readLines()) {
          lines.push(line);
        }
      } finally {
        await handle?.close();
        await fs.rm(file, { force: true });
      }
      expect(lines.length).to.equal(1);
      expect(lines[0]).to.equal('before exit');
```

Let's ensure we always do the `expect` calls even if there's an error thrown or the file is empty, otherwise we might miss a regression. Also added an `fs.rm` to clean up the temp file.

Code after:
      const child = utilityProcess.fork(path.join(fixturesPath, 'exception.mjs'));
      const [code] = await once(child, 'exit');
      expect(code).to.equal(1);
    });

    it('emits \'exit\' when process.exit is called', async () => {
      const exitCode = 2;
      const child = utilityProcess.fork(path.join(fixturesPath, 'custom-exit.js'), [`--exitCode=${exitCode}`]);
      const [code] = await once(child, 'exit');
      expect(code).to.equal(exitCode);
    });

    it('does not run JS after process.exit is called', async () => {
      const file = path.join(os.tmpdir(), `no-js-after-exit-log-${Math.random()}`);
      const child = utilityProcess.fork(path.join(fixturesPath, 'no-js-after-exit.js'), [`--testPath=${file}`]);
      const [code] = await once(child, 'exit');
      expect(code).to.equal(1);
      let handle = null;
      const lines = [];
      try {
        handle = await fs.open(file);
        for await (const line of handle.readLines()) {
          lines.push(line);
        }
      } finally {
        await handle?.close();
        await fs.rm(file, { force: true });
      }
      expect(lines.length).to.equal(1);
      expect(lines[0]).to.equal('before exit');
    });

    // 32-bit system will not have V8 Sandbox enabled.
    // WoA testing does not have VS toolchain configured to build native addons.
    ifit(process.arch !== 'ia32' && process.arch !== 'arm' && !isWindowsOnArm)('emits \'error\' when fatal error is triggered from V8', async () => {
      const child = utilityProcess.fork(path.join(fixturesPath, 'external-ab-test.js'));
      const [type, location, report] = await once(child, 'error');
      const [code] = await once(child, 'exit');
      expect(type).to.equal('FatalError');
      expect(location).to.equal('v8_ArrayBuffer_NewBackingStore');
      const reportJSON = JSON.parse(report);
      expect(reportJSON.header.trigger).to.equal('v8_ArrayBuffer_NewBackingStore');
      const addonPath = path.join(require.resolve('@electron-ci/external-ab'), '..', '..', 'build', 'Release', 'external_ab.node');
      expect(reportJSON.sharedObjects).to.include(path.toNamespacedPath(addonPath));
      expect(code).to.not.equal(0);
    });
  });

  describe('app \'child-process-gone\' event', () => {
    const waitForCrash = (name: string) => {
      return new Promise<Electron.Details>((resolve) => {