为什么< body>当我< Router>在Jest中向我的测试添加a时,我的render函数会呈现空值?

nhjlsmyf  于 11个月前  发布在  Jest
关注(0)|答案(2)|浏览(106)

我正在尝试使用React Router V3测试下面的场景。基于step prop,我设置了一些状态变量,然后渲染组件。然后根据传递给

const TestComponent = ({
  languageData,
  locale,
  route: { step },
}) => {
  const [showTiles, setShowTiles] = useState(true);
  const [showAdsSearch, setShowAdsSearch] = useState(false);
  const [showBasicSearch, setShowBasicSearch] = useState(false);
  const [showSubmitterFields, setShowSubmitterFields] = useState(false);

  const viewHome = () => {
    setShowBasicSearch(false);
    setShowSubmitterFields(false);
    setShowAdsSearch(false);
    setShowTiles(true);
  };

  const viewBasicSearch = () => {
    setShowBasicSearch(true);
    setShowSubmitterFields(false);
    setShowAdsSearch(false);
    setShowTiles(false);
  };

  const viewAdSearch = () => {
    setShowBasicSearch(false);
    setShowSubmitterFields(false);
    setShowAdsSearch(true);
    setShowTiles(false);
  };

  const viewCreateSubmitterProfileFields = () => {
    setShowBasicSearch(false);
    setShowSubmitterFields(true);
    setShowAdsSearch(false);
    setShowTiles(false);
  };

  const stepMap = new Map([
    [1, viewHome],
    [2, viewCreateSubmitterProfileFields],
    [3, viewBasicSearch],
    [4, viewAdSearch],
  ]);

  useEffect(() => {
    const currentState = stepMap.get(step) || viewHome;
    currentState();
  }, [step]);

  if (Object.entries(languageData).length === 0) {
    return <ProgressCircle />;
  }

  return (
    <IntlProvider locale={locale} messages={languageData}>
      <UserContext.Consumer>
        {(user) => (Object.keys(user).length > 0 ? (
          <HomeView
            className={styles.grayBg}
            showAdsSearch={showAdsSearch}
            setShowAdsSearch={setShowAdsSearch}
            showSubmitterFields={showSubmitterFields}
            setShowSubmitterFields={setShowSubmitterFields}
            showBasicSearch={showBasicSearch}
            setShowBasicSearch={setShowBasicSearch}
            showTiles={showTiles}
            setShowTiles={setShowTiles}
          />
        ) : <div>NO USER CONTEXT SET IN ROOT MODULE</div>)}
      </UserContext.Consumer>
    </IntlProvider>
  );
};

字符串
Home组件:

export function Home({
  showTiles,
  setShowTiles,
  showBasicSearch,
  setShowBasicSearch,
  showAdsSearch,
  setShowAdsSearch,
  showSubmitterFields,
  setShowSubmitterFields,
}) {

  return (
    <React.Fragment>
      <HeaderSection
        setShowBasicSearch={setShowBasicSearch}
        showBasicSearch={showBasicSearch}
        setShowTiles={setShowTiles}
        setShowAdsSearch={setShowAdsSearch}
        setSubmitterIdToView={setSubmitterIdToView}
        setSubmitterName={setSubmitterName}
        setShowSubmitterFields={setShowSubmitterFields}
      />
      <div id="home" className={styles.grayBgForHome}>
        {showTiles && (
          <TilesView
            setShowBasicSearch={setShowBasicSearch}
            setShowTiles={setShowTiles}
            setShowAdsSearch={setShowAdsSearch}
            showAdsSearch={showAdsSearch}
            showSubmitterFields={showSubmitterFields}
            setShowSubmitterFields={setShowSubmitterFields}
          />
        )}
        {showBasicSearch && (
          <React.Fragment>
            <h1 className={styles.headingText}>
              Search Submitter Profile
            </h1>
            <ConnectedBasicSearch/>
          </React.Fragment>
        )}
        {showAdsSearch && (
          <React.Fragment>
            <h1 className={styles.headingText}>
              Advanced Search Submitter Profile
            </h1>
            <ConnectedAdvancedSearch/>
          </React.Fragment>
        )}
        {showSubmitterFields && (
          <React.Fragment>
            <h1 className={styles.headingText}>Create Submitter Profile</h1>
            <ConnectedSubmitterProfile/>
          </React.Fragment>
        )}
      </div>
      <FooterSection />
    </React.Fragment>
  );
}


