使用jest和酶的React测试案例。

问题描述 投票:0回答:1
import React from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'

import { pluck } from 'wf-dbd-react-ui/es/lib'
import Form from 'wf-dbd-react-ui/es/Form'
import FormInputHidden from 'wf-dbd-react-ui/es/FormInputHidden'
import { changeField } from 'wf-dbd-react-ui/es/actions'

import AccountDisclosures from '../../../../../common/disclosures/account-disclosures/AccountDisclosures'
import EditPaymentPayeeName from './fields/EditPaymentPayeeName'
import EditPaymentAccount from './fields/EditPaymentAccount'
import EditPaymentSingleAccount from './fields/EditPaymentSingleAccount'
import EditPaymentAccountSelect from './fields/EditPaymentAccountSelect'
import AmountInput from './fields/AmountInput'
import EditPaymentSendOnDate from './fields/EditPaymentSendOnDate'
import Memo from '../../../../../common/payment-card/fields/Memo'
import EditPaymentFormButtons from './fields/EditPaymentFormButtons'
import MessageDisplay from '../../../../../common/message-display/MessageDisplay'
import TermsAndConditionsLink from '../../../../../common/terms-and-conditions-link/TermsAndConditionsLink'
import TermsAndConditionsModal from '../../../../../common/terms-and-conditions-modal/TermsAndConditionsModal'
import { getInitiallySelectedAccountId } from '../../../../../../lib/selectors/selectors'
import { addTermsAcceptedAccount } from '../../../../../../lib/store/terms-and-conditions/actions'

import styles from './EditPaymentForm.less'

class EditPaymentForm extends React.Component {

  constructor(props) {
    super(props)
    const selectedAccount = props.accounts.find(account => account.get('selected')) || props.accounts.first()
    this.state = {
      disclosureIndicators: this.getInitialDisclosureIndicator(selectedAccount),
      termsAndConditionsType: selectedAccount.get('termsType'),
      showTermsAndConditions: false,
      currentAccount: {},
      termsAcceptedOnScreenForAccounts: [],
      termsAcceptedOnScreenForSelectedAccount: false,
      termsRequired: selectedAccount.get('termsRequired')
    }
  }

  getInitialDisclosureIndicator = selectedAccount => selectedAccount.get('disclosureIndicator') ? [selectedAccount.get('disclosureIndicator')] : []

  onAccountSelect = newAccount => {
    const { setCheckboxStatus } = this.props
    const { termsAcceptedOnScreenForAccounts, currentAccount, termsAcceptedOnScreenForSelectedAccount } = this.state

    const newTermsAcceptedOnScreenForSelectedAccount = termsAcceptedOnScreenForAccounts.indexOf(newAccount.id) >= 0
    // update the acceptance status and current account in component state
    if (newAccount.id !== currentAccount.id) {
      this.setState({
        termsAndConditionsType: newAccount.termsType || '',
        termsRequired: newAccount.termsRequired,
        termsAcceptedOnScreenForSelectedAccount: newTermsAcceptedOnScreenForSelectedAccount,
        currentAccount: newAccount
      },
      // update checkboxes once current account is updated in state
      () => {
        if (newTermsAcceptedOnScreenForSelectedAccount !== termsAcceptedOnScreenForSelectedAccount) {
          setCheckboxStatus('termsAccepted', newTermsAcceptedOnScreenForSelectedAccount)
        }
        setCheckboxStatus('defaultAccount', false)
      }
      )
    }
  }

  onToggleTermsAcceptanceOnScreen = termsAccepted => {
    const { termsAcceptedOnScreenForAccounts, currentAccount, termsAcceptedOnScreenForSelectedAccount } = this.state

    if (termsAccepted !== termsAcceptedOnScreenForSelectedAccount) {
      const newTermsAcceptedOnScreenForAccounts = this.persistTermsAndConditionsAcceptanceStatus(currentAccount.id, termsAccepted, termsAcceptedOnScreenForAccounts)
      this.setState({ termsAcceptedOnScreenForSelectedAccount: termsAccepted, termsAcceptedOnScreenForAccounts: newTermsAcceptedOnScreenForAccounts })
    }
  }

  isTermsAndConditionsAcceptedForAccount = (accountId, termsAcceptedOnScreenForAccounts) => (
    termsAcceptedOnScreenForAccounts.indexOf(accountId) >= 0
  )

