mirror of
https://github.com/BlueWallet/BlueWallet.git
synced 2025-03-15 11:59:21 +01:00
FIX: transactions list screen would not always update with new transactions
This commit is contained in:
parent
80fb4a74a8
commit
85cb6c1287
6 changed files with 104 additions and 12 deletions
|
@ -362,6 +362,7 @@ export const TransactionListItem: React.FC<TransactionListItemProps> = React.mem
|
|||
rightTitle={rowTitle}
|
||||
rightTitleStyle={rowTitleStyle}
|
||||
containerStyle={combinedStyle}
|
||||
testID="TransactionListItem"
|
||||
/>
|
||||
</ToolTipMenu>
|
||||
);
|
||||
|
|
|
@ -367,12 +367,17 @@ const WalletDetails: React.FC = () => {
|
|||
const purgeTransactions = async () => {
|
||||
if (backdoorPressed < 10) return setBackdoorPressed(backdoorPressed + 1);
|
||||
setBackdoorPressed(0);
|
||||
const msg = 'Transactions purged. Pls go to main screen and back to rerender screen';
|
||||
const msg = 'Transactions & balances purged. Pls go to main screen and back to rerender screen';
|
||||
|
||||
if (wallet.type === HDSegwitBech32Wallet.type) {
|
||||
wallet._txs_by_external_index = {};
|
||||
wallet._txs_by_internal_index = {};
|
||||
presentAlert({ message: msg });
|
||||
|
||||
wallet._balances_by_external_index = {};
|
||||
wallet._balances_by_internal_index = {};
|
||||
wallet._lastTxFetch = 0;
|
||||
wallet._lastBalanceFetch = 0;
|
||||
}
|
||||
|
||||
// @ts-expect-error: Need to fix later
|
||||
|
@ -381,6 +386,15 @@ const WalletDetails: React.FC = () => {
|
|||
wallet._hdWalletInstance._txs_by_external_index = {};
|
||||
// @ts-expect-error: Need to fix later
|
||||
wallet._hdWalletInstance._txs_by_internal_index = {};
|
||||
|
||||
// @ts-expect-error: Need to fix later
|
||||
wallet._hdWalletInstance._balances_by_external_index = {};
|
||||
// @ts-expect-error: Need to fix later
|
||||
wallet._hdWalletInstance._balances_by_internal_index = {};
|
||||
// @ts-expect-error: Need to fix later
|
||||
wallet._hdWalletInstance._lastTxFetch = 0;
|
||||
// @ts-expect-error: Need to fix later
|
||||
wallet._hdWalletInstance._lastBalanceFetch = 0;
|
||||
presentAlert({ message: msg });
|
||||
}
|
||||
};
|
||||
|
@ -528,7 +542,7 @@ const WalletDetails: React.FC = () => {
|
|||
</View>
|
||||
</>
|
||||
<>
|
||||
<Text onPress={purgeTransactions} style={[styles.textLabel2, stylesHook.textLabel2]}>
|
||||
<Text onPress={purgeTransactions} style={[styles.textLabel2, stylesHook.textLabel2]} testID="PurgeBackdoorButton">
|
||||
{loc.transactions.transactions_count.toLowerCase()}
|
||||
</Text>
|
||||
<BlueText>{wallet.getTransactions().length}</BlueText>
|
||||
|
|
|
@ -119,7 +119,9 @@ const WalletTransactions: React.FC<WalletTransactionsProps> = ({ route }) => {
|
|||
const txs = wallet.getTransactions();
|
||||
txs.sort((a: { received: string }, b: { received: string }) => +new Date(b.received) - +new Date(a.received));
|
||||
return txs;
|
||||
}, [wallet]);
|
||||
// we use `wallet.getLastTxFetch()` to tell if txs list changed
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [wallet, wallet?.getLastTxFetch()]);
|
||||
|
||||
const getTransactions = useCallback((lmt = Infinity): Transaction[] => sortedTransactions.slice(0, lmt), [sortedTransactions]);
|
||||
|
||||
|
@ -171,7 +173,6 @@ const WalletTransactions: React.FC<WalletTransactionsProps> = ({ route }) => {
|
|||
setFetchFailures(0);
|
||||
const newTimestamp = Date.now();
|
||||
setLastFetchTimestamp(newTimestamp);
|
||||
wallet._lastTxFetch = newTimestamp;
|
||||
} catch (err) {
|
||||
setFetchFailures(prev => {
|
||||
const newFailures = prev + 1;
|
||||
|
@ -290,11 +291,6 @@ const WalletTransactions: React.FC<WalletTransactionsProps> = ({ route }) => {
|
|||
index,
|
||||
});
|
||||
|
||||
const listData: Transaction[] = useMemo(() => {
|
||||
const transactions = getTransactions(limit);
|
||||
return transactions;
|
||||
}, [getTransactions, limit]);
|
||||
|
||||
const renderItem = useCallback(
|
||||
// eslint-disable-next-line react/no-unused-prop-types
|
||||
({ item }: { item: Transaction }) => {
|
||||
|
@ -521,6 +517,7 @@ const WalletTransactions: React.FC<WalletTransactionsProps> = ({ route }) => {
|
|||
styles.refreshIndicatorBackground,
|
||||
{ backgroundColor: wallet ? WalletGradient.headerColorFor(wallet.type) : colors.background },
|
||||
]}
|
||||
testID="TransactionsListView"
|
||||
/>
|
||||
|
||||
<FlatList<Transaction>
|
||||
|
@ -529,7 +526,7 @@ const WalletTransactions: React.FC<WalletTransactionsProps> = ({ route }) => {
|
|||
onEndReachedThreshold={0.3}
|
||||
onEndReached={loadMoreTransactions}
|
||||
ListFooterComponent={renderListFooterComponent}
|
||||
data={listData}
|
||||
data={getTransactions(limit)}
|
||||
extraData={wallet}
|
||||
keyExtractor={_keyExtractor}
|
||||
renderItem={renderItem}
|
||||
|
@ -544,7 +541,7 @@ const WalletTransactions: React.FC<WalletTransactionsProps> = ({ route }) => {
|
|||
ListHeaderComponent={ListHeaderComponent}
|
||||
ListEmptyComponent={
|
||||
<ScrollView style={[styles.flex, { backgroundColor: colors.background }]} contentContainerStyle={styles.scrollViewContent}>
|
||||
<Text numberOfLines={0} style={styles.emptyTxs}>
|
||||
<Text numberOfLines={0} style={styles.emptyTxs} testID="TransactionsListEmpty">
|
||||
{(isLightning() && loc.wallets.list_empty_txs1_lightning) || loc.wallets.list_empty_txs1}
|
||||
</Text>
|
||||
{isLightning() && <Text style={styles.emptyTxsLightning}>{loc.wallets.list_empty_txs2_lightning}</Text>}
|
||||
|
|
|
@ -12,8 +12,17 @@ import {
|
|||
tapAndTapAgainIfTextIsNotVisible,
|
||||
tapIfTextPresent,
|
||||
waitForId,
|
||||
countElements,
|
||||
} from './helperz';
|
||||
|
||||
// if loglevel is set to `error`, this kind of logging will still get through
|
||||
console.warn = console.log = (...args) => {
|
||||
let output = '';
|
||||
args.map(arg => (output += String(arg)));
|
||||
|
||||
process.stdout.write(output + '\n');
|
||||
};
|
||||
|
||||
/**
|
||||
* in this suite each test requires that there is one specific wallet present, thus, we import it
|
||||
* before anything else.
|
||||
|
@ -27,7 +36,7 @@ beforeAll(async () => {
|
|||
// reinstalling the app just for any case to clean up app's storage
|
||||
await device.launchApp({ delete: true });
|
||||
|
||||
console.log('before all - importing bip48...');
|
||||
console.log('before all - importing bip84...');
|
||||
await helperImportWallet(process.env.HD_MNEMONIC_BIP84, 'HDsegwitBech32', 'Imported HD SegWit (BIP84 Bech32 Native)', '0.00105526');
|
||||
console.log('...imported!');
|
||||
await device.pressBack();
|
||||
|
@ -711,4 +720,54 @@ describe('BlueWallet UI Tests - import BIP84 wallet', () => {
|
|||
|
||||
process.env.TRAVIS && require('fs').writeFileSync(lockFile, '1');
|
||||
});
|
||||
|
||||
it('can purge txs and balance, then refetch data from tx list screen and see data on screen update', async () => {
|
||||
const lockFile = '/tmp/travislock.' + hashIt('t24');
|
||||
if (process.env.TRAVIS) {
|
||||
if (require('fs').existsSync(lockFile)) return console.warn('skipping', JSON.stringify('t24'), 'as it previously passed on Travis');
|
||||
}
|
||||
if (!process.env.HD_MNEMONIC_BIP84) {
|
||||
console.error('process.env.HD_MNEMONIC_BIP84 not set, skipped');
|
||||
return;
|
||||
}
|
||||
|
||||
await device.launchApp({ newInstance: true });
|
||||
// go inside the wallet
|
||||
await element(by.text('Imported HD SegWit (BIP84 Bech32 Native)')).tap();
|
||||
await element(by.id('WalletDetails')).tap();
|
||||
|
||||
// tapping backdoor button to purge txs and balance:
|
||||
for (let c = 0; c <= 10; c++) {
|
||||
await element(by.id('PurgeBackdoorButton')).tap();
|
||||
await sleep(500);
|
||||
}
|
||||
|
||||
await waitForText('OK');
|
||||
await tapIfTextPresent('OK');
|
||||
|
||||
if (device.getPlatform() === 'ios') {
|
||||
console.warn('rest of the test is Android only, skipped');
|
||||
return;
|
||||
}
|
||||
|
||||
await device.pressBack();
|
||||
|
||||
// asserting there are no transactions and balance is 0:
|
||||
|
||||
await expect(element(by.id('WalletBalance'))).toHaveText('0');
|
||||
await waitForId('TransactionsListEmpty');
|
||||
assert.strictEqual(await countElements('TransactionListItem'), 0);
|
||||
|
||||
await element(by.id('TransactionsListView')).swipe('down', 'slow'); // pul-to-refresh
|
||||
|
||||
// asserting balance and txs loaded:
|
||||
await waitForText('0.00105526'); // the wait inside allows network request to propagate
|
||||
await waitFor(element(by.id('TransactionsListEmpty')))
|
||||
.not.toBeVisible()
|
||||
.withTimeout(25_000);
|
||||
await expect(element(by.id('WalletBalance'))).toHaveText('0.00105526');
|
||||
await expect(element(by.id('TransactionsListEmpty'))).not.toBeVisible();
|
||||
|
||||
assert.ok((await countElements('TransactionListItem')) >= 3); // 3 is arbitrary, real txs on screen depend on screen size
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,5 +1,13 @@
|
|||
import { hashIt, helperDeleteWallet, helperImportWallet, sleep, waitForId } from './helperz';
|
||||
|
||||
// if loglevel is set to `error`, this kind of logging will still get through
|
||||
console.warn = console.log = (...args) => {
|
||||
let output = '';
|
||||
args.map(arg => (output += String(arg)));
|
||||
|
||||
process.stdout.write(output + '\n');
|
||||
};
|
||||
|
||||
beforeAll(async () => {
|
||||
// reinstalling the app just for any case to clean up app's storage
|
||||
await device.launchApp({ delete: true });
|
||||
|
|
|
@ -228,3 +228,16 @@ export async function tapIfTextPresent(text) {
|
|||
} catch (_) {}
|
||||
// no need to check for visibility, just silently ignore exception if such testID is not present
|
||||
}
|
||||
|
||||
export async function countElements(testId) {
|
||||
let count = 0;
|
||||
while (true) {
|
||||
try {
|
||||
await expect(element(by.id(testId)).atIndex(count)).toExist();
|
||||
count++;
|
||||
} catch (_) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue