Files
psf-memo-client/test/unit/memo-action-helpers.js
T
Chris Troutner b4508e8909 Reduce DRY duplication in reply-memo tests
Refactor the coder's new memo-reply and reply-thread-page tests to use
the shared test helpers (fake wallet, MemoAction tests, page-controller
tests, page submit tests, page build wiring). Extend the memo-action and
page-build helpers to support the reply slice's extra parent-txid
argument and byte-based multi-byte tests. Behavior is preserved; all
unit, property, and acceptance tests pass.

By refactorer.
2026-08-25 21:15:07 -07:00

108 lines
4.1 KiB
JavaScript

'use strict'
const test = require('node:test')
const assert = require('node:assert/strict')
const { fakeWallet } = require('../helpers/fake-wallet')
// Register the MemoAction tests shared by the Memo post and Set Name slices.
// Both slices broadcast a value through a wallet and reflect the result on an
// injected store, so the maximum-length and over-length behaviors are
// identical; only the slice-specific pieces differ. `cfg` supplies:
// Action - the action class (MemoPost or MemoSetName)
// method - the broadcast method name ('post' or 'setName')
// MAX - the length limit
// lengthCode - the length error code
// validationCode - the validation error code
// label - a short label for test names
// storeKey - the action's store dependency key ('feed' or 'profiles')
// storeFactory - () => a fresh store
// assertStoreEmpty - (store, wallet) => asserts the store was not updated
// assertBroadcastMsg - (broadcast, value) => asserts the broadcast message
// byteBased - true when the slice counts bytes (registers multi-byte tests)
// extraArgs - extra arguments passed to the broadcast method after the value
function registerMemoActionTests (cfg) {
const { Action, method, MAX, lengthCode, validationCode, label, storeKey, storeFactory, assertStoreEmpty, assertBroadcastMsg, byteBased = false, extraArgs = [] } = cfg
const checkBroadcastMsg = assertBroadcastMsg || ((broadcast, value) => assert.equal(broadcast.msg, value))
test(`${label} at the maximum length (${MAX}) is accepted`, async () => {
const wallet = fakeWallet()
const action = new Action({ wallet })
const value = 'x'.repeat(MAX)
const txid = await action[method](value, ...extraArgs)
assert.equal(txid, 'fake-txid')
checkBroadcastMsg(wallet.broadcasts[0], value)
})
test(`${label} over the limit (${MAX + 1}) throws a length error and broadcasts nothing`, async () => {
const wallet = fakeWallet()
const store = storeFactory()
const action = new Action({ wallet, [storeKey]: store })
await assert.rejects(
action[method]('y'.repeat(MAX + 1), ...extraArgs),
(err) => err.code === lengthCode
)
assert.equal(wallet.broadcasts.length, 0)
assertStoreEmpty(store, wallet)
})
test(`${label} that is whitespace-only or non-string throws a validation error and broadcasts nothing`, async () => {
for (const invalid of [' ', 42]) {
const wallet = fakeWallet()
const action = new Action({ wallet })
await assert.rejects(
action[method](invalid, ...extraArgs),
(err) => err.code === validationCode
)
assert.equal(wallet.broadcasts.length, 0)
}
})
test(`${label} that is empty throws a validation error and broadcasts nothing`, async () => {
const wallet = fakeWallet()
const store = storeFactory()
const action = new Action({ wallet, [storeKey]: store })
await assert.rejects(
action[method]('', ...extraArgs),
(err) => err.code === validationCode
)
assert.equal(wallet.broadcasts.length, 0)
assertStoreEmpty(store, wallet)
})
if (byteBased) {
test(`${label} with multi-byte characters at the byte limit is accepted`, async () => {
const wallet = fakeWallet()
const action = new Action({ wallet })
// 'é' encodes to 2 UTF-8 bytes, so floor(MAX/2) characters reach the limit.
const count = Math.floor(MAX / 2)
const value = 'é'.repeat(count)
assert.equal(Buffer.byteLength(value, 'utf8'), count * 2)
const txid = await action[method](value, ...extraArgs)
assert.equal(txid, 'fake-txid')
})
test(`${label} with multi-byte characters that exceed the byte limit throws a length error`, async () => {
const wallet = fakeWallet()
const action = new Action({ wallet })
const count = Math.floor(MAX / 2) + 1
const value = 'é'.repeat(count)
assert.ok(Buffer.byteLength(value, 'utf8') > MAX)
await assert.rejects(
action[method](value, ...extraArgs),
(err) => err.code === lengthCode
)
assert.equal(wallet.broadcasts.length, 0)
})
}
}
module.exports = { registerMemoActionTests }