  persistTermsAndConditionsAcceptanceStatus = (accountId, accepted, termsAcceptedOnScreenForAccounts) => {
    if (this.isTermsAndConditionsAcceptedForAccount(accountId, termsAcceptedOnScreenForAccounts) && !accepted) {
      return termsAcceptedOnScreenForAccounts.filter(id => id !== accountId)
    } else if (!this.isTermsAndConditionsAcceptedForAccount(accountId, termsAcceptedOnScreenForAccounts) && accepted) {
      return termsAcceptedOnScreenForAccounts.concat(accountId)
    } else {
      return termsAcceptedOnScreenForAccounts
    }
  }

  setDisclosureIndicators = selectedDisclosureType => {
    const { disclosureIndicators } = this.state
    const [disclosureType] = disclosureIndicators
    if (disclosureType !== selectedDisclosureType) {
      if (selectedDisclosureType) {
        this.setState({ disclosureIndicators: [selectedDisclosureType] })
      } else {
        this.setState({ disclosureIndicators: [] })
      }
    }
  }

  toggleTermsAndConditions = () => {
    const { showTermsAndConditions } = this.state
    this.setState({ showTermsAndConditions: !showTermsAndConditions })
  }

  transformData = ({ payload }) => {
    let updatedPayload = payload
    if (!payload.termsAccepted) {
      updatedPayload = pluck(['termsAccepted'], updatedPayload)
    }
    if (!payload.defaultAccount) {
      updatedPayload = pluck(['defaultAccount'], updatedPayload)
    }
    return updatedPayload
  }

  render() {
    const { paymentDetails, accounts, editPaymentPayee, failureMessage, cancelSuccessMessage, termsAcceptedAccounts,
      addTermsAcceptedAccount, onTermsAndConditionsDecline, initialSelectedAccountId, potentialDuplicatePayment } = this.props
    const { currentAccount, disclosureIndicators, showTermsAndConditions, termsAndConditionsType, termsRequired, termsAcceptedOnScreenForSelectedAccount } = this.state
    const displaySaveAccount = accounts.size > 1 && currentAccount && (initialSelectedAccountId !== currentAccount.id)
    const selectedAccount = accounts.find(account => account.get('selected'))
    return (
      <Form formId="editPaymentForm" action="/billpay/pendingpayment/save" transform={this.transformData}>
        <div className={styles.editPaymentFormFields}>
          {failureMessage && <MessageDisplay messages={failureMessage} focusOnMount={true} />}
          {cancelSuccessMessage && <MessageDisplay messages={cancelSuccessMessage} />}
          <EditPaymentPayeeName nickName={paymentDetails.get('nickName')} paymentType={paymentDetails.get('paymentType')} />
          <EditPaymentAccount displaySaveAccount={displaySaveAccount}>
            {(accounts && selectedAccount && accounts.size === 1) ?
              <EditPaymentSingleAccount account={accounts.first()} /> :
              <EditPaymentAccountSelect
                accountsList={accounts}
                termsAcceptedAccounts={termsAcceptedAccounts}
                setDisclosureIndicators={this.setDisclosureIndicators}
                addTermsAcceptedAccount={addTermsAcceptedAccount}
                setTermsAndConditionsLink={this.onAccountSelect}
                onTermsAndConditionsDecline={onTermsAndConditionsDecline}
              />
            }
          </EditPaymentAccount>
          <AmountInput amount={paymentDetails.get('amount')} />
          <EditPaymentSendOnDate payee={editPaymentPayee} sendOnDate={paymentDetails.get('sendOnDate')} />
          <Memo fieldId="memo" defaultMemo={paymentDetails.get('memo')} />
          <FormInputHidden fieldId="F" initialValue="J" />
          <FormInputHidden fieldId="id" initialValue={paymentDetails.get('id')} />
          <FormInputHidden fieldId="payeeId" initialValue={paymentDetails.get('payeeId')} />
          <FormInputHidden fieldId="termsRequired" initialValue="Y" />
          <FormInputHidden fieldId="skipPotentialDuplicateCheck" initialValue={potentialDuplicatePayment ? true : ''} />
        </div>
        <TermsAndConditionsLink
          termsAccepted={termsAcceptedOnScreenForSelectedAccount}
          termsAndConditionsType={termsAndConditionsType}
          termsRequired={termsRequired}
          onTermsAndConditionsLinkClick={this.toggleTermsAndConditions}
          onToggleTermsAcceptanceOnScreen={this.onToggleTermsAcceptanceOnScreen}
        />
        <div>
          <EditPaymentFormButtons paymentDetails={paymentDetails} />
        </div>
        {disclosureIndicators.length > 0 && (
          <div className={styles.disclosuresContainer}>
            <AccountDisclosures disclosureIndicators={disclosureIndicators} />
          </div>
        )
        }
        <TermsAndConditionsModal
          isOpen={showTermsAndConditions}
          termType={termsAndConditionsType}
          withActionButtons={false}
          onClose={this.toggleTermsAndConditions}
        />
      </Form>
    )
  }
}

