mirror of
https://github.com/Permissionless-Software-Foundation/psf-memo.git
synced 2026-09-21 16:52:01 -07:00
Review txid wire encoding: harden mutation coverage and DRY test doubles
Refresh the mutate4javascript and Gherkin acceptance-mutation manifests, kill the memo-like/memo-reply boundary survivors, and extract the shared FakeDb/makeLevel double used by the txid repair unit and property tests. By architect.
This commit is contained in:
@@ -1,3 +1,7 @@
|
||||
# acceptance-mutation-manifest-begin
|
||||
# {"version":1,"tested_at":"2026-09-16T22:22:12.675245296Z","feature_name":"Txid wire encoding","feature_path":"/home/trout/work/psf-memo/.worktrees/architect/psf-memo-client/specs/txid-wire-encoding.feature","background_hash":"e1d5f81f1ed083ac6934c429ca3cb4a0f8d4dac44c2eaa45c0960920bde2c017","implementation_hash":"unknown","scenarios":[{"index":0,"name":"Txid wire encoding - 1 a like broadcasts the post txid in little-endian wire order","scenario_hash":"42f1932ce013d74c217b8becad4e7f496e84e5236a2728dcc2418b57d67bd6e6","mutation_count":2,"result":{"Total":2,"Killed":2,"Survived":0,"Errors":0},"tested_at":"2026-09-16T22:22:12.675245296Z"}]}
|
||||
# acceptance-mutation-manifest-end
|
||||
|
||||
# Scenarios: Txid wire encoding - 1, Txid wire encoding - 2, Txid wire encoding - 3, Txid wire encoding - 4
|
||||
#
|
||||
# Memo actions that reference a parent transaction embed that txid as 32 raw
|
||||
|
||||
@@ -48,5 +48,5 @@ function buildTxidTextPayload (txid, text, label = 'Poll txid') {
|
||||
module.exports = { hexToBytes, txidToWireBytes, buildTxidTextPayload }
|
||||
|
||||
// mutate4javascript-manifest-begin
|
||||
// {"version":1,"tested_at":"2026-08-28T22:43:42.484Z","module_hash":"7f3445b7df4d792113f2736232f69faee044f71f6b4a5985224615b36909607b","functions":[{"id":"func/hexToBytes","name":"hexToBytes","line":12,"end_line":26,"hash":"dbf7e0a434598f85365f5a60a0ca227a17a1bcd6718a78bb5aaf7afb8eb2487b"},{"id":"func/buildTxidTextPayload","name":"buildTxidTextPayload","line":30,"end_line":37,"hash":"542a47a13d30c845b7ac9a04079d7a131ece3368a604840ffef75adf97b11f7d"}]}
|
||||
// {"version":1,"tested_at":"2026-09-16T22:01:27.280Z","module_hash":"454b45f3ce08c5ea6346c113db6384f7a44dddbd21e2fb0a35c41ce6701e62c8","functions":[{"id":"func/hexToBytes","name":"hexToBytes","line":12,"end_line":26,"hash":"dbf7e0a434598f85365f5a60a0ca227a17a1bcd6718a78bb5aaf7afb8eb2487b"},{"id":"func/txidToWireBytes","name":"txidToWireBytes","line":32,"end_line":34,"hash":"ac25753fecb32c929134b6e6379cae0bfddd4aa6f7ae438a08da650450e9ea1a"},{"id":"func/buildTxidTextPayload","name":"buildTxidTextPayload","line":39,"end_line":46,"hash":"068504ea13a037adabbbfeab122fb5ec6113625a9e0b009cbbe8b46b6bebdaee"}]}
|
||||
// mutate4javascript-manifest-end
|
||||
|
||||
@@ -198,5 +198,5 @@ MemoLike.MAX_TIP_SATS = MAX_TIP_SATS
|
||||
module.exports = MemoLike
|
||||
|
||||
// mutate4javascript-manifest-begin
|
||||
// {"version":1,"tested_at":"2026-08-26T13:36:49.209Z","module_hash":"f27440db63274125b6b03bafd66222b31966670d8956b865e0bf2c695aacb54b","functions":[{"id":"func/MemoLike.constructor","name":"MemoLike.constructor","line":42,"end_line":47,"hash":"6ebbf231548843e23238988fde00cca861fd89513abba00febba964f3ef32365"},{"id":"func/MemoLike.validate","name":"MemoLike.validate","line":51,"end_line":60,"hash":"d9267f14ac52c7aa3afc07333b621c5faa751efa217bf02ae7695bb640827d44"},{"id":"func/MemoLike.validateTip","name":"MemoLike.validateTip","line":64,"end_line":74,"hash":"504b41cfa8db9754d31b0698550f9fe791d005c5b44bd30ec380202f1df11d6f"},{"id":"func/MemoLike._validateTipAmount","name":"MemoLike._validateTipAmount","line":77,"end_line":95,"hash":"98483bcf6212c2e0a2400d4da1b667b9f1c017a06ee6e4f282ccdf71cb8e397a"},{"id":"func/MemoLike.getSpendableSats","name":"MemoLike.getSpendableSats","line":99,"end_line":106,"hash":"7790154b7489758e6254cc7be00802fde237a33e0bb1440a2da33d303a2bdbe7"},{"id":"func/MemoLike.like","name":"MemoLike.like","line":112,"end_line":139,"hash":"5a748442d77446643448f1835b5e546569524af642af6be7c338e33ca4901051"},{"id":"func/MemoLike.reflect","name":"MemoLike.reflect","line":142,"end_line":145,"hash":"b159b912ba5b88468e5bfb7458385edc932850fe43948f3028e8ed9fea7269e9"},{"id":"func/MemoLike._requireTipAddress","name":"MemoLike._requireTipAddress","line":148,"end_line":154,"hash":"3b838a583b14112523e2cbe856a63896b1045a1ad91dac500e38693332b7c890"},{"id":"func/MemoLike._buildTipOutput","name":"MemoLike._buildTipOutput","line":157,"end_line":161,"hash":"e2a602c0afa9730dee67497869c4d18ed75708f6503d68fb1f0c0ba596826b5a"},{"id":"func/MemoLike._notifyFeed","name":"MemoLike._notifyFeed","line":164,"end_line":173,"hash":"bfc0e888ee106e21ee73146e92ebd3e4ce41d2ed8595a1539f823dc6c8f31d06"},{"id":"func/MemoLike._incrementPostCount","name":"MemoLike._incrementPostCount","line":176,"end_line":182,"hash":"61ae383f836b64a7aeabaf0d04e50ac9a24b87f726d5d6afac5f5585cdc6031c"}]}
|
||||
// {"version":1,"tested_at":"2026-09-16T22:10:37.562Z","module_hash":"62f705760252a76903f00c4f95b1b8f8a8608ad5c257c3c4a9e8b37f2b9e6cdd","functions":[{"id":"func/MemoLike.constructor","name":"MemoLike.constructor","line":44,"end_line":50,"hash":"058496fa3f123b3876e8312ed6effcc78dd2b11fb3e02f815d552dddf5c9bc22"},{"id":"func/MemoLike.validate","name":"MemoLike.validate","line":54,"end_line":63,"hash":"d9267f14ac52c7aa3afc07333b621c5faa751efa217bf02ae7695bb640827d44"},{"id":"func/MemoLike.validateTip","name":"MemoLike.validateTip","line":67,"end_line":77,"hash":"504b41cfa8db9754d31b0698550f9fe791d005c5b44bd30ec380202f1df11d6f"},{"id":"func/MemoLike._validateTipAmount","name":"MemoLike._validateTipAmount","line":80,"end_line":98,"hash":"b0f8a9d775f83c92aec63f0c4bf5b83a035648909cc9e3e4880903ea20c6a6d7"},{"id":"func/MemoLike.getSpendableSats","name":"MemoLike.getSpendableSats","line":102,"end_line":114,"hash":"e9ba4b8f5013276261487d4d5890f27d8724a34f35878416bbbd0aaa2ef221af"},{"id":"func/MemoLike.like","name":"MemoLike.like","line":120,"end_line":147,"hash":"109c1e6dbf56a76166b17cae013fbd4a5ac79d64958d6e28003174139d015a2e"},{"id":"func/MemoLike.reflect","name":"MemoLike.reflect","line":150,"end_line":153,"hash":"b159b912ba5b88468e5bfb7458385edc932850fe43948f3028e8ed9fea7269e9"},{"id":"func/MemoLike._requireTipAddress","name":"MemoLike._requireTipAddress","line":156,"end_line":162,"hash":"3b838a583b14112523e2cbe856a63896b1045a1ad91dac500e38693332b7c890"},{"id":"func/MemoLike._buildTipOutput","name":"MemoLike._buildTipOutput","line":165,"end_line":169,"hash":"e2a602c0afa9730dee67497869c4d18ed75708f6503d68fb1f0c0ba596826b5a"},{"id":"func/MemoLike._notifyFeed","name":"MemoLike._notifyFeed","line":172,"end_line":181,"hash":"bfc0e888ee106e21ee73146e92ebd3e4ce41d2ed8595a1539f823dc6c8f31d06"},{"id":"func/MemoLike._incrementPostCount","name":"MemoLike._incrementPostCount","line":184,"end_line":190,"hash":"61ae383f836b64a7aeabaf0d04e50ac9a24b87f726d5d6afac5f5585cdc6031c"}]}
|
||||
// mutate4javascript-manifest-end
|
||||
|
||||
@@ -85,5 +85,5 @@ MemoReply.MAX_REPLY_BYTES = MAX_REPLY_BYTES
|
||||
module.exports = MemoReply
|
||||
|
||||
// mutate4javascript-manifest-begin
|
||||
// {"version":1,"tested_at":"2026-08-26T12:18:17.625Z","module_hash":"3eb068f9f90f27c5d7acf2bb5a6c517d1085bcb379123ca2d7134d4fb48a092b","functions":[{"id":"func/MemoReply.constructor","name":"MemoReply.constructor","line":36,"end_line":39,"hash":"23091c1b8f7847199bab3b54d8d81e9d8432c6da96138d72ac03fcf9426d542c"},{"id":"func/MemoReply.isTooLong","name":"MemoReply.isTooLong","line":42,"end_line":44,"hash":"2e867501d184010313ba9b27a6bb1e446df8f093514ee231b90ce77699ecbaf2"},{"id":"func/MemoReply.reply","name":"MemoReply.reply","line":48,"end_line":67,"hash":"2d7b425e350b640caf6ca821146065e9c21fe56f1e8a9d8b1f6cab5504a523c1"},{"id":"func/MemoReply.reflect","name":"MemoReply.reflect","line":70,"end_line":79,"hash":"344e1bf304a4dfd475b02824b7ddbf555da0f3ec89f73b4f6009cf0bf097fb02"},{"id":"func/buildReplyPayload","name":"buildReplyPayload","line":84,"end_line":91,"hash":"ef9ee77938593f1dbf2d168c20ea4f8dee0300f64f0fdb4f06a4ba647bb782d5"},{"id":"func/hexToBytes","name":"hexToBytes","line":94,"end_line":107,"hash":"29b401020452eabcb1b54634029d8015758b77b536be3d1ed508e9d560ac93b1"}]}
|
||||
// {"version":1,"tested_at":"2026-09-16T22:14:19.213Z","module_hash":"6c515a91afe94a6be8671a1541302446bb6b1015d03ce0e278644508ebd20090","functions":[{"id":"func/MemoReply.constructor","name":"MemoReply.constructor","line":36,"end_line":39,"hash":"23091c1b8f7847199bab3b54d8d81e9d8432c6da96138d72ac03fcf9426d542c"},{"id":"func/MemoReply.isTooLong","name":"MemoReply.isTooLong","line":42,"end_line":44,"hash":"2e867501d184010313ba9b27a6bb1e446df8f093514ee231b90ce77699ecbaf2"},{"id":"func/MemoReply.reply","name":"MemoReply.reply","line":48,"end_line":67,"hash":"00fb3598d5c3bdc3c6744d1316ad552364574fed105438af4aa011347f3306ce"},{"id":"func/MemoReply.reflect","name":"MemoReply.reflect","line":70,"end_line":79,"hash":"344e1bf304a4dfd475b02824b7ddbf555da0f3ec89f73b4f6009cf0bf097fb02"}]}
|
||||
// mutate4javascript-manifest-end
|
||||
|
||||
@@ -175,3 +175,60 @@ test('_buildTipOutput omits the output for a zero tip', () => {
|
||||
|
||||
assert.deepEqual(memoLike._buildTipOutput(0, MY_ADDRESS), [])
|
||||
})
|
||||
|
||||
test('validate reports ok for a valid post txid', () => {
|
||||
const memoLike = new MemoLike()
|
||||
|
||||
assert.deepEqual(memoLike.validate(POST_TXID), { ok: true })
|
||||
})
|
||||
|
||||
test('validateTip reports ok when the tip exactly matches the spendable balance', () => {
|
||||
const memoLike = new MemoLike()
|
||||
|
||||
assert.deepEqual(memoLike.validateTip(3000, 3000), { ok: true })
|
||||
})
|
||||
|
||||
test('_validateTipAmount accepts a tip exactly at the maximum', () => {
|
||||
const memoLike = new MemoLike()
|
||||
|
||||
assert.equal(memoLike._validateTipAmount(MemoLike.MAX_TIP_SATS), undefined)
|
||||
})
|
||||
|
||||
test('getSpendableSats treats a utxo without a value field as zero', () => {
|
||||
const wallet = { utxos: [{ satoshis: 1000 }, { txid: 'no-value' }] }
|
||||
const memoLike = new MemoLike({ wallet })
|
||||
|
||||
assert.equal(memoLike.getSpendableSats(), 1000)
|
||||
})
|
||||
|
||||
test('_requireTipAddress requires an address for a positive tip', () => {
|
||||
const memoLike = new MemoLike()
|
||||
|
||||
assert.throws(
|
||||
() => memoLike._requireTipAddress(1, ''),
|
||||
(err) => err.code === 'like_validation'
|
||||
)
|
||||
})
|
||||
|
||||
test('_requireTipAddress accepts a one-character address', () => {
|
||||
const memoLike = new MemoLike()
|
||||
|
||||
assert.equal(memoLike._requireTipAddress(1000, 'a'), undefined)
|
||||
})
|
||||
|
||||
test('_buildTipOutput builds the output for a positive tip', () => {
|
||||
const memoLike = new MemoLike()
|
||||
|
||||
assert.deepEqual(memoLike._buildTipOutput(1, MY_ADDRESS), [
|
||||
{ address: MY_ADDRESS, amountSat: 1 }
|
||||
])
|
||||
})
|
||||
|
||||
test('_incrementPostCount defaults a missing likeCount to zero', () => {
|
||||
const feed = { posts: [{ txid: POST_TXID }] }
|
||||
const memoLike = new MemoLike({ feed })
|
||||
|
||||
memoLike._incrementPostCount(POST_TXID)
|
||||
|
||||
assert.equal(feed.posts[0].likeCount, 1)
|
||||
})
|
||||
|
||||
@@ -44,6 +44,18 @@ test('reply broadcasts the parent txid in little-endian wire order', async () =>
|
||||
assert.equal(buf.slice(32).toString('utf8'), 'hello memo')
|
||||
})
|
||||
|
||||
test('isTooLong accepts a message exactly at the byte limit', () => {
|
||||
const memoReply = new MemoReply()
|
||||
|
||||
assert.equal(memoReply.isTooLong('a'.repeat(MemoReply.MAX_REPLY_BYTES)), false)
|
||||
})
|
||||
|
||||
test('isTooLong rejects a message over the byte limit', () => {
|
||||
const memoReply = new MemoReply()
|
||||
|
||||
assert.equal(memoReply.isTooLong('a'.repeat(MemoReply.MAX_REPLY_BYTES + 1)), true)
|
||||
})
|
||||
|
||||
test('reply reflects the parent txid in display order on the thread store', async () => {
|
||||
const wallet = makeWallet()
|
||||
const added = []
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
# acceptance-mutation-manifest-begin
|
||||
# {"version":1,"tested_at":"2026-09-16T22:24:03.359920055Z","feature_name":"Repair txid encoding","feature_path":"/home/trout/work/psf-memo/.worktrees/architect/psf-memo-db/specs/repair-txid-encoding.feature","background_hash":"102ec6cf98fcd7e4ef6107baa6284bd1b425d2a2e9716f86bbff8aa3ecf39273","implementation_hash":"unknown","scenarios":[{"index":2,"name":"Repair txid encoding - 3 the repair utility corrects reversed poll option and vote references","scenario_hash":"87dcb9d331d2293c81385b9fa3e26b445626a94f2780b50d3dfa36264d062901","mutation_count":3,"result":{"Total":3,"Killed":3,"Survived":0,"Errors":0},"tested_at":"2026-09-16T22:24:03.359920055Z"},{"index":3,"name":"Repair txid encoding - 4 the repair utility leaves correctly-encoded references unchanged","scenario_hash":"bd644eb959c765fa80d54b8d4bc2a413b87e5d125f3491cddb129f9754846e96","mutation_count":6,"result":{"Total":6,"Killed":6,"Survived":0,"Errors":0},"tested_at":"2026-09-16T22:24:03.359920055Z"},{"index":4,"name":"Repair txid encoding - 5 the repair utility leaves an unknown reference unchanged","scenario_hash":"e8fcfddce1ae48596f7ef21e6de50d7962fea6eb2a37313ce69a1e22c2a08aaa","mutation_count":2,"result":{"Total":2,"Killed":2,"Survived":0,"Errors":0},"tested_at":"2026-09-16T22:24:03.359920055Z"}]}
|
||||
# acceptance-mutation-manifest-end
|
||||
|
||||
# Scenarios: Repair txid encoding - 1, Repair txid encoding - 2, Repair txid encoding - 3, Repair txid encoding - 4, Repair txid encoding - 5, Repair txid encoding - 6
|
||||
#
|
||||
# Older psf-memo-client broadcasts embedded a referenced txid in big-endian
|
||||
|
||||
@@ -110,3 +110,7 @@ export async function repairTxidEncoding (level) {
|
||||
|
||||
return { likes, replies, pollOptions, pollVotes }
|
||||
}
|
||||
|
||||
// mutate4javascript-manifest-begin
|
||||
// {"version":1,"tested_at":"2026-09-16T22:08:39.973Z","module_hash":"503f8556da96560869090037a52d4e6f25755c56115514d69000bb766c3a34b1","functions":[{"id":"func/reverseTxid","name":"reverseTxid","line":20,"end_line":23,"hash":"34ca3f58033b0a4e34f613eca6dbb92874930d818b4258dd1fc3983dc60f5c59"},{"id":"func/hasRecord","name":"hasRecord","line":26,"end_line":34,"hash":"06580e61d91df680470d1702724aa084dad7f830a3d4be251d4bed430c893008"},{"id":"func/correctReference","name":"correctReference","line":39,"end_line":44,"hash":"d21e349238201c186d0c1216290e1c3bc4c357e42cd1bbe12273ae691f33ff32"},{"id":"func/repairStore","name":"repairStore","line":49,"end_line":70,"hash":"4a03f168d7c9ee3bbcd2dced4cca2903ef27b3d1b5616e77ff8b92302e275ab8"},{"id":"func/txidIndex","name":"txidIndex","line":74,"end_line":80,"hash":"2193de97502a9d50cef2cd9077a29a2bd141562b4a52b6f2b234c16f42e98606"},{"id":"func/repairTxidEncoding","name":"repairTxidEncoding","line":84,"end_line":112,"hash":"b1a18916b2681e83b59b1b14e1727a46d6780f47b8efdcd5b7726d2452a89467"}]}
|
||||
// mutate4javascript-manifest-end
|
||||
|
||||
@@ -22,51 +22,10 @@ import {
|
||||
correctReference,
|
||||
repairTxidEncoding
|
||||
} from '../../src/lib/repair-txid-encoding.js'
|
||||
import { makeLevel } from '../support/level-double.js'
|
||||
|
||||
const rng = seededRandom(20260916)
|
||||
|
||||
class FakeDb {
|
||||
constructor () {
|
||||
this.map = new Map()
|
||||
}
|
||||
|
||||
async get (key) {
|
||||
if (!this.map.has(key)) {
|
||||
const err = new Error(`not found: ${key}`)
|
||||
err.notFound = true
|
||||
throw err
|
||||
}
|
||||
return this.map.get(key)
|
||||
}
|
||||
|
||||
async put (key, value) {
|
||||
this.map.set(key, value)
|
||||
}
|
||||
|
||||
async del (key) {
|
||||
this.map.delete(key)
|
||||
}
|
||||
|
||||
async * iterator () {
|
||||
for (const [key, value] of this.map) {
|
||||
yield [key, value]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function makeLevel () {
|
||||
return {
|
||||
postsDb: new FakeDb(),
|
||||
pollsDb: new FakeDb(),
|
||||
likesDb: new FakeDb(),
|
||||
postLikesDb: new FakeDb(),
|
||||
postParentsDb: new FakeDb(),
|
||||
postChildrenDb: new FakeDb(),
|
||||
pollOptionsDb: new FakeDb(),
|
||||
pollVotesDb: new FakeDb()
|
||||
}
|
||||
}
|
||||
|
||||
// Snapshot every store as a stable string so a second run can be compared.
|
||||
function snapshot (level) {
|
||||
const stores = {}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
In-memory LevelDB double shared by the txid repair unit and property tests.
|
||||
|
||||
FakeDb implements just the get/put/del/iterator surface the repair library
|
||||
uses, plus keys() for assertions. makeLevel() wires the same store names the
|
||||
real psf-memo-db exposes so the repair library can be driven without opening
|
||||
any real LevelDB files.
|
||||
*/
|
||||
|
||||
export class FakeDb {
|
||||
constructor () {
|
||||
this.map = new Map()
|
||||
}
|
||||
|
||||
async get (key) {
|
||||
if (!this.map.has(key)) {
|
||||
const err = new Error(`not found: ${key}`)
|
||||
err.notFound = true
|
||||
throw err
|
||||
}
|
||||
return this.map.get(key)
|
||||
}
|
||||
|
||||
async put (key, value) {
|
||||
this.map.set(key, value)
|
||||
}
|
||||
|
||||
async del (key) {
|
||||
this.map.delete(key)
|
||||
}
|
||||
|
||||
async * iterator () {
|
||||
for (const [key, value] of this.map) {
|
||||
yield [key, value]
|
||||
}
|
||||
}
|
||||
|
||||
keys () {
|
||||
return [...this.map.keys()].sort()
|
||||
}
|
||||
}
|
||||
|
||||
export function makeLevel () {
|
||||
return {
|
||||
postsDb: new FakeDb(),
|
||||
pollsDb: new FakeDb(),
|
||||
likesDb: new FakeDb(),
|
||||
postLikesDb: new FakeDb(),
|
||||
postParentsDb: new FakeDb(),
|
||||
postChildrenDb: new FakeDb(),
|
||||
pollOptionsDb: new FakeDb(),
|
||||
pollVotesDb: new FakeDb()
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
correctReference,
|
||||
repairTxidEncoding
|
||||
} from '../../../src/lib/repair-txid-encoding.js'
|
||||
import { makeLevel } from '../../support/level-double.js'
|
||||
|
||||
const DISPLAY_POST = '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef'
|
||||
const REVERSED_POST = 'efcdab8967452301efcdab8967452301efcdab8967452301efcdab8967452301'
|
||||
@@ -22,52 +23,6 @@ const DISPLAY_POLL = '00112233445566778899aabbccddeeff00112233445566778899aabbcc
|
||||
const REVERSED_POLL = 'ffeeddccbbaa99887766554433221100ffeeddccbbaa99887766554433221100'
|
||||
const UNKNOWN = 'deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef'
|
||||
|
||||
class FakeDb {
|
||||
constructor () {
|
||||
this.map = new Map()
|
||||
}
|
||||
|
||||
async get (key) {
|
||||
if (!this.map.has(key)) {
|
||||
const err = new Error(`not found: ${key}`)
|
||||
err.notFound = true
|
||||
throw err
|
||||
}
|
||||
return this.map.get(key)
|
||||
}
|
||||
|
||||
async put (key, value) {
|
||||
this.map.set(key, value)
|
||||
}
|
||||
|
||||
async del (key) {
|
||||
this.map.delete(key)
|
||||
}
|
||||
|
||||
async * iterator () {
|
||||
for (const [key, value] of this.map) {
|
||||
yield [key, value]
|
||||
}
|
||||
}
|
||||
|
||||
keys () {
|
||||
return [...this.map.keys()].sort()
|
||||
}
|
||||
}
|
||||
|
||||
function makeLevel () {
|
||||
return {
|
||||
postsDb: new FakeDb(),
|
||||
likesDb: new FakeDb(),
|
||||
postLikesDb: new FakeDb(),
|
||||
postParentsDb: new FakeDb(),
|
||||
postChildrenDb: new FakeDb(),
|
||||
pollsDb: new FakeDb(),
|
||||
pollOptionsDb: new FakeDb(),
|
||||
pollVotesDb: new FakeDb()
|
||||
}
|
||||
}
|
||||
|
||||
function loadReversedFixture (level) {
|
||||
level.postsDb.put(DISPLAY_POST, { addr: 'addr-a', text: 'post', blockHeight: 1 })
|
||||
level.pollsDb.put(DISPLAY_POLL, { question: 'q', pollType: 1, optionCount: 2, blockHeight: 2 })
|
||||
|
||||
Reference in New Issue
Block a user