Skip to content

Commit af427b2

Browse files
Merge branch 'develop' into fix/ddw-1011-fix-stake-pool-list-view-overlap
2 parents 4cc98f1 + 3c981a7 commit af427b2

33 files changed

+373
-111
lines changed

CHANGELOG.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,20 @@
77
- Improved RTS flags splash screen message ([PR 2901](https://github.com/input-output-hk/daedalus/pull/2901))
88
- Implemented error message when trying to leave wallet without enough ada to support tokens ([PR 2783](https://github.com/input-output-hk/daedalus/pull/2783))
99

10+
### Fixes
11+
12+
- Fixed stake pool list view overlapping news feed ([PR 2917](https://github.com/input-output-hk/daedalus/pull/2917))
13+
- Fixed styling of the incentivized testnet rewards wallet dropdown ([PR 2907](https://github.com/input-output-hk/daedalus/pull/2907))
14+
- Fix warning sign displayed when recommend decimals is zero ([PR 2905](https://github.com/input-output-hk/daedalus/pull/2905))
15+
- Fixed discrete tooltip being clipped by loading overlay when stake pools are adjusted ([PR 2902](https://github.com/input-output-hk/daedalus/pull/2902))
16+
- Sets minimum transaction fee to ada input field when tokens are removed ([PR 2918](https://github.com/input-output-hk/daedalus/pull/2918))
17+
1018
### Chores
1119

1220
- Fixed spelling issues and typos ([PR 2915](https://github.com/input-output-hk/daedalus/pull/2915))
1321
- Removed SASS ts-lint ignore comments ([PR 2870](https://github.com/input-output-hk/daedalus/pull/2870))
1422
- Enabled debugging of the main process ([PR 2893](https://github.com/input-output-hk/daedalus/pull/2893))
1523

16-
### Fixes
17-
18-
- Fixed stake pool list view overlapping news feed ([PR 2917](https://github.com/input-output-hk/daedalus/pull/2917))
19-
- Fixed discrete tooltip being clipped by loading overlay when stake pools are adjusted ([PR 2902](https://github.com/input-output-hk/daedalus/pull/2902))
20-
2124
## 4.9.0
2225

2326
### Features

jest.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ module.exports = {
8989
// Jest does not support WASM imports from ESM modules
9090
// https://github.com/facebook/jest/issues/9430
9191
'^@iohk-jormungandr/wallet-js$': 'identity-obj-proxy',
92+
'tests/(.*)': '<rootDir>/tests/$1',
9293
},
9394

9495
// An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@
255255
"react-intl": "2.7.2",
256256
"react-lottie": "1.2.3",
257257
"react-markdown": "4.3.1",
258-
"react-polymorph": "1.0.2",
258+
"react-polymorph": "1.0.3",
259259
"react-router": "5.2.0",
260260
"react-router-dom": "5.2.0",
261261
"react-svg-inline": "2.1.1",

source/renderer/app/components/assets/Asset.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,9 @@ class Asset extends Component<Props, State> {
209209
})}
210210
className={styles.warningIconWrapper}
211211
>
212-
<SVGInline className={styles.warningIcon} svg={warningIcon} />
212+
<span data-testid="warning-icon">
213+
<SVGInline className={styles.warningIcon} svg={warningIcon} />
214+
</span>
213215
</PopOver>
214216
</div>
215217
)}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import '@testing-library/jest-dom';
2+
3+
import React from 'react';
4+
import noop from 'lodash/noop';
5+
import { cleanup, screen, waitFor } from '@testing-library/react';
6+
7+
import createTestBed from 'tests/_utils/TestBed';
8+
import {
9+
withDecimalPlacesToken,
10+
zeroDecimalPlacesToken,
11+
} from 'tests/mocks/asset';
12+
13+
import AssetSettingsDialog from './AssetSettingsDialog';
14+
15+
describe('AssetSettingsDialog', () => {
16+
afterEach(() => cleanup());
17+
18+
it('should not show a warning when an asset is set to zero recommended decimal places', async () => {
19+
createTestBed(
20+
<AssetSettingsDialog
21+
asset={zeroDecimalPlacesToken}
22+
onSubmit={noop}
23+
onCancel={noop}
24+
/>
25+
);
26+
await waitFor(() => screen.getByText('Number of decimal places'));
27+
expect(screen.queryByTestId('warning-icon')).not.toBeInTheDocument();
28+
});
29+
30+
it('should show a warning when an asset is not set to the recommended decimal places', async () => {
31+
createTestBed(
32+
<AssetSettingsDialog
33+
asset={withDecimalPlacesToken}
34+
onSubmit={noop}
35+
onCancel={noop}
36+
/>
37+
);
38+
await waitFor(() => screen.getByText('Number of decimal places'));
39+
expect(screen.queryByTestId('warning-icon')).toBeInTheDocument();
40+
});
41+
});

source/renderer/app/components/assets/AssetSettingsDialog.tsx

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
MAX_DECIMAL_PRECISION,
1818
} from '../../config/assetsConfig';
1919
import { DiscreetTokenWalletAmount } from '../../features/discreet-mode';
20+
import { isRecommendedDecimal } from '../wallet/tokens/wallet-token/helpers';
2021

2122
const messages = defineMessages({
2223
title: {
@@ -135,7 +136,6 @@ class AssetSettingsDialog extends Component<Props, State> {
135136
const { decimals: savedDecimals, recommendedDecimals } = asset;
136137
const { decimals } = this.state;
137138
const hasSavedDecimals = typeof savedDecimals === 'number';
138-
const hasRecommendedDecimals = typeof recommendedDecimals === 'number';
139139
const options = range(MAX_DECIMAL_PRECISION + 1).map((value) => ({
140140
value,
141141
}));
@@ -153,8 +153,12 @@ class AssetSettingsDialog extends Component<Props, State> {
153153
onClick: () => onSubmit(asset, decimals),
154154
},
155155
];
156-
const hasWarning =
157-
hasRecommendedDecimals && savedDecimals !== recommendedDecimals;
156+
157+
const hasWarning = isRecommendedDecimal({
158+
recommendedDecimals,
159+
decimals: savedDecimals,
160+
});
161+
158162
let warningPopOverMessage;
159163

160164
if (hasWarning) {
@@ -209,10 +213,12 @@ class AssetSettingsDialog extends Component<Props, State> {
209213
recommendedDecimals,
210214
})}
211215
>
212-
<SVGInline
213-
className={styles.warningIcon}
214-
svg={warningIcon}
215-
/>
216+
<span data-testid="warning-icon">
217+
<SVGInline
218+
className={styles.warningIcon}
219+
svg={warningIcon}
220+
/>
221+
</span>
216222
</PopOver>
217223
)}
218224
</span>

source/renderer/app/components/staking/redeem-itn-rewards/Step1ConfigurationDialog.scss

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -38,20 +38,6 @@
3838
margin-bottom: 17px;
3939
}
4040

41-
.walletsDropdown {
42-
&.disabled {
43-
pointer-events: none;
44-
:global {
45-
.SelectOverrides_selectInput:after {
46-
opacity: 0.5;
47-
}
48-
.SimpleFormField_inputWrapper {
49-
opacity: 0.5;
50-
}
51-
}
52-
}
53-
}
54-
5541
.checkbox {
5642
margin-bottom: 20px;
5743

source/renderer/app/components/staking/redeem-itn-rewards/Step1ConfigurationDialog.tsx

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,10 @@ type Props = {
142142
wallets: Array<Wallet>;
143143
};
144144

145+
type State = {
146+
wasRecoveryPhraseValidAtLeastOnce: boolean;
147+
};
148+
145149
interface FormFields {
146150
checkboxAcceptance1: string;
147151
checkboxAcceptance2: string;
@@ -150,14 +154,19 @@ interface FormFields {
150154
}
151155

152156
@observer
153-
class Step1ConfigurationDialog extends Component<Props> {
157+
class Step1ConfigurationDialog extends Component<Props, State> {
154158
static contextTypes = {
155159
intl: intlShape.isRequired,
156160
};
157161
static defaultProps = {
158162
error: null,
159163
recoveryPhrase: [],
160164
};
165+
166+
state = {
167+
wasRecoveryPhraseValidAtLeastOnce: false,
168+
};
169+
161170
recoveryPhraseAutocomplete: Autocomplete;
162171
form = new ReactToolboxMobxForm<FormFields>(
163172
{
@@ -177,6 +186,16 @@ class Step1ConfigurationDialog extends Component<Props> {
177186
this.context.intl.formatMessage(messages.invalidRecoveryPhrase),
178187
],
179188
}),
189+
hooks: {
190+
onChange: (field) => {
191+
if (
192+
this.state.wasRecoveryPhraseValidAtLeastOnce === false &&
193+
field.isValid
194+
) {
195+
this.setState({ wasRecoveryPhraseValidAtLeastOnce: true });
196+
}
197+
},
198+
},
180199
},
181200
walletsDropdown: {
182201
type: 'select',
@@ -276,11 +295,11 @@ class Step1ConfigurationDialog extends Component<Props> {
276295
const checkboxAcceptance1Field = form.$('checkboxAcceptance1');
277296
const checkboxAcceptance2Field = form.$('checkboxAcceptance2');
278297
const walletId = get(wallet, 'id', null);
279-
const validRecoveryPhase = recoveryPhraseField.isValid;
280-
const walletsDropdownClasses = classnames([
281-
styles.walletsDropdown,
282-
!validRecoveryPhase ? styles.disabled : null,
283-
]);
298+
const walletsDropdownDisabled = !(
299+
recoveryPhraseField.isValid ||
300+
this.state.wasRecoveryPhraseValidAtLeastOnce
301+
);
302+
284303
const actions = {
285304
direction: 'column',
286305
items: [
@@ -365,7 +384,6 @@ class Step1ConfigurationDialog extends Component<Props> {
365384
/>
366385
<div className={styles.walletsDropdownWrapper}>
367386
<WalletsDropdown
368-
className={walletsDropdownClasses}
369387
{...walletsDropdownField.bind()}
370388
numberOfStakePools={4}
371389
wallets={wallets}
@@ -376,6 +394,7 @@ class Step1ConfigurationDialog extends Component<Props> {
376394
value={walletId}
377395
getStakePoolById={() => {}}
378396
errorPosition="bottom"
397+
disabled={walletsDropdownDisabled}
379398
/>
380399
</div>
381400
<Checkbox

source/renderer/app/components/wallet/WalletSendForm.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656

5757
input {
5858
background-color: var(--rp-input-bg-color-disabled) !important;
59-
border-color: var(--rp-input-bg-color-disabled) !important;
59+
border-color: var(--rp-input-border-color-disabled) !important;
6060
font-family: var(--font-regular);
6161
pointer-events: none;
6262

source/renderer/app/components/wallet/WalletSendForm.spec.tsx

Lines changed: 59 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -174,32 +174,50 @@ describe('wallet/Wallet Send Form', () => {
174174
return mock;
175175
}
176176

177+
const MINIMUM_AMOUNT_UPDATED_MESSAGE_TEST_ID =
178+
'WalletSendForm::minimumAmountNotice::updated';
179+
180+
function assertMinimumAmountNoticeMessage(minimumAda: number) {
181+
expect(
182+
screen.getByTestId(MINIMUM_AMOUNT_UPDATED_MESSAGE_TEST_ID)
183+
).toHaveTextContent(
184+
`Note: the ada field was automatically updated because this transaction requires a minimum of ${minimumAda} ADA.`
185+
);
186+
}
187+
177188
test('should update Ada input field to minimum required and restore to original value when tokens are removed', async () => {
178189
expect.assertions(4);
190+
179191
const minimumAda = 2;
180-
const calculateTransactionFeeMock = createTransactionFeeMock(2, minimumAda);
192+
const calculateTransactionFeeMock = createTransactionFeeMock(1, minimumAda);
193+
181194
render(
182195
<SetupWallet calculateTransactionFee={calculateTransactionFeeMock} />
183196
);
197+
184198
enterReceiverAddress();
199+
185200
const removeToken1 = await addToken();
201+
186202
await waitForMinimumAdaRequiredMsg();
187203
assertAdaInput(minimumAda);
204+
188205
const minimumAmountNoticeTestId =
189206
'WalletSendForm::minimumAmountNotice::updated';
207+
190208
expect(screen.getByTestId(minimumAmountNoticeTestId)).toHaveTextContent(
191209
`Note: the ada field was automatically updated because this transaction requires a minimum of ${minimumAda} ADA.`
192210
);
211+
193212
await removeToken1();
194-
const minimumAdaRequiredMsg = screen.getByTestId('minimumAdaRequiredMsg');
195-
await within(minimumAdaRequiredMsg).findByText(
196-
`to the minimum of 1 ADA required`
197-
);
198-
assertAdaInput(0);
199-
expect(
200-
screen.queryByTestId(minimumAmountNoticeTestId)
201-
).not.toBeInTheDocument();
213+
214+
await waitForMinimumAdaRequiredMsg(1);
215+
216+
assertAdaInput(1);
217+
218+
expect(screen.queryByTestId(minimumAmountNoticeTestId)).toBeInTheDocument();
202219
});
220+
203221
test('should display an update button when Ada input field is less than minimum required', async () => {
204222
expect.assertions(3);
205223
const minimumAda = 2;
@@ -227,6 +245,7 @@ describe('wallet/Wallet Send Form', () => {
227245
await waitForElementToBeRemoved(updateButton);
228246
assertAdaInput(minimumAda);
229247
});
248+
230249
test('should favour user Ada input instead of minimum required when the value is greater than the minimum one', async () => {
231250
expect.assertions(2);
232251
const minimumAda = 2.5;
@@ -253,6 +272,7 @@ describe('wallet/Wallet Send Form', () => {
253272
`Note: the ada field was automatically updated to ${userAdaAmount} ADA because now it fulfills the minimum amount of 1 ADA for the transaction.`
254273
);
255274
});
275+
256276
test('should remove message when user entry is higher than minimum amount', async () => {
257277
expect.assertions(3);
258278
const minimumAda = 2.5;
@@ -287,6 +307,7 @@ describe('wallet/Wallet Send Form', () => {
287307
screen.queryByTestId(minimumAmountNoticeTestId)
288308
).not.toBeInTheDocument();
289309
});
310+
290311
test('should not display any minimum amount notice message when ada input is greater than minimum amount', async () => {
291312
expect.assertions(2);
292313
const calculateTransactionFeeMock = jest.fn().mockResolvedValue({
@@ -311,6 +332,7 @@ describe('wallet/Wallet Send Form', () => {
311332
screen.findByTestId('WalletSendForm::minimumAmountNotice::restored')
312333
).rejects.toBeTruthy();
313334
});
335+
314336
test('should apply minimum fee to ada field when user has removed the previous update', async () => {
315337
expect.assertions(3);
316338
const minimumAda = 2;
@@ -334,6 +356,7 @@ describe('wallet/Wallet Send Form', () => {
334356
await waitForMinimumAdaRequiredMsg();
335357
assertAdaInput(minimumAda);
336358
});
359+
337360
test('should format ada input field using numeric format profile', async () => {
338361
expect.assertions(1);
339362
const minimumAda = 2;
@@ -350,6 +373,7 @@ describe('wallet/Wallet Send Form', () => {
350373
const adaInput = getInput('Ada');
351374
expect(adaInput).toHaveValue(`${minimumAda},000000`);
352375
});
376+
353377
test('should calculate transaction fee even when one of the assets are empty', async () => {
354378
expect.assertions(2);
355379
const minimumAda = 2;
@@ -365,4 +389,30 @@ describe('wallet/Wallet Send Form', () => {
365389
await waitForMinimumAdaRequiredMsg();
366390
assertAdaInput(minimumAda);
367391
});
392+
393+
test('should keep transaction fee when assets are removed and ada field is untouched', async () => {
394+
expect.assertions(3);
395+
396+
const fee = 2;
397+
const minimumAda = 1;
398+
const calculateTransactionFeeMock = createTransactionFeeMock(1, fee);
399+
400+
render(
401+
<SetupWallet calculateTransactionFee={calculateTransactionFeeMock} />
402+
);
403+
404+
enterReceiverAddress();
405+
406+
const removeToken = await addToken();
407+
await waitForMinimumAdaRequiredMsg();
408+
409+
assertAdaInput(fee);
410+
411+
await removeToken();
412+
413+
await waitForMinimumAdaRequiredMsg(minimumAda);
414+
415+
assertAdaInput(minimumAda);
416+
assertMinimumAmountNoticeMessage(minimumAda);
417+
});
368418
});

0 commit comments

Comments
 (0)