在我的测试中,我有下面的。我试图做的是用step = 1渲染Home,它应该显示Tiles组件。然后我点击#basicSearchTile,这是一个链接到/submitter-profile/basic-search,并希望检查显示的某些元素:

async function clickElement(container, selector) {
  const user = userEvent.setup();
  const element = container.querySelector(selector);
  await user.click(element);
}

async function checkDisplayed(container, selector, shouldBeDisplayed) {
  const element = container.querySelector(selector);
  if (shouldBeDisplayed) {
    expect(element).toBeInTheDocument();
  } else {
    expect(element).not.toBeInTheDocument();
  }
}

const props1 = {
  languageData: { intlKeyMock: 'intlValueMock' },
  locale: 'localeMock',
  route: { step: 1 },
};
const props2 = {
  languageData: { intlKeyMock: 'intlValueMock' },
  locale: 'localeMock',
  route: { step: 2 },
};
const props3 = {
  languageData: { intlKeyMock: 'intlValueMock' },
  locale: 'localeMock',
  route: { step: 3 },
};
const props4 = {
  languageData: { intlKeyMock: 'intlValueMock' },
  locale: 'localeMock',
  route: { step: 4 },
};

  describe('Navigation tests', () => {
    it('invalid submitterId on save for edit profile', async () => {
      const { container } = render(
        <Router initialEntries={['/submitter-profile']} history={createMemoryHistory()}>
          <UserContext.Provider value={loggedInUser}>
            <Route path="/" element={<TestableAxpSubmissionsWebSearchSubmitterProfile {...props1} />} />
            <Route path="/submitter-profile" element={<TestableAxpSubmissionsWebSearchSubmitterProfile {...props1} />} />
            <Route path="/submitter-profile/basic-search" element={<TestableAxpSubmissionsWebSearchSubmitterProfile {...props3} />} />
            <Route path="/submitter-profile/create" element={<TestableAxpSubmissionsWebSearchSubmitterProfile {...props2} />} />
            <Route path="/submitter-profile/advanced-search" element={<TestableAxpSubmissionsWebSearchSubmitterProfile {...props4} />} />
          </UserContext.Provider>
        </Router>
      );
      screen.debug();
      await clickElement(container, '#basicSearchTile');
      await clickElement(container, '#search-button');
      await clickElement(container, '#resultTableRowsubmitterId123');
      await clickElement(container, '#editToggle');
      await clickElement(container, '#saveButton');
      screen.debug();
      await checkDisplayed(container, '#responseModalMsg', true);
      await checkTextValue(container, '#responseModal', 'Must enter a valid value for Submitter ID.');
      await clickElement(container, '#responseModal');
      await checkDisplayed(container, '#responseModalMsg', false);
    });
});


但是,每当我使用render时,screen.debug()调用都返回一个空的主体。

<body>
  <div />
</body>


我也添加了路由定义的情况下,他们是有帮助的。路由在应用程序是伟大的工作。这只是测试,我不能得到工作

const Routes = [
  <Route
    key="submitter-profile-route"
    path="/submitter-profile"
    moduleName="axp-submissions-web-search-submitter-profile"
    step={1}
  />,
  <Route
    key="create-submitter-profile-route"
    path="/submitter-profile/create"
    moduleName="axp-submissions-web-search-submitter-profile"
    step={2}
  />,
  <Route
    key="basic-search-submitter-profile-route"
    path="/submitter-profile/basic-search"
    moduleName="axp-submissions-web-search-submitter-profile"
    step={3}
  />,
  <Route
    key="advanced-search-submitter-profile-route"
    path="/submitter-profile/advanced-search"
    moduleName="axp-submissions-web-search-submitter-profile"
    step={4}
  />];


解决方案:我能够使用Drews的答案来嘲笑我的路由器,就像这样