EditPaymentForm.propTypes = {
  paymentDetails: PropTypes.object,
  accounts: PropTypes.object,
  editPaymentPayee: PropTypes.object,
  failureMessage: PropTypes.object,
  payees: PropTypes.object,
  cancelSuccessMessage: PropTypes.object,
  termsAcceptedAccounts: PropTypes.object,
  addTermsAcceptedAccount: PropTypes.func,
  onTermsAndConditionsDecline: PropTypes.func,
  setCheckboxStatus: PropTypes.func,
  initialSelectedAccountId: PropTypes.string
}

const mapStateToProps = state => ({
  paymentDetails: state.app.editPayment.enterDetails.paymentDetails,
  accounts: state.app.editPayment.enterDetails.accounts,
  initialSelectedAccountId: getInitiallySelectedAccountId(state),
  editPaymentPayee: state.app.editPayment.enterDetails.payee,
  failureMessage: state.app.editPayment.enterDetails.failureMessage,
  cancelSuccessMessage: state.app.hub.successMessage,
  payees: state.app.payees.payees,
  termsAcceptedAccounts: state.app.termsAndConditions.termsAcceptedAccounts,
  potentialDuplicatePayment: state.app.editPayment.enterDetails.potentialDuplicatePayment,
})

const mapDispatchToProps = dispatch => ({
  addTermsAcceptedAccount: accountId => dispatch(addTermsAcceptedAccount(accountId)),
  onTermsAndConditionsDecline: accountId => { dispatch(changeField({ formId: 'editPaymentForm', fieldId: 'paymentAccountId', value: accountId })) },
  setCheckboxStatus: (fieldId, status) => { dispatch(changeField({ formId: 'editPaymentForm', fieldId: fieldId, value: status })) }
})

export default connect(mapStateToProps, mapDispatchToProps)(EditPaymentForm)

这就是测试案例,这是测试案例。

import React from 'react'
import PropTypes from 'prop-types'

import FormField from 'wf-dbd-react-ui/es/FormField'
import FormFieldLabel from 'wf-dbd-react-ui/es/FormFieldLabel'
import FormFieldErrors from 'wf-dbd-react-ui/es/FormFieldErrors'
import Translatable from 'wf-dbd-react-ui/es/Translatable'
import Block from 'wf-dbd-react-ui/es/Block'
import withStrings from 'wf-dbd-react-ui/es/withStrings'

import { getMemoLabel } from '../../../../lib/utils/manage-payee-util'
import FormInput from '../../with-dirty-check/FormInput'

import styles from './Memo.less'

const Memo = ({ fieldId, defaultMemo, memo, isConfirm, getString }) => {
  const memoLabel = getMemoLabel()
  return !isConfirm ? (
    <Block className={styles.memo}>
      <FormField fieldId={fieldId}>
        <FormFieldLabel>
          <strong>
            <Translatable id={memoLabel} />
          </strong>
        </FormFieldLabel>
        <FormInput
          className={styles.input}
          initialValue={defaultMemo}
          type="text"
          maxLength="32"
          placeholder={getString('memoPlaceholder')}
          deleteOnUnmount={true}
        />
        <FormFieldErrors />
      </FormField>
    </Block>
  ) : (
    <React.Fragment>
      <Translatable id={memoLabel} />
      <Block>
        <strong>{memo}</strong>
      </Block>
    </React.Fragment>
  )
}

