Refactor Generate Transaction (#960)

* Make generic modal

* Allow generic modals to be injected into send button component

* Refactor generate transaction, cleanup transaction sagas, simplify signing process

* Get passing unit tests

* Make previous test more comprehensive

* Fix ts errors
This commit is contained in:
Daniel Ternyak 2018-01-29 16:58:07 -06:00 committed by GitHub
parent f748f22e2e
commit 84bae60c02
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 160 additions and 177 deletions

View File

@ -1,9 +1,8 @@
import { import {
SignTransactionFailedAction, SignTransactionFailedAction,
SignLocalTransactionRequestedAction,
SignWeb3TransactionRequestedAction,
SignLocalTransactionSucceededAction, SignLocalTransactionSucceededAction,
SignWeb3TransactionSucceededAction SignWeb3TransactionSucceededAction,
SignTransactionRequestedAction
} from '../actionTypes'; } from '../actionTypes';
import { TypeKeys } from '../constants'; import { TypeKeys } from '../constants';
@ -12,6 +11,12 @@ const signTransactionFailed = (): SignTransactionFailedAction => ({
type: TypeKeys.SIGN_TRANSACTION_FAILED type: TypeKeys.SIGN_TRANSACTION_FAILED
}); });
type TSignTransactionRequested = typeof signTransactionRequested;
const signTransactionRequested = (payload: SignTransactionRequestedAction['payload']) => ({
type: TypeKeys.SIGN_TRANSACTION_REQUESTED,
payload
});
type TSignLocalTransactionSucceeded = typeof signLocalTransactionSucceeded; type TSignLocalTransactionSucceeded = typeof signLocalTransactionSucceeded;
const signLocalTransactionSucceeded = ( const signLocalTransactionSucceeded = (
payload: SignLocalTransactionSucceededAction['payload'] payload: SignLocalTransactionSucceededAction['payload']
@ -20,14 +25,6 @@ const signLocalTransactionSucceeded = (
payload payload
}); });
type TSignLocalTransactionRequested = typeof signLocalTransactionRequested;
const signLocalTransactionRequested = (
payload: SignLocalTransactionRequestedAction['payload']
): SignLocalTransactionRequestedAction => ({
type: TypeKeys.SIGN_LOCAL_TRANSACTION_REQUESTED,
payload
});
type TSignWeb3TransactionSucceeded = typeof signWeb3TransactionSucceeded; type TSignWeb3TransactionSucceeded = typeof signWeb3TransactionSucceeded;
const signWeb3TransactionSucceeded = ( const signWeb3TransactionSucceeded = (
payload: SignWeb3TransactionSucceededAction['payload'] payload: SignWeb3TransactionSucceededAction['payload']
@ -36,23 +33,13 @@ const signWeb3TransactionSucceeded = (
payload payload
}); });
type TSignWeb3TransactionRequested = typeof signWeb3TransactionRequested;
const signWeb3TransactionRequested = (
payload: SignWeb3TransactionRequestedAction['payload']
): SignWeb3TransactionRequestedAction => ({
type: TypeKeys.SIGN_WEB3_TRANSACTION_REQUESTED,
payload
});
export { export {
signTransactionRequested,
signTransactionFailed, signTransactionFailed,
signLocalTransactionSucceeded, signLocalTransactionSucceeded,
signLocalTransactionRequested,
signWeb3TransactionSucceeded, signWeb3TransactionSucceeded,
signWeb3TransactionRequested,
TSignLocalTransactionSucceeded, TSignLocalTransactionSucceeded,
TSignLocalTransactionRequested,
TSignWeb3TransactionSucceeded, TSignWeb3TransactionSucceeded,
TSignWeb3TransactionRequested, TSignTransactionFailed,
TSignTransactionFailed TSignTransactionRequested
}; };

View File

