添加测试后,NodeJs JavaScript react-scripts-ts 堆内存不足崩溃

NodeJs JavaScript heap out of memory crash on react-scripts-ts after adding tests

我有一个 React + TypeScript 项目。自从几天前,我的 webstorm IDE 崩溃了(JavaScript 堆内存不足)on every update that I make to codes。我正在使用 nodeJs 12.3.1、typescript 3.7.5、react 16.12.0、react-scripts-ts 3.1.0、webstorm 2021.2,我的 OS 是 windows 10.

自那时以来,我所做的唯一重大更改是添加了一堆测试(准确地说是 48 个测试和 5000 行代码)。这些测试是使用 jest 和 enzyme 编写的。这些测试包括模拟一些 API 和事件,以及安装元素以检查它们的存在和状态。我应该说所有这些测试都会通过。

我的问题是,为什么每次更改代码后 nodeJs 都会中断? react-scripts-ts starthot reloads 上做什么?写测试的时候要不要考虑一些具体的隐藏点?

如果能提供任何帮助或线索来找出问题,我将不胜感激。

PS:我很乐意分享任何必要的信息以帮助澄清问题。

这是其中一个测试的代码:

import * as React from 'react';
import * as Adapter from 'enzyme-adapter-react-16';
import * as enzyme from 'enzyme';
import DonutObjectKpi from './donutObjectKpi';
import {
  ChartType,
  DashboardItemType,
  DonutChartProps,
  NamedKpiSeriesSelector,
} from '../../../../utils/dashboardUtils/dashboardItem/props';
import KpiDefinition from '../../../../../model/kpi/customKpi/kpiDefinition';
import Kpi from '../../../../../model/kpi/kpi';
import KpiDefinitionType from '../../../../../model/kpi/kpiDefinitionType';
import { CHART_REFRESH_RATE } from '../../../../../config/constants';
import { Button, HorizontalLayout, IconButton, PieChartType, Table } from '../../../../view';
import { InputLabeledField } from '../../../../../modules/panels/baseCrud/layouts';
import { EnumDropDown } from '../../../../input';
import BuildOption from '../../../dropdown/buildOption/component';

