update fav boost accounts for stale views (#510)
This commit is contained in:
parent
6d50c65352
commit
01b1d083a9
|
@ -12,9 +12,22 @@ import {
|
||||||
getTimeline as getTimelineFromDatabase
|
getTimeline as getTimelineFromDatabase
|
||||||
} from '../_database/timelines/pagination'
|
} from '../_database/timelines/pagination'
|
||||||
import { getStatus, getStatusContext } from '../_api/statuses'
|
import { getStatus, getStatusContext } from '../_api/statuses'
|
||||||
|
import { emit } from '../_utils/eventBus'
|
||||||
|
|
||||||
const FETCH_LIMIT = 20
|
const FETCH_LIMIT = 20
|
||||||
|
|
||||||
|
async function storeFreshTimelineItemsInDatabase (instanceName, timelineName, items) {
|
||||||
|
await insertTimelineItemsInDatabase(instanceName, timelineName, items)
|
||||||
|
if (timelineName.startsWith('status/')) {
|
||||||
|
// For status threads, we want to be sure to update the favorite/reblog counts even if
|
||||||
|
// this is a stale "view" of the status. See 119-status-counts-update.js for
|
||||||
|
// an example of why we need this.
|
||||||
|
items.forEach(item => {
|
||||||
|
emit('statusUpdated', item)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function fetchTimelineItemsFromNetwork (instanceName, accessToken, timelineName, lastTimelineItemId) {
|
async function fetchTimelineItemsFromNetwork (instanceName, accessToken, timelineName, lastTimelineItemId) {
|
||||||
if (timelineName.startsWith('status/')) { // special case - this is a list of descendents and ancestors
|
if (timelineName.startsWith('status/')) { // special case - this is a list of descendents and ancestors
|
||||||
let statusId = timelineName.split('/').slice(-1)[0]
|
let statusId = timelineName.split('/').slice(-1)[0]
|
||||||
|
@ -37,7 +50,7 @@ async function fetchTimelineItems (instanceName, accessToken, timelineName, last
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
items = await fetchTimelineItemsFromNetwork(instanceName, accessToken, timelineName, lastTimelineItemId)
|
items = await fetchTimelineItemsFromNetwork(instanceName, accessToken, timelineName, lastTimelineItemId)
|
||||||
/* no await */ insertTimelineItemsInDatabase(instanceName, timelineName, items)
|
/* no await */ storeFreshTimelineItemsInDatabase(instanceName, timelineName, items)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e)
|
console.error(e)
|
||||||
toast.say('Internet request failed. Showing offline content.')
|
toast.say('Internet request failed. Showing offline content.')
|
||||||
|
|
|
@ -133,16 +133,43 @@
|
||||||
import ExternalLink from '../ExternalLink.html'
|
import ExternalLink from '../ExternalLink.html'
|
||||||
import { store } from '../../_store/store'
|
import { store } from '../../_store/store'
|
||||||
import { getDateFormatter, getShortDateFormatter } from '../../_utils/formatters'
|
import { getDateFormatter, getShortDateFormatter } from '../../_utils/formatters'
|
||||||
|
import { on } from '../../_utils/eventBus'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
oncreate () {
|
||||||
|
let { originalStatusId } = this.get()
|
||||||
|
on('statusUpdated', this, status => {
|
||||||
|
if (status.id === originalStatusId) {
|
||||||
|
this.set({
|
||||||
|
overrideNumReblogs: status.reblogs_count || 0,
|
||||||
|
overrideNumFavs: status.favourites_count || 0
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
store: () => store,
|
store: () => store,
|
||||||
|
data: () => ({
|
||||||
|
overrideNumReblogs: void 0,
|
||||||
|
overrideNumFavs: void 0
|
||||||
|
}),
|
||||||
computed: {
|
computed: {
|
||||||
|
originalStatusId: ({ originalStatus }) => originalStatus.id,
|
||||||
application: ({ originalStatus }) => originalStatus.application,
|
application: ({ originalStatus }) => originalStatus.application,
|
||||||
applicationName: ({ application }) => (application && application.name),
|
applicationName: ({ application }) => (application && application.name),
|
||||||
applicationWebsite: ({ application }) => (application && application.website),
|
applicationWebsite: ({ application }) => (application && application.website),
|
||||||
createdAtDate: ({ originalStatus }) => originalStatus.created_at,
|
createdAtDate: ({ originalStatus }) => originalStatus.created_at,
|
||||||
numReblogs: ({ originalStatus }) => originalStatus.reblogs_count || 0,
|
numReblogs: ({ overrideNumReblogs, originalStatus }) => {
|
||||||
numFavs: ({ originalStatus }) => originalStatus.favourites_count || 0,
|
if (typeof overrideNumReblogs === 'number') {
|
||||||
|
return overrideNumReblogs
|
||||||
|
}
|
||||||
|
return originalStatus.reblogs_count || 0
|
||||||
|
},
|
||||||
|
numFavs: ({ overrideNumFavs, originalStatus }) => {
|
||||||
|
if (typeof overrideNumFavs === 'number') {
|
||||||
|
return overrideNumFavs
|
||||||
|
}
|
||||||
|
return originalStatus.favourites_count || 0
|
||||||
|
},
|
||||||
formattedDate: ({ createdAtDate, $isMobileSize }) => {
|
formattedDate: ({ createdAtDate, $isMobileSize }) => {
|
||||||
let formatter = $isMobileSize ? getShortDateFormatter() : getDateFormatter()
|
let formatter = $isMobileSize ? getShortDateFormatter() : getDateFormatter()
|
||||||
return formatter.format(new Date(createdAtDate))
|
return formatter.format(new Date(createdAtDate))
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { deleteStatus } from '../routes/_api/delete'
|
||||||
import { authorizeFollowRequest, getFollowRequests } from '../routes/_actions/followRequests'
|
import { authorizeFollowRequest, getFollowRequests } from '../routes/_actions/followRequests'
|
||||||
import { followAccount, unfollowAccount } from '../routes/_api/follow'
|
import { followAccount, unfollowAccount } from '../routes/_api/follow'
|
||||||
import { updateCredentials } from '../routes/_api/updateCredentials'
|
import { updateCredentials } from '../routes/_api/updateCredentials'
|
||||||
|
import { reblogStatus } from '../routes/_api/reblog'
|
||||||
|
|
||||||
global.fetch = fetch
|
global.fetch = fetch
|
||||||
global.File = FileApi.File
|
global.File = FileApi.File
|
||||||
|
@ -18,6 +19,10 @@ export async function favoriteStatusAs (username, statusId) {
|
||||||
return favoriteStatus(instanceName, users[username].accessToken, statusId)
|
return favoriteStatus(instanceName, users[username].accessToken, statusId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function reblogStatusAs (username, statusId) {
|
||||||
|
return reblogStatus(instanceName, users[username].accessToken, statusId)
|
||||||
|
}
|
||||||
|
|
||||||
export async function postAs (username, text) {
|
export async function postAs (username, text) {
|
||||||
return postStatus(instanceName, users[username].accessToken, text,
|
return postStatus(instanceName, users[username].accessToken, text,
|
||||||
null, null, false, null, 'public')
|
null, null, false, null, 'public')
|
||||||
|
|
87
tests/spec/119-status-counts-update.js
Normal file
87
tests/spec/119-status-counts-update.js
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
import { loginAsFoobar } from '../roles'
|
||||||
|
import {
|
||||||
|
getFavoritesCount,
|
||||||
|
getNthStatus, getNthStatusContent, getReblogsCount, homeNavButton
|
||||||
|
} from '../utils'
|
||||||
|
import { favoriteStatusAs, postAs, reblogStatusAs } from '../serverActions'
|
||||||
|
|
||||||
|
fixture`119-status-counts-update.js`
|
||||||
|
.page`http://localhost:4002`
|
||||||
|
|
||||||
|
test('Fav stats update', async t => {
|
||||||
|
let status = await postAs('foobar', 'hey hello look at this toot')
|
||||||
|
let statusId = status.id
|
||||||
|
await favoriteStatusAs('admin', statusId)
|
||||||
|
await loginAsFoobar(t)
|
||||||
|
await t
|
||||||
|
.expect(getNthStatusContent(0).innerText).contains('hey hello look at this toot')
|
||||||
|
.click(getNthStatus(0))
|
||||||
|
.expect(getFavoritesCount()).eql(1)
|
||||||
|
.click(homeNavButton)
|
||||||
|
await favoriteStatusAs('quux', statusId)
|
||||||
|
await t
|
||||||
|
.click(getNthStatus(0))
|
||||||
|
.expect(getFavoritesCount()).eql(2)
|
||||||
|
.click(homeNavButton)
|
||||||
|
await favoriteStatusAs('baz', statusId)
|
||||||
|
await t
|
||||||
|
.click(getNthStatus(0))
|
||||||
|
.expect(getFavoritesCount()).eql(3)
|
||||||
|
.click(homeNavButton)
|
||||||
|
await favoriteStatusAs('LockedAccount', statusId)
|
||||||
|
await t
|
||||||
|
.click(getNthStatus(0))
|
||||||
|
.expect(getFavoritesCount()).eql(4)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('Reblog stats update', async t => {
|
||||||
|
let status = await postAs('foobar', 'oh why hello it looks like another toot')
|
||||||
|
let statusId = status.id
|
||||||
|
await reblogStatusAs('admin', statusId)
|
||||||
|
await loginAsFoobar(t)
|
||||||
|
await t
|
||||||
|
.expect(getNthStatusContent(0).innerText).contains('oh why hello it looks like another toot')
|
||||||
|
.click(getNthStatus(0))
|
||||||
|
.expect(getReblogsCount()).eql(1)
|
||||||
|
.click(homeNavButton)
|
||||||
|
await reblogStatusAs('quux', statusId)
|
||||||
|
await t
|
||||||
|
.click(getNthStatus(0))
|
||||||
|
.expect(getReblogsCount()).eql(2)
|
||||||
|
.click(homeNavButton)
|
||||||
|
await reblogStatusAs('baz', statusId)
|
||||||
|
await t
|
||||||
|
.click(getNthStatus(0))
|
||||||
|
.expect(getReblogsCount()).eql(3)
|
||||||
|
.click(homeNavButton)
|
||||||
|
await reblogStatusAs('LockedAccount', statusId)
|
||||||
|
await t
|
||||||
|
.click(getNthStatus(0))
|
||||||
|
.expect(getReblogsCount()).eql(4)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('Fav and reblog stats update for a boosted toot', async t => {
|
||||||
|
let status = await postAs('ExternalLinks', 'this will get boosted')
|
||||||
|
let statusId = status.id
|
||||||
|
await reblogStatusAs('admin', statusId)
|
||||||
|
await favoriteStatusAs('admin', statusId)
|
||||||
|
await favoriteStatusAs('quux', statusId)
|
||||||
|
await loginAsFoobar(t)
|
||||||
|
await t
|
||||||
|
.expect(getNthStatusContent(0).innerText).contains('this will get boosted')
|
||||||
|
.click(getNthStatus(0))
|
||||||
|
.expect(getReblogsCount()).eql(1)
|
||||||
|
.expect(getFavoritesCount()).eql(2)
|
||||||
|
.click(homeNavButton)
|
||||||
|
await favoriteStatusAs('baz', statusId)
|
||||||
|
await t
|
||||||
|
.click(getNthStatus(0))
|
||||||
|
.expect(getReblogsCount()).eql(1)
|
||||||
|
.expect(getFavoritesCount()).eql(3)
|
||||||
|
.click(homeNavButton)
|
||||||
|
await favoriteStatusAs('LockedAccount', statusId)
|
||||||
|
await t
|
||||||
|
.click(getNthStatus(0))
|
||||||
|
.expect(getReblogsCount()).eql(1)
|
||||||
|
.expect(getFavoritesCount()).eql(4)
|
||||||
|
})
|
Loading…
Reference in a new issue