Selhávající Test: Nic se vrátil z render. identický test projde, jediný rozdíl s selhávající test je použití initialEntries

0

Otázka

Snažím se otestovat, zda moje cesty jsou pracovní, první test projde, když jsem test výchozí "/" cesta, nicméně druhý test neprojde. jediný rozdíl je, že v druhém testu initialEntries={['/register']} je zaveden, a jako výsledek druhého testu selže z tohoto důvodu:

"Přihlásit se(...): Nic se vrátil z render. To obvykle znamená návrat prohlášení chybí. Nebo, k tomu, aby nic není, vrátí null."

Zkontrolovala jsem ostatní dotazy týkající se tohoto, ale nezdá se, že zápas můj konkrétní problém

to je moje app.js to obsahuje všechny trasy

import React from 'react';
import {BrowserRouter as Router, Route, Switch} from 'react-router-dom'
import PrivateRoute from './components/PrivateRoute';
import Login from './components/LoginRegister/Login';
import Dashboard from './components/Dashboard/Dashboard';
import Register from './components/LoginRegister/Register';
import PageNotFound from './components/Pages/PageNotFound';
import Header from './components/LoginRegister/Header';
function App() {

  return (
    <Router>
      <div className="main-container">
          <div className="Route-container">
          <Header/>
              <Switch>
                <PrivateRoute exact path = '/dashboard' component = {Dashboard}></PrivateRoute> 
                <Route exact path = '/' component = {Login} />
                <Route exact path = '/test' component = {Dashboard} />
                <Route exact path = '/register' component = {Register} /> 
                <Route component = {PageNotFound} /> 
              </Switch>
          </div>
        </div>
    </Router>
  );
}

export default App; 

To je moje App.test.js

import React from 'react'
import { render, screen } from '@testing-library/react';
import { MemoryRouter } from 'react-router';
import App from "./App";
import Dashboard from './components/Dashboard/Dashboard'; 
import Header from './components/LoginRegister/Header';
import Login from './components/LoginRegister/Login';
import Register from './components/LoginRegister/Register';
import PageNotFound from './components/Pages/PageNotFound';
import '@testing-library/jest-dom/extend-expect';

jest.mock('./components/Dashboard/Dashboard');
jest.mock('./components/LoginRegister/Login');
jest.mock('./components/LoginRegister/Register');
jest.mock('./components/Pages/PageNotFound');
jest.mock('./components/LoginRegister/Header');

describe("App component", () =>{
    it("renders page header and login component on default route", ()=>{
        Header.mockImplementation(()=> <div>HeaderMock</div>);
        Login.mockImplementation(()=> <div>LoginMock</div>);

        render(
          <MemoryRouter>
            <App />
          </MemoryRouter>
        );
        
        expect(screen.getByText("HeaderMock")).toBeInTheDocument();
        expect(screen.getByText("LoginMock")).toBeInTheDocument();
    });

    it("Renders page header and Register component on Register route", ()=>{
      Header.mockImplementation(()=> <div>HeaderMock</div>);
      Register.mockImplementation(()=> <div>RegisterMock</div>);

      render(
        <MemoryRouter initialEntries={['/register']}>
            <App />
        </MemoryRouter>
      );
      
      expect(screen.getByText("HeaderMock")).toBeInTheDocument();
      expect(screen.getByText("RegisterMock")).toBeInTheDocument();
  });
});

To je Register.js součástí

import React from 'react'
import { useState } from 'react';
import { Link, useHistory } from 'react-router-dom';

const initialState = {
    credentials: {
    name: '',
    username: '',
    password: ''
  }
}

function Register() {
    const [state, setState] = useState(initialState)
    const history = useHistory()

    function goToLogin () {
        history.push('/')
    }

function handleChange(e) {
    setState({
        credentials: {
            ...state.credentials,
            [e.target.name]: e.target.value
        }
    })
   }
    return (
        <div className = "main-container">
            
            <div className = "middle-section">
                
                <div className= "login-section">
                
                    <div className = "selection login-flex-item">
                        Already a member? &nbsp;
                        <Link to ='/' className = 'select-logreg'>Login</Link>
                    </div>

                    <form className = 'login-flex-item' onSubmit = {goToLogin}>
                
                        <input className = 'form-item'
                            type = 'text'
                            name = 'name'
                            placeholder = "Enter Name"
                            value = {state.credentials.name}
                            onChange ={handleChange}
                        />
                        <input className = 'form-item'
                            type = 'text'
                            name = 'username'
                            placeholder = "Username"
                            value = {state.credentials.username}
                            onChange ={handleChange}
                        />
                        <input className = 'form-item'
                            type="password"
                            name="password"
                            placeholder = "Password"
                            value={state.credentials.password}
                            onChange={handleChange}
                        />
                        <button className = 'form-item btn'>Sign Up</button>
                    </form>
                </div>
            </div>
        </div>
    );
};

export default Register;

