mirror of
https://github.com/Permissionless-Software-Foundation/psf-memo.git
synced 2026-09-21 16:52:01 -07:00
Implement like broadcast result modal
Keep the like/tip modal open after a successful like and show a broadcast result instead of closing: the success message, the like transaction id, and a link to that transaction on bch.loping.net that opens in a new tab. The like count and filled heart update immediately, and dismissing the result closes the modal. The result state lives on the testable LikeTipPage controller; a server-renderable LikeResult component backs the modal and the acceptance adapter, with acceptance step handlers for the new wording. By coder.
This commit is contained in:
@@ -55,6 +55,7 @@ const PollVotePage = require('../../src/services/poll-vote-page')
|
||||
const { renderPostText } = require('./render-post')
|
||||
const { renderAccountAvatar } = require('./render-account-avatar')
|
||||
const { renderPostOptions } = require('./render-post-options')
|
||||
const { renderLikeResult } = require('./render-like-result')
|
||||
const PostOptions = require('../../src/services/post-options')
|
||||
const { YOUTUBE_EMBED_BASE_URL } = require('../../src/services/youtube-embed')
|
||||
|
||||
@@ -1493,6 +1494,92 @@ const handlers = [
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'like/tip modal remains open',
|
||||
pattern: /^the like\/tip modal remains open$/,
|
||||
run (m, example, world) {
|
||||
if (!world.likeTipPage.modalOpen) {
|
||||
throw new Error('Expected like/tip modal to remain open.')
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'like/tip modal shows a broadcast success message',
|
||||
pattern: /^the like\/tip modal shows a broadcast success message$/,
|
||||
run (m, example, world) {
|
||||
const page = world.likeTipPage
|
||||
if (!page.showResultModal) {
|
||||
throw new Error('Expected the like broadcast result to be shown.')
|
||||
}
|
||||
const message = page.getBroadcastMessage()
|
||||
if (!message) {
|
||||
throw new Error('Expected a like broadcast success message.')
|
||||
}
|
||||
const html = renderLikeResult({
|
||||
txid: page.lastResult.txid,
|
||||
message,
|
||||
explorerUrl: page.explorerUrl(page.lastResult.txid)
|
||||
})
|
||||
if (!html.includes(message)) {
|
||||
throw new Error(`The rendered like result does not show the message "${message}".`)
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'like/tip modal shows the like transaction id',
|
||||
pattern: /^the like\/tip modal shows the like transaction id$/,
|
||||
run (m, example, world) {
|
||||
const page = world.likeTipPage
|
||||
if (!page.showResultModal || !page.lastResult || !page.lastResult.ok) {
|
||||
throw new Error('Expected a successful like broadcast result.')
|
||||
}
|
||||
const txid = page.lastResult.txid
|
||||
if (!txid) {
|
||||
throw new Error('Expected the like result to include a transaction id.')
|
||||
}
|
||||
const html = renderLikeResult({
|
||||
txid,
|
||||
message: page.getBroadcastMessage(),
|
||||
explorerUrl: page.explorerUrl(txid)
|
||||
})
|
||||
if (!html.includes(txid)) {
|
||||
throw new Error(`The rendered like result does not show the transaction id ${txid}.`)
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'like/tip modal shows a block explorer link',
|
||||
pattern: /^the like\/tip modal shows a link to the block explorer for the like transaction$/,
|
||||
run (m, example, world) {
|
||||
const page = world.likeTipPage
|
||||
if (!page.showResultModal || !page.lastResult || !page.lastResult.ok) {
|
||||
throw new Error('Expected a successful like broadcast result.')
|
||||
}
|
||||
const txid = page.lastResult.txid
|
||||
const url = page.explorerUrl(txid)
|
||||
if (!url.startsWith('https://bch.loping.net/tx/')) {
|
||||
throw new Error(`Expected a bch.loping.net explorer link, got "${url}".`)
|
||||
}
|
||||
const html = renderLikeResult({
|
||||
txid,
|
||||
message: page.getBroadcastMessage(),
|
||||
explorerUrl: url
|
||||
})
|
||||
if (!html.includes(`href="${url}"`)) {
|
||||
throw new Error(`The rendered like result does not link to ${url}.`)
|
||||
}
|
||||
if (!html.includes('target="_blank"')) {
|
||||
throw new Error('The rendered like explorer link does not open in a new tab.')
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'dismiss like result',
|
||||
pattern: /^I dismiss the like result$/,
|
||||
run (m, example, world) {
|
||||
world.likeTipPage.dismissResult()
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'API serves post with explicit address and like count',
|
||||
pattern: /^the psf-memo-db API serves a post with txid (.+) authored by the address (.+) with a like count of (.+)$/,
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
Acceptance rendering adapter for the like broadcast result.
|
||||
|
||||
Renders the same LikeResult component the browser uses to a static HTML
|
||||
string, so acceptance assertions can inspect the success message, the like
|
||||
transaction id, and the block explorer link without running a browser.
|
||||
*/
|
||||
|
||||
'use strict'
|
||||
|
||||
const React = require('react')
|
||||
const ReactDOMServer = require('react-dom/server')
|
||||
const LikeResult = require('../../src/components/post-feed/like-result')
|
||||
|
||||
function renderLikeResult ({ txid = '', message = '', explorerUrl = '' } = {}) {
|
||||
const element = React.createElement(LikeResult, { txid, message, explorerUrl })
|
||||
return ReactDOMServer.renderToStaticMarkup(element)
|
||||
}
|
||||
|
||||
module.exports = { renderLikeResult }
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
Broadcast result for a like/tip submission.
|
||||
|
||||
Shown after a like is broadcast: the success message, the like transaction
|
||||
id, and a link to that transaction on the block explorer. The link opens in
|
||||
a new tab.
|
||||
|
||||
Written in plain React.createElement style so the same module can be used by
|
||||
the JSX components in the browser build and by the acceptance adapter that
|
||||
renders HTML under Node.
|
||||
*/
|
||||
|
||||
const React = require('react')
|
||||
|
||||
function LikeResult ({ txid = '', message = '', explorerUrl = '' }) {
|
||||
return React.createElement(
|
||||
'div',
|
||||
{ className: 'like-result' },
|
||||
React.createElement('p', { className: 'like-result-message' }, message),
|
||||
txid
|
||||
? React.createElement(
|
||||
'p',
|
||||
{ className: 'like-result-txid mb-0' },
|
||||
'Transaction ID: ',
|
||||
React.createElement(
|
||||
'a',
|
||||
{
|
||||
href: explorerUrl,
|
||||
target: '_blank',
|
||||
rel: 'noopener noreferrer',
|
||||
style: { wordBreak: 'break-all' }
|
||||
},
|
||||
txid
|
||||
)
|
||||
)
|
||||
: null
|
||||
)
|
||||
}
|
||||
|
||||
module.exports = LikeResult
|
||||
@@ -12,6 +12,7 @@ import { Modal, Form, Button } from 'react-bootstrap'
|
||||
|
||||
import MemoLike from '../../services/memo-like'
|
||||
import LikeTipPage from '../../services/like-tip-page'
|
||||
import LikeResult from './like-result'
|
||||
import { getDisplayName } from './post-display'
|
||||
import './post-feed.css'
|
||||
|
||||
@@ -24,6 +25,8 @@ function LikeTipModal ({ show, post, wallet, profiles = {}, onHide, onSuccess })
|
||||
const [tip, setTip] = useState('')
|
||||
const [error, setError] = useState('')
|
||||
const [submitting, setSubmitting] = useState(false)
|
||||
const [resultTxid, setResultTxid] = useState('')
|
||||
const [showResult, setShowResult] = useState(false)
|
||||
|
||||
const displayName = post ? getDisplayName(post.addr, profiles) : ''
|
||||
|
||||
@@ -33,12 +36,16 @@ function LikeTipModal ({ show, post, wallet, profiles = {}, onHide, onSuccess })
|
||||
setTip('')
|
||||
setError('')
|
||||
setSubmitting(false)
|
||||
setResultTxid('')
|
||||
setShowResult(false)
|
||||
return
|
||||
}
|
||||
|
||||
setTip('')
|
||||
setError('')
|
||||
setSubmitting(false)
|
||||
setResultTxid('')
|
||||
setShowResult(false)
|
||||
|
||||
let cancelled = false
|
||||
|
||||
@@ -82,6 +89,8 @@ function LikeTipModal ({ show, post, wallet, profiles = {}, onHide, onSuccess })
|
||||
const result = await page.submit()
|
||||
if (result.ok) {
|
||||
setTip('')
|
||||
setResultTxid(result.txid)
|
||||
setShowResult(true)
|
||||
if (typeof onSuccess === 'function') {
|
||||
onSuccess()
|
||||
}
|
||||
@@ -95,12 +104,18 @@ function LikeTipModal ({ show, post, wallet, profiles = {}, onHide, onSuccess })
|
||||
}
|
||||
}
|
||||
|
||||
function handleCancel () {
|
||||
function handleDismiss () {
|
||||
setTip('')
|
||||
setError('')
|
||||
setResultTxid('')
|
||||
setShowResult(false)
|
||||
onHide()
|
||||
}
|
||||
|
||||
function handleCancel () {
|
||||
handleDismiss()
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal show={show} onHide={handleCancel} centered>
|
||||
<Modal.Header closeButton>
|
||||
@@ -108,47 +123,69 @@ function LikeTipModal ({ show, post, wallet, profiles = {}, onHide, onSuccess })
|
||||
</Modal.Header>
|
||||
|
||||
<Modal.Body>
|
||||
{post && (
|
||||
{post && !showResult && (
|
||||
<p className='like-tip-modal-target'>
|
||||
Like the post by <strong>{displayName}</strong>
|
||||
</p>
|
||||
)}
|
||||
|
||||
<Form onSubmit={(e) => { e.preventDefault(); handleSubmit() }}>
|
||||
<Form.Group controlId='like-tip-amount' className='mb-3'>
|
||||
<Form.Label>Tip (satoshis, optional)</Form.Label>
|
||||
<Form.Control
|
||||
type='number'
|
||||
min='0'
|
||||
step='1'
|
||||
placeholder='0'
|
||||
value={tip}
|
||||
onChange={(e) => {
|
||||
setTip(e.target.value)
|
||||
// Clear a previous validation error so the user can retry.
|
||||
setError('')
|
||||
}}
|
||||
disabled={submitting}
|
||||
{showResult
|
||||
? (
|
||||
<LikeResult
|
||||
txid={resultTxid}
|
||||
message={LikeTipPage.SUCCESS_MESSAGE}
|
||||
explorerUrl={LikeTipPage.explorerUrl(resultTxid)}
|
||||
/>
|
||||
</Form.Group>
|
||||
</Form>
|
||||
)
|
||||
: (
|
||||
<>
|
||||
<Form onSubmit={(e) => { e.preventDefault(); handleSubmit() }}>
|
||||
<Form.Group controlId='like-tip-amount' className='mb-3'>
|
||||
<Form.Label>Tip (satoshis, optional)</Form.Label>
|
||||
<Form.Control
|
||||
type='number'
|
||||
min='0'
|
||||
step='1'
|
||||
placeholder='0'
|
||||
value={tip}
|
||||
onChange={(e) => {
|
||||
setTip(e.target.value)
|
||||
// Clear a previous validation error so the user can retry.
|
||||
setError('')
|
||||
}}
|
||||
disabled={submitting}
|
||||
/>
|
||||
</Form.Group>
|
||||
</Form>
|
||||
|
||||
{error && (
|
||||
<p className='like-tip-modal-error text-danger'>{error}</p>
|
||||
)}
|
||||
{error && (
|
||||
<p className='like-tip-modal-error text-danger'>{error}</p>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</Modal.Body>
|
||||
|
||||
<Modal.Footer>
|
||||
<Button variant='secondary' onClick={handleCancel}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
variant='primary'
|
||||
onClick={handleSubmit}
|
||||
disabled={submitting || !post || !wallet}
|
||||
>
|
||||
{submitting ? 'Liking...' : 'Like'}
|
||||
</Button>
|
||||
{showResult
|
||||
? (
|
||||
<Button variant='primary' onClick={handleDismiss}>
|
||||
Close
|
||||
</Button>
|
||||
)
|
||||
: (
|
||||
<>
|
||||
<Button variant='secondary' onClick={handleCancel}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
variant='primary'
|
||||
onClick={handleSubmit}
|
||||
disabled={submitting || !post || !wallet}
|
||||
>
|
||||
{submitting ? 'Liking...' : 'Like'}
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</Modal.Footer>
|
||||
</Modal>
|
||||
)
|
||||
|
||||
@@ -77,9 +77,10 @@ function PostFeedItem ({
|
||||
}
|
||||
|
||||
const handleLikeSuccess = () => {
|
||||
// Reflect the like immediately. The modal stays open to show the
|
||||
// broadcast result until the user dismisses it.
|
||||
setLiked(true)
|
||||
setLikeCount((count) => count + 1)
|
||||
setShowLikeModal(false)
|
||||
}
|
||||
|
||||
const handleLikeModalHide = () => {
|
||||
|
||||
@@ -681,6 +681,18 @@
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
.like-result {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.like-result-message {
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
.like-result-txid {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.posts-feed-item-youtube {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
|
||||
const PageController = require('./page-controller')
|
||||
|
||||
const EXPLORER_TX_BASE = 'https://bch.loping.net/tx'
|
||||
const SUCCESS_MESSAGE = 'Your like was broadcast to the Bitcoin Cash network.'
|
||||
|
||||
class LikeTipPage extends PageController {
|
||||
constructor (deps = {}) {
|
||||
super(deps)
|
||||
@@ -25,6 +28,10 @@ class LikeTipPage extends PageController {
|
||||
this.authorAddress = deps.authorAddress || ''
|
||||
this.successPath = null
|
||||
this.validationCodes = ['like_validation', 'like_dust', 'like_maximum', 'like_balance', 'like_empty_balance']
|
||||
// After a broadcast, the like/tip modal stays open and shows the result
|
||||
// until the user dismisses it.
|
||||
this.showResultModal = false
|
||||
this.lastResult = null
|
||||
}
|
||||
|
||||
// Open the like/tip modal for a post and check that the wallet has enough
|
||||
@@ -33,6 +40,8 @@ class LikeTipPage extends PageController {
|
||||
this.postTxid = postTxid
|
||||
this.authorAddress = authorAddress
|
||||
this.modalOpen = true
|
||||
this.showResultModal = false
|
||||
this.lastResult = null
|
||||
this.submitError = null
|
||||
this.broadcastError = null
|
||||
|
||||
@@ -75,6 +84,38 @@ class LikeTipPage extends PageController {
|
||||
this.tipping = value
|
||||
}
|
||||
|
||||
// Submit the like. A successful broadcast leaves the modal open and shows
|
||||
// the broadcast result instead of closing or navigating. Validation and
|
||||
// broadcast failures stay on the form.
|
||||
async submit () {
|
||||
this.showResultModal = false
|
||||
this.lastResult = null
|
||||
const result = await super.submit()
|
||||
this.lastResult = result
|
||||
if (result.ok) {
|
||||
this.showResultModal = true
|
||||
this.modalOpen = true
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// The broadcast success message shown while the result is visible.
|
||||
getBroadcastMessage () {
|
||||
if (!this.lastResult || !this.lastResult.ok) return ''
|
||||
return SUCCESS_MESSAGE
|
||||
}
|
||||
|
||||
// Block explorer URL for a broadcast like transaction.
|
||||
explorerUrl (txid) {
|
||||
return LikeTipPage.explorerUrl(txid)
|
||||
}
|
||||
|
||||
// Dismiss the broadcast result. This closes the like/tip modal.
|
||||
dismissResult () {
|
||||
this.showResultModal = false
|
||||
this.close()
|
||||
}
|
||||
|
||||
// Parse a non-empty tip string into an integer number of satoshis.
|
||||
_parseTip (input) {
|
||||
if (input === '' || input === null || input === undefined) return 0
|
||||
@@ -104,3 +145,10 @@ class LikeTipPage extends PageController {
|
||||
}
|
||||
|
||||
module.exports = LikeTipPage
|
||||
|
||||
LikeTipPage.EXPLORER_TX_BASE = EXPLORER_TX_BASE
|
||||
LikeTipPage.SUCCESS_MESSAGE = SUCCESS_MESSAGE
|
||||
LikeTipPage.explorerUrl = function (txid) {
|
||||
if (!txid) return ''
|
||||
return `${EXPLORER_TX_BASE}/${txid}`
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
Unit tests for the like broadcast result component.
|
||||
|
||||
The component shows the broadcast success message, the like transaction id,
|
||||
and a link to that transaction on the block explorer that opens in a new tab.
|
||||
*/
|
||||
|
||||
'use strict'
|
||||
|
||||
const test = require('node:test')
|
||||
const assert = require('node:assert/strict')
|
||||
const React = require('react')
|
||||
const ReactDOMServer = require('react-dom/server')
|
||||
const LikeResult = require('../../src/components/post-feed/like-result')
|
||||
|
||||
const SAMPLE_TXID = '1111111111111111111111111111111111111111111111111111111111111111'
|
||||
const MESSAGE = 'Your like was broadcast to the Bitcoin Cash network.'
|
||||
const EXPLORER_URL = `https://bch.loping.net/tx/${SAMPLE_TXID}`
|
||||
|
||||
function renderResult (props = {}) {
|
||||
return ReactDOMServer.renderToStaticMarkup(
|
||||
React.createElement(LikeResult, {
|
||||
txid: SAMPLE_TXID,
|
||||
message: MESSAGE,
|
||||
explorerUrl: EXPLORER_URL,
|
||||
...props
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
test('renders the broadcast success message', () => {
|
||||
const html = renderResult()
|
||||
|
||||
assert.ok(html.includes(MESSAGE))
|
||||
})
|
||||
|
||||
test('renders the like transaction id', () => {
|
||||
const html = renderResult()
|
||||
|
||||
assert.ok(html.includes(SAMPLE_TXID))
|
||||
})
|
||||
|
||||
test('renders a link to the block explorer', () => {
|
||||
const html = renderResult()
|
||||
|
||||
assert.match(html, new RegExp(`href="${EXPLORER_URL}"`))
|
||||
})
|
||||
|
||||
test('the explorer link opens in a new tab', () => {
|
||||
const html = renderResult()
|
||||
|
||||
assert.match(html, /target="_blank"/)
|
||||
})
|
||||
|
||||
test('renders no link without a transaction id', () => {
|
||||
const html = renderResult({ txid: '' })
|
||||
|
||||
assert.ok(!html.includes('<a '))
|
||||
})
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
Unit tests for the like/tip page controller's broadcast result.
|
||||
|
||||
After a like is broadcast, the like/tip modal no longer closes
|
||||
automatically. The controller records the successful result and keeps the
|
||||
modal open so the modal can show a broadcast result (message, txid, and
|
||||
explorer link). Dismissing the result closes the modal.
|
||||
*/
|
||||
|
||||
'use strict'
|
||||
|
||||
const test = require('node:test')
|
||||
const assert = require('node:assert/strict')
|
||||
const LikeTipPage = require('../../src/services/like-tip-page')
|
||||
const MemoLike = require('../../src/services/memo-like')
|
||||
|
||||
const MY_ADDRESS = 'bitcoincash:qqlrzp23w08434twmvr4fxw672whkjy0py26r63g3d'
|
||||
const AUTHOR_ADDRESS = 'bitcoincash:qz7v6ztvzu2f2xd2ww8pnx9vwk0g4ncvfvavktg0jc'
|
||||
const SAMPLE_TXID = '1111111111111111111111111111111111111111111111111111111111111111'
|
||||
const LIKE_TXID = 'ab'.repeat(32)
|
||||
|
||||
function makeWallet () {
|
||||
return {
|
||||
walletInfo: { cashAddress: MY_ADDRESS },
|
||||
utxos: [{ txid: 'utxo', value: 100000 }],
|
||||
broadcasts: [],
|
||||
async getUtxos () {
|
||||
return this.utxos
|
||||
},
|
||||
async sendOpReturn (msg, prefix, bchOutput = []) {
|
||||
this.broadcasts.push({ msg, prefix, bchOutput })
|
||||
if (this.failWith) throw new Error(this.failWith)
|
||||
return LIKE_TXID
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function makePage (opts = {}) {
|
||||
const wallet = makeWallet()
|
||||
if (opts.failWith) wallet.failWith = opts.failWith
|
||||
const memoLike = new MemoLike({ wallet })
|
||||
return { wallet, page: new LikeTipPage({ memoLike }) }
|
||||
}
|
||||
|
||||
test('the result modal starts hidden', () => {
|
||||
const { page } = makePage()
|
||||
|
||||
assert.equal(page.showResultModal, false)
|
||||
assert.equal(page.lastResult, null)
|
||||
})
|
||||
|
||||
test('explorerUrl builds a bch.loping.net transaction link', () => {
|
||||
assert.equal(
|
||||
LikeTipPage.explorerUrl(SAMPLE_TXID),
|
||||
`https://bch.loping.net/tx/${SAMPLE_TXID}`
|
||||
)
|
||||
assert.equal(LikeTipPage.explorerUrl(''), '')
|
||||
|
||||
const { page } = makePage()
|
||||
assert.equal(page.explorerUrl(SAMPLE_TXID), LikeTipPage.explorerUrl(SAMPLE_TXID))
|
||||
})
|
||||
|
||||
test('SUCCESS_MESSAGE announces the broadcast', () => {
|
||||
assert.equal(typeof LikeTipPage.SUCCESS_MESSAGE, 'string')
|
||||
assert.match(LikeTipPage.SUCCESS_MESSAGE, /broadcast/i)
|
||||
})
|
||||
|
||||
test('a successful like keeps the modal open and shows the result', async () => {
|
||||
const { page } = makePage()
|
||||
page.open(SAMPLE_TXID, AUTHOR_ADDRESS)
|
||||
page.setTip('')
|
||||
|
||||
const result = await page.submit()
|
||||
|
||||
assert.equal(result.ok, true)
|
||||
assert.equal(result.txid, LIKE_TXID)
|
||||
assert.equal(page.modalOpen, true)
|
||||
assert.equal(page.showResultModal, true)
|
||||
assert.equal(page.lastResult.txid, LIKE_TXID)
|
||||
assert.equal(page.getBroadcastMessage(), LikeTipPage.SUCCESS_MESSAGE)
|
||||
})
|
||||
|
||||
test('dismissing the result closes the like/tip modal', async () => {
|
||||
const { page } = makePage()
|
||||
page.open(SAMPLE_TXID, AUTHOR_ADDRESS)
|
||||
page.setTip('')
|
||||
await page.submit()
|
||||
|
||||
page.dismissResult()
|
||||
|
||||
assert.equal(page.showResultModal, false)
|
||||
assert.equal(page.modalOpen, false)
|
||||
})
|
||||
|
||||
test('opening the modal clears any previous result', async () => {
|
||||
const { page } = makePage()
|
||||
page.open(SAMPLE_TXID, AUTHOR_ADDRESS)
|
||||
page.setTip('')
|
||||
await page.submit()
|
||||
|
||||
page.open(SAMPLE_TXID, AUTHOR_ADDRESS)
|
||||
|
||||
assert.equal(page.showResultModal, false)
|
||||
assert.equal(page.lastResult, null)
|
||||
})
|
||||
|
||||
test('a validation failure stays on the form and opens no result', async () => {
|
||||
const { page } = makePage()
|
||||
page.open(SAMPLE_TXID, AUTHOR_ADDRESS)
|
||||
page.setTip('abc')
|
||||
|
||||
const result = await page.submit()
|
||||
|
||||
assert.equal(result.ok, false)
|
||||
assert.equal(result.error, 'like_validation')
|
||||
assert.equal(page.modalOpen, true)
|
||||
assert.equal(page.showResultModal, false)
|
||||
assert.equal(page.lastResult.ok, false)
|
||||
})
|
||||
|
||||
test('a broadcast failure stays on the form and opens no result', async () => {
|
||||
const { page } = makePage({ failWith: 'Insufficient balance' })
|
||||
page.open(SAMPLE_TXID, AUTHOR_ADDRESS)
|
||||
page.setTip('')
|
||||
|
||||
const result = await page.submit()
|
||||
|
||||
assert.equal(result.ok, false)
|
||||
assert.equal(result.error, 'broadcast')
|
||||
assert.match(page.broadcastError, /Insufficient balance/)
|
||||
assert.equal(page.modalOpen, true)
|
||||
assert.equal(page.showResultModal, false)
|
||||
assert.equal(page.getBroadcastMessage(), '')
|
||||
})
|
||||
Reference in New Issue
Block a user