mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Changing cancel button labels in send screen when in editing stage (#12056)
* Changing cancel button labels in send screen when in editing stage * Re-route user to home page when reject is clicked on edit transaction page
This commit is contained in:
parent
ae84b0cb6d
commit
ade9e4ac4b
@ -305,6 +305,9 @@
|
||||
"cancel": {
|
||||
"message": "Cancel"
|
||||
},
|
||||
"cancelEdit": {
|
||||
"message": "Cancel Edit"
|
||||
},
|
||||
"cancelPopoverTitle": {
|
||||
"message": "Cancel transaction"
|
||||
},
|
||||
|
@ -1736,6 +1736,10 @@ export function getSendHexData(state) {
|
||||
return state[name].draftTransaction.userInputHexData;
|
||||
}
|
||||
|
||||
export function getDraftTransactionID(state) {
|
||||
return state[name].draftTransaction.id;
|
||||
}
|
||||
|
||||
export function sendAmountIsInError(state) {
|
||||
return Boolean(state[name].amount.error);
|
||||
}
|
||||
|
@ -51,6 +51,7 @@ import sendReducer, {
|
||||
getSendAmount,
|
||||
getIsBalanceInsufficient,
|
||||
getSendMaxModeState,
|
||||
getDraftTransactionID,
|
||||
sendAmountIsInError,
|
||||
getSendHexData,
|
||||
getSendTo,
|
||||
@ -2459,6 +2460,21 @@ describe('Send Slice', () => {
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('has a selector to get the draft transaction ID', () => {
|
||||
expect(getDraftTransactionID({ send: initialState })).toBeNull();
|
||||
expect(
|
||||
getDraftTransactionID({
|
||||
send: {
|
||||
...initialState,
|
||||
draftTransaction: {
|
||||
...initialState.draftTransaction,
|
||||
id: 'ID',
|
||||
},
|
||||
},
|
||||
}),
|
||||
).toBe('ID');
|
||||
});
|
||||
|
||||
it('has a selector to get the user entered hex data', () => {
|
||||
expect(getSendHexData({ send: initialState })).toBeNull();
|
||||
expect(
|
||||
|
@ -2,7 +2,11 @@ import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { isEqual } from 'lodash';
|
||||
import PageContainerFooter from '../../../components/ui/page-container/page-container-footer';
|
||||
import { CONFIRM_TRANSACTION_ROUTE } from '../../../helpers/constants/routes';
|
||||
import {
|
||||
CONFIRM_TRANSACTION_ROUTE,
|
||||
DEFAULT_ROUTE,
|
||||
} from '../../../helpers/constants/routes';
|
||||
import { SEND_STAGES } from '../../../ducks/send';
|
||||
|
||||
export default class SendFooter extends Component {
|
||||
static propTypes = {
|
||||
@ -13,9 +17,12 @@ export default class SendFooter extends Component {
|
||||
sign: PropTypes.func,
|
||||
to: PropTypes.string,
|
||||
toAccounts: PropTypes.array,
|
||||
sendStage: PropTypes.string,
|
||||
sendErrors: PropTypes.object,
|
||||
gasEstimateType: PropTypes.string,
|
||||
mostRecentOverviewPage: PropTypes.string.isRequired,
|
||||
cancelTx: PropTypes.func,
|
||||
draftTransactionID: PropTypes.string,
|
||||
};
|
||||
|
||||
static contextTypes = {
|
||||
@ -24,9 +31,21 @@ export default class SendFooter extends Component {
|
||||
};
|
||||
|
||||
onCancel() {
|
||||
const { resetSendState, history, mostRecentOverviewPage } = this.props;
|
||||
const {
|
||||
cancelTx,
|
||||
draftTransactionID,
|
||||
history,
|
||||
mostRecentOverviewPage,
|
||||
resetSendState,
|
||||
sendStage,
|
||||
} = this.props;
|
||||
|
||||
if (draftTransactionID) cancelTx({ id: draftTransactionID });
|
||||
resetSendState();
|
||||
history.push(mostRecentOverviewPage);
|
||||
|
||||
const nextRoute =
|
||||
sendStage === SEND_STAGES.EDIT ? DEFAULT_ROUTE : mostRecentOverviewPage;
|
||||
history.push(nextRoute);
|
||||
}
|
||||
|
||||
async onSubmit(event) {
|
||||
@ -85,11 +104,14 @@ export default class SendFooter extends Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { t } = this.context;
|
||||
const { sendStage } = this.props;
|
||||
return (
|
||||
<PageContainerFooter
|
||||
onCancel={() => this.onCancel()}
|
||||
onSubmit={(e) => this.onSubmit(e)}
|
||||
disabled={this.props.disabled}
|
||||
cancelText={sendStage === SEND_STAGES.EDIT ? t('reject') : t('cancel')}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -1,8 +1,12 @@
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import sinon from 'sinon';
|
||||
import { CONFIRM_TRANSACTION_ROUTE } from '../../../helpers/constants/routes';
|
||||
import {
|
||||
CONFIRM_TRANSACTION_ROUTE,
|
||||
DEFAULT_ROUTE,
|
||||
} from '../../../helpers/constants/routes';
|
||||
import PageContainerFooter from '../../../components/ui/page-container/page-container-footer';
|
||||
import { renderWithProvider } from '../../../../test/jest';
|
||||
import SendFooter from './send-footer.component';
|
||||
|
||||
describe('SendFooter Component', () => {
|
||||
@ -10,6 +14,7 @@ describe('SendFooter Component', () => {
|
||||
|
||||
const propsMethodSpies = {
|
||||
addToAddressBookIfNew: sinon.spy(),
|
||||
cancelTx: sinon.spy(),
|
||||
resetSendState: sinon.spy(),
|
||||
sign: sinon.spy(),
|
||||
update: sinon.spy(),
|
||||
@ -20,31 +25,40 @@ describe('SendFooter Component', () => {
|
||||
};
|
||||
const MOCK_EVENT = { preventDefault: () => undefined };
|
||||
|
||||
const renderShallow = (props) => {
|
||||
return shallow(
|
||||
<SendFooter
|
||||
addToAddressBookIfNew={propsMethodSpies.addToAddressBookIfNew}
|
||||
resetSendState={propsMethodSpies.resetSendState}
|
||||
cancelTx={propsMethodSpies.cancelTx}
|
||||
disabled
|
||||
draftTransactionID="ID"
|
||||
history={historySpies}
|
||||
sign={propsMethodSpies.sign}
|
||||
to="mockTo"
|
||||
toAccounts={['mockAccount']}
|
||||
sendErrors={{}}
|
||||
sendStage="DRAFT"
|
||||
gasEstimateType="BASIC"
|
||||
mostRecentOverviewPage="mostRecentOverviewPage"
|
||||
{...props}
|
||||
/>,
|
||||
{ context: { t: (str) => str, metricsEvent: () => ({}) } },
|
||||
);
|
||||
};
|
||||
|
||||
beforeAll(() => {
|
||||
sinon.spy(SendFooter.prototype, 'onCancel');
|
||||
sinon.spy(SendFooter.prototype, 'onSubmit');
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(
|
||||
<SendFooter
|
||||
addToAddressBookIfNew={propsMethodSpies.addToAddressBookIfNew}
|
||||
resetSendState={propsMethodSpies.resetSendState}
|
||||
disabled
|
||||
history={historySpies}
|
||||
sign={propsMethodSpies.sign}
|
||||
to="mockTo"
|
||||
toAccounts={['mockAccount']}
|
||||
sendErrors={{}}
|
||||
gasEstimateType="BASIC"
|
||||
mostRecentOverviewPage="mostRecentOverviewPage"
|
||||
/>,
|
||||
{ context: { t: (str) => str, metricsEvent: () => ({}) } },
|
||||
);
|
||||
wrapper = renderShallow();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
propsMethodSpies.resetSendState.resetHistory();
|
||||
propsMethodSpies.cancelTx.resetHistory();
|
||||
propsMethodSpies.addToAddressBookIfNew.resetHistory();
|
||||
propsMethodSpies.resetSendState.resetHistory();
|
||||
propsMethodSpies.sign.resetHistory();
|
||||
@ -65,6 +79,15 @@ describe('SendFooter Component', () => {
|
||||
expect(propsMethodSpies.resetSendState.callCount).toStrictEqual(1);
|
||||
});
|
||||
|
||||
it('should call cancelTx', () => {
|
||||
expect(propsMethodSpies.cancelTx.callCount).toStrictEqual(0);
|
||||
wrapper.instance().onCancel();
|
||||
expect(propsMethodSpies.cancelTx.callCount).toStrictEqual(1);
|
||||
expect(propsMethodSpies.cancelTx.getCall(0).args[0]?.id).toStrictEqual(
|
||||
'ID',
|
||||
);
|
||||
});
|
||||
|
||||
it('should call history.push', () => {
|
||||
expect(historySpies.push.callCount).toStrictEqual(0);
|
||||
wrapper.instance().onCancel();
|
||||
@ -73,6 +96,14 @@ describe('SendFooter Component', () => {
|
||||
'mostRecentOverviewPage',
|
||||
);
|
||||
});
|
||||
|
||||
it('should call history.push with DEFAULT_ROUTE in edit stage', () => {
|
||||
wrapper = renderShallow({ sendStage: 'EDIT' });
|
||||
expect(historySpies.push.callCount).toStrictEqual(0);
|
||||
wrapper.instance().onCancel();
|
||||
expect(historySpies.push.callCount).toStrictEqual(1);
|
||||
expect(historySpies.push.getCall(0).args[0]).toStrictEqual(DEFAULT_ROUTE);
|
||||
});
|
||||
});
|
||||
|
||||
describe('onSubmit', () => {
|
||||
@ -107,7 +138,9 @@ describe('SendFooter Component', () => {
|
||||
addToAddressBookIfNew={propsMethodSpies.addToAddressBookIfNew}
|
||||
amount="mockAmount"
|
||||
resetSendState={propsMethodSpies.resetSendState}
|
||||
cancelTx={propsMethodSpies.cancelTx}
|
||||
disabled
|
||||
draftTransactionID="ID"
|
||||
editingTransactionId="mockEditingTransactionId"
|
||||
errors={{}}
|
||||
from={{ address: 'mockAddress', balance: 'mockBalance' }}
|
||||
@ -147,4 +180,28 @@ describe('SendFooter Component', () => {
|
||||
expect(SendFooter.prototype.onCancel.callCount).toStrictEqual(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Cancel Button', () => {
|
||||
const renderFooter = (props) =>
|
||||
renderWithProvider(
|
||||
<SendFooter
|
||||
disabled
|
||||
mostRecentOverviewPage="mostRecentOverviewPage"
|
||||
draftTransactionID="ID"
|
||||
sendErrors={{}}
|
||||
sendStage="DRAFT"
|
||||
{...props}
|
||||
/>,
|
||||
);
|
||||
|
||||
it('has a cancel button in footer', () => {
|
||||
const { getByText } = renderFooter();
|
||||
expect(getByText('Cancel')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('has label changed to Reject in editing stage', () => {
|
||||
const { getByText } = renderFooter({ sendStage: 'EDIT' });
|
||||
expect(getByText('Reject')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { connect } from 'react-redux';
|
||||
import { addToAddressBook } from '../../../store/actions';
|
||||
import { addToAddressBook, cancelTx } from '../../../store/actions';
|
||||
import {
|
||||
getRenderableEstimateDataForSmallButtonsFromGWEI,
|
||||
getDefaultActiveButtonIndex,
|
||||
@ -7,10 +7,12 @@ import {
|
||||
import {
|
||||
resetSendState,
|
||||
getGasPrice,
|
||||
getSendStage,
|
||||
getSendTo,
|
||||
getSendErrors,
|
||||
isSendFormInvalid,
|
||||
signTransaction,
|
||||
getDraftTransactionID,
|
||||
} from '../../../ducks/send';
|
||||
import { getMostRecentOverviewPage } from '../../../ducks/history/history';
|
||||
import { addHexPrefix } from '../../../../app/scripts/lib/util';
|
||||
@ -43,7 +45,9 @@ function mapStateToProps(state) {
|
||||
disabled: isSendFormInvalid(state),
|
||||
to: getSendTo(state),
|
||||
toAccounts: getSendToAccounts(state),
|
||||
sendStage: getSendStage(state),
|
||||
sendErrors: getSendErrors(state),
|
||||
draftTransactionID: getDraftTransactionID(state),
|
||||
gasEstimateType,
|
||||
mostRecentOverviewPage: getMostRecentOverviewPage(state),
|
||||
};
|
||||
@ -52,6 +56,7 @@ function mapStateToProps(state) {
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
resetSendState: () => dispatch(resetSendState()),
|
||||
cancelTx: (t) => dispatch(cancelTx(t)),
|
||||
sign: () => dispatch(signTransaction()),
|
||||
addToAddressBookIfNew: (newAddress, toAccounts, nickname = '') => {
|
||||
const hexPrefixedAddress = addHexPrefix(newAddress);
|
||||
|
@ -1,6 +1,6 @@
|
||||
import sinon from 'sinon';
|
||||
|
||||
import { addToAddressBook } from '../../../store/actions';
|
||||
import { addToAddressBook, cancelTx } from '../../../store/actions';
|
||||
import { resetSendState, signTransaction } from '../../../ducks/send';
|
||||
|
||||
let mapDispatchToProps;
|
||||
@ -14,6 +14,7 @@ jest.mock('react-redux', () => ({
|
||||
|
||||
jest.mock('../../../store/actions.js', () => ({
|
||||
addToAddressBook: jest.fn(),
|
||||
cancelTx: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('../../../ducks/metamask/metamask', () => ({
|
||||
@ -24,6 +25,8 @@ jest.mock('../../../ducks/send', () => ({
|
||||
getGasPrice: (s) => `mockGasPrice:${s}`,
|
||||
getSendTo: (s) => `mockTo:${s}`,
|
||||
getSendErrors: (s) => `mockSendErrors:${s}`,
|
||||
getSendStage: (s) => `mockStage:${s}`,
|
||||
getDraftTransaction: (s) => ({ id: `draftTransaction:${s}` }),
|
||||
resetSendState: jest.fn(),
|
||||
signTransaction: jest.fn(),
|
||||
}));
|
||||
@ -53,6 +56,16 @@ describe('send-footer container', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('cancelTx()', () => {
|
||||
it('should dispatch an action', () => {
|
||||
const draftTansaction = { id: 'ID' };
|
||||
mapDispatchToPropsObject.cancelTx(draftTansaction);
|
||||
expect(dispatchSpy.calledOnce).toStrictEqual(true);
|
||||
expect(cancelTx).toHaveBeenCalledTimes(1);
|
||||
expect(cancelTx).toHaveBeenCalledWith(draftTansaction);
|
||||
});
|
||||
});
|
||||
|
||||
describe('sign()', () => {
|
||||
it('should dispatch a signTransaction action', () => {
|
||||
mapDispatchToPropsObject.sign();
|
||||
|
@ -38,7 +38,9 @@ export default function SendHeader() {
|
||||
className="send__header"
|
||||
onClose={onClose}
|
||||
title={title}
|
||||
headerCloseText={t('cancel')}
|
||||
headerCloseText={
|
||||
stage === SEND_STAGES.EDIT ? t('cancelEdit') : t('cancel')
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -103,6 +103,18 @@ describe('SendHeader Component', () => {
|
||||
expect(getByText('Cancel')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('has button label changed to Cancel Edit in editing stage', () => {
|
||||
const { getByText } = renderWithProvider(
|
||||
<SendHeader />,
|
||||
configureMockStore(middleware)({
|
||||
send: { ...initialState, stage: SEND_STAGES.EDIT },
|
||||
gas: { basicEstimateStatus: 'LOADING' },
|
||||
history: { mostRecentOverviewPage: 'activity' },
|
||||
}),
|
||||
);
|
||||
expect(getByText('Cancel Edit')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('resets send state when clicked', () => {
|
||||
const store = configureMockStore(middleware)({
|
||||
send: initialState,
|
||||
|
@ -22,6 +22,7 @@
|
||||
right: 1rem;
|
||||
width: min-content;
|
||||
font-size: 0.75rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user