Memo.defaultProps = {
  isConfirm: false
}

Memo.propTypes = {
  fieldId: PropTypes.string,
  defaultMemo: PropTypes.string,
  isConfirm: PropTypes.bool,
  memo: PropTypes.string
}

export default withStrings(Memo)
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

/*
Copyright (c) 2017 Wells Fargo. 455 Market St., San Francisco, CA 94105 All rights reserved.

This software is the confidential and proprietary information of Wells Fargo
bank. ('Confidential Information'). You shall not disclose such Confidential
Information and shall use it only in accordance with the terms of the license
agreement you entered into with WellsFargo.

Author: Thomas Barry

Description:
*/
import React from 'react';
import PropTypes from 'prop-types';
import Input from '../../input/Input';
import FieldContainer from '../field-container/FieldContainer';
import WithFieldLabels from '../field-container/WithFieldLabels';
import WithFieldMessages from '../field-container/WithFieldMessages';
import { toggleZoom } from '../../../lib/fields/zoom';
import { pluck } from '../../../lib/prop-utils/prop-utils';

class FormInput extends React.Component {
  constructor(...args) {
    super(...args);

    _defineProperty(this, "getInputHandlers", () => ({
      onBlur: () => {
        const {
          fieldId,
          formId,
          dirty,
          errorMessage,
          blurField
        } = this.props;
        toggleZoom(true);
        blurField({
          fieldId,
          formId,
          siblingFieldIds: [],
          dirty,
          errorMessage
        });
      },
      onFocus: () => {
        const {
          fieldId,
          formId,
          focusField
        } = this.props;
        toggleZoom(false);
        focusField({
          fieldId,
          formId
        });
      },
      onInput: value => {
        const {
          props: {
            fieldId,
            formId,
            changeField,
            onChangeCallback,
            onChange
          }
        } = this;
        changeField({
          fieldId,
          formId,
          value,
          onChangeCallback,
          onChange
        });
      },
      onClear: () => {
        const {
          props: {
            fieldId,
            formId,
            changeField,
            onChangeCallback,
            onChange,
            clearedValue
          }
        } = this;
        changeField({
          fieldId,
          formId,
          value: clearedValue,
          onChangeCallback,
          onChange
        });
      },

      onTouchEnd() {
        toggleZoom(false);
      }

    }));
  }

  render() {
    const {
      el,
      id,
      name,
      value,
      type,
      labelId,
      fieldMessageIds,
      placeholder,
      required,
      maxLength,
      minLength,
      disabled,
      showError,
      className,
      clearable,
      clearLabel,
      onClear,
      clearedValue,
      fieldId,
      ...restProps
    } = this.props; // Don't pass onChange prop to Input to avoid duplicate calls

    const inputProps = pluck(['onChange'], restProps);
    const InputElement = el;
    return React.createElement(InputElement, _extends({
      id: id || fieldId,
      name: name,
      value: value,
      type: type,
      placeholder: placeholder,
      maxLength: maxLength,
      minLength: minLength,
      disabled: disabled,
      required: required,
      invalid: showError,
      inputRef: element => this.inputRef = element,
      labelId: labelId,
      fieldMessageIds: fieldMessageIds,
      className: className,
      clearable: clearable,
      clearedValue: clearedValue,
      clearLabel: clearLabel,
      onClear: onClear
    }, inputProps, this.getInputHandlers()));
  }

}

FormInput.defaultProps = {
  dataType: 'ALL',
  value: '',
  clearedValue: '',
  el: Input,
  type: 'text'
};
FormInput.propTypes = {
  fieldId: PropTypes.string.isRequired,
  name: PropTypes.string,
  type: PropTypes.string,
  value: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
  dataType: PropTypes.string,
  required: PropTypes.bool,
  clearedValue: PropTypes.string,
  clearLabel: PropTypes.string,
  el: PropTypes.oneOfType([PropTypes.func, PropTypes.object])
};
export default FieldContainer(WithFieldLabels(WithFieldMessages(FormInput)));
reactjs react-redux jestjs enzyme react-testing-library
1个回答
1
投票

maxLength是FormInput的一个道具,所以你应该可以做这样的事情。

expect(wrapper.find(FormInput).props().maxLength).toEqual(32);

© www.soinside.com 2019 - 2024. All rights reserved.