Changeset View
Changeset View
Standalone View
Standalone View
cashtab/src/components/Send/__tests__/SendByUrlParams.test.js
| Show First 20 Lines • Show All 86 Lines • ▼ Show 20 Lines | it('Legacy params. Address and value keys are set and valid.', async () => { | ||||
| expect( | expect( | ||||
| await screen.findByTitle('Balance XEC', {}, { timeout: 10000 }), | await screen.findByTitle('Balance XEC', {}, { timeout: 10000 }), | ||||
| ).toHaveTextContent('9,513.12 XEC'); | ).toHaveTextContent('9,513.12 XEC'); | ||||
| // Wait for ecashWallet to be initialized (component renders after ecashWallet is set) | // Wait for ecashWallet to be initialized (component renders after ecashWallet is set) | ||||
| const addressInputEl = await screen.findByPlaceholderText('Address'); | const addressInputEl = await screen.findByPlaceholderText('Address'); | ||||
| const amountInputEl = screen.getByPlaceholderText('Amount'); | const amountInputEl = screen.getByPlaceholderText('Amount'); | ||||
| // The "Send to Many" switch is disabled | |||||
| const toggleMultisend = await screen.findByTitle('Toggle Multisend'); | |||||
| expect(toggleMultisend).toHaveProperty('disabled', true); | |||||
| // The 'Send To' input field has this address as a value | // The 'Send To' input field has this address as a value | ||||
| await waitFor(() => | await waitFor(() => | ||||
| expect(addressInputEl).toHaveValue(destinationAddress), | expect(addressInputEl).toHaveValue(destinationAddress), | ||||
| ); | ); | ||||
| // The address input is disabled | // The address input is disabled | ||||
| expect(addressInputEl).toHaveProperty('disabled', true); | expect(addressInputEl).toHaveProperty('disabled', true); | ||||
| // The amount input is set to the expected value | // The amount input is set to the expected value | ||||
| ▲ Show 20 Lines • Show All 51 Lines • ▼ Show 20 Lines | it('Legacy params. Address and value keys are set and valid. Invalid bip21 string is ignored.', async () => { | ||||
| expect( | expect( | ||||
| await screen.findByTitle('Balance XEC', {}, { timeout: 10000 }), | await screen.findByTitle('Balance XEC', {}, { timeout: 10000 }), | ||||
| ).toHaveTextContent('9,513.12 XEC'); | ).toHaveTextContent('9,513.12 XEC'); | ||||
| // Wait for ecashWallet to be initialized (component renders after ecashWallet is set) | // Wait for ecashWallet to be initialized (component renders after ecashWallet is set) | ||||
| const addressInputEl = await screen.findByPlaceholderText('Address'); | const addressInputEl = await screen.findByPlaceholderText('Address'); | ||||
| const amountInputEl = screen.getByPlaceholderText('Amount'); | const amountInputEl = screen.getByPlaceholderText('Amount'); | ||||
| // The "Send to Many" switch is disabled | |||||
| const toggleMultisend = await screen.findByTitle('Toggle Multisend'); | |||||
| expect(toggleMultisend).toHaveProperty('disabled', true); | |||||
| // The 'Send To' input field has this address as a value | // The 'Send To' input field has this address as a value | ||||
| await waitFor(() => | await waitFor(() => | ||||
| expect(addressInputEl).toHaveValue(destinationAddress), | expect(addressInputEl).toHaveValue(destinationAddress), | ||||
| ); | ); | ||||
| // The address input is disabled | // The address input is disabled | ||||
| expect(addressInputEl).toHaveProperty('disabled', true); | expect(addressInputEl).toHaveProperty('disabled', true); | ||||
| // The amount input is filled out per legacy passed amount | // The amount input is filled out per legacy passed amount | ||||
| ▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | it('Legacy params. Address field is populated + disabled while value field is empty + enabled if legacy url params have address defined and value present as undefined', async () => { | ||||
| expect( | expect( | ||||
| await screen.findByTitle('Balance XEC', {}, { timeout: 10000 }), | await screen.findByTitle('Balance XEC', {}, { timeout: 10000 }), | ||||
| ).toHaveTextContent('9,513.12 XEC'); | ).toHaveTextContent('9,513.12 XEC'); | ||||
| // Wait for ecashWallet to be initialized (component renders after ecashWallet is set) | // Wait for ecashWallet to be initialized (component renders after ecashWallet is set) | ||||
| const addressInputEl = await screen.findByPlaceholderText('Address'); | const addressInputEl = await screen.findByPlaceholderText('Address'); | ||||
| const amountInputEl = screen.getByPlaceholderText('Amount'); | const amountInputEl = screen.getByPlaceholderText('Amount'); | ||||
| // The "Send to Many" switch is disabled | |||||
| const toggleMultisend = await screen.findByTitle('Toggle Multisend'); | |||||
| expect(toggleMultisend).toHaveProperty('disabled', true); | |||||
| // The 'Send To' input field has this address as a value | // The 'Send To' input field has this address as a value | ||||
| await waitFor(() => | await waitFor(() => | ||||
| expect(addressInputEl).toHaveValue(destinationAddress), | expect(addressInputEl).toHaveValue(destinationAddress), | ||||
| ); | ); | ||||
| // The address input is disabled | // The address input is disabled | ||||
| expect(addressInputEl).toHaveProperty('disabled', true); | expect(addressInputEl).toHaveProperty('disabled', true); | ||||
| // The amount input is empty | // The amount input is empty | ||||
| ▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | it('Legacy params. Address field is populated + disabled while value field is empty + enabled if legacy url params have address defined and no value key present', async () => { | ||||
| expect( | expect( | ||||
| await screen.findByTitle('Balance XEC', {}, { timeout: 10000 }), | await screen.findByTitle('Balance XEC', {}, { timeout: 10000 }), | ||||
| ).toHaveTextContent('9,513.12 XEC'); | ).toHaveTextContent('9,513.12 XEC'); | ||||
| // Wait for ecashWallet to be initialized (component renders after ecashWallet is set) | // Wait for ecashWallet to be initialized (component renders after ecashWallet is set) | ||||
| const addressInputEl = await screen.findByPlaceholderText('Address'); | const addressInputEl = await screen.findByPlaceholderText('Address'); | ||||
| const amountInputEl = screen.getByPlaceholderText('Amount'); | const amountInputEl = screen.getByPlaceholderText('Amount'); | ||||
| // The "Send to Many" switch is disabled | |||||
| const toggleMultisend = screen.getByTitle('Toggle Multisend'); | |||||
| await waitFor(() => expect(toggleMultisend).toBeDisabled()); | |||||
| // The 'Send To' input field has this address as a value | // The 'Send To' input field has this address as a value | ||||
| await waitFor(() => | await waitFor(() => | ||||
| expect(addressInputEl).toHaveValue(destinationAddress), | expect(addressInputEl).toHaveValue(destinationAddress), | ||||
| ); | ); | ||||
| // The address input is disabled | // The address input is disabled | ||||
| expect(addressInputEl).toHaveProperty('disabled', true); | expect(addressInputEl).toHaveProperty('disabled', true); | ||||
| // The amount input is empty | // The amount input is empty | ||||
| Show All 37 Lines | it('Legacy params. Params are ignored if only value param is present', async () => { | ||||
| screen.queryByTitle('Cashtab Loading'), | screen.queryByTitle('Cashtab Loading'), | ||||
| ).not.toBeInTheDocument(), | ).not.toBeInTheDocument(), | ||||
| ); | ); | ||||
| // Wait for ecashWallet to be initialized (component renders after ecashWallet is set) | // Wait for ecashWallet to be initialized (component renders after ecashWallet is set) | ||||
| const addressInputEl = await screen.findByPlaceholderText('Address'); | const addressInputEl = await screen.findByPlaceholderText('Address'); | ||||
| const amountInputEl = screen.getByPlaceholderText('Amount'); | const amountInputEl = screen.getByPlaceholderText('Amount'); | ||||
| // The "Send to Many" switch is not disabled | |||||
| expect(screen.getByTitle('Toggle Multisend')).toHaveProperty( | |||||
| 'disabled', | |||||
| false, | |||||
| ); | |||||
| // The 'Send To' input field is untouched | // The 'Send To' input field is untouched | ||||
| expect(addressInputEl).toHaveValue(''); | expect(addressInputEl).toHaveValue(''); | ||||
| // The address input is not disabled | // The address input is not disabled | ||||
| expect(addressInputEl).toHaveProperty('disabled', false); | expect(addressInputEl).toHaveProperty('disabled', false); | ||||
| // The amount input is empty | // The amount input is empty | ||||
| expect(amountInputEl).toHaveValue(null); | expect(amountInputEl).toHaveValue(null); | ||||
| // The amount input is not disabled | // The amount input is not disabled | ||||
| Show All 37 Lines | it('Legacy params. Params are ignored if param is duplicated', async () => { | ||||
| screen.queryByTitle('Cashtab Loading'), | screen.queryByTitle('Cashtab Loading'), | ||||
| ).not.toBeInTheDocument(), | ).not.toBeInTheDocument(), | ||||
| ); | ); | ||||
| // Wait for ecashWallet to be initialized (component renders after ecashWallet is set) | // Wait for ecashWallet to be initialized (component renders after ecashWallet is set) | ||||
| const addressInputEl = await screen.findByPlaceholderText('Address'); | const addressInputEl = await screen.findByPlaceholderText('Address'); | ||||
| const amountInputEl = screen.getByPlaceholderText('Amount'); | const amountInputEl = screen.getByPlaceholderText('Amount'); | ||||
| // The "Send to Many" switch is not disabled | |||||
| expect(screen.getByTitle('Toggle Multisend')).toHaveProperty( | |||||
| 'disabled', | |||||
| false, | |||||
| ); | |||||
| // The 'Send To' input field is untouched | // The 'Send To' input field is untouched | ||||
| expect(addressInputEl).toHaveValue(''); | expect(addressInputEl).toHaveValue(''); | ||||
| // The address input is not disabled | // The address input is not disabled | ||||
| expect(addressInputEl).toHaveProperty('disabled', false); | expect(addressInputEl).toHaveProperty('disabled', false); | ||||
| // The amount input is empty | // The amount input is empty | ||||
| expect(amountInputEl).toHaveValue(null); | expect(amountInputEl).toHaveValue(null); | ||||
| // The amount input is not disabled | // The amount input is not disabled | ||||
| ▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | it('Legacy params are not parsed as bip21 even if the bip21 param appears in the string', async () => { | ||||
| expect( | expect( | ||||
| await screen.findByTitle('Balance XEC', {}, { timeout: 10000 }), | await screen.findByTitle('Balance XEC', {}, { timeout: 10000 }), | ||||
| ).toHaveTextContent('9,513.12 XEC'); | ).toHaveTextContent('9,513.12 XEC'); | ||||
| // Wait for ecashWallet to be initialized (component renders after ecashWallet is set) | // Wait for ecashWallet to be initialized (component renders after ecashWallet is set) | ||||
| const addressInputEl = await screen.findByPlaceholderText('Address'); | const addressInputEl = await screen.findByPlaceholderText('Address'); | ||||
| const amountInputEl = screen.getByPlaceholderText('Amount'); | const amountInputEl = screen.getByPlaceholderText('Amount'); | ||||
| // The "Send to Many" switch is disabled | |||||
| const toggleMultisend = await screen.findByTitle('Toggle Multisend'); | |||||
| expect(toggleMultisend).toHaveProperty('disabled', true); | |||||
| // The 'Send To' input field has this address as a value | // The 'Send To' input field has this address as a value | ||||
| await waitFor(() => | await waitFor(() => | ||||
| expect(addressInputEl).toHaveValue(destinationAddress), | expect(addressInputEl).toHaveValue(destinationAddress), | ||||
| ); | ); | ||||
| // The address input is disabled | // The address input is disabled | ||||
| expect(addressInputEl).toHaveProperty('disabled', true); | expect(addressInputEl).toHaveProperty('disabled', true); | ||||
| // The amount input has the expected value | // The amount input has the expected value | ||||
| ▲ Show 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | it('bip21 param - valid bip21 param with amount and op_return_raw is parsed as expected', async () => { | ||||
| expect( | expect( | ||||
| await screen.findByTitle('Balance XEC', {}, { timeout: 10000 }), | await screen.findByTitle('Balance XEC', {}, { timeout: 10000 }), | ||||
| ).toHaveTextContent('9,513.12 XEC'); | ).toHaveTextContent('9,513.12 XEC'); | ||||
| // Wait for ecashWallet to be initialized (component renders after ecashWallet is set) | // Wait for ecashWallet to be initialized (component renders after ecashWallet is set) | ||||
| const addressInputEl = await screen.findByPlaceholderText('Address'); | const addressInputEl = await screen.findByPlaceholderText('Address'); | ||||
| const amountInputEl = screen.getByPlaceholderText('Amount'); | const amountInputEl = screen.getByPlaceholderText('Amount'); | ||||
| // The "Send to Many" switch is disabled | |||||
| const toggleMultisend = await screen.findByTitle('Toggle Multisend'); | |||||
| expect(toggleMultisend).toHaveProperty('disabled', true); | |||||
| // The 'Send To' input field has this address as a value | // The 'Send To' input field has this address as a value | ||||
| await waitFor(() => expect(addressInputEl).toHaveValue(bip21Str)); | await waitFor(() => expect(addressInputEl).toHaveValue(bip21Str)); | ||||
| // The address input is disabled for app txs with bip21 strings | // The address input is disabled for app txs with bip21 strings | ||||
| // Note it is NOT disabled for txs where the user inputs the bip21 string | // Note it is NOT disabled for txs where the user inputs the bip21 string | ||||
| // This is covered in SendXec.test.js | // This is covered in SendXec.test.js | ||||
| expect(addressInputEl).toHaveProperty('disabled', true); | expect(addressInputEl).toHaveProperty('disabled', true); | ||||
| // The "Send to Many" switch is disabled | |||||
| expect(screen.getByTitle('Toggle Multisend')).toHaveProperty( | |||||
| 'disabled', | |||||
| true, | |||||
| ); | |||||
| // Amount input is the valid amount param value | // Amount input is the valid amount param value | ||||
| expect(amountInputEl).toHaveValue(amount); | expect(amountInputEl).toHaveValue(amount); | ||||
| // The amount input is disabled because it is set by a bip21 query string | // The amount input is disabled because it is set by a bip21 query string | ||||
| expect(amountInputEl).toHaveProperty('disabled', true); | expect(amountInputEl).toHaveProperty('disabled', true); | ||||
| const opReturnRawInput = screen.getByPlaceholderText( | const opReturnRawInput = screen.getByPlaceholderText( | ||||
| `(Advanced) Enter raw hex to be included with this transaction's OP_RETURN`, | `(Advanced) Enter raw hex to be included with this transaction's OP_RETURN`, | ||||
| Show All 9 Lines | it('bip21 param - valid bip21 param with amount and op_return_raw is parsed as expected', async () => { | ||||
| for (const addrErr of SEND_ADDRESS_VALIDATION_ERRORS) { | for (const addrErr of SEND_ADDRESS_VALIDATION_ERRORS) { | ||||
| expect(screen.queryByText(addrErr)).not.toBeInTheDocument(); | expect(screen.queryByText(addrErr)).not.toBeInTheDocument(); | ||||
| } | } | ||||
| // No amount validation errors on load | // No amount validation errors on load | ||||
| for (const amountErr of SEND_AMOUNT_VALIDATION_ERRORS) { | for (const amountErr of SEND_AMOUNT_VALIDATION_ERRORS) { | ||||
| expect(screen.queryByText(amountErr)).not.toBeInTheDocument(); | expect(screen.queryByText(amountErr)).not.toBeInTheDocument(); | ||||
| } | } | ||||
| // The op_return_raw switch is disabled because we have txInfoFromUrl | |||||
| expect(screen.getByTitle('Toggle op_return_raw')).toHaveProperty( | |||||
| 'disabled', | |||||
| true, | |||||
| ); | |||||
| // The op_return_raw switch is checked because it is set by txInfoFromUrl | |||||
| expect(screen.getByTitle('Toggle op_return_raw')).toHaveProperty( | |||||
| 'checked', | |||||
| true, | |||||
| ); | |||||
| // We see the preview of this op_return_raw | // We see the preview of this op_return_raw | ||||
| expect( | expect( | ||||
| screen.getByText('cashtab message with op_return_raw'), | screen.getByText('cashtab message with op_return_raw'), | ||||
| ).toBeInTheDocument(); | ).toBeInTheDocument(); | ||||
| // The Send button is enabled as we have valid address and amount params | // The Send button is enabled as we have valid address and amount params | ||||
| expect( | expect( | ||||
| await screen.findByRole('button', { name: 'Accept' }), | await screen.findByRole('button', { name: 'Accept' }), | ||||
| ).not.toHaveStyle('cursor: not-allowed'); | ).not.toHaveStyle('cursor: not-allowed'); | ||||
| // The Cashtab Msg switch is disabled because we have txInfoFromUrl | |||||
| expect(screen.getByTitle('Toggle Cashtab Msg')).toHaveProperty( | |||||
| 'disabled', | |||||
| true, | |||||
| ); | |||||
| }); | }); | ||||
| it('bip21 param - an invalid bip21 param shows validation errors but cannot be changed', async () => { | it('bip21 param - an invalid bip21 param shows validation errors but cannot be changed', async () => { | ||||
| const destinationAddress = | const destinationAddress = | ||||
| 'ecash:qp33mh3a7qq7p8yulhnvwty2uq5ynukqcvuxmvzfhm'; | 'ecash:qp33mh3a7qq7p8yulhnvwty2uq5ynukqcvuxmvzfhm'; | ||||
| const amount = 17; | const amount = 17; | ||||
| const op_return_raw = | const op_return_raw = | ||||
| '04007461622263617368746162206d6573736167652077697468206f705f72657475726e5f726177'; | '04007461622263617368746162206d6573736167652077697468206f705f72657475726e5f726177'; | ||||
| // Repeat the op_return_raw param | // Repeat the op_return_raw param | ||||
| Show All 24 Lines | it('bip21 param - an invalid bip21 param shows validation errors but cannot be changed', async () => { | ||||
| expect( | expect( | ||||
| await screen.findByTitle('Balance XEC', {}, { timeout: 10000 }), | await screen.findByTitle('Balance XEC', {}, { timeout: 10000 }), | ||||
| ).toHaveTextContent('9,513.12 XEC'); | ).toHaveTextContent('9,513.12 XEC'); | ||||
| // Wait for ecashWallet to be initialized (component renders after ecashWallet is set) | // Wait for ecashWallet to be initialized (component renders after ecashWallet is set) | ||||
| const addressInputEl = await screen.findByPlaceholderText('Address'); | const addressInputEl = await screen.findByPlaceholderText('Address'); | ||||
| const amountInputEl = screen.getByPlaceholderText('Amount'); | const amountInputEl = screen.getByPlaceholderText('Amount'); | ||||
| // The "Send to Many" switch is disabled | |||||
| const toggleMultisend = await screen.findByTitle('Toggle Multisend'); | |||||
| expect(toggleMultisend).toHaveProperty('disabled', true); | |||||
| // The 'Send To' input field has this address as a value | // The 'Send To' input field has this address as a value | ||||
| await waitFor(() => expect(addressInputEl).toHaveValue(bip21Str)); | await waitFor(() => expect(addressInputEl).toHaveValue(bip21Str)); | ||||
| // The address input is disabled for app txs with bip21 strings | // The address input is disabled for app txs with bip21 strings | ||||
| // Note it is NOT disabled for txs where the user inputs the bip21 string | // Note it is NOT disabled for txs where the user inputs the bip21 string | ||||
| // This is covered in SendXec.test.js | // This is covered in SendXec.test.js | ||||
| expect(addressInputEl).toHaveProperty('disabled', true); | expect(addressInputEl).toHaveProperty('disabled', true); | ||||
| // The "Send to Many" switch is disabled | |||||
| expect(screen.getByTitle('Toggle Multisend')).toHaveProperty( | |||||
| 'disabled', | |||||
| true, | |||||
| ); | |||||
| // Amount input is updated despite invalid bip21 query, so the user can see the amount | // Amount input is updated despite invalid bip21 query, so the user can see the amount | ||||
| expect(amountInputEl).toHaveValue(amount); | expect(amountInputEl).toHaveValue(amount); | ||||
| // The amount input is disabled because it was set by a bip21 query string and URL routing | // The amount input is disabled because it was set by a bip21 query string and URL routing | ||||
| expect(amountInputEl).toHaveProperty('disabled', true); | expect(amountInputEl).toHaveProperty('disabled', true); | ||||
| // We get the expected validation error | // We get the expected validation error | ||||
| expect( | expect( | ||||
| screen.getByText( | screen.getByText( | ||||
| 'The op_return_raw param may not appear more than once', | 'The op_return_raw param may not appear more than once', | ||||
| ), | ), | ||||
| ).toBeInTheDocument(); | ).toBeInTheDocument(); | ||||
| // The Send button is disabled | // The Send button is disabled | ||||
| expect( | expect( | ||||
| await screen.findByRole('button', { name: 'Accept' }), | await screen.findByRole('button', { name: 'Accept' }), | ||||
| ).toHaveStyle('cursor: not-allowed'); | ).toHaveStyle('cursor: not-allowed'); | ||||
| // The Cashtab Msg switch is disabled because we have txInfoFromUrl | |||||
| expect(screen.getByTitle('Toggle Cashtab Msg')).toHaveProperty( | |||||
| 'disabled', | |||||
| true, | |||||
| ); | |||||
| }); | }); | ||||
| it('No params. Send screen loads normally with no rendered input.', async () => { | it('No params. Send screen loads normally with no rendered input.', async () => { | ||||
| const hash = `#/send`; | const hash = `#/send`; | ||||
| Object.defineProperty(window, 'location', { | Object.defineProperty(window, 'location', { | ||||
| value: { | value: { | ||||
| hash, | hash, | ||||
| }, | }, | ||||
| writable: true, // possibility to override | writable: true, // possibility to override | ||||
| Show All 11 Lines | it('No params. Send screen loads normally with no rendered input.', async () => { | ||||
| screen.queryByTitle('Cashtab Loading'), | screen.queryByTitle('Cashtab Loading'), | ||||
| ).not.toBeInTheDocument(), | ).not.toBeInTheDocument(), | ||||
| ); | ); | ||||
| // Wait for ecashWallet to be initialized (component renders after ecashWallet is set) | // Wait for ecashWallet to be initialized (component renders after ecashWallet is set) | ||||
| const addressInputEl = await screen.findByPlaceholderText('Address'); | const addressInputEl = await screen.findByPlaceholderText('Address'); | ||||
| const amountInputEl = screen.getByPlaceholderText('Amount'); | const amountInputEl = screen.getByPlaceholderText('Amount'); | ||||
| // The "Send to Many" switch is not disabled | |||||
| expect(screen.getByTitle('Toggle Multisend')).toHaveProperty( | |||||
| 'disabled', | |||||
| false, | |||||
| ); | |||||
| // The 'Send To' input field has this address as a value | // The 'Send To' input field has this address as a value | ||||
| expect(addressInputEl).toHaveValue(''); | expect(addressInputEl).toHaveValue(''); | ||||
| // The address input is not disabled | // The address input is not disabled | ||||
| expect(addressInputEl).toHaveProperty('disabled', false); | expect(addressInputEl).toHaveProperty('disabled', false); | ||||
| // The amount input is empty | // The amount input is empty | ||||
| expect(amountInputEl).toHaveValue(null); | expect(amountInputEl).toHaveValue(null); | ||||
| // The amount input is not disabled | // The amount input is not disabled | ||||
| expect(amountInputEl).toHaveProperty('disabled', false); | expect(amountInputEl).toHaveProperty('disabled', false); | ||||
| // The Send button is disabled | // The Send button is disabled (no URL params = regular Send flow, button says "Send") | ||||
| expect(await screen.findByRole('button', { name: 'Send' })).toHaveStyle( | expect(await screen.findByRole('button', { name: 'Send' })).toHaveStyle( | ||||
| 'cursor: not-allowed', | 'cursor: not-allowed', | ||||
| ); | ); | ||||
| // No addr validation errors on load | // No addr validation errors on load | ||||
| for (const addrErr of SEND_ADDRESS_VALIDATION_ERRORS) { | for (const addrErr of SEND_ADDRESS_VALIDATION_ERRORS) { | ||||
| expect(screen.queryByText(addrErr)).not.toBeInTheDocument(); | expect(screen.queryByText(addrErr)).not.toBeInTheDocument(); | ||||
| } | } | ||||
| Show All 37 Lines | it('bip21 param - valid bip21 param with amount, op_return_raw, and additional output with amount is parsed as expected', async () => { | ||||
| // Wait for balance to be loaded | // Wait for balance to be loaded | ||||
| expect( | expect( | ||||
| await screen.findByTitle('Balance XEC', {}, { timeout: 10000 }), | await screen.findByTitle('Balance XEC', {}, { timeout: 10000 }), | ||||
| ).toHaveTextContent('9,513.12 XEC'); | ).toHaveTextContent('9,513.12 XEC'); | ||||
| // Wait for ecashWallet to be initialized (component renders after ecashWallet is set) | // Wait for ecashWallet to be initialized (component renders after ecashWallet is set) | ||||
| const addressInputEl = await screen.findByPlaceholderText('Address'); | const addressInputEl = await screen.findByPlaceholderText('Address'); | ||||
| // The "Send to Many" switch is disabled | |||||
| expect(await screen.findByTitle('Toggle Multisend')).toBeDisabled(); | |||||
| // The 'Send To' input field has this address as a value | // The 'Send To' input field has this address as a value | ||||
| await waitFor(() => expect(addressInputEl).toHaveValue(bip21Str)); | await waitFor(() => expect(addressInputEl).toHaveValue(bip21Str)); | ||||
| // The address input is disabled for app txs with bip21 strings | // The address input is disabled for app txs with bip21 strings | ||||
| // Note it is NOT disabled for txs where the user inputs the bip21 string | // Note it is NOT disabled for txs where the user inputs the bip21 string | ||||
| // This is covered in SendXec.test.js | // This is covered in SendXec.test.js | ||||
| expect(addressInputEl).toHaveProperty('disabled', true); | expect(addressInputEl).toHaveProperty('disabled', true); | ||||
| // The "Send to Many" switch is disabled | |||||
| expect(screen.getByTitle('Toggle Multisend')).toHaveProperty( | |||||
| 'disabled', | |||||
| true, | |||||
| ); | |||||
| // Amount input is not displayed | // Amount input is not displayed | ||||
| expect(screen.queryByPlaceholderText('Amount')).not.toBeInTheDocument(); | expect(screen.queryByPlaceholderText('Amount')).not.toBeInTheDocument(); | ||||
| // Instead, we see a bip21 output summary | // Instead, we see a bip21 output summary | ||||
| expect( | expect( | ||||
| screen.getByText('BIP21: Sending 115.50 XEC to 2 outputs'), | screen.getByText('BIP21: Sending 115.50 XEC to 2 outputs'), | ||||
| ).toBeInTheDocument(); | ).toBeInTheDocument(); | ||||
| Show All 11 Lines | it('bip21 param - valid bip21 param with amount, op_return_raw, and additional output with amount is parsed as expected', async () => { | ||||
| for (const addrErr of SEND_ADDRESS_VALIDATION_ERRORS) { | for (const addrErr of SEND_ADDRESS_VALIDATION_ERRORS) { | ||||
| expect(screen.queryByText(addrErr)).not.toBeInTheDocument(); | expect(screen.queryByText(addrErr)).not.toBeInTheDocument(); | ||||
| } | } | ||||
| // No amount validation errors on load | // No amount validation errors on load | ||||
| for (const amountErr of SEND_AMOUNT_VALIDATION_ERRORS) { | for (const amountErr of SEND_AMOUNT_VALIDATION_ERRORS) { | ||||
| expect(screen.queryByText(amountErr)).not.toBeInTheDocument(); | expect(screen.queryByText(amountErr)).not.toBeInTheDocument(); | ||||
| } | } | ||||
| // The op_return_raw switch is disabled because we have txInfoFromUrl | |||||
| expect(screen.getByTitle('Toggle op_return_raw')).toHaveProperty( | |||||
| 'disabled', | |||||
| true, | |||||
| ); | |||||
| // The op_return_raw switch is checked because it is set by txInfoFromUrl | |||||
| expect(screen.getByTitle('Toggle op_return_raw')).toHaveProperty( | |||||
| 'checked', | |||||
| true, | |||||
| ); | |||||
| // We see the preview of this op_return_raw | // We see the preview of this op_return_raw | ||||
| expect(screen.getByText('Parsed op_return_raw')).toBeInTheDocument(); | expect(screen.getByText('Parsed op_return_raw')).toBeInTheDocument(); | ||||
| // The Send button is enabled as we have valid address and amount params | // The Send button is enabled as we have valid address and amount params | ||||
| expect( | expect( | ||||
| await screen.findByRole('button', { name: 'Accept' }), | await screen.findByRole('button', { name: 'Accept' }), | ||||
| ).not.toHaveStyle('cursor: not-allowed'); | ).not.toHaveStyle('cursor: not-allowed'); | ||||
| // The Cashtab Msg switch is disabled because we have txInfoFromUrl | |||||
| expect(screen.getByTitle('Toggle Cashtab Msg')).toHaveProperty( | |||||
| 'disabled', | |||||
| true, | |||||
| ); | |||||
| // We see expected summary of additional bip21 outputs | // We see expected summary of additional bip21 outputs | ||||
| expect(screen.getByText('Parsed BIP21 outputs')).toBeInTheDocument(); | expect(screen.getByText('Parsed BIP21 outputs')).toBeInTheDocument(); | ||||
| expect( | expect( | ||||
| screen.getByText(`qr6lws...6lyxkv, 110.00 XEC`), | screen.getByText(`qr6lws...6lyxkv, 110.00 XEC`), | ||||
| ).toBeInTheDocument(); | ).toBeInTheDocument(); | ||||
| expect( | expect( | ||||
| screen.getByText(`qp4dxt...qkrjp5, 5.50 XEC`), | screen.getByText(`qp4dxt...qkrjp5, 5.50 XEC`), | ||||
| ).toBeInTheDocument(); | ).toBeInTheDocument(); | ||||
| Show All 13 Lines | it('bip21 param - valid bip21 token send', async () => { | ||||
| }, | }, | ||||
| writable: true, | writable: true, | ||||
| }); | }); | ||||
| // Mock the app with context at the Send screen | // Mock the app with context at the Send screen | ||||
| const mockedChronik = await initializeCashtabStateForTests( | const mockedChronik = await initializeCashtabStateForTests( | ||||
| walletWithXecAndTokensActive, | walletWithXecAndTokensActive, | ||||
| localforage, | localforage, | ||||
| ); | ); | ||||
| mockedChronik.setTx(slp1FixedBear.tx.txid, slp1FixedBear.tx); | |||||
| mockedChronik.setToken(slp1FixedBear.tokenId, slp1FixedBear.token); | |||||
| render(<CashtabTestWrapper chronik={mockedChronik} route="/send" />); | render(<CashtabTestWrapper chronik={mockedChronik} route="/send" />); | ||||
| // Wait for the app to load | // Wait for the app to load | ||||
| await waitFor(() => | await waitFor(() => | ||||
| expect( | expect( | ||||
| screen.queryByTitle('Cashtab Loading'), | screen.queryByTitle('Cashtab Loading'), | ||||
| ).not.toBeInTheDocument(), | ).not.toBeInTheDocument(), | ||||
| ); | ); | ||||
| // Wait for balance to be loaded | // Wait for balance to be loaded | ||||
| expect( | expect( | ||||
| await screen.findByTitle('Balance XEC', {}, { timeout: 10000 }), | await screen.findByTitle('Balance XEC', {}, { timeout: 10000 }), | ||||
| ).toHaveTextContent('9,513.12 XEC'); | ).toHaveTextContent('9,513.12 XEC'); | ||||
| // Wait for token mode to be activated (toggle should be on "Tokens") | // BIP21 with token_id switches to token mode automatically | ||||
| // Wait for ecashWallet to be initialized first (component renders after ecashWallet is set) | // Wait for token mode UI and parsed tx to appear (confirms async token load completed) | ||||
| const tokenModeSwitch = await screen.findByTitle( | const { tokenName, tokenTicker } = slp1FixedBear.token.genesisInfo; | ||||
| 'Toggle XEC/Token Mode', | const addressPreview = `${destinationAddress.slice( | ||||
| 0, | |||||
| 'ecash:'.length + 3, | |||||
| )}...${destinationAddress.slice(-3)}`; | |||||
| await waitFor( | |||||
| () => | |||||
| expect( | |||||
| screen.getByText( | |||||
| `Sending ${token_decimalized_qty} ${tokenName} (${tokenTicker}) to ${addressPreview}`, | |||||
| ), | |||||
| ).toBeInTheDocument(), | |||||
| { timeout: 5000 }, | |||||
| ); | ); | ||||
| await waitFor(() => { | |||||
| expect(tokenModeSwitch).toHaveProperty('checked', true); | |||||
| }); | |||||
| // The "Send to Many" switch should not be visible in token mode | |||||
| expect(screen.queryByTitle('Toggle Multisend')).not.toBeInTheDocument(); | |||||
| // Get the token address input (in token mode) | // Get the token address input (in token mode) | ||||
| // Wait for ecashWallet to be initialized (component renders after ecashWallet is set) | const addressInputEl = screen.getByPlaceholderText('Address'); | ||||
| const addressInputEl = await screen.findByPlaceholderText('Address'); | |||||
| // The 'Send To' input field has this address as a value | // The 'Send To' input field has this address as a value | ||||
| await waitFor(() => expect(addressInputEl).toHaveValue(bip21Str)); | expect(addressInputEl).toHaveValue(bip21Str); | ||||
| // The address input is disabled for app txs with bip21 strings | // The address input is disabled for app txs with bip21 strings | ||||
| // Note it is NOT disabled for txs where the user inputs the bip21 string | // Note it is NOT disabled for txs where the user inputs the bip21 string | ||||
| // This is covered in SendXec.test.js | // This is covered in SendXec.test.js | ||||
| expect(addressInputEl).toBeDisabled(); | expect(addressInputEl).toBeDisabled(); | ||||
| // The token amount input is visible and populated from the BIP21 string | // The token amount input is visible and populated from the BIP21 string | ||||
| const amountInputEl = screen.getByPlaceholderText('Amount'); | const amountInputEl = screen.getByPlaceholderText('Amount'); | ||||
| expect(amountInputEl).toBeInTheDocument(); | expect(amountInputEl).toBeInTheDocument(); | ||||
| expect(amountInputEl).toHaveValue(token_decimalized_qty); | expect(amountInputEl).toHaveValue(token_decimalized_qty); | ||||
| // This input field should be disabled for URL-based transactions, because it is controlled by the bip21 string in the URL | // This input field should be disabled for URL-based transactions, because it is controlled by the bip21 string in the URL | ||||
| expect(amountInputEl).toBeDisabled(); | expect(amountInputEl).toBeDisabled(); | ||||
| // We do not see a token ID query error | // We do not see a token ID query error | ||||
| expect( | expect( | ||||
| screen.queryByText(`Error querying token info for ${token_id}`), | screen.queryByText(`Error querying token info for ${token_id}`), | ||||
| ).not.toBeInTheDocument(); | ).not.toBeInTheDocument(); | ||||
| // We see the parsed tx | |||||
| const { tokenName, tokenTicker } = slp1FixedBear.token.genesisInfo; | |||||
| const addressPreview = `${destinationAddress.slice( | |||||
| 0, | |||||
| 'ecash:'.length + 3, | |||||
| )}...${destinationAddress.slice(-3)}`; | |||||
| expect( | |||||
| screen.getByText( | |||||
| `Sending ${token_decimalized_qty} ${tokenName} (${tokenTicker}) to ${addressPreview}`, | |||||
| ), | |||||
| ).toBeInTheDocument(); | |||||
| // The send button is enabled as we have valid bip21 token send for a token qty supported | // The send button is enabled as we have valid bip21 token send for a token qty supported | ||||
| // by the wallet | // by the wallet | ||||
| expect(screen.getByRole('button', { name: 'Accept' })).toBeEnabled(); | expect(screen.getByRole('button', { name: 'Accept' })).toBeEnabled(); | ||||
| // The Cashtab Msg and op_return_raw switches are not visible in token mode | // The Cashtab Msg and op_return_raw switches are not visible in token mode | ||||
| expect( | expect( | ||||
| screen.queryByTitle('Toggle Cashtab Msg'), | screen.queryByTitle('Toggle Cashtab Msg'), | ||||
| ).not.toBeInTheDocument(); | ).not.toBeInTheDocument(); | ||||
| ▲ Show 20 Lines • Show All 69 Lines • ▼ Show 20 Lines | it('bip21 - ALP token send with firma param', async () => { | ||||
| // Wait for the app to load | // Wait for the app to load | ||||
| await waitFor(() => | await waitFor(() => | ||||
| expect( | expect( | ||||
| screen.queryByTitle('Cashtab Loading'), | screen.queryByTitle('Cashtab Loading'), | ||||
| ).not.toBeInTheDocument(), | ).not.toBeInTheDocument(), | ||||
| ); | ); | ||||
| // Wait for token mode to be activated (toggle should be on "Tokens") | // BIP21 with token_id switches to token mode automatically | ||||
| // Wait for ecashWallet to be initialized first (component renders after ecashWallet is set) | // Wait for token mode UI and parsed tx to appear | ||||
| const tokenModeSwitch = await screen.findByTitle( | const { tokenName, tokenTicker } = FIRMA.token.genesisInfo; | ||||
| 'Toggle XEC/Token Mode', | const addressPreview = `${destinationAddress.slice( | ||||
| 0, | |||||
| 'ecash:'.length + 3, | |||||
| )}...${destinationAddress.slice(-3)}`; | |||||
| await waitFor( | |||||
| () => | |||||
| expect( | |||||
| screen.getByText( | |||||
| `Sending ${token_decimalized_qty} ${tokenName} (${tokenTicker}) to ${addressPreview}`, | |||||
| ), | |||||
| ).toBeInTheDocument(), | |||||
| { timeout: 5000 }, | |||||
| ); | ); | ||||
| await waitFor(() => { | |||||
| expect(tokenModeSwitch).toHaveProperty('checked', true); | |||||
| }); | |||||
| // The "Send to Many" switch should not be visible in token mode | |||||
| expect(screen.queryByTitle('Toggle Multisend')).not.toBeInTheDocument(); | |||||
| // Get the token address input (in token mode) | // Get the token address input (in token mode) | ||||
| // Wait for ecashWallet to be initialized (component renders after ecashWallet is set) | const addressInputEl = screen.getByPlaceholderText('Address'); | ||||
| const addressInputEl = await screen.findByPlaceholderText('Address'); | |||||
| // The 'Send To' input field has this address as a value | // The 'Send To' input field has this address as a value | ||||
| await waitFor(() => expect(addressInputEl).toHaveValue(bip21Str)); | expect(addressInputEl).toHaveValue(bip21Str); | ||||
| // The address input is disabled for app txs with bip21 strings | // The address input is disabled for app txs with bip21 strings | ||||
| // Note it is NOT disabled for txs where the user inputs the bip21 string | |||||
| // This is covered in SendXec.test.js | |||||
| expect(addressInputEl).toBeDisabled(); | expect(addressInputEl).toBeDisabled(); | ||||
| // The token amount input is visible and populated from the BIP21 string | // The token amount input is visible and populated from the BIP21 string | ||||
| const amountInputEl = screen.getByPlaceholderText('Amount'); | const amountInputEl = screen.getByPlaceholderText('Amount'); | ||||
| expect(amountInputEl).toBeInTheDocument(); | expect(amountInputEl).toBeInTheDocument(); | ||||
| expect(amountInputEl).toHaveValue(token_decimalized_qty); | expect(amountInputEl).toHaveValue(token_decimalized_qty); | ||||
| // This input field should be disabled for URL-based transactions, because it is controlled by the bip21 string in the URL | |||||
| expect(amountInputEl).toBeDisabled(); | expect(amountInputEl).toBeDisabled(); | ||||
| // We do not see a token ID query error | // We do not see a token ID query error | ||||
| expect( | expect( | ||||
| screen.queryByText(`Error querying token info for ${token_id}`), | screen.queryByText(`Error querying token info for ${token_id}`), | ||||
| ).not.toBeInTheDocument(); | ).not.toBeInTheDocument(); | ||||
| // We see the parsed tx | // We see the parsed firma field for a valid solana address action | ||||
| const { tokenName, tokenTicker } = FIRMA.token.genesisInfo; | expect(screen.getByText('Parsed firma')).toBeInTheDocument(); | ||||
| const addressPreview = `${destinationAddress.slice( | expect(screen.getByText('Solana Address')).toBeInTheDocument(); | ||||
| 0, | |||||
| 'ecash:'.length + 3, | |||||
| )}...${destinationAddress.slice(-3)}`; | |||||
| expect( | expect( | ||||
| screen.getByText( | screen.getByText('6JKwz43wDTgk5n8eNCJrtsnNtkDdKd1XUZAvB9WkiEQ4'), | ||||
| `Sending ${token_decimalized_qty} ${tokenName} (${tokenTicker}) to ${addressPreview}`, | |||||
| ), | |||||
| ).toBeInTheDocument(); | ).toBeInTheDocument(); | ||||
| // The send button is enabled as we have valid bip21 token send for a token qty supported | // The send button is enabled | ||||
| // by the wallet | |||||
| expect(screen.getByRole('button', { name: 'Accept' })).toBeEnabled(); | expect(screen.getByRole('button', { name: 'Accept' })).toBeEnabled(); | ||||
| // The Cashtab Msg and op_return_raw switches are not visible in token mode | // The Cashtab Msg and op_return_raw switches are not visible in token mode | ||||
| expect( | expect( | ||||
| screen.queryByTitle('Toggle Cashtab Msg'), | screen.queryByTitle('Toggle Cashtab Msg'), | ||||
| ).not.toBeInTheDocument(); | ).not.toBeInTheDocument(); | ||||
| expect( | expect( | ||||
| screen.queryByTitle('Toggle op_return_raw'), | screen.queryByTitle('Toggle op_return_raw'), | ||||
| ).not.toBeInTheDocument(); | ).not.toBeInTheDocument(); | ||||
| // We see the parsed firma field for a valid solana address action | |||||
| expect(screen.getByText('Parsed firma')).toBeInTheDocument(); | |||||
| expect(screen.getByText('Solana Address')).toBeInTheDocument(); | |||||
| expect( | |||||
| screen.getByText('6JKwz43wDTgk5n8eNCJrtsnNtkDdKd1XUZAvB9WkiEQ4'), | |||||
| ).toBeInTheDocument(); | |||||
| }); | }); | ||||
| it('bip21 - valid FIRMA-USDT redeem tx', async () => { | it('bip21 - valid FIRMA-USDT redeem tx', async () => { | ||||
| const destinationAddress = FIRMA_REDEEM_ADDRESS; | const destinationAddress = FIRMA_REDEEM_ADDRESS; | ||||
| const token_id = FIRMA.tokenId; | const token_id = FIRMA.tokenId; | ||||
| const token_decimalized_qty = '5'; | const token_decimalized_qty = '5'; | ||||
| // Cashtab msg | // Cashtab msg | ||||
| const firma = | const firma = | ||||
| '534f4c304ebabba2b443691c1a9180426004d5fd3419e9f9c64e5839b853cecdaacbf745'; | '534f4c304ebabba2b443691c1a9180426004d5fd3419e9f9c64e5839b853cecdaacbf745'; | ||||
| Show All 19 Lines | it('bip21 - valid FIRMA-USDT redeem tx', async () => { | ||||
| // Wait for the app to load | // Wait for the app to load | ||||
| await waitFor(() => | await waitFor(() => | ||||
| expect( | expect( | ||||
| screen.queryByTitle('Cashtab Loading'), | screen.queryByTitle('Cashtab Loading'), | ||||
| ).not.toBeInTheDocument(), | ).not.toBeInTheDocument(), | ||||
| ); | ); | ||||
| // Wait for token mode to be activated (toggle should be on "Tokens") | // BIP21 with token_id switches to token mode automatically | ||||
| // Wait for ecashWallet to be initialized first (component renders after ecashWallet is set) | // Wait for firma redeem tx UI to appear | ||||
| const tokenModeSwitch = await screen.findByTitle( | await waitFor( | ||||
| 'Toggle XEC/Token Mode', | () => { | ||||
| expect(screen.getByAltText('Firma reward')).toBeInTheDocument(); | |||||
| expect( | |||||
| screen.getByAltText('USDT Tether logo'), | |||||
| ).toBeInTheDocument(); | |||||
| }, | |||||
| { timeout: 5000 }, | |||||
| ); | ); | ||||
| await waitFor(() => { | |||||
| expect(tokenModeSwitch).toHaveProperty('checked', true); | |||||
| }); | |||||
| // The "Send to Many" switch should not be visible in token mode | |||||
| expect(screen.queryByTitle('Toggle Multisend')).not.toBeInTheDocument(); | |||||
| // Get the token address input (in token mode) | // Get the token address input (in token mode) | ||||
| // Wait for ecashWallet to be initialized (component renders after ecashWallet is set) | const addressInputEl = screen.getByPlaceholderText('Address'); | ||||
| const addressInputEl = await screen.findByPlaceholderText('Address'); | |||||
| // The 'Send To' input field has this address as a value | // The 'Send To' input field has this address as a value | ||||
| await waitFor(() => expect(addressInputEl).toHaveValue(bip21Str)); | expect(addressInputEl).toHaveValue(bip21Str); | ||||
| // The address input is disabled for app txs with bip21 strings | // The address input is disabled for app txs with bip21 strings | ||||
| // Note it is NOT disabled for txs where the user inputs the bip21 string | |||||
| // This is covered in SendXec.test.js | |||||
| expect(addressInputEl).toBeDisabled(); | expect(addressInputEl).toBeDisabled(); | ||||
| // The token amount input is visible and populated from the BIP21 string | // The token amount input is visible and populated from the BIP21 string | ||||
| const amountInputEl = screen.getByPlaceholderText('Amount'); | const amountInputEl = screen.getByPlaceholderText('Amount'); | ||||
| expect(amountInputEl).toBeInTheDocument(); | expect(amountInputEl).toBeInTheDocument(); | ||||
| expect(amountInputEl).toHaveValue(token_decimalized_qty); | expect(amountInputEl).toHaveValue(token_decimalized_qty); | ||||
| // This input field should be disabled for URL-based transactions, because it is controlled by the bip21 string in the URL | |||||
| expect(amountInputEl).toBeDisabled(); | expect(amountInputEl).toBeDisabled(); | ||||
| // We do not see a token ID query error | // We do not see a token ID query error | ||||
| expect( | expect( | ||||
| screen.queryByText(`Error querying token info for ${token_id}`), | screen.queryByText(`Error querying token info for ${token_id}`), | ||||
| ).not.toBeInTheDocument(); | ).not.toBeInTheDocument(); | ||||
| // We see the valid firma redeem tx info, accounting for the fee | // We see the valid firma redeem tx info, accounting for the fee | ||||
| ▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | it('bip21 - SLP token send with empp_raw shows error', async () => { | ||||
| ).not.toBeInTheDocument(), | ).not.toBeInTheDocument(), | ||||
| ); | ); | ||||
| // Wait for balance to be loaded | // Wait for balance to be loaded | ||||
| expect( | expect( | ||||
| await screen.findByTitle('Balance XEC', {}, { timeout: 10000 }), | await screen.findByTitle('Balance XEC', {}, { timeout: 10000 }), | ||||
| ).toHaveTextContent('9,513.12 XEC'); | ).toHaveTextContent('9,513.12 XEC'); | ||||
| // Wait for token mode to be activated (toggle should be on "Tokens") | // BIP21 with token_id switches to token mode automatically | ||||
| // Wait for ecashWallet to be initialized first (component renders after ecashWallet is set) | // Wait for token info to load (check for parsed tx info) | ||||
| const tokenModeSwitch = await screen.findByTitle( | const { tokenName, tokenTicker } = slp1FixedBear.token.genesisInfo; | ||||
| 'Toggle XEC/Token Mode', | const addressPreview = `${destinationAddress.slice( | ||||
| 0, | |||||
| 'ecash:'.length + 3, | |||||
| )}...${destinationAddress.slice(-3)}`; | |||||
| await waitFor( | |||||
| () => | |||||
| expect( | |||||
| screen.getByText( | |||||
| `Sending ${token_decimalized_qty} ${tokenName} (${tokenTicker}) to ${addressPreview}`, | |||||
| ), | |||||
| ).toBeInTheDocument(), | |||||
| { timeout: 5000 }, | |||||
| ); | ); | ||||
| await waitFor(() => { | |||||
| expect(tokenModeSwitch).toHaveProperty('checked', true); | |||||
| }); | |||||
| // The "Send to Many" switch should not be visible in token mode | |||||
| expect(screen.queryByTitle('Toggle Multisend')).not.toBeInTheDocument(); | |||||
| // Get the token address input (in token mode) | // Get the token address input (in token mode) | ||||
| // Wait for ecashWallet to be initialized (component renders after ecashWallet is set) | const addressInputEl = screen.getByPlaceholderText('Address'); | ||||
| const addressInputEl = await screen.findByPlaceholderText('Address'); | |||||
| // The 'Send To' input field has this address as a value | // The 'Send To' input field has this address as a value | ||||
| await waitFor(() => expect(addressInputEl).toHaveValue(bip21Str)); | expect(addressInputEl).toHaveValue(bip21Str); | ||||
| // The address input is disabled for app txs with bip21 strings | // The address input is disabled for app txs with bip21 strings | ||||
| expect(addressInputEl).toBeDisabled(); | expect(addressInputEl).toBeDisabled(); | ||||
| // The token amount input is visible and populated from the BIP21 string | // The token amount input is visible and populated from the BIP21 string | ||||
| const amountInputEl = screen.getByPlaceholderText('Amount'); | const amountInputEl = screen.getByPlaceholderText('Amount'); | ||||
| expect(amountInputEl).toBeInTheDocument(); | expect(amountInputEl).toBeInTheDocument(); | ||||
| expect(amountInputEl).toHaveValue(token_decimalized_qty); | expect(amountInputEl).toHaveValue(token_decimalized_qty); | ||||
| expect(amountInputEl).toBeDisabled(); | expect(amountInputEl).toBeDisabled(); | ||||
| // We do not see a token ID query error | // We do not see a token ID query error | ||||
| expect( | expect( | ||||
| screen.queryByText(`Error querying token info for ${token_id}`), | screen.queryByText(`Error querying token info for ${token_id}`), | ||||
| ).not.toBeInTheDocument(); | ).not.toBeInTheDocument(); | ||||
| // Wait for token info to load (check for parsed tx info) | |||||
| const { tokenName, tokenTicker } = slp1FixedBear.token.genesisInfo; | |||||
| const addressPreview = `${destinationAddress.slice( | |||||
| 0, | |||||
| 'ecash:'.length + 3, | |||||
| )}...${destinationAddress.slice(-3)}`; | |||||
| await waitFor(() => { | |||||
| expect( | |||||
| screen.getByText( | |||||
| `Sending ${token_decimalized_qty} ${tokenName} (${tokenTicker}) to ${addressPreview}`, | |||||
| ), | |||||
| ).toBeInTheDocument(); | |||||
| }); | |||||
| // Wait for validation error to appear | // Wait for validation error to appear | ||||
| await waitFor(() => { | await waitFor(() => { | ||||
| // We see the error message for empp_raw with non-ALP token | // We see the error message for empp_raw with non-ALP token | ||||
| expect( | expect( | ||||
| screen.getByText( | screen.getByText( | ||||
| 'empp_raw is only supported for ALP token txs', | 'empp_raw is only supported for ALP token txs', | ||||
| ), | ), | ||||
| ).toBeInTheDocument(); | ).toBeInTheDocument(); | ||||
| ▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | it('bip21 - ALP token send with empp_raw cashtab msg', async () => { | ||||
| ).not.toBeInTheDocument(), | ).not.toBeInTheDocument(), | ||||
| ); | ); | ||||
| // Wait for balance to be loaded | // Wait for balance to be loaded | ||||
| expect( | expect( | ||||
| await screen.findByTitle('Balance XEC', {}, { timeout: 10000 }), | await screen.findByTitle('Balance XEC', {}, { timeout: 10000 }), | ||||
| ).toHaveTextContent('9,970.81 XEC'); | ).toHaveTextContent('9,970.81 XEC'); | ||||
| // Wait for token mode to be activated (toggle should be on "Tokens") | // BIP21 with token_id switches to token mode automatically | ||||
| const tokenModeSwitch = await screen.findByTitle( | // Wait for token mode UI and parsed tx to appear | ||||
| 'Toggle XEC/Token Mode', | const { tokenName, tokenTicker } = FIRMA.token.genesisInfo; | ||||
| const addressPreview = `${destinationAddress.slice( | |||||
| 0, | |||||
| 'ecash:'.length + 3, | |||||
| )}...${destinationAddress.slice(-3)}`; | |||||
| await waitFor( | |||||
| () => | |||||
| expect( | |||||
| screen.getByText( | |||||
| `Sending ${token_decimalized_qty} ${tokenName} (${tokenTicker}) to ${addressPreview}`, | |||||
| ), | |||||
| ).toBeInTheDocument(), | |||||
| { timeout: 5000 }, | |||||
| ); | ); | ||||
| await waitFor(() => { | |||||
| expect(tokenModeSwitch).toHaveProperty('checked', true); | |||||
| }); | |||||
| // The "Send to Many" switch should not be visible in token mode | |||||
| expect(screen.queryByTitle('Toggle Multisend')).not.toBeInTheDocument(); | |||||
| // Get the token address input (in token mode) | // Get the token address input (in token mode) | ||||
| const addressInputEl = await screen.findByPlaceholderText('Address'); | const addressInputEl = screen.getByPlaceholderText('Address'); | ||||
| // The 'Send To' input field has this address as a value | // The 'Send To' input field has this address as a value | ||||
| await waitFor(() => expect(addressInputEl).toHaveValue(bip21Str)); | expect(addressInputEl).toHaveValue(bip21Str); | ||||
| // The address input is disabled for app txs with bip21 strings | // The address input is disabled for app txs with bip21 strings | ||||
| expect(addressInputEl).toBeDisabled(); | expect(addressInputEl).toBeDisabled(); | ||||
| // The token amount input is visible and populated from the BIP21 string | // The token amount input is visible and populated from the BIP21 string | ||||
| const amountInputEl = screen.getByPlaceholderText('Amount'); | const amountInputEl = screen.getByPlaceholderText('Amount'); | ||||
| expect(amountInputEl).toBeInTheDocument(); | expect(amountInputEl).toBeInTheDocument(); | ||||
| expect(amountInputEl).toHaveValue(token_decimalized_qty); | expect(amountInputEl).toHaveValue(token_decimalized_qty); | ||||
| expect(amountInputEl).toBeDisabled(); | expect(amountInputEl).toBeDisabled(); | ||||
| // We do not see a token ID query error | // We do not see a token ID query error | ||||
| expect( | expect( | ||||
| screen.queryByText(`Error querying token info for ${token_id}`), | screen.queryByText(`Error querying token info for ${token_id}`), | ||||
| ).not.toBeInTheDocument(); | ).not.toBeInTheDocument(); | ||||
| // Wait for token info to load (check for parsed tx info) | |||||
| const { tokenName, tokenTicker } = FIRMA.token.genesisInfo; | |||||
| const addressPreview = `${destinationAddress.slice( | |||||
| 0, | |||||
| 'ecash:'.length + 3, | |||||
| )}...${destinationAddress.slice(-3)}`; | |||||
| await waitFor(() => { | |||||
| expect( | |||||
| screen.getByText( | |||||
| `Sending ${token_decimalized_qty} ${tokenName} (${tokenTicker}) to ${addressPreview}`, | |||||
| ), | |||||
| ).toBeInTheDocument(); | |||||
| }); | |||||
| // Wait for parsed empp_raw info to appear | // Wait for parsed empp_raw info to appear | ||||
| await waitFor(() => { | await waitFor(() => { | ||||
| expect(screen.getByText('Parsed empp_raw')).toBeInTheDocument(); | expect(screen.getByText('Parsed empp_raw')).toBeInTheDocument(); | ||||
| }); | }); | ||||
| // We see the parsed empp_raw as a cashtab msg (the switch label and the parsed empp raw) | // We see the parsed empp_raw as a cashtab msg (the switch label and the parsed empp raw) | ||||
| expect(screen.getAllByText('Cashtab Msg')).toHaveLength(2); | expect(screen.getAllByText('Cashtab Msg')).toHaveLength(2); | ||||
| // We parse the empp_raw Cashtab msg | // We parse the empp_raw Cashtab msg | ||||
| expect(screen.getByText('test message')).toBeInTheDocument(); | expect(screen.getByText('test message')).toBeInTheDocument(); | ||||
| // The send button is enabled | // The send button is enabled | ||||
| expect( | expect( | ||||
| await screen.findByRole('button', { name: 'Accept' }), | await screen.findByRole('button', { name: 'Accept' }), | ||||
| ).toBeEnabled(); | ).toBeEnabled(); | ||||
| }); | }); | ||||
| }); | }); | ||||