@ -8,8 +8,8 @@ import { TypeKeys } from 'actions/transaction/constants';
*/ */
/* Signing / Async actions */ /* Signing / Async actions */
interface SignLocalTransactionRequestedAction { interface SignTransactionRequestedAction {
type: TypeKeys.SIGN_LOCAL_TRANSACTION_REQUESTED; type: TypeKeys.SIGN_TRANSACTION_REQUESTED;
payload: EthTx; payload: EthTx;
} }
interface SignLocalTransactionSucceededAction { interface SignLocalTransactionSucceededAction {
@ -17,10 +17,6 @@ interface SignLocalTransactionSucceededAction {
payload: { signedTransaction: Buffer; indexingHash: string; noVerify?: boolean }; // dont verify against fields, for pushTx payload: { signedTransaction: Buffer; indexingHash: string; noVerify?: boolean }; // dont verify against fields, for pushTx
} }
interface SignWeb3TransactionRequestedAction {
type: TypeKeys.SIGN_WEB3_TRANSACTION_REQUESTED;
payload: EthTx;
}
interface SignWeb3TransactionSucceededAction { interface SignWeb3TransactionSucceededAction {
type: TypeKeys.SIGN_WEB3_TRANSACTION_SUCCEEDED; type: TypeKeys.SIGN_WEB3_TRANSACTION_SUCCEEDED;
payload: { transaction: Buffer; indexingHash: string; noVerify?: boolean }; payload: { transaction: Buffer; indexingHash: string; noVerify?: boolean };
@ -30,16 +26,14 @@ interface SignTransactionFailedAction {
} }
type SignAction = type SignAction =
| SignLocalTransactionRequestedAction | SignTransactionRequestedAction
| SignLocalTransactionSucceededAction | SignLocalTransactionSucceededAction
| SignWeb3TransactionRequestedAction
| SignWeb3TransactionSucceededAction | SignWeb3TransactionSucceededAction
| SignTransactionFailedAction; | SignTransactionFailedAction;
export { export {
SignLocalTransactionRequestedAction, SignTransactionRequestedAction,
SignLocalTransactionSucceededAction, SignLocalTransactionSucceededAction,
SignWeb3TransactionRequestedAction,
SignWeb3TransactionSucceededAction, SignWeb3TransactionSucceededAction,
SignTransactionFailedAction, SignTransactionFailedAction,
SignAction SignAction

View File

@ -12,9 +12,8 @@ export enum TypeKeys {
GET_NONCE_SUCCEEDED = 'GET_NONCE_SUCCEEDED', GET_NONCE_SUCCEEDED = 'GET_NONCE_SUCCEEDED',
GET_NONCE_FAILED = 'GET_NONCE_FAILED', GET_NONCE_FAILED = 'GET_NONCE_FAILED',
SIGN_WEB3_TRANSACTION_REQUESTED = 'SIGN_WEB3_TRANSACTION_REQUESTED', SIGN_TRANSACTION_REQUESTED = 'SIGN_TRANSACTION_REQUESTED',
SIGN_WEB3_TRANSACTION_SUCCEEDED = 'SIGN_WEB3_TRANSACTION_SUCCEEDED', SIGN_WEB3_TRANSACTION_SUCCEEDED = 'SIGN_WEB3_TRANSACTION_SUCCEEDED',
SIGN_LOCAL_TRANSACTION_REQUESTED = 'SIGN_LOCAL_TRANSACTION_REQUESTED',
SIGN_LOCAL_TRANSACTION_SUCCEEDED = 'SIGN_LOCAL_TRANSACTION_SUCCEEDED', SIGN_LOCAL_TRANSACTION_SUCCEEDED = 'SIGN_LOCAL_TRANSACTION_SUCCEEDED',
SIGN_TRANSACTION_FAILED = 'SIGN_TRANSACTION_FAILED', SIGN_TRANSACTION_FAILED = 'SIGN_TRANSACTION_FAILED',

View File

@ -0,0 +1,13 @@
import { GenerateTransactionFactory } from './GenerateTransactionFactory';
import React from 'react';
import translate from 'translations';
export const GenerateTransaction: React.SFC<{}> = () => (
<GenerateTransactionFactory
withProps={({ disabled, isWeb3Wallet, onClick }) => (
<button disabled={disabled} className="btn btn-info btn-block" onClick={onClick}>
{isWeb3Wallet ? translate('Send to MetaMask / Mist') : translate('DEP_signtx')}
</button>
)}
/>
);

View File

@ -1,43 +0,0 @@
import {
signLocalTransactionRequested,
signWeb3TransactionRequested,
TSignLocalTransactionRequested,
TSignWeb3TransactionRequested,
SignLocalTransactionRequestedAction,
SignWeb3TransactionRequestedAction
} from 'actions/transaction';
import React, { Component } from 'react';
import { connect, Dispatch } from 'react-redux';
import { bindActionCreators } from 'redux';
import { AppState } from 'reducers';
type Payload =
| SignLocalTransactionRequestedAction['payload']
| SignWeb3TransactionRequestedAction['payload'];
type Signer = (
payload: Payload
) => () => SignLocalTransactionRequestedAction | SignWeb3TransactionRequestedAction;
interface DispatchProps {
signer: TSignLocalTransactionRequested | TSignWeb3TransactionRequested;
}
interface Props {
isWeb3: boolean;
withSigner(signer: Signer): React.ReactElement<any> | null;
}
class Container extends Component<DispatchProps & Props, {}> {
public render() {
return this.props.withSigner(this.sign);
}
private sign = (payload: Payload) => () => this.props.signer(payload);
}
export const WithSigner = connect(null, (dispatch: Dispatch<AppState>, ownProps: Props) => {
return bindActionCreators(
{
signer: ownProps.isWeb3 ? signWeb3TransactionRequested : signLocalTransactionRequested
},
dispatch
);
})(Container);

View File

@ -1 +0,0 @@
export * from './GenerateTransaction';

View File

@ -0,0 +1,20 @@
import { signTransactionRequested, TSignTransactionRequested } from 'actions/transaction';
import React, { Component } from 'react';
import { connect } from 'react-redux';
interface DispatchProps {
signTransactionRequested: TSignTransactionRequested;
}
interface OwnProps {
isWeb3: boolean;
withSigner(signer: TSignTransactionRequested): React.ReactElement<any> | null;
}
class Container extends Component<DispatchProps & OwnProps, {}> {
public render() {
return this.props.withSigner(this.props.signTransactionRequested);
}
}
export const WithSigner = connect(null, { signTransactionRequested })(Container);

View File

@ -1,4 +1,3 @@
import translate from 'translations';
import { WithSigner } from './Container'; import { WithSigner } from './Container';
import EthTx from 'ethereumjs-tx'; import EthTx from 'ethereumjs-tx';
import React, { Component } from 'react'; import React, { Component } from 'react';
@ -12,6 +11,12 @@ import {
} from 'selectors/transaction'; } from 'selectors/transaction';
import { getWalletType } from 'selectors/wallet'; import { getWalletType } from 'selectors/wallet';
export interface CallbackProps {
disabled: boolean;
isWeb3Wallet: boolean;
onClick(): void;
}
interface StateProps { interface StateProps {
transaction: EthTx; transaction: EthTx;
networkRequestPending: boolean; networkRequestPending: boolean;
@ -21,16 +26,21 @@ interface StateProps {
validGasLimit: boolean; validGasLimit: boolean;
} }
class GenerateTransactionClass extends Component<StateProps> { interface OwnProps {
withProps(props: CallbackProps): React.ReactElement<any> | null;
}
type Props = OwnProps & StateProps;
class GenerateTransactionFactoryClass extends Component<Props> {
public render() { public render() {
const { const {
isFullTransaction, isFullTransaction,
isWeb3Wallet, isWeb3Wallet,
transaction,
networkRequestPending, networkRequestPending,
validGasPrice, validGasPrice,
validGasLimit validGasLimit,
transaction
} = this.props; } = this.props;
const isButtonDisabled = const isButtonDisabled =
@ -38,24 +48,22 @@ class GenerateTransactionClass extends Component<StateProps> {
return ( return (
<WithSigner <WithSigner
isWeb3={isWeb3Wallet} isWeb3={isWeb3Wallet}
withSigner={signer => ( withSigner={signer =>
<button this.props.withProps({
disabled={isButtonDisabled} disabled: isButtonDisabled,
className="btn btn-info btn-block" isWeb3Wallet,
onClick={signer(transaction)} onClick: () => signer(transaction)
> })
{isWeb3Wallet ? translate('Send to MetaMask / Mist') : translate('DEP_signtx')} }
</button>
)}
/> />
); );
} }
} }
export const GenerateTransaction = connect((state: AppState) => ({ export const GenerateTransactionFactory = connect((state: AppState) => ({
...getTransaction(state), ...getTransaction(state),
networkRequestPending: isNetworkRequestPending(state), networkRequestPending: isNetworkRequestPending(state),
isWeb3Wallet: getWalletType(state).isWeb3Wallet, isWeb3Wallet: getWalletType(state).isWeb3Wallet,
validGasPrice: isValidGasPrice(state), validGasPrice: isValidGasPrice(state),
validGasLimit: isValidGasLimit(state) validGasLimit: isValidGasLimit(state)
}))(GenerateTransactionClass); }))(GenerateTransactionFactoryClass);

View File

@ -0,0 +1 @@
export * from './GenerateTransactionFactory';

View File

@ -14,7 +14,7 @@ const INITIAL_STATE: State = {
pending: false pending: false
}; };
const signLocalTransactionRequested = (): State => ({ const signTransactionRequested = (): State => ({
...INITIAL_STATE, ...INITIAL_STATE,
pending: true pending: true
}); });
@ -30,7 +30,7 @@ const signLocalTransactionSucceeded = (
web3: { transaction: null } web3: { transaction: null }
}); });
const signWeb3TranscationRequested = ( const signWeb3TranscationSucceeded = (
_: State, _: State,
{ payload }: SignWeb3TransactionSucceededAction { payload }: SignWeb3TransactionSucceededAction
): State => ({ ): State => ({
@ -47,12 +47,12 @@ const reset = () => INITIAL_STATE;
export const sign = (state: State = INITIAL_STATE, action: SignAction | ResetAction) => { export const sign = (state: State = INITIAL_STATE, action: SignAction | ResetAction) => {
switch (action.type) { switch (action.type) {
case TK.SIGN_LOCAL_TRANSACTION_REQUESTED: case TK.SIGN_TRANSACTION_REQUESTED:
return signLocalTransactionRequested(); return signTransactionRequested();
case TK.SIGN_LOCAL_TRANSACTION_SUCCEEDED: case TK.SIGN_LOCAL_TRANSACTION_SUCCEEDED:
return signLocalTransactionSucceeded(state, action); return signLocalTransactionSucceeded(state, action);
case TK.SIGN_WEB3_TRANSACTION_SUCCEEDED: case TK.SIGN_WEB3_TRANSACTION_SUCCEEDED:
return signWeb3TranscationRequested(state, action); return signWeb3TranscationSucceeded(state, action);
case TK.SIGN_TRANSACTION_FAILED: case TK.SIGN_TRANSACTION_FAILED:
return signTransactionFailed(); return signTransactionFailed();
case TK.RESET: case TK.RESET:

View File

@ -12,11 +12,16 @@ import { SetCurrentValueAction, TypeKeys } from 'actions/transaction';
import { toTokenBase } from 'libs/units'; import { toTokenBase } from 'libs/units';
import { validateInput, IInput } from 'sagas/transaction/validationHelpers'; import { validateInput, IInput } from 'sagas/transaction/validationHelpers';
import { validNumber, validDecimal } from 'libs/validators'; import { validNumber, validDecimal } from 'libs/validators';
export function* setCurrentValue({ payload }: SetCurrentValueAction): SagaIterator {
export function* setCurrentValue(action: SetCurrentValueAction): SagaIterator {
const etherTransaction = yield select(isEtherTransaction); const etherTransaction = yield select(isEtherTransaction);
const setter = etherTransaction ? setValueField : setTokenValue;
return yield call(valueHandler, action, setter);
}
export function* valueHandler({ payload }: SetCurrentValueAction, setter) {
const decimal: number = yield select(getDecimal); const decimal: number = yield select(getDecimal);
const unit: string = yield select(getUnit); const unit: string = yield select(getUnit);
const setter = etherTransaction ? setValueField : setTokenValue;
if (!validNumber(+payload) || !validDecimal(payload, decimal)) { if (!validNumber(+payload) || !validDecimal(payload, decimal)) {
return yield put(setter({ raw: payload, value: null })); return yield put(setter({ raw: payload, value: null }));
@ -51,6 +56,7 @@ export function* reparseCurrentValue(value: IInput): SagaIterator {
return null; return null;
} }
} }
export const currentValue = [ export const currentValue = [
takeEvery([TypeKeys.CURRENT_VALUE_SET], setCurrentValue), takeEvery([TypeKeys.CURRENT_VALUE_SET], setCurrentValue),
takeEvery([TypeKeys.GAS_LIMIT_FIELD_SET, TypeKeys.GAS_PRICE_FIELD_SET], revalidateCurrentValue) takeEvery([TypeKeys.GAS_LIMIT_FIELD_SET, TypeKeys.GAS_PRICE_FIELD_SET], revalidateCurrentValue)

View File

@ -4,12 +4,11 @@ import { getNetworkConfig } from 'selectors/config';
import { select, call, put, take } from 'redux-saga/effects'; import { select, call, put, take } from 'redux-saga/effects';
import { import {
signTransactionFailed, signTransactionFailed,
SignWeb3TransactionRequestedAction,
SignLocalTransactionRequestedAction,
GetFromFailedAction, GetFromFailedAction,
GetFromSucceededAction, GetFromSucceededAction,
getFromRequested, getFromRequested,
TypeKeys as TK TypeKeys as TK,
SignTransactionRequestedAction
} from 'actions/transaction'; } from 'actions/transaction';
import Tx from 'ethereumjs-tx'; import Tx from 'ethereumjs-tx';
import { NetworkConfig } from 'config'; import { NetworkConfig } from 'config';
@ -22,7 +21,7 @@ interface IFullWalletAndTransaction {
} }
const signTransactionWrapper = (func: (IWalletAndTx: IFullWalletAndTransaction) => SagaIterator) => const signTransactionWrapper = (func: (IWalletAndTx: IFullWalletAndTransaction) => SagaIterator) =>
function*(partialTx: SignLocalTransactionRequestedAction | SignWeb3TransactionRequestedAction) { function*(partialTx: SignTransactionRequestedAction) {
try { try {
const IWalletAndTx: IFullWalletAndTransaction = yield call( const IWalletAndTx: IFullWalletAndTransaction = yield call(
getWalletAndTransaction, getWalletAndTransaction,
@ -40,9 +39,7 @@ const signTransactionWrapper = (func: (IWalletAndTx: IFullWalletAndTransaction)
* the rest of the tx parameters from the action * the rest of the tx parameters from the action
* @param partialTx * @param partialTx
*/ */
function* getWalletAndTransaction( function* getWalletAndTransaction(partialTx: SignTransactionRequestedAction['payload']) {
partialTx: (SignLocalTransactionRequestedAction | SignWeb3TransactionRequestedAction)['payload']
) {
// get the wallet we're going to sign with // get the wallet we're going to sign with
const wallet: null | IFullWallet = yield select(getWalletInst); const wallet: null | IFullWallet = yield select(getWalletInst);
if (!wallet) { if (!wallet) {

View File

@ -7,11 +7,13 @@ import {
TypeKeys, TypeKeys,
reset, reset,
SignWeb3TransactionSucceededAction, SignWeb3TransactionSucceededAction,
SignLocalTransactionSucceededAction SignLocalTransactionSucceededAction,
SignTransactionRequestedAction
} from 'actions/transaction'; } from 'actions/transaction';
import { computeIndexingHash } from 'libs/transaction'; import { computeIndexingHash } from 'libs/transaction';
import { serializedAndTransactionFieldsMatch } from 'selectors/transaction'; import { serializedAndTransactionFieldsMatch } from 'selectors/transaction';
import { showNotification } from 'actions/notifications'; import { showNotification } from 'actions/notifications';
import { getWalletType, IWalletType } from 'selectors/wallet';
export function* signLocalTransactionHandler({ export function* signLocalTransactionHandler({
tx, tx,
@ -64,9 +66,15 @@ function* verifyTransaction({
yield put(reset()); yield put(reset());
} }
} }
function* handleTransactionRequest(action: SignTransactionRequestedAction): SagaIterator {
const walletType: IWalletType = yield select(getWalletType);
const signingHandler = walletType.isWeb3Wallet ? signWeb3Transaction : signLocalTransaction;
return yield call(signingHandler, action);
}
export const signing = [ export const signing = [
takeEvery(TypeKeys.SIGN_LOCAL_TRANSACTION_REQUESTED, signLocalTransaction), takeEvery(TypeKeys.SIGN_TRANSACTION_REQUESTED, handleTransactionRequest),
takeEvery(TypeKeys.SIGN_WEB3_TRANSACTION_REQUESTED, signWeb3Transaction),
takeEvery( takeEvery(
[TypeKeys.SIGN_LOCAL_TRANSACTION_SUCCEEDED, TypeKeys.SIGN_WEB3_TRANSACTION_SUCCEEDED], [TypeKeys.SIGN_LOCAL_TRANSACTION_SUCCEEDED, TypeKeys.SIGN_WEB3_TRANSACTION_SUCCEEDED],
verifyTransaction verifyTransaction

View File

@ -6,8 +6,10 @@ import { validateInput } from 'sagas/transaction/validationHelpers';
import { import {
setCurrentValue, setCurrentValue,
revalidateCurrentValue, revalidateCurrentValue,
reparseCurrentValue reparseCurrentValue,
valueHandler
} from 'sagas/transaction/current/currentValue'; } from 'sagas/transaction/current/currentValue';
import { cloneableGenerator, SagaIteratorClone } from 'redux-saga/utils';
const itShouldBeDone = gen => { const itShouldBeDone = gen => {
it('should be done', () => { it('should be done', () => {
@ -15,77 +17,69 @@ const itShouldBeDone = gen => {
}); });
}; };
describe('setCurrentValue*', () => { describe('valueHandler', () => {
const sharedLogic = (gen, etherTransaction, decimal: number) => { const action: any = { payload: '5.1' };
it('should select isEtherTransaction', () => { const setter = setValueField;
expect(gen.next().value).toEqual(select(isEtherTransaction)); const decimal = 1;
}); const gen: { [key: string]: SagaIteratorClone } = {};
it('should select getDecimal', () => { const failCases = {
expect(gen.next(etherTransaction).value).toEqual(select(getDecimal)); invalidDecimal: 0,
}); invalidNumber: {
it('should select getUnit', () => { decimal: 1,
expect(gen.next(decimal).value).toEqual(select(getUnit)); action: { payload: 'x' }
}); }
}; };
describe('when invalid number or decimal', () => { gen.pass = cloneableGenerator(valueHandler)(action, setter);
const invalidDecimal: any = { gen.invalidNumber = cloneableGenerator(valueHandler)(
payload: '10.01' failCases.invalidNumber.action as any,
}; setter
const invalidNumber: any = { );
payload: 'invalidNumber' const value = toTokenBase(action.payload, decimal);
}; const unit = 'eth';
const etherTransaction = true;
const decimal = 1;
const gen1 = setCurrentValue(invalidNumber);
const gen2 = setCurrentValue(invalidDecimal);
sharedLogic(gen2, etherTransaction, decimal); it('should select getDecimal', () => {
sharedLogic(gen1, etherTransaction, decimal); expect(gen.pass.next().value).toEqual(select(getDecimal));
expect(gen.invalidNumber.next().value).toEqual(select(getDecimal));
});
it('should select getUnit', () => {
gen.invalidDecimal = gen.pass.clone();
it('should put setter', () => { expect(gen.pass.next(decimal).value).toEqual(select(getUnit));
expect(gen1.next().value).toEqual( expect(gen.invalidNumber.next(decimal).value).toEqual(select(getUnit));
put(setValueField({ raw: invalidNumber.payload, value: null })) expect(gen.invalidDecimal.next(failCases.invalidDecimal).value).toEqual(select(getUnit));
);
expect(gen2.next().value).toEqual(
put(setValueField({ raw: invalidDecimal.payload, value: null }))
);
});
itShouldBeDone(gen1);
itShouldBeDone(gen2);
}); });
describe('when valid number and decimal', () => { it('should fail on invalid number or decimal and put null as a value', () => {
const payload = '100'; expect(gen.invalidNumber.next(unit).value).toEqual(
const action: any = { payload }; put(setter({ raw: failCases.invalidNumber.action.payload, value: null }))
const etherTransaction = true; );
const unit = 'ether'; expect(gen.invalidDecimal.next(unit).value).toEqual(
const decimal = 0; put(setter({ raw: action.payload, value: null }))
const value = toTokenBase(payload, decimal); );
const isValid = true;
const gen = setCurrentValue(action);
sharedLogic(gen, etherTransaction, decimal);
it('should call validateInput', () => {
expect(gen.next(unit).value).toEqual(call(validateInput, value, unit));
});
it('should put setter', () => {
expect(gen.next(isValid).value).toEqual(
put(
setValueField({
raw: payload,
value
})
)
);
});
itShouldBeDone(gen);
}); });
it('should call isValid', () => {
expect(gen.pass.next(unit).value).toEqual(call(validateInput, value, unit));
});
it('should put setter', () => {
expect(gen.pass.next(true).value).toEqual(put(setter({ raw: action.payload, value })));
});
itShouldBeDone(gen.pass);
});
describe('setCurrentValue*', () => {
const action: any = { payload: '5' };
const gen = setCurrentValue(action);
it('should select isEtherTransaction', () => {
expect(gen.next().value).toEqual(select(isEtherTransaction));
});
it('should call valueHandler', () => {
expect(gen.next(isEtherTransaction).value).toEqual(call(valueHandler, action, setValueField));
});
itShouldBeDone(gen);
}); });
describe('revalidateCurrentValue*', () => { describe('revalidateCurrentValue*', () => {