enzyme.configure({adapter: new Adapter()});
describe('ObjectKpiItem Test', () => {
  let chartType = ChartType.DONUT;
  let showTitle = true;
  let title: string | undefined = 'Test';
  let cancelModal: boolean = false;
  let dataModal: DonutChartProps | undefined;
  let changeType: boolean = false;
  const obj = {value: '1', label: 'item1'};
  const resourceObj = {value: '2', label: 'item2'};
  const kpiDef: KpiDefinition = {
    kpi: Kpi.DB2Z_DSCDBAT,
    type: KpiDefinitionType.OBJECT_KPI,
    monitoringObject: {id: '3', presentation: 'item3'},
  };
  const description = 'donut Test';

  const selectors: NamedKpiSeriesSelector[] = [
    {kpi: Kpi.ACTIVE_DIRECTORY_COMPUTERS_COUNT, kpiDefinition: kpiDef, objectId: '1', objectIdName: 'item1'},
    {kpi: Kpi.ACTIVE_DIRECTORY_DISABLED_USERS_COUNT, kpiDefinition: kpiDef, objectId: '2', objectIdName: 'item2'},
    {kpi: Kpi.HBASE_REGION_SERVER_STORE_FILE_SIZE_20210, kpiDefinition: kpiDef, objectId: '3', objectIdName: 'item3'},
  ];

  it('check render:', () => {
    const wrapper = enzyme.mount(
      <DonutObjectKpi
        onObjectKpiChartTypeChange={(newType, showTitleRes, titleRes) => {
          chartType = newType;
          showTitle = showTitleRes;
          title = titleRes;
        }}
        showTitle={showTitle}
        chartType={chartType}
        title={title}
        objectId={obj}
        onCancel={() => cancelModal = true}
        submitModal={(data: DonutChartProps) => dataModal = data}
        onDashboardItemTypeChange={() => changeType = true}
      />,
    );
    expect(wrapper.find(InputLabeledField).length).toEqual(8);
    expect(wrapper.find(Table).length).toEqual(2);
    expect(wrapper.find(IconButton).length).toEqual(1);
    expect(wrapper.find(EnumDropDown).length).toEqual(9); // 4 self + 5 border table
  });

  it('check change value:', () => {
    const wrapper = enzyme.mount(
      <DonutObjectKpi
        onObjectKpiChartTypeChange={(newType, showTitleRes, titleRes) => {
          chartType = newType;
          showTitle = showTitleRes;
          title = titleRes;
        }}
        showTitle={showTitle}
        chartType={chartType}
        title={title}
        objectId={obj}
        onCancel={() => cancelModal = true}
        submitModal={(data: DonutChartProps) => dataModal = data}
        onDashboardItemTypeChange={() => changeType = true}
        data={{
          title,
          showTitle: true,
          selectors,
          chartType: ChartType.DONUT,
          type: PieChartType.KPI,
          dashboardItemType: DashboardItemType.OBJECT_KPI,
          interval: CHART_REFRESH_RATE,
          description,
        }}
      />,
    );
    wrapper.setState({
      resourceId: resourceObj,
      kpiDefinition: kpiDef,
      objectId: obj,
      selectors,
      title,
    });
    wrapper.update();
    wrapper.find(IconButton).last().simulate('click');
    expect(dataModal).not.toEqual(undefined);
    expect(dataModal!.title).toEqual(title);
    expect(dataModal!.description).toEqual(description);
    expect(dataModal!.chartType).toEqual(chartType);
    expect(dataModal!.selectors.length).toEqual(selectors.length);
    expect(dataModal!.dashboardItemType).toEqual(DashboardItemType.OBJECT_KPI);
  });

  it('check cancel modal:', () => {
    const newObj = {value: '2', label: 'item2'};
    const newResourceObj = {value: '3', label: 'item3'};
    const newKpiDef: KpiDefinition = {
      kpi: Kpi.HBASE_REGION_SERVER_NUM_OF_HLOG_FILE_20206,
      type: KpiDefinitionType.OBJECT_KPI,
      monitoringObject: {id: '4', presentation: 'item4'},
    };

    const newSelectors: NamedKpiSeriesSelector[] = [
      {kpi: Kpi.ACTIVE_DIRECTORY_COMPUTERS_COUNT, kpiDefinition: kpiDef, objectId: '1', objectIdName: 'item1'},
      {kpi: Kpi.ACTIVE_DIRECTORY_DISABLED_USERS_COUNT, kpiDefinition: kpiDef, objectId: '2', objectIdName: 'item2'},
      {kpi: Kpi.HBASE_REGION_SERVER_STORE_FILE_SIZE_20210, kpiDefinition: kpiDef, objectId: '3', objectIdName: 'item3'},
      {kpi: Kpi.HBASE_REGION_SERVER_NUM_OF_REGIONS_20204, kpiDefinition: kpiDef, objectId: '4', objectIdName: 'item4'},
    ];

    const wrapper = enzyme.mount(
      <DonutObjectKpi
        onObjectKpiChartTypeChange={(newType, showTitleRes, titleRes) => {
          chartType = newType;
          showTitle = showTitleRes;
          title = titleRes;
        }}
        showTitle={showTitle}
        chartType={chartType}
        title={title}
        objectId={newObj}
        onCancel={() => cancelModal = true}
        submitModal={(data: DonutChartProps) => dataModal = data}
        onDashboardItemTypeChange={() => changeType = true}
        data={{
          title,
          showTitle: true,
          selectors,
          chartType: ChartType.DONUT,
          type: PieChartType.KPI,
          dashboardItemType: DashboardItemType.OBJECT_KPI,
          interval: CHART_REFRESH_RATE,
          description,
        }}
      />,
    );
    wrapper.setState({
      resourceId: newResourceObj,
      kpiDefinition: newKpiDef,
      objectId: newObj,
      selectors: newSelectors,
      title,
    });
    wrapper.update();
    expect(dataModal!.selectors.length).toEqual(selectors.length);
    expect(cancelModal).toEqual(false);
    wrapper.find(Button).at(1).simulate('click');
    expect(dataModal!.selectors.length).not.toEqual(newSelectors.length);
    expect(cancelModal).toEqual(true);
  });

  it('check change type:', () => {
    const wrapper = enzyme.mount(
      <DonutObjectKpi
        onObjectKpiChartTypeChange={(newType, showTitleRes, titleRes) => {
          chartType = newType;
          showTitle = showTitleRes;
          title = titleRes;
        }}
        showTitle={showTitle}
        chartType={chartType}
        title={title}
        objectId={obj}
        onCancel={() => cancelModal = true}
        submitModal={(data: DonutChartProps) => dataModal = data}
        onDashboardItemTypeChange={() => changeType = true}
        data={{
          title,
          showTitle: true,
          selectors,
          chartType: ChartType.DONUT,
          type: PieChartType.KPI,
          dashboardItemType: DashboardItemType.OBJECT_KPI,
          interval: CHART_REFRESH_RATE,
          description,
        }}
      />,
    );
    wrapper.find(InputLabeledField).first().find(EnumDropDown).first().find('div').at(1).simulate('click');
    const type = wrapper.find(InputLabeledField).first().find(EnumDropDown).first();
    expect(changeType).toEqual(false);
    type.find(BuildOption).first().find(HorizontalLayout).first().find('div').first().simulate('click');
    expect(changeType).toEqual(true);
  });
});

对于可能遇到我的问题的任何人,我找到的解决方法是typescript 编译 中排除所有测试文件。这是我的 tsconfig.json 中的排除部分(我添加了最后两行):

"exclude": [
    "node_modules",
    "build",
    "scripts",
    "acceptance-tests",
    "webpack",
    "jest",
    "src/setupTests.ts",
    "src/**/*.test.ts",
    "src/**/*.test.tsx"
  ]

我应该提一下,关于内存使用的优化测试没有帮助。