TypeError Невозможно прочитать свойство 'состояние' из неопределенного - PullRequest
0 голосов
/ 24 октября 2019

Я продолжаю получать эту ошибку в этой строке, и я не уверен, что вызывает ее, поскольку я довольно новичок в шутке / реакции / энзиме

const { from } = this.props.location.state || { from: { pathname: "/" } };

это происходит всякий раз, когда я пытаюсь запустить эту

import React from 'react';
import { shallow, mount, render } from '../../enzyme';
import Login from '../login'

describe('Login Test Suite', () => {

    it('should render the form', () => {
        const wrapper = shallow(<Login />);

        expect(wrapper.find('form').exists()).toBe(true);
        expect(wrapper.find('#userName').length).toEqual(1);
        expect(wrapper.find('#password').length).toEqual(1);
    })
})

describe('userName Test Suite', () => {

    it('should change the state of the Login component', () => {

        const wrapper = shallow(<Login />);
        wrapper.find('#userName').simulate('blur',
            {
                target: { name: 'userName', value: 'adastest' }
            });

        expect(wrapper.state('userName')).toEqual('adastest');
    })
})

describe('Password Test Suite', () => {

    it('should change the state of the Login component', () => {

        const wrapper = mount(<Login />);
        wrapper.find('#password').simulate('blur',
            {
                target: { name: 'password', value: 'adastest' }
            });

        expect(wrapper.state('password')).toEqual('adastest');
    })
})

Какие-либо предложения / документацию я должен проверить? Спасибо

Это также мой компонент входа в систему

import TextField from "@material-ui/core/TextField";
import clsx from "clsx";
import Button from "@material-ui/core/Button";
import { createMuiTheme, makeStyles } from "@material-ui/core/styles";
import { ThemeProvider } from "@material-ui/styles";
import { red, grey } from "@material-ui/core/colors";
import Paper from "@material-ui/core/Paper";
import "../App.css";
import { Route, Redirect } from "react-router-dom";

var tokenUi = require("./../token-ui.js");
var fetchUi = require("./../fetch-ui.js");

const theme = createMuiTheme({
  palette: {
    primary: { main: red[900] },
    secondary: { main: grey[900] }
  }
});

const useStyles = makeStyles(theme => ({
  margin: {
    margin: theme.spacing(1)
  },
  textField: {
    flexBasis: 200
  }
}));

const AuthCentralState = {
  isAuthenticated: false,
  jwt: "",
  async authenticate(user, pass, callback) {
    let loginInfo = { password: pass, username: user };
    try {
      var response = await fetchUi.post(
        "/adas/user/checkuser",
        JSON.stringify(loginInfo),
        false
      );
      this.jwt = await response.json();

      if (this.jwt.tokenId) {
        this.isAuthenticated = true;
        tokenUi.updateToken(this.jwt.tokenId);
      }
    } catch (error) {
      alert(`Error occurred: ${error.message}`);
    }

    setTimeout(callback, 300);
  }
};

export class Login extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      username: "",
      password: "",
      redirectToReferrer: false,
      showPassword: false
    };
    this.login = this.login.bind(this);
  }

  onChange = prop => event => {
    this.setState({ [prop]: event.target.value });
  };

  login = event => {
    event.preventDefault();

    var username = this.state.username;
    var password = this.state.password;

    AuthCentralState.authenticate(username, password, () => {
      this.setState({
        redirectToReferrer: true
      });
    }); 
  };

  handleClickShowPassword = () => {
    this.setState({ ...this.state, showPassword: !this.state.showPassword });
  };

  render() {
    const { from } = this.props.location.state || { from: { pathname: "/" } };
    const { redirectToReferrer } = this.state;
    if (redirectToReferrer === true) {
      this.props.history.push(from.pathname);
    }
    return (
      <div>
        <Paper elevation={2} className={useStyles.root} id="container">
          <ThemeProvider theme={theme}>
            <form onSubmit={this.login}>
              <TextField
                autoFocus
                id="outlined-multiline-flexible"
                label="Username"
                fullWidth
                onChange={this.onChange("username")}
                className={clsx(useStyles.margin, useStyles.textField)}
                margin="normal"
                variant="outlined"
              />
              <br />
              <TextField
                id="outlined-adornment-password"
                fullWidth
                onChange={this.onChange("password")}
                className={clsx(useStyles.margin, useStyles.textField)}
                variant="outlined"
                type={this.state.showPassword ? "text" : "password"}
                label="Password"
                // InputProps={{
                //   endAdornment: (
                //     <InputAdornment position="end">
                //       <IconButton
                //         edge="end"
                //         aria-label="Toggle password visibility"
                //         onClick={this.handleClickShowPassword}
                //       >
                //         {this.state.showPassword ? (
                //           <VisibilityOff />
                //         ) : (
                //           <Visibility />
                //         )}
                //       </IconButton>
                //     </InputAdornment>
                //   )
                // }}
              />
              <br />
              <Button type="submit">Log in</Button>
            </form>
          </ThemeProvider>
        </Paper>
      </div>
    );
  }
}
export default Login;

export const ProtectedRoute = ({ component: Component, ...rest }) => (
  <Route
    {...rest}
    render={props =>
      tokenUi.getToken() ? (
        <Component {...props} />
      ) : (
        <Redirect
          to={{ pathname: "/login", state: { from: props.location } }}
        />
      )
    }
  />
);

1 Ответ

0 голосов
/ 24 октября 2019

Вам необходимо предоставить контекст react-router, чтобы иметь доступ к props.location. Согласно документации react-router, вы можете достичь этого, используя компонент MemoryRouter.

Из примера doc :

// app.test.js
test("clicking filter links updates product query params", () => {
  let history, location;
  render(
    <MemoryRouter initialEntries={["/my/initial/route"]}>
      <App />
      <Route
        path="*"
        render={({ history, location }) => {
          history = history;
          location = location;
          return null;
        }}
      />
    </MemoryRouter>,
    node
  );

  act(() => {
    // example: click a <Link> to /products?id=1234
  });

  // assert about url
  expect(location.pathname).toBe("/products");
  const searchParams = new URLSearchParams(location.search);
  expect(searchParams.has("id")).toBe(true);
  expect(searchParams.get("id")).toEqual("1234");
});


Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...