Нарушение инварианта при использовании библиотеки внешних компонентов - PullRequest
0 голосов
/ 03 мая 2018

Я работаю над внесением изменений в реагирующий компонент, написанный на машинописи. Изменение, которое я делаю в кодовой базе, включает в себя удаление компонента, которым мы владеем, для внешней библиотеки act-dual-listbox .

Как только я импортирую зависимость, все мои существующие тесты начали давать сбой, и я не совсем уверен, почему. Я получаю ошибку

Error: Uncaught [Invariant Violation: Element type is invalid: expected a string 
(for built-in components) or a class/function (for composite components) but got: 
undefined. You likely forgot to export your component from the file it's defined in, 
or you might have mixed up default and named imports.

Check the render method of `default_1`.

Вот мой тестовый файл:

import { shallow, configure, mount } from 'enzyme';
import * as React from 'react';
import PolicyEditor, { PolicyEditorProps } from '../PolicyEditor';
import * as Adapter from 'enzyme-adapter-react-16';

configure({ adapter: new Adapter() });

const defaultProps: PolicyEditorProps = {
  id: 'id',
  serviceId: 'service id',
  data: { data: { policy: { id: '1', name: 'policy', permissions: [] } } },
  permissionsData: { data: { service: { id: '1', permissions: [] } } },
  create: jest.fn(),
  update: jest.fn(),
  updatePermissions: jest.fn(),
  delete: jest.fn(),
  back: jest.fn(),
};

describe('PolicyEditor.tsx', () => {
  it('sets the state when the name is changed', done => {
    const wrapper = mount(<PolicyEditor {...defaultProps} />);
    const input = wrapper.find('input[id="policyName"]').first();

    const event = { target: { value: 'new policy name' } };

    input.simulate('change', event);

    process.nextTick(() => {
      expect(wrapper.state().name).toEqual('new policy name');
      done();
    });
  });
});

Компонент:

import 'react-dual-listbox/lib/react-dual-listbox.css';

import * as React from 'react';
import { MutationFn } from 'react-apollo';
import { isQueryReady, isQueryLoading } from '../util/actionHelpers';
import {
  Permission,
  PolicyWithPermissions,
  ServicePermissionsQueryResult,
  PolicyQueryResult,
} from './types';
import AuthModal from '../shared/AuthModal';
import { Container, Row, Col, Label, Button, Form, FormGroup, Input } from 'reactstrap';
import DualListBox from 'react-dual-listbox';

export interface PolicyEditorProps {
  id?: string;
  serviceId: string;
  data: PolicyQueryResult;
  permissionsData: ServicePermissionsQueryResult;
  create: MutationFn;
  update: MutationFn;
  updatePermissions: MutationFn;
  delete: MutationFn;
  back(): void;
}

interface PolicyEditorState {
  name: string;
  selectedPermissions: Permission[];
}

export default class extends React.Component<PolicyEditorProps, PolicyEditorState> {
  static getDerivedStateFromProps(
    nextProps: PolicyEditorProps,
    prevState: PolicyEditorState
  ): Partial<PolicyEditorState> | null {
    if (nextProps.id && isQueryReady(nextProps.data)) {
      const policy: PolicyWithPermissions = nextProps.data.data!.policy;

      return {
        name: policy.name,
        selectedPermissions: policy.permissions,
      };
    }

    if (!nextProps.id) {
      return {
        name: '',
      };
    }

    return null;
  }

  constructor(props: PolicyEditorProps) {
    super(props);
    this.state = {
      name: '',
      selectedPermissions: [],
    };
  }

  render() {
    const isEdit: boolean = !!this.props.id;
    if (isEdit) {
      if (isQueryLoading(this.props.data)) {
        return <div>Loading...</div>;
      }
      if (this.props.data.error !== undefined) {
        return <div>Something went wrong!</div>;
      }
    }

    const { loading, error } = this.props.permissionsData;
    return (
      <AuthModal title="Policy Editor" isOpen={true} toggle={this.props.back}>
        <Form>
          <FormGroup>
            <Label for="policyName">Name</Label>
            <Input
              id="policyName"
              onChange={e => this.setState({ name: e.target.value })}
              value={this.state.name}
            />
          </FormGroup>
          {isEdit ? (
            <div>
              <hr />
              {loading ? (
                <div>Loading...</div>
              ) : error ? (
                <div>Error</div>
              ) : (
                <Container className="m-2">
                  <Row>
                    <Col className="text-center" xs="6">
                      Available Permissions
                    </Col>
                    <Col className="text-center" xs="6">
                      Current Permissions
                    </Col>
                  </Row>
                  <DualListBox
                    canFilter={true}
                    options={this.props.permissionsData.data!.service.permissions.map(p => ({
                      value: p.id,
                      label: p.name,
                    }))}
                    selected={this.state.selectedPermissions.map(p => p.id)}
                    onChange={this.updateSelectedPermissions}
                  />
                </Container>
              )}
              <FormGroup>
                <Row>
                  <Col xs={{ size: 1 }}>
                    <Button onClick={this.onUpdate} color="success">
                      Update
                    </Button>
                  </Col>
                  <Col xs={{ size: 1, offset: 1 }}>
                    <Button onClick={this.onDelete} color="danger">
                      Delete
                    </Button>
                  </Col>
                </Row>
              </FormGroup>
            </div>
          ) : (
            <FormGroup>
              <Button color="success" onClick={this.onCreate}>
                Create
              </Button>
            </FormGroup>
          )}
        </Form>
      </AuthModal>
    );
  }
}

Сообщение об ошибке кажется загадочным. Он говорит мне, что ожидал, что что-то будет строкой, но не определено. Я не совсем уверен, что именно не определено. Тем не менее, я могу пройти тесты, если просто не отображаю DualListBox, но это не поможет моей проблеме.

Странно то, что он работает в браузере без ошибок, и проблема только в моих тестах. Очевидно, что у людей, которые имеют такое же сообщение об ошибке, возникает проблема с импортом, но если это работает в браузере, он должен импортироваться правильно, нет?

Я что-то упускаю или не понимаю здесь?

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