const TestHomeComponent = () => <UserContext.Provider value={loggedInUser}><TestableAxpSubmissionsWebSearchSubmitterProfile {...props1} /></UserContext.Provider>;
const TestBasicSearchComponent = () => <UserContext.Provider value={loggedInUser}><TestableAxpSubmissionsWebSearchSubmitterProfile {...props3} /></UserContext.Provider>;
const TestCreateComponent = () => <UserContext.Provider value={loggedInUser}><TestableAxpSubmissionsWebSearchSubmitterProfile {...props2} /></UserContext.Provider>;
const TestAdvSearchComponent = () => <UserContext.Provider value={loggedInUser}><TestableAxpSubmissionsWebSearchSubmitterProfile {...props4} /></UserContext.Provider>;

const { container, debug } = render(
  <Router initialEntries={['/submitter-profile']} history={createMemoryHistory()}>
    <UserContext.Provider value={loggedInUser}>
      <Route path="/submitter-profile" component={TestHomeComponent} />
      <Route path="/submitter-profile/basic-search" component={TestBasicSearchComponent} />
      <Route path="/submitter-profile/create" component={TestCreateComponent} />
      <Route path="/submitter-profile/advanced-search" component={TestAdvSearchComponent} />
      <Route path="/" component={TestHomeComponent} />
    </UserContext.Provider>
  </Router>
);

rqdpfwrv

rqdpfwrv1#

React-Router v3 Route组件没有element prop,它有一个component prop。更新测试代码以使用component prop,并传递一个引用到组件而不是JSX。
请确保以路径特异性的相反顺序指定路由,例如在 * 较少 * 特定路径之前呈现 * 更多 * 特定路径。
范例:

describe('Navigation tests', () => {
  it('invalid submitterId on save for edit profile', async () => {
    const memoryHistory = createMemoryHistory();

    const { container } = render(
      <Router
        initialEntries={['/submitter-profile']}
        history={memoryHistory}
      >
        <UserContext.Provider value={loggedInUser}>
          <Route
            path="/submitter-profile/basic-search"
            component={TestableAxpSubmissionsWebSearchSubmitterProfile}
          />
          <Route
            path="/submitter-profile/create"
            component={TestableAxpSubmissionsWebSearchSubmitterProfile}
          />
          <Route
            path="/submitter-profile/advanced-search"
            component={TestableAxpSubmissionsWebSearchSubmitterProfile}
          />
          <Route
            path="/submitter-profile"
            component={TestableAxpSubmissionsWebSearchSubmitterProfile}
          />
          <Route
            path="/"
            component={TestableAxpSubmissionsWebSearchSubmitterProfile}
          />
        </UserContext.Provider>
      </Router>
    );

    ...
  });
});

字符串

hs1ihplo

hs1ihplo2#

我已经添加了路由定义,以防它们有帮助。应用程序中的路由工作得很好。只是我无法进行测试。
首先,它似乎设置正确。但在您的测试中,您使用@testing-library/react中的render来渲染组件,但这不支持react-router v3
我只是在想,你需要一个Router组件来在测试中导航。
我在这里使用history中的createMemoryHistory,因为我们需要先创建一个历史对象,然后将其传递给Router
如果找不到createMemoryHistory或没有history,通过执行npm install --save history安装它。然后,创建一个路由器,如下面的示例,以允许您在测试中模拟导航。

import { createMemoryHistory } from 'history';
import { Router } from 'react-router';

// ...

it('invalid submitterId on save for edit profile', async () => {
 const history = createMemoryHistory();
 history.push('/');

 const { container } = render(
 <Router history={history}>
   <UserContext.Provider value={loggedInUser}>
     <Route path="/" element={<TestableAxpSubmissionsWebSearchSubmitterProfile {...props1} />} />
     <Route path="/submitter-profile" element={<TestableAxpSubmissionsWebSearchSubmitterProfile {...props1} />} />
     <Route path="/submitter-profile/basic-search" element={<TestableAxpSubmissionsWebSearchSubmitterProfile {...props3} />} />
     <Route path="/submitter-profile/create" element={<TestableAxpSubmissionsWebSearchSubmitterProfile {...props2} />} />
     <Route path="/submitter-profile/advanced-search" element={<TestableAxpSubmissionsWebSearchSubmitterProfile {...props4} />} />
   </UserContext.Provider>
 </Router>
 );

 // ...
});

字符串

相关问题