mirror of
https://github.com/Permissionless-Software-Foundation/psf-memo.git
synced 2026-09-21 16:52:01 -07:00
Display like counts on feed, profile, and thread
- Add testable RecentFeedPage, ProfilePage, and ThreadPage controllers. - Wire acceptance handlers for the like-count-display feature. - Render like counts on the profile page with a read-only LikeButton. - Add unit tests for the new display page services. By coder.
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
Unit tests for the profile page controller.
|
||||
|
||||
The profile page loads a single address's posts from the MemoDb client. The
|
||||
like count returned by the API must be preserved so the view can display it.
|
||||
*/
|
||||
|
||||
'use strict'
|
||||
|
||||
const test = require('node:test')
|
||||
const assert = require('node:assert/strict')
|
||||
const ProfilePage = require('../../src/services/profile-page')
|
||||
|
||||
function makeMemoDb (postsByAddr) {
|
||||
return {
|
||||
async getPostsByAddr (addr, { limit, offset }) {
|
||||
return { posts: postsByAddr[addr] || [], pagination: { total: (postsByAddr[addr] || []).length } }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
test('load returns posts with like counts for the address', async () => {
|
||||
const addr = 'bitcoincash:qqlrzp23w08434twmvr4fxw672whkjy0py26r63g3d'
|
||||
const posts = [{ txid: 'a'.repeat(64), likeCount: 17 }]
|
||||
const page = new ProfilePage({ memoDb: makeMemoDb({ [addr]: posts }), addr })
|
||||
|
||||
const result = await page.load()
|
||||
|
||||
assert.equal(result.posts[0].likeCount, 17)
|
||||
})
|
||||
|
||||
test('getPost returns the like count for a loaded post', async () => {
|
||||
const addr = 'bitcoincash:second'
|
||||
const posts = [{ txid: 'b'.repeat(64), likeCount: 3 }]
|
||||
const page = new ProfilePage({ memoDb: makeMemoDb({ [addr]: posts }), addr })
|
||||
|
||||
await page.load()
|
||||
|
||||
assert.equal(page.getPost('b'.repeat(64)).likeCount, 3)
|
||||
})
|
||||
|
||||
test('load throws when no memo db client is provided', async () => {
|
||||
const page = new ProfilePage({ addr: 'bitcoincash:qqlrzp23w08434twmvr4fxw672whkjy0py26r63g3d' })
|
||||
|
||||
await assert.rejects(
|
||||
() => page.load(),
|
||||
/requires a memo db client/
|
||||
)
|
||||
})
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
Unit tests for the recent feed page controller.
|
||||
|
||||
The recent feed page is a thin, testable wrapper around the MemoDb client.
|
||||
It loads the paginated list of recent posts and exposes each post so the
|
||||
view can render properties such as the like count.
|
||||
*/
|
||||
|
||||
'use strict'
|
||||
|
||||
const test = require('node:test')
|
||||
const assert = require('node:assert/strict')
|
||||
const RecentFeedPage = require('../../src/services/recent-feed-page')
|
||||
|
||||
function makeMemoDb (posts, pagination) {
|
||||
return {
|
||||
async getRecentPosts ({ limit, offset }) {
|
||||
return { posts, pagination }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
test('load returns posts with like counts', async () => {
|
||||
const posts = [
|
||||
{ txid: 'a'.repeat(64), likeCount: 17 },
|
||||
{ txid: 'b'.repeat(64), likeCount: 3 }
|
||||
]
|
||||
const page = new RecentFeedPage({ memoDb: makeMemoDb(posts, { total: 2 }) })
|
||||
|
||||
const result = await page.load()
|
||||
|
||||
assert.deepEqual(result.posts, posts)
|
||||
assert.equal(result.pagination.total, 2)
|
||||
})
|
||||
|
||||
test('getPost returns the like count for a loaded post', async () => {
|
||||
const posts = [{ txid: 'a'.repeat(64), likeCount: 17 }]
|
||||
const page = new RecentFeedPage({ memoDb: makeMemoDb(posts, {}) })
|
||||
|
||||
await page.load()
|
||||
|
||||
assert.equal(page.getPost('a'.repeat(64)).likeCount, 17)
|
||||
})
|
||||
|
||||
test('load forwards limit and offset to the memo db client', async () => {
|
||||
const calls = []
|
||||
const memoDb = {
|
||||
async getRecentPosts (params) {
|
||||
calls.push(params)
|
||||
return { posts: [], pagination: {} }
|
||||
}
|
||||
}
|
||||
const page = new RecentFeedPage({ memoDb })
|
||||
|
||||
await page.load({ limit: 10, offset: 20 })
|
||||
|
||||
assert.deepEqual(calls, [{ limit: 10, offset: 20 }])
|
||||
})
|
||||
|
||||
test('load throws when no memo db client is provided', async () => {
|
||||
const page = new RecentFeedPage({})
|
||||
|
||||
await assert.rejects(
|
||||
() => page.load(),
|
||||
/requires a memo db client/
|
||||
)
|
||||
})
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
Unit tests for the thread page controller.
|
||||
|
||||
The thread page loads a post and its nested replies from the MemoDb client.
|
||||
The like count returned for the root post and for every reply must be
|
||||
preserved so the view can display it.
|
||||
*/
|
||||
|
||||
'use strict'
|
||||
|
||||
const test = require('node:test')
|
||||
const assert = require('node:assert/strict')
|
||||
const ThreadPage = require('../../src/services/thread-page')
|
||||
|
||||
function makeMemoDb (threads) {
|
||||
return {
|
||||
async getPostThread (txid) {
|
||||
return threads[txid]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
test('load preserves the root post like count', async () => {
|
||||
const txid = 'a'.repeat(64)
|
||||
const memoDb = makeMemoDb({
|
||||
[txid]: { post: { txid, likeCount: 17, replies: [] } }
|
||||
})
|
||||
const page = new ThreadPage({ memoDb })
|
||||
|
||||
await page.load(txid)
|
||||
|
||||
assert.equal(page.rootPost.likeCount, 17)
|
||||
})
|
||||
|
||||
test('load flattens replies and preserves their like counts', async () => {
|
||||
const txid = 'a'.repeat(64)
|
||||
const replyTxid = 'd'.repeat(64)
|
||||
const memoDb = makeMemoDb({
|
||||
[txid]: {
|
||||
post: {
|
||||
txid,
|
||||
likeCount: 17,
|
||||
replies: [{ txid: replyTxid, likeCount: 5, replies: [] }]
|
||||
}
|
||||
}
|
||||
})
|
||||
const page = new ThreadPage({ memoDb })
|
||||
|
||||
await page.load(txid)
|
||||
|
||||
assert.equal(page.getPost(replyTxid).likeCount, 5)
|
||||
})
|
||||
|
||||
test('load recursively flattens nested replies', async () => {
|
||||
const txid = 'a'.repeat(64)
|
||||
const replyTxid = 'd'.repeat(64)
|
||||
const nestedTxid = 'n'.repeat(64)
|
||||
const memoDb = makeMemoDb({
|
||||
[txid]: {
|
||||
post: {
|
||||
txid,
|
||||
likeCount: 17,
|
||||
replies: [{
|
||||
txid: replyTxid,
|
||||
likeCount: 5,
|
||||
replies: [{ txid: nestedTxid, likeCount: 9, replies: [] }]
|
||||
}]
|
||||
}
|
||||
}
|
||||
})
|
||||
const page = new ThreadPage({ memoDb })
|
||||
|
||||
await page.load(txid)
|
||||
|
||||
assert.equal(page.getPost(replyTxid).likeCount, 5)
|
||||
assert.equal(page.getPost(nestedTxid).likeCount, 9)
|
||||
})
|
||||
|
||||
test('load throws when no memo db client is provided', async () => {
|
||||
const page = new ThreadPage({})
|
||||
|
||||
await assert.rejects(
|
||||
() => page.load('a'.repeat(64)),
|
||||
/requires a memo db client/
|
||||
)
|
||||
})
|
||||
Reference in New Issue
Block a user