a to je test nezdaří popis jsem dostat žádnou pomoc by bylo úžasné, byl jsem zíral na hodiny a cant zdá se najít řešení.

 FAIL  src/App.test.js
  App component
    √ renders page header and login component on default route (33 ms)
    × Renders page header and Register component on Register route (198 ms)

  ● App component › Renders page header and Register component on Register route

    Login(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null.

      35 |       Register.mockImplementation(()=> <div>RegisterMock</div>);
      36 |
    > 37 |       render(
         |       ^
      38 |         <MemoryRouter initialEntries={['/register']}>
      39 |             <App />
      40 |         </MemoryRouter>

      at reconcileChildFibers (node_modules/react-dom/cjs/react-dom.development.js:14169:23)
      at reconcileChildren (node_modules/react-dom/cjs/react-dom.development.js:16990:28)
      at mountIndeterminateComponent (node_modules/react-dom/cjs/react-dom.development.js:17890:5)
      at beginWork (node_modules/react-dom/cjs/react-dom.development.js:19049:16)
      at HTMLUnknownElement.callCallback (node_modules/react-dom/cjs/react-dom.development.js:3945:14)
      at HTMLUnknownElement.callTheUserObjectsOperation (node_modules/jsdom/lib/jsdom/living/generated/EventListener.js:26:30)
      at innerInvokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:338:25)
      at invokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:274:3)
      at HTMLUnknownElementImpl._dispatch (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:221:9)
      at HTMLUnknownElementImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:94:17)
      at HTMLUnknownElement.dispatchEvent (node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:231:34)
      at Object.invokeGuardedCallbackDev (node_modules/react-dom/cjs/react-dom.development.js:3994:16)
      at invokeGuardedCallback (node_modules/react-dom/cjs/react-dom.development.js:4056:31)
      at beginWork$1 (node_modules/react-dom/cjs/react-dom.development.js:23964:7)
      at performUnitOfWork (node_modules/react-dom/cjs/react-dom.development.js:22779:12)
      at workLoopSync (node_modules/react-dom/cjs/react-dom.development.js:22707:5)
      at renderRootSync (node_modules/react-dom/cjs/react-dom.development.js:22670:7)
      at performSyncWorkOnRoot (node_modules/react-dom/cjs/react-dom.development.js:22293:18)
      at scheduleUpdateOnFiber (node_modules/react-dom/cjs/react-dom.development.js:21881:7)
      at updateContainer (node_modules/react-dom/cjs/react-dom.development.js:25482:3)
      at node_modules/react-dom/cjs/react-dom.development.js:26021:7
      at unbatchedUpdates (node_modules/react-dom/cjs/react-dom.development.js:22431:12)
      at legacyRenderSubtreeIntoContainer (node_modules/react-dom/cjs/react-dom.development.js:26020:5)
      at Object.render (node_modules/react-dom/cjs/react-dom.development.js:26103:10)
      at node_modules/@testing-library/react/dist/pure.js:101:25
      at batchedUpdates$1 (node_modules/react-dom/cjs/react-dom.development.js:22380:12)
      at act (node_modules/react-dom/cjs/react-dom-test-utils.development.js:1042:14)
      at render (node_modules/@testing-library/react/dist/pure.js:97:26)
      at Object.<anonymous> (src/App.test.js:37:7)
1

Nejlepší odpověď

1

Z doc <Router>:

Společné low-level rozhraní pro všechny směrovače komponenty. Obvykle aplikace bude používat jeden z high-úrovni směrovačů místo:

  • <BrowserRouter>
  • <HashRouter>
  • <MemoryRouter>
  • <NativeRouter>
  • <StaticRouter>

Problém je <BrowserRouter> součástí je zabalené v <MemoryRouter> takhle:

<MemoryRouter>
  <BrowserRouter>
    <Switch>
     ....
    </Switch>
  </BrowserRouter>
</MemoryRouter>

To vám dá location z <BrowserRouter>, to bude:

location:  { pathname: '/', search: '', hash: '', state: undefined }

Měli byste rozdělit <Switch> a jeho děti jako nezávislé komponenty, jako Routes:

import React from 'react';
import { BrowserRouter as Router, Route, Switch, useLocation } from 'react-router-dom';

const Login = () => <div>login</div>;
const Register = () => <div>Register</div>;

export const Routes = () => {
  const location = useLocation();
  console.log('location: ', location);
  return (
    <Switch>
      <Route exact path="/" component={Login} />
      <Route exact path="/register" component={Register} />
    </Switch>
  );
};

function App() {
  return (
    <Router>
      <Routes />
    </Router>
  );
}

export default App;

Tak, že můžete použít Routes s <MemoryRouter> pro testování:

import React from 'react';
import { MemoryRouter } from 'react-router-dom';
import { render, screen } from '@testing-library/react';
import '@testing-library/jest-dom/extend-expect';
import { Routes } from './app';

describe('App component', () => {
  it('renders page header and login component on default route', () => {
    render(
      <MemoryRouter>
        <Routes />
      </MemoryRouter>
    );
    expect(screen.getByText('login')).toBeInTheDocument();
  });

  it('Renders page header and Register component on Register route', () => {
    render(
      <MemoryRouter initialEntries={['/register']}>
        <Routes />
      </MemoryRouter>
    );
    expect(screen.getByText('Register')).toBeInTheDocument();
  });
});

výsledek testu:

 PASS  examples/70090905/app.test.tsx (8.087 s)
  App component
    ✓ renders page header and login component on default route (45 ms)
    ✓ Renders page header and Register component on Register route (3 ms)

  console.log
    location:  {
      pathname: '/',
      search: '',
      hash: '',
      state: undefined,
      key: 'zlnxcn'
    }

      at Routes (examples/70090905/app.tsx:9:11)

  console.log
    location:  {
      pathname: '/register',
      search: '',
      hash: '',
      state: undefined,
      key: '8z804n'
    }

      at Routes (examples/70090905/app.tsx:9:11)

Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        8.625 s, estimated 11 s

Pro názorné a demonstrační účely jsem odstraní zbytečné kód.

Balíček verze:

"react-router-dom": "^5.2.0"
2021-11-24 07:54:05

V jiných jazycích

Tato stránka je v jiných jazycích

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................