statuses unit tests
This commit is contained in:
parent
ed62403d96
commit
1396eeb71b
23 changed files with 860 additions and 742 deletions
|
|
@ -26,15 +26,17 @@ export const MASTODON_FOLLOWERS_URL = (
|
||||||
|
|
||||||
export const MASTODON_STATUS_URL = (id) => `/api/v1/statuses/${id}`
|
export const MASTODON_STATUS_URL = (id) => `/api/v1/statuses/${id}`
|
||||||
const MASTODON_STATUS_CONTEXT_URL = (id) => `/api/v1/statuses/${id}/context`
|
const MASTODON_STATUS_CONTEXT_URL = (id) => `/api/v1/statuses/${id}/context`
|
||||||
const MASTODON_STATUS_SOURCE_URL = (id) => `/api/v1/statuses/${id}/source`
|
export const MASTODON_STATUS_SOURCE_URL = (id) =>
|
||||||
const MASTODON_STATUS_HISTORY_URL = (id) => `/api/v1/statuses/${id}/history`
|
`/api/v1/statuses/${id}/source`
|
||||||
|
export const MASTODON_STATUS_HISTORY_URL = (id) =>
|
||||||
|
`/api/v1/statuses/${id}/history`
|
||||||
const MASTODON_USER_URL = '/api/v1/accounts'
|
const MASTODON_USER_URL = '/api/v1/accounts'
|
||||||
const MASTODON_USER_LOOKUP_URL = ({ acct }) =>
|
const MASTODON_USER_LOOKUP_URL = ({ acct }) =>
|
||||||
`/api/v1/accounts/lookup${paramsString({ acct })}`
|
`/api/v1/accounts/lookup${paramsString({ acct })}`
|
||||||
const MASTODON_POLL_URL = (id = '') => `/api/v1/polls/${id}`
|
const MASTODON_POLL_URL = (id = '') => `/api/v1/polls/${id}`
|
||||||
const MASTODON_STATUS_FAVORITEDBY_URL = (id) =>
|
export const MASTODON_STATUS_FAVORITEDBY_URL = (id) =>
|
||||||
`/api/v1/statuses/${id}/favourited_by`
|
`/api/v1/statuses/${id}/favourited_by`
|
||||||
const MASTODON_STATUS_REBLOGGEDBY_URL = (id) =>
|
export const MASTODON_STATUS_REBLOGGEDBY_URL = (id) =>
|
||||||
`/api/v1/statuses/${id}/reblogged_by`
|
`/api/v1/statuses/${id}/reblogged_by`
|
||||||
const MASTODON_SEARCH_2 = ({
|
const MASTODON_SEARCH_2 = ({
|
||||||
q,
|
q,
|
||||||
|
|
@ -51,7 +53,7 @@ const MASTODON_SEARCH_2 = ({
|
||||||
const MASTODON_USER_SEARCH_URL = ({ q, resolve }) =>
|
const MASTODON_USER_SEARCH_URL = ({ q, resolve }) =>
|
||||||
`/api/v1/accounts/search${paramsString({ q, resolve })}`
|
`/api/v1/accounts/search${paramsString({ q, resolve })}`
|
||||||
const MASTODON_KNOWN_DOMAIN_LIST_URL = '/api/v1/instance/peers'
|
const MASTODON_KNOWN_DOMAIN_LIST_URL = '/api/v1/instance/peers'
|
||||||
const PLEROMA_EMOJI_REACTIONS_URL = (id) =>
|
export const PLEROMA_EMOJI_REACTIONS_URL = (id) =>
|
||||||
`/api/v1/pleroma/statuses/${id}/reactions`
|
`/api/v1/pleroma/statuses/${id}/reactions`
|
||||||
const PLEROMA_SCROBBLES_URL = (id, { maxId, sinceId, minId, limit, offset }) =>
|
const PLEROMA_SCROBBLES_URL = (id, { maxId, sinceId, minId, limit, offset }) =>
|
||||||
`/api/v1/pleroma/accounts/${id}/scrobbles${paramsString({ maxId, sinceId, minId, limit, offset })}`
|
`/api/v1/pleroma/accounts/${id}/scrobbles${paramsString({ maxId, sinceId, minId, limit, offset })}`
|
||||||
|
|
@ -174,15 +176,18 @@ export const fetchStatusSource = ({ id, credentials }) =>
|
||||||
credentials,
|
credentials,
|
||||||
}).then(({ data, ...rest }) => ({ ...rest, data: parseSource(data) }))
|
}).then(({ data, ...rest }) => ({ ...rest, data: parseSource(data) }))
|
||||||
|
|
||||||
export const fetchStatusHistory = ({ status, credentials }) =>
|
export const fetchStatusHistory = ({ id, credentials }) =>
|
||||||
promisedRequest({
|
promisedRequest({
|
||||||
url: MASTODON_STATUS_HISTORY_URL(status.id),
|
url: MASTODON_STATUS_HISTORY_URL(id),
|
||||||
credentials,
|
credentials,
|
||||||
}).then(({ data, ...rest }) => {
|
}).then(({ data, ...rest }) => {
|
||||||
return [...data].reverse().map((item) => {
|
return {
|
||||||
item.originalStatus = status
|
...rest,
|
||||||
return { ...rest, data: parseStatus(item) }
|
data: [...data].reverse().map((item) => {
|
||||||
})
|
item.originalStatus = status
|
||||||
|
return parseStatus(item)
|
||||||
|
}),
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export const listEmojiPacks = ({ page, pageSize, credentials }) =>
|
export const listEmojiPacks = ({ page, pageSize, credentials }) =>
|
||||||
|
|
|
||||||
|
|
@ -29,11 +29,12 @@ const MFA_DISABLE_OTP_URL = '/api/pleroma/accounts/mfa/totp'
|
||||||
|
|
||||||
const MASTODON_DISMISS_NOTIFICATION_URL = (id) =>
|
const MASTODON_DISMISS_NOTIFICATION_URL = (id) =>
|
||||||
`/api/v1/notifications/${id}/dismiss`
|
`/api/v1/notifications/${id}/dismiss`
|
||||||
const MASTODON_FAVORITE_URL = (id) => `/api/v1/statuses/${id}/favourite`
|
export const MASTODON_FAVORITE_URL = (id) => `/api/v1/statuses/${id}/favourite`
|
||||||
const MASTODON_UNFAVORITE_URL = (id) => `/api/v1/statuses/${id}/unfavourite`
|
export const MASTODON_UNFAVORITE_URL = (id) =>
|
||||||
const MASTODON_RETWEET_URL = (id) => `/api/v1/statuses/${id}/reblog`
|
`/api/v1/statuses/${id}/unfavourite`
|
||||||
const MASTODON_UNRETWEET_URL = (id) => `/api/v1/statuses/${id}/unreblog`
|
export const MASTODON_RETWEET_URL = (id) => `/api/v1/statuses/${id}/reblog`
|
||||||
const MASTODON_DELETE_URL = (id) => `/api/v1/statuses/${id}`
|
export const MASTODON_UNRETWEET_URL = (id) => `/api/v1/statuses/${id}/unreblog`
|
||||||
|
export const MASTODON_DELETE_URL = (id) => `/api/v1/statuses/${id}`
|
||||||
export const MASTODON_FOLLOW_URL = (id) => `/api/v1/accounts/${id}/follow`
|
export const MASTODON_FOLLOW_URL = (id) => `/api/v1/accounts/${id}/follow`
|
||||||
export const MASTODON_UNFOLLOW_URL = (id) => `/api/v1/accounts/${id}/unfollow`
|
export const MASTODON_UNFOLLOW_URL = (id) => `/api/v1/accounts/${id}/unfollow`
|
||||||
|
|
||||||
|
|
@ -68,25 +69,29 @@ export const MASTODON_UNMUTE_USER_URL = (id) => `/api/v1/accounts/${id}/unmute`
|
||||||
export const MASTODON_REMOVE_USER_FROM_FOLLOWERS_URL = (id) =>
|
export const MASTODON_REMOVE_USER_FROM_FOLLOWERS_URL = (id) =>
|
||||||
`/api/v1/accounts/${id}/remove_from_followers`
|
`/api/v1/accounts/${id}/remove_from_followers`
|
||||||
export const MASTODON_USER_NOTE_URL = (id) => `/api/v1/accounts/${id}/note`
|
export const MASTODON_USER_NOTE_URL = (id) => `/api/v1/accounts/${id}/note`
|
||||||
const MASTODON_BOOKMARK_STATUS_URL = (id) => `/api/v1/statuses/${id}/bookmark`
|
export const MASTODON_BOOKMARK_STATUS_URL = (id) =>
|
||||||
const MASTODON_UNBOOKMARK_STATUS_URL = (id) =>
|
`/api/v1/statuses/${id}/bookmark`
|
||||||
|
export const MASTODON_UNBOOKMARK_STATUS_URL = (id) =>
|
||||||
`/api/v1/statuses/${id}/unbookmark`
|
`/api/v1/statuses/${id}/unbookmark`
|
||||||
const MASTODON_POST_STATUS_URL = '/api/v1/statuses'
|
const MASTODON_POST_STATUS_URL = '/api/v1/statuses'
|
||||||
const MASTODON_MEDIA_UPLOAD_URL = '/api/v1/media'
|
const MASTODON_MEDIA_UPLOAD_URL = '/api/v1/media'
|
||||||
const MASTODON_VOTE_URL = (id) => `/api/v1/polls/${id}/votes`
|
const MASTODON_VOTE_URL = (id) => `/api/v1/polls/${id}/votes`
|
||||||
const MASTODON_PROFILE_UPDATE_URL = '/api/v1/accounts/update_credentials'
|
const MASTODON_PROFILE_UPDATE_URL = '/api/v1/accounts/update_credentials'
|
||||||
const MASTODON_REPORT_USER_URL = '/api/v1/reports'
|
const MASTODON_REPORT_USER_URL = '/api/v1/reports'
|
||||||
const MASTODON_PIN_OWN_STATUS = (id) => `/api/v1/statuses/${id}/pin`
|
export const MASTODON_PIN_OWN_STATUS_URL = (id) => `/api/v1/statuses/${id}/pin`
|
||||||
const MASTODON_UNPIN_OWN_STATUS = (id) => `/api/v1/statuses/${id}/unpin`
|
export const MASTODON_UNPIN_OWN_STATUS_URL = (id) =>
|
||||||
const MASTODON_MUTE_CONVERSATION = (id) => `/api/v1/statuses/${id}/mute`
|
`/api/v1/statuses/${id}/unpin`
|
||||||
const MASTODON_UNMUTE_CONVERSATION = (id) => `/api/v1/statuses/${id}/unmute`
|
export const MASTODON_MUTE_CONVERSATION_URL = (id) =>
|
||||||
|
`/api/v1/statuses/${id}/mute`
|
||||||
|
export const MASTODON_UNMUTE_CONVERSATION_URL = (id) =>
|
||||||
|
`/api/v1/statuses/${id}/unmute`
|
||||||
export const MASTODON_DOMAIN_BLOCKS_URL = '/api/v1/domain_blocks'
|
export const MASTODON_DOMAIN_BLOCKS_URL = '/api/v1/domain_blocks'
|
||||||
const MASTODON_ANNOUNCEMENTS_URL = '/api/v1/announcements'
|
const MASTODON_ANNOUNCEMENTS_URL = '/api/v1/announcements'
|
||||||
const MASTODON_ANNOUNCEMENTS_DISMISS_URL = (id) =>
|
const MASTODON_ANNOUNCEMENTS_DISMISS_URL = (id) =>
|
||||||
`/api/v1/announcements/${id}/dismiss`
|
`/api/v1/announcements/${id}/dismiss`
|
||||||
const PLEROMA_EMOJI_REACT_URL = (id, emoji) =>
|
export const PLEROMA_EMOJI_REACT_URL = (id, emoji) =>
|
||||||
`/api/v1/pleroma/statuses/${id}/reactions/${emoji}`
|
`/api/v1/pleroma/statuses/${id}/reactions/${emoji}`
|
||||||
const PLEROMA_EMOJI_UNREACT_URL = (id, emoji) =>
|
export const PLEROMA_EMOJI_UNREACT_URL = (id, emoji) =>
|
||||||
`/api/v1/pleroma/statuses/${id}/reactions/${emoji}`
|
`/api/v1/pleroma/statuses/${id}/reactions/${emoji}`
|
||||||
const PLEROMA_BACKUP_URL = '/api/v1/pleroma/backups'
|
const PLEROMA_BACKUP_URL = '/api/v1/pleroma/backups'
|
||||||
const PLEROMA_BOOKMARK_FOLDERS_URL = '/api/v1/pleroma/bookmark_folders'
|
const PLEROMA_BOOKMARK_FOLDERS_URL = '/api/v1/pleroma/bookmark_folders'
|
||||||
|
|
@ -155,28 +160,28 @@ export const unbookmarkStatus = ({ id, credentials }) =>
|
||||||
|
|
||||||
export const pinOwnStatus = ({ id, credentials }) =>
|
export const pinOwnStatus = ({ id, credentials }) =>
|
||||||
promisedRequest({
|
promisedRequest({
|
||||||
url: MASTODON_PIN_OWN_STATUS(id),
|
url: MASTODON_PIN_OWN_STATUS_URL(id),
|
||||||
credentials,
|
credentials,
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
}).then(({ data, ...rest }) => ({ ...rest, data: parseStatus(data) }))
|
}).then(({ data, ...rest }) => ({ ...rest, data: parseStatus(data) }))
|
||||||
|
|
||||||
export const unpinOwnStatus = ({ id, credentials }) =>
|
export const unpinOwnStatus = ({ id, credentials }) =>
|
||||||
promisedRequest({
|
promisedRequest({
|
||||||
url: MASTODON_UNPIN_OWN_STATUS(id),
|
url: MASTODON_UNPIN_OWN_STATUS_URL(id),
|
||||||
credentials,
|
credentials,
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
}).then(({ data, ...rest }) => ({ ...rest, data: parseStatus(data) }))
|
}).then(({ data, ...rest }) => ({ ...rest, data: parseStatus(data) }))
|
||||||
|
|
||||||
export const muteConversation = ({ id, credentials }) =>
|
export const muteConversation = ({ id, credentials }) =>
|
||||||
promisedRequest({
|
promisedRequest({
|
||||||
url: MASTODON_MUTE_CONVERSATION(id),
|
url: MASTODON_MUTE_CONVERSATION_URL(id),
|
||||||
credentials,
|
credentials,
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
}).then(({ data, ...rest }) => ({ ...rest, data: parseStatus(data) }))
|
}).then(({ data, ...rest }) => ({ ...rest, data: parseStatus(data) }))
|
||||||
|
|
||||||
export const unmuteConversation = ({ id, credentials }) =>
|
export const unmuteConversation = ({ id, credentials }) =>
|
||||||
promisedRequest({
|
promisedRequest({
|
||||||
url: MASTODON_UNMUTE_CONVERSATION(id),
|
url: MASTODON_UNMUTE_CONVERSATION_URL(id),
|
||||||
credentials,
|
credentials,
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
}).then(({ data, ...rest }) => ({ ...rest, data: parseStatus(data) }))
|
}).then(({ data, ...rest }) => ({ ...rest, data: parseStatus(data) }))
|
||||||
|
|
|
||||||
|
|
@ -109,6 +109,11 @@ const conversation = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
status() {
|
||||||
|
console.log(this.statusId)
|
||||||
|
console.log(useStatusesStore().allStatuses.get(this.statusId))
|
||||||
|
return useStatusesStore().allStatuses.get(this.statusId)
|
||||||
|
},
|
||||||
maxDepthToShowByDefault() {
|
maxDepthToShowByDefault() {
|
||||||
// maxDepthInThread = max number of depths that is *visible*
|
// maxDepthInThread = max number of depths that is *visible*
|
||||||
// since our depth starts with 0 and "showing" means "showing children"
|
// since our depth starts with 0 and "showing" means "showing children"
|
||||||
|
|
@ -152,9 +157,6 @@ const conversation = {
|
||||||
hideStatus() {
|
hideStatus() {
|
||||||
return this.virtualHidden && this.suspendable
|
return this.virtualHidden && this.suspendable
|
||||||
},
|
},
|
||||||
status() {
|
|
||||||
return useStatusesStore().allStatuses.get(this.statusId)
|
|
||||||
},
|
|
||||||
originalStatusId() {
|
originalStatusId() {
|
||||||
if (this.status.retweeted_status) {
|
if (this.status.retweeted_status) {
|
||||||
return this.status.retweeted_status.id
|
return this.status.retweeted_status.id
|
||||||
|
|
@ -178,7 +180,9 @@ const conversation = {
|
||||||
this.conversationId,
|
this.conversationId,
|
||||||
)
|
)
|
||||||
|
|
||||||
return [...conversation.values()].toSorted(sortById)
|
return [...conversation.keys()]
|
||||||
|
.map((k) => useStatusesStore().allStatuses.get(k))
|
||||||
|
.toSorted(sortById)
|
||||||
},
|
},
|
||||||
statusMap() {
|
statusMap() {
|
||||||
return this.conversation.reduce((res, s) => {
|
return this.conversation.reduce((res, s) => {
|
||||||
|
|
@ -472,7 +476,7 @@ const conversation = {
|
||||||
}
|
}
|
||||||
|
|
||||||
useStatusesStore().fetchFavsAndRepeats(id)
|
useStatusesStore().fetchFavsAndRepeats(id)
|
||||||
useStatusesStore().fetchEmojiReactionsBy(id)
|
useStatusesStore().fetchEmojiReactions(id)
|
||||||
},
|
},
|
||||||
toggleExpanded() {
|
toggleExpanded() {
|
||||||
this.expanded = !this.expanded
|
this.expanded = !this.expanded
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,7 @@
|
||||||
ref="statusComponent"
|
ref="statusComponent"
|
||||||
class="conversation-status status-fadein panel-body"
|
class="conversation-status status-fadein panel-body"
|
||||||
|
|
||||||
:statusoid="status"
|
:status-id="status.id"
|
||||||
:replies="getReplies(status.id)"
|
:replies="getReplies(status.id)"
|
||||||
|
|
||||||
:expandable="!isExpanded"
|
:expandable="!isExpanded"
|
||||||
|
|
@ -152,7 +152,7 @@
|
||||||
ref="statusComponent"
|
ref="statusComponent"
|
||||||
:depth="0"
|
:depth="0"
|
||||||
|
|
||||||
:status="status"
|
:status-id="status.id"
|
||||||
:in-profile="inProfile"
|
:in-profile="inProfile"
|
||||||
:conversation="conversation"
|
:conversation="conversation"
|
||||||
:collapsable="collapsable"
|
:collapsable="collapsable"
|
||||||
|
|
@ -186,7 +186,7 @@
|
||||||
:key="status.id"
|
:key="status.id"
|
||||||
ref="statusComponent"
|
ref="statusComponent"
|
||||||
class="conversation-status status-fadein panel-body"
|
class="conversation-status status-fadein panel-body"
|
||||||
:statusoid="status"
|
:status-id="status.id"
|
||||||
:replies="getReplies(status.id)"
|
:replies="getReplies(status.id)"
|
||||||
|
|
||||||
:expandable="!isExpanded"
|
:expandable="!isExpanded"
|
||||||
|
|
|
||||||
|
|
@ -60,10 +60,10 @@ const EmojiReactions = {
|
||||||
reactedWith(emoji) {
|
reactedWith(emoji) {
|
||||||
return this.status.emoji_reactions.find((r) => r.name === emoji).me
|
return this.status.emoji_reactions.find((r) => r.name === emoji).me
|
||||||
},
|
},
|
||||||
async fetchEmojiReactionsByIfMissing() {
|
async fetchEmojiReactionsIfMissing() {
|
||||||
const hasNoAccounts = this.status.emoji_reactions.find((r) => !r.accounts)
|
const hasNoAccounts = this.status.emoji_reactions.find((r) => !r.accounts)
|
||||||
if (hasNoAccounts) {
|
if (!hasNoAccounts) {
|
||||||
return await useStatusesStore().fetchEmojiReactionsBy(this.status.id)
|
return await useStatusesStore().fetchEmojiReactions(this.status.id)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
reactWith(emoji) {
|
reactWith(emoji) {
|
||||||
|
|
@ -75,7 +75,7 @@ const EmojiReactions = {
|
||||||
async emojiOnClick(emoji) {
|
async emojiOnClick(emoji) {
|
||||||
if (!this.loggedIn) return
|
if (!this.loggedIn) return
|
||||||
|
|
||||||
await this.fetchEmojiReactionsByIfMissing()
|
await this.fetchEmojiReactionsIfMissing()
|
||||||
if (this.reactedWith(emoji)) {
|
if (this.reactedWith(emoji)) {
|
||||||
this.unreact(emoji)
|
this.unreact(emoji)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@
|
||||||
class="emoji-reaction-popover"
|
class="emoji-reaction-popover"
|
||||||
:normal-button="true"
|
:normal-button="true"
|
||||||
:trigger-attrs="counterTriggerAttrs(reaction)"
|
:trigger-attrs="counterTriggerAttrs(reaction)"
|
||||||
@show="fetchEmojiReactionsByIfMissing()"
|
@show="fetchEmojiReactionsIfMissing()"
|
||||||
>
|
>
|
||||||
<span class="emoji-reaction-counts">{{ reaction.count }}</span>
|
<span class="emoji-reaction-counts">{{ reaction.count }}</span>
|
||||||
</UserListPopover>
|
</UserListPopover>
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,6 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
doUnfollow() {
|
doUnfollow() {
|
||||||
const store = this.$store
|
|
||||||
this.inProgress = true
|
this.inProgress = true
|
||||||
useUsersStore()
|
useUsersStore()
|
||||||
.unfollowUser(this.relationship.id)
|
.unfollowUser(this.relationship.id)
|
||||||
|
|
|
||||||
|
|
@ -184,6 +184,7 @@ const Notification = {
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
status() {
|
status() {
|
||||||
|
// Used for StatusContent
|
||||||
if (this.notification.status) {
|
if (this.notification.status) {
|
||||||
return useStatusesStore().allStatuses.get(this.notification.status.id)
|
return useStatusesStore().allStatuses.get(this.notification.status.id)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
<Status
|
<Status
|
||||||
class="Notification panel-body"
|
class="Notification panel-body"
|
||||||
:compact="true"
|
:compact="true"
|
||||||
:statusoid="status"
|
:status-id="notification.status?.id"
|
||||||
@click="interacted"
|
@click="interacted"
|
||||||
/>
|
/>
|
||||||
</article>
|
</article>
|
||||||
|
|
|
||||||
|
|
@ -94,6 +94,7 @@ const Status = {
|
||||||
StatusActionButtons,
|
StatusActionButtons,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
statusId: String,
|
||||||
statusoid: Object,
|
statusoid: Object,
|
||||||
replies: Array,
|
replies: Array,
|
||||||
|
|
||||||
|
|
@ -128,9 +129,13 @@ const Status = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
status() {
|
||||||
|
return this.statusoid ?? useStatusesStore().allStatuses.get(this.statusId)
|
||||||
|
},
|
||||||
showReasonMutedThread() {
|
showReasonMutedThread() {
|
||||||
return (
|
return (
|
||||||
(this.status.thread_muted || this.status.reblog?.thread_muted) &&
|
(this.mainStatus.thread_muted ||
|
||||||
|
this.smainSatus.reblog?.thread_muted) &&
|
||||||
!this.inConversation
|
!this.inConversation
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
@ -144,27 +149,27 @@ const Status = {
|
||||||
return this.mergedConfig.scaleMfm
|
return this.mergedConfig.scaleMfm
|
||||||
},
|
},
|
||||||
repeaterClass() {
|
repeaterClass() {
|
||||||
const user = this.statusoid.user
|
const user = this.status.user
|
||||||
return highlightClass(user)
|
return highlightClass(user)
|
||||||
},
|
},
|
||||||
userClass() {
|
userClass() {
|
||||||
const user = this.retweet
|
const user = this.retweet
|
||||||
? this.statusoid.retweeted_status.user
|
? this.status.retweeted_status.user
|
||||||
: this.statusoid.user
|
: this.status.user
|
||||||
return highlightClass(user)
|
return highlightClass(user)
|
||||||
},
|
},
|
||||||
deleted() {
|
deleted() {
|
||||||
return this.statusoid.deleted
|
return this.status.deleted
|
||||||
},
|
},
|
||||||
repeaterStyle() {
|
repeaterStyle() {
|
||||||
const user = this.statusoid.user
|
const user = this.status.user
|
||||||
return highlightStyle(useUserHighlightStore().get(user.screen_name))
|
return highlightStyle(useUserHighlightStore().get(user.screen_name))
|
||||||
},
|
},
|
||||||
userStyle() {
|
userStyle() {
|
||||||
if (this.noHeading) return
|
if (this.noHeading) return
|
||||||
const user = this.retweet
|
const user = this.retweet
|
||||||
? this.statusoid.retweeted_status.user
|
? this.status.retweeted_status.user
|
||||||
: this.statusoid.user
|
: this.status.user
|
||||||
return highlightStyle(useUserHighlightStore().get(user.screen_name))
|
return highlightStyle(useUserHighlightStore().get(user.screen_name))
|
||||||
},
|
},
|
||||||
userProfileLink() {
|
userProfileLink() {
|
||||||
|
|
@ -181,28 +186,28 @@ const Status = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
retweet() {
|
retweet() {
|
||||||
return !!this.statusoid.retweeted_status
|
return !!this.status.retweeted_status
|
||||||
},
|
},
|
||||||
retweeterUser() {
|
retweeterUser() {
|
||||||
return this.statusoid.user
|
return this.status.user
|
||||||
},
|
},
|
||||||
retweeter() {
|
retweeter() {
|
||||||
return this.statusoid.user.name || this.statusoid.user.screen_name_ui
|
return this.status.user.name || this.status.user.screen_name_ui
|
||||||
},
|
},
|
||||||
retweeterHtml() {
|
retweeterHtml() {
|
||||||
return this.statusoid.user.name
|
return this.status.user.name
|
||||||
},
|
},
|
||||||
retweeterProfileLink() {
|
retweeterProfileLink() {
|
||||||
return this.generateUserProfileLink(
|
return this.generateUserProfileLink(
|
||||||
this.statusoid.user.id,
|
this.status.user.id,
|
||||||
this.statusoid.user.screen_name,
|
this.status.user.screen_name,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
status() {
|
mainStatus() {
|
||||||
if (this.retweet) {
|
if (this.retweet) {
|
||||||
return this.statusoid.retweeted_status
|
return this.status.retweeted_status
|
||||||
} else {
|
} else {
|
||||||
return this.statusoid
|
return this.status
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
statusFromGlobalRepository() {
|
statusFromGlobalRepository() {
|
||||||
|
|
@ -231,14 +236,14 @@ const Status = {
|
||||||
const writtenSet = new Set(
|
const writtenSet = new Set(
|
||||||
this.headTailLinks.writtenMentions.map((_) => _.url),
|
this.headTailLinks.writtenMentions.map((_) => _.url),
|
||||||
)
|
)
|
||||||
return this.status.attentions
|
return this.mainStatus.attentions
|
||||||
.filter((attn) => {
|
.filter((attn) => {
|
||||||
// no reply user
|
// no reply user
|
||||||
return (
|
return (
|
||||||
attn.id !== this.status.in_reply_to_user_id &&
|
attn.id !== this.mainStatus.in_reply_to_user_id &&
|
||||||
// no self-replies
|
// no self-replies
|
||||||
attn.statusnet_profile_url !==
|
attn.statusnet_profile_url !==
|
||||||
this.status.user.statusnet_profile_url &&
|
this.mainStatus.user.statusnet_profile_url &&
|
||||||
// don't include if mentions is written
|
// don't include if mentions is written
|
||||||
!writtenSet.has(attn.statusnet_profile_url)
|
!writtenSet.has(attn.statusnet_profile_url)
|
||||||
)
|
)
|
||||||
|
|
@ -255,7 +260,7 @@ const Status = {
|
||||||
muteReasons() {
|
muteReasons() {
|
||||||
return [
|
return [
|
||||||
this.userIsMuted ? 'user' : null,
|
this.userIsMuted ? 'user' : null,
|
||||||
this.status.thread_muted ? 'thread' : null,
|
this.mainStatus.thread_muted ? 'thread' : null,
|
||||||
this.muteFilterHits.length > 0 ? 'filtered' : null,
|
this.muteFilterHits.length > 0 ? 'filtered' : null,
|
||||||
this.muteBotStatuses && this.botStatus ? 'bot' : null,
|
this.muteBotStatuses && this.botStatus ? 'bot' : null,
|
||||||
this.muteSensitiveStatuses && this.sensitiveStatus ? 'nsfw' : null,
|
this.muteSensitiveStatuses && this.sensitiveStatus ? 'nsfw' : null,
|
||||||
|
|
@ -299,14 +304,13 @@ const Status = {
|
||||||
},
|
},
|
||||||
muted() {
|
muted() {
|
||||||
if (this.ignoreMute) return false
|
if (this.ignoreMute) return false
|
||||||
if (this.statusoid.user.id === this.currentUser?.id) return false
|
if (this.status.user.id === this.currentUser?.id) return false
|
||||||
return !this.unmuted && !this.shouldNotMute && this.muteReasons.length > 0
|
return !this.unmuted && !this.shouldNotMute && this.muteReasons.length > 0
|
||||||
},
|
},
|
||||||
userIsMuted() {
|
userIsMuted() {
|
||||||
if (this.statusoid.user.id === this.currentUser?.id) return false
|
if (this.status.user.id === this.currentUser?.id) return false
|
||||||
const { status } = this
|
const { reblog } = this.status
|
||||||
const { reblog } = status
|
const relationship = useUsersStore().relationship(this.status.user.id)
|
||||||
const relationship = useUsersStore().relationship(status.user.id)
|
|
||||||
const relationshipReblog =
|
const relationshipReblog =
|
||||||
reblog && useUsersStore().relationship(reblog.user.id)
|
reblog && useUsersStore().relationship(reblog.user.id)
|
||||||
return (
|
return (
|
||||||
|
|
@ -322,8 +326,7 @@ const Status = {
|
||||||
shouldNotMute() {
|
shouldNotMute() {
|
||||||
if (this.ignoreMute) return true
|
if (this.ignoreMute) return true
|
||||||
if (this.focused) return true
|
if (this.focused) return true
|
||||||
const { status } = this
|
const { reblog } = this.status
|
||||||
const { reblog } = status
|
|
||||||
return (
|
return (
|
||||||
((this.inProfile &&
|
((this.inProfile &&
|
||||||
// Don't mute user's posts on user timeline (except reblogs)
|
// Don't mute user's posts on user timeline (except reblogs)
|
||||||
|
|
@ -576,7 +579,7 @@ const Status = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
isSuspendable: function (suspend) {
|
isSuspendable: function (suspend) {
|
||||||
this.$emit('suspendableStateChange', { id: this.statusoid.id, suspend })
|
this.$emit('suspendableStateChange', { id: this.status.id, suspend })
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -187,7 +187,7 @@ export const BUTTONS = [
|
||||||
'summary_raw_html',
|
'summary_raw_html',
|
||||||
]
|
]
|
||||||
stripFieldsList.forEach((p) => delete originalStatus[p])
|
stripFieldsList.forEach((p) => delete originalStatus[p])
|
||||||
useStatusHistoryStore().openStatusHistoryModal(originalStatus)
|
useStatusHistoryStore().openModal(originalStatus.id)
|
||||||
return Promise.resolve()
|
return Promise.resolve()
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,14 @@
|
||||||
import { get } from 'lodash'
|
import { mapState } from 'pinia'
|
||||||
|
|
||||||
import Modal from 'src/components/modal/modal.vue'
|
import Modal from 'src/components/modal/modal.vue'
|
||||||
|
import StatusContent from 'src/components/status_content/status_content.vue'
|
||||||
|
|
||||||
import { useStatusesStore } from 'src/stores/statuses.js'
|
|
||||||
import { useStatusHistoryStore } from 'src/stores/statusHistory.js'
|
import { useStatusHistoryStore } from 'src/stores/statusHistory.js'
|
||||||
|
|
||||||
const StatusHistoryModal = {
|
const StatusHistoryModal = {
|
||||||
components: {
|
components: {
|
||||||
Modal,
|
Modal,
|
||||||
|
StatusContent,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
|
@ -15,50 +16,14 @@ const StatusHistoryModal = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
modalActivated() {
|
|
||||||
return useStatusHistoryStore().modalActivated
|
|
||||||
},
|
|
||||||
params() {
|
|
||||||
return useStatusHistoryStore().params
|
|
||||||
},
|
|
||||||
statusId() {
|
|
||||||
return this.params.id
|
|
||||||
},
|
|
||||||
historyCount() {
|
historyCount() {
|
||||||
return this.statuses.length
|
return this.history.length
|
||||||
},
|
|
||||||
history() {
|
|
||||||
return this.statuses
|
|
||||||
},
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
params(newVal, oldVal) {
|
|
||||||
const newStatusId = get(newVal, 'id') !== get(oldVal, 'id')
|
|
||||||
if (newStatusId) {
|
|
||||||
this.resetHistory()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
newStatusId ||
|
|
||||||
get(newVal, 'edited_at') !== get(oldVal, 'edited_at')
|
|
||||||
) {
|
|
||||||
this.fetchStatusHistory()
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
...mapState(useStatusHistoryStore, ['modalActivated', 'history']),
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
resetHistory() {
|
|
||||||
this.statuses = []
|
|
||||||
},
|
|
||||||
fetchStatusHistory() {
|
|
||||||
useStatusesStore()
|
|
||||||
.fetchStatusHistory(this.params)
|
|
||||||
.then((data) => {
|
|
||||||
this.statuses = data
|
|
||||||
})
|
|
||||||
},
|
|
||||||
closeModal() {
|
closeModal() {
|
||||||
useStatusHistoryStore().closeStatusHistoryModal()
|
useStatusHistoryStore().closeModal()
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,10 +15,10 @@
|
||||||
v-if="historyCount > 0"
|
v-if="historyCount > 0"
|
||||||
class="history-body"
|
class="history-body"
|
||||||
>
|
>
|
||||||
<status
|
<StatusContent
|
||||||
v-for="status in history"
|
v-for="status in history"
|
||||||
:key="status.id"
|
:key="status.id"
|
||||||
:statusoid="status"
|
:status="status"
|
||||||
:is-preview="true"
|
:is-preview="true"
|
||||||
class="conversation-status status-fadein panel-body"
|
class="conversation-status status-fadein panel-body"
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -15,11 +15,6 @@ const StatusPopover = {
|
||||||
error: false,
|
error: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
|
||||||
status() {
|
|
||||||
return useStatusesStore().allStatuses.get(this.statusId)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
components: {
|
components: {
|
||||||
Popover,
|
Popover,
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
<Status
|
<Status
|
||||||
v-if="status"
|
v-if="status"
|
||||||
:is-preview="true"
|
:is-preview="true"
|
||||||
:statusoid="status"
|
:status-id="statusId"
|
||||||
:compact="true"
|
:compact="true"
|
||||||
:ignore-mute="true"
|
:ignore-mute="true"
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ const ThreadTree = {
|
||||||
name: 'ThreadTree',
|
name: 'ThreadTree',
|
||||||
props: {
|
props: {
|
||||||
depth: Number,
|
depth: Number,
|
||||||
status: Object,
|
statusId: String,
|
||||||
inProfile: Boolean,
|
inProfile: Boolean,
|
||||||
conversation: Array,
|
conversation: Array,
|
||||||
collapsable: Boolean,
|
collapsable: Boolean,
|
||||||
|
|
@ -34,8 +34,8 @@ const ThreadTree = {
|
||||||
computed: {
|
computed: {
|
||||||
reverseLookupTable() {
|
reverseLookupTable() {
|
||||||
return this.conversation.reduce(
|
return this.conversation.reduce(
|
||||||
(table, status, index) => {
|
(table, statusId, index) => {
|
||||||
table[status.id] = index
|
table[statusId] = index
|
||||||
return table
|
return table
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -44,12 +44,10 @@ const ThreadTree = {
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
currentReplies() {
|
currentReplies() {
|
||||||
return this.getReplies(this.status.id).map(({ id }) =>
|
return this.getReplies(this.statusId).map(({ id }) => this.statusById(id))
|
||||||
this.statusById(id),
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
threadShowing() {
|
threadShowing() {
|
||||||
return this.threadDisplayStatus[this.status.id] === 'showing'
|
return this.threadDisplayStatus[this.statusId] === 'showing'
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,25 @@
|
||||||
<template>
|
<template>
|
||||||
<article class="thread-tree">
|
<article class="thread-tree">
|
||||||
<Status
|
<Status
|
||||||
:key="status.id"
|
:key="statusId"
|
||||||
ref="statusComponent"
|
ref="statusComponent"
|
||||||
:statusoid="status"
|
:status-id="statusId"
|
||||||
:replies="getReplies(status.id)"
|
:replies="getReplies(statusId)"
|
||||||
:inline-expanded="collapsable && isExpanded"
|
:inline-expanded="collapsable && isExpanded"
|
||||||
:expandable="!isExpanded"
|
:expandable="!isExpanded"
|
||||||
:show-pinned="pinnedStatusIdsObject && pinnedStatusIdsObject[status.id]"
|
:show-pinned="pinnedStatusIdsObject && pinnedStatusIdsObject[status.id]"
|
||||||
:in-conversation="isExpanded"
|
:in-conversation="isExpanded"
|
||||||
:focused="focused === status.id || focused === status.retweeted_status?.id"
|
:focused="focused === statusId"
|
||||||
:in-profile="inProfile"
|
:in-profile="inProfile"
|
||||||
:profile-user-id="profileUserId"
|
:profile-user-id="profileUserId"
|
||||||
class="conversation-status conversation-status-treeview status-fadein panel-body"
|
class="conversation-status conversation-status-treeview status-fadein panel-body"
|
||||||
|
|
||||||
:simple-tree="simple"
|
:simple-tree="simple"
|
||||||
:thread-display-status="threadDisplayStatus[status.id]"
|
:thread-display-status="threadDisplayStatus[statusId]"
|
||||||
:can-dive="canDive"
|
:can-dive="canDive"
|
||||||
|
|
||||||
@dive="$emit('dive', status.id)"
|
@dive="$emit('dive', statusId)"
|
||||||
@goto="$emit('goto', status.id)"
|
@goto="$emit('goto', statusId)"
|
||||||
@toggle-expanded="toggleExpanded"
|
@toggle-expanded="toggleExpanded"
|
||||||
@suspendable-state-change="e => $emit('suspendableStateChange', e)"
|
@suspendable-state-change="e => $emit('suspendableStateChange', e)"
|
||||||
/>
|
/>
|
||||||
|
|
@ -29,10 +29,10 @@
|
||||||
>
|
>
|
||||||
<ThreadTree
|
<ThreadTree
|
||||||
v-for="replyStatus in currentReplies"
|
v-for="replyStatus in currentReplies"
|
||||||
:key="replyStatus.id"
|
:key="replyStatusId"
|
||||||
ref="childComponent"
|
ref="childComponent"
|
||||||
:depth="depth + 1"
|
:depth="depth + 1"
|
||||||
:status="replyStatus"
|
:status-id="replyStatusId"
|
||||||
|
|
||||||
:in-profile="inProfile"
|
:in-profile="inProfile"
|
||||||
:conversation="conversation"
|
:conversation="conversation"
|
||||||
|
|
@ -67,7 +67,7 @@
|
||||||
tag="button"
|
tag="button"
|
||||||
keypath="status.thread_follow_with_icon"
|
keypath="status.thread_follow_with_icon"
|
||||||
class="button-unstyled -link thread-tree-show-replies-button"
|
class="button-unstyled -link thread-tree-show-replies-button"
|
||||||
@click.prevent="$emit('dive', status.id)"
|
@click.prevent="$emit('dive', statusId)"
|
||||||
>
|
>
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<FAIcon
|
<FAIcon
|
||||||
|
|
@ -76,7 +76,7 @@
|
||||||
</template>
|
</template>
|
||||||
<template #text>
|
<template #text>
|
||||||
<span>
|
<span>
|
||||||
{{ $t('status.thread_follow', { numStatus: totalReplyCount[status.id] }, totalReplyCount[status.id]) }}
|
{{ $t('status.thread_follow', { numStatus: totalReplyCount[statusId] }, totalReplyCount[statusId]) }}
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</i18n-t>
|
</i18n-t>
|
||||||
|
|
@ -86,7 +86,7 @@
|
||||||
tag="button"
|
tag="button"
|
||||||
keypath="status.thread_show_full_with_icon"
|
keypath="status.thread_show_full_with_icon"
|
||||||
class="button-unstyled -link thread-tree-show-replies-button"
|
class="button-unstyled -link thread-tree-show-replies-button"
|
||||||
@click.prevent="showThreadRecursively(status.id)"
|
@click.prevent="showThreadRecursively(statusId)"
|
||||||
>
|
>
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<FAIcon
|
<FAIcon
|
||||||
|
|
@ -95,7 +95,7 @@
|
||||||
</template>
|
</template>
|
||||||
<template #text>
|
<template #text>
|
||||||
<span>
|
<span>
|
||||||
{{ $t('status.thread_show_full', { numStatus: totalReplyCount[status.id], depth: totalReplyDepth[status.id] }, totalReplyCount[status.id]) }}
|
{{ $t('status.thread_show_full', { numStatus: totalReplyCount[statusId], depth: totalReplyDepth[statusId] }, totalReplyCount[statusId]) }}
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</i18n-t>
|
</i18n-t>
|
||||||
|
|
|
||||||
|
|
@ -173,7 +173,7 @@ export const useNotificationsStore = defineStore('notifications', {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (notification.type === 'pleroma:emoji_reaction') {
|
if (notification.type === 'pleroma:emoji_reaction') {
|
||||||
useStatusesStore().fetchEmojiReactionsBy(notification.status.id)
|
useStatusesStore().fetchEmojiReactions(notification.status.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only add a new notification if we don't have one for the same action
|
// Only add a new notification if we don't have one for the same action
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,34 @@
|
||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
|
|
||||||
|
import { useOAuthStore } from 'src/stores/oauth.js'
|
||||||
|
|
||||||
|
import { fetchStatusHistory } from 'src/api/public.js'
|
||||||
|
|
||||||
export const useStatusHistoryStore = defineStore('statusHistory', {
|
export const useStatusHistoryStore = defineStore('statusHistory', {
|
||||||
state: () => ({
|
state: () => ({
|
||||||
params: {},
|
id: null,
|
||||||
modalActivated: false,
|
modalActivated: false,
|
||||||
|
history: null,
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
openStatusHistoryModal(params) {
|
openModal(id) {
|
||||||
this.params = params
|
this.fetchStatusHistory(id).then(() => {
|
||||||
this.modalActivated = true
|
this.id = id
|
||||||
|
this.modalActivated = true
|
||||||
|
})
|
||||||
},
|
},
|
||||||
closeStatusHistoryModal() {
|
closeModal() {
|
||||||
|
this.id = null
|
||||||
this.modalActivated = false
|
this.modalActivated = false
|
||||||
|
this.history = null
|
||||||
|
},
|
||||||
|
fetchStatusHistory(id) {
|
||||||
|
return fetchStatusHistory({
|
||||||
|
id,
|
||||||
|
credentials: useOAuthStore().token,
|
||||||
|
}).then(({ data }) => {
|
||||||
|
this.history = data
|
||||||
|
})
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@ import {
|
||||||
fetchRebloggedByUsers,
|
fetchRebloggedByUsers,
|
||||||
fetchScrobbles,
|
fetchScrobbles,
|
||||||
fetchStatus,
|
fetchStatus,
|
||||||
fetchStatusHistory,
|
|
||||||
fetchStatusSource,
|
fetchStatusSource,
|
||||||
search2,
|
search2,
|
||||||
} from 'src/api/public.js'
|
} from 'src/api/public.js'
|
||||||
|
|
@ -128,16 +127,16 @@ export const useStatusesStore = defineStore('statuses', {
|
||||||
const addStatus = (data) => {
|
const addStatus = (data) => {
|
||||||
getLatestScrobble(data.user)
|
getLatestScrobble(data.user)
|
||||||
|
|
||||||
const [status] = this.mergeOrAdd(this.allStatuses, data)
|
const [status] = this.mergeOrAdd(this.allStatuses, data, timestamp)
|
||||||
|
|
||||||
// Add to conversation
|
// Add to conversation
|
||||||
const conversations = this.conversations
|
const conversations = this.conversations
|
||||||
const conversationId = status.statusnet_conversation_id
|
const conversationId = status.statusnet_conversation_id
|
||||||
|
|
||||||
if (conversations.has(conversationId)) {
|
if (conversations.has(conversationId)) {
|
||||||
conversations.get(conversationId).set(status.id, status)
|
conversations.get(conversationId).add(status.id)
|
||||||
} else {
|
} else {
|
||||||
conversations.set(conversationId, new Map([[status.id, status]]))
|
conversations.set(conversationId, new Set([status.id]))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Work on quote
|
// Work on quote
|
||||||
|
|
@ -160,30 +159,6 @@ export const useStatusesStore = defineStore('statuses', {
|
||||||
if (status.retweeted_status) addStatus(status.retweeted_status)
|
if (status.retweeted_status) addStatus(status.retweeted_status)
|
||||||
return addStatus(status)
|
return addStatus(status)
|
||||||
},
|
},
|
||||||
favorite: (favorite) => {
|
|
||||||
// Only update if this is a new favorite.
|
|
||||||
// Ignore our own favorites because we get info about likes as response to like request
|
|
||||||
if (!this.favorites.has(favorite.id)) {
|
|
||||||
this.favorites.add(favorite.id)
|
|
||||||
|
|
||||||
const status = this.allStatuses.get(favorite.in_reply_to_status_id)
|
|
||||||
|
|
||||||
if (status) {
|
|
||||||
// This is our favorite, so the relevant bit.
|
|
||||||
if (favorite.user.id === useUsersStore().currentUser?.id) {
|
|
||||||
status.favorited = true
|
|
||||||
} else {
|
|
||||||
status.fave_num += 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return status
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
},
|
|
||||||
follow: () => {
|
|
||||||
// NOOP, it is known status but we don't do anything about it for now
|
|
||||||
return null
|
|
||||||
},
|
|
||||||
default: (unknown) => {
|
default: (unknown) => {
|
||||||
console.warn('unknown status type', unknown)
|
console.warn('unknown status type', unknown)
|
||||||
return null
|
return null
|
||||||
|
|
@ -228,7 +203,10 @@ export const useStatusesStore = defineStore('statuses', {
|
||||||
|
|
||||||
// Fetches
|
// Fetches
|
||||||
fetchStatus(id) {
|
fetchStatus(id) {
|
||||||
return fetchStatus({ id }).then(({ data: status, timestamp }) =>
|
return fetchStatus({
|
||||||
|
id,
|
||||||
|
credentials: useOAuthStore().token,
|
||||||
|
}).then(({ data: status, timestamp }) =>
|
||||||
this.addNewStatuses({ statuses: [status], timestamp }),
|
this.addNewStatuses({ statuses: [status], timestamp }),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
@ -238,10 +216,7 @@ export const useStatusesStore = defineStore('statuses', {
|
||||||
credentials: useOAuthStore().token,
|
credentials: useOAuthStore().token,
|
||||||
}).then(({ data }) => data)
|
}).then(({ data }) => data)
|
||||||
},
|
},
|
||||||
fetchStatusHistory(status) {
|
fetchEmojiReactions(id) {
|
||||||
return fetchStatusHistory({ status }).then(({ data }) => data)
|
|
||||||
},
|
|
||||||
fetchEmojiReactionsBy(id) {
|
|
||||||
return fetchEmojiReactions({
|
return fetchEmojiReactions({
|
||||||
id,
|
id,
|
||||||
credentials: useOAuthStore().token,
|
credentials: useOAuthStore().token,
|
||||||
|
|
@ -452,7 +427,7 @@ export const useStatusesStore = defineStore('statuses', {
|
||||||
|
|
||||||
const accounts = value
|
const accounts = value
|
||||||
? [...reaction.accounts, currentUser]
|
? [...reaction.accounts, currentUser]
|
||||||
: accounts.filter((acc) => acc.id !== currentUser.id)
|
: reaction.accounts.filter((acc) => acc.id !== currentUser.id)
|
||||||
|
|
||||||
const newReaction = {
|
const newReaction = {
|
||||||
...reaction,
|
...reaction,
|
||||||
|
|
@ -480,7 +455,7 @@ export const useStatusesStore = defineStore('statuses', {
|
||||||
apiCall: bookmarkStatus,
|
apiCall: bookmarkStatus,
|
||||||
optimisticCall: this.setBookmarked,
|
optimisticCall: this.setBookmarked,
|
||||||
argument: bookmark_folder_id,
|
argument: bookmark_folder_id,
|
||||||
value: false,
|
value: true,
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
unbookmark(id) {
|
unbookmark(id) {
|
||||||
|
|
@ -511,7 +486,7 @@ export const useStatusesStore = defineStore('statuses', {
|
||||||
id,
|
id,
|
||||||
apiCall: muteConversation,
|
apiCall: muteConversation,
|
||||||
optimisticCall: this.setMutedStatus,
|
optimisticCall: this.setMutedStatus,
|
||||||
value: false,
|
value: true,
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
unmuteConversation(id) {
|
unmuteConversation(id) {
|
||||||
|
|
@ -532,8 +507,8 @@ export const useStatusesStore = defineStore('statuses', {
|
||||||
if (newStatus.thread_muted !== undefined) {
|
if (newStatus.thread_muted !== undefined) {
|
||||||
this.conversations
|
this.conversations
|
||||||
.get(newStatus.statusnet_conversation_id)
|
.get(newStatus.statusnet_conversation_id)
|
||||||
.forEach((status) => {
|
.forEach((statusId) => {
|
||||||
status.thread_muted = value
|
this.allStatuses.get(statusId).thread_muted = value
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -564,7 +539,7 @@ export const useStatusesStore = defineStore('statuses', {
|
||||||
|
|
||||||
/// Delete
|
/// Delete
|
||||||
deleteStatus(id) {
|
deleteStatus(id) {
|
||||||
deleteStatus({
|
return deleteStatus({
|
||||||
id,
|
id,
|
||||||
credentials: useOAuthStore().token,
|
credentials: useOAuthStore().token,
|
||||||
})
|
})
|
||||||
|
|
@ -584,17 +559,10 @@ export const useStatusesStore = defineStore('statuses', {
|
||||||
const newStatus = this.allStatuses.get(id)
|
const newStatus = this.allStatuses.get(id)
|
||||||
if (newStatus) newStatus.deleted = true
|
if (newStatus) newStatus.deleted = true
|
||||||
},
|
},
|
||||||
setManyDeleted(condition) {
|
|
||||||
this.allStatuses.values().forEach((status) => {
|
|
||||||
if (condition(status)) {
|
|
||||||
status.deleted = true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
// For when blocking a user
|
// For when blocking a user
|
||||||
wipeUserStatuses(userId) {
|
wipeUserStatuses(userId) {
|
||||||
this.allStatuses.values().forEach((status) => {
|
this.allStatuses.forEach((status) => {
|
||||||
if (status.user.id === userId) {
|
if (status.user.id === userId) {
|
||||||
this.allStatuses.delete(status.id)
|
this.allStatuses.delete(status.id)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,447 +0,0 @@
|
||||||
import { createTestingPinia } from '@pinia/testing'
|
|
||||||
|
|
||||||
import {
|
|
||||||
defaultState,
|
|
||||||
mutations,
|
|
||||||
prepareStatus,
|
|
||||||
} from '../../../../src/modules/statuses.js'
|
|
||||||
|
|
||||||
createTestingPinia()
|
|
||||||
|
|
||||||
const makeMockStatus = ({ id, text, type = 'status' }) => {
|
|
||||||
return {
|
|
||||||
id,
|
|
||||||
user: { id: '0' },
|
|
||||||
name: 'status',
|
|
||||||
text: text || `Text number ${id}`,
|
|
||||||
fave_num: 0,
|
|
||||||
uri: '',
|
|
||||||
type,
|
|
||||||
attentions: [],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('Statuses module', () => {
|
|
||||||
describe('prepareStatus', () => {
|
|
||||||
it('sets deleted flag to false', () => {
|
|
||||||
const aStatus = makeMockStatus({ id: '1', text: 'Hello oniichan' })
|
|
||||||
expect(prepareStatus(aStatus).deleted).to.eq(false)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('addNewStatuses', () => {
|
|
||||||
it('adds the status to allStatuses and to the given timeline', () => {
|
|
||||||
const state = defaultState()
|
|
||||||
const status = makeMockStatus({ id: '1' })
|
|
||||||
|
|
||||||
mutations.addNewStatuses(state, {
|
|
||||||
statuses: [status],
|
|
||||||
timeline: 'public',
|
|
||||||
})
|
|
||||||
|
|
||||||
expect(state.allStatuses).to.eql([status])
|
|
||||||
expect(state.timelines.public.statuses).to.eql([status])
|
|
||||||
expect(state.timelines.public.visibleStatuses).to.eql([])
|
|
||||||
expect(state.timelines.public.newStatusCount).to.equal(1)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('counts the status as new if it has not been seen on this timeline', () => {
|
|
||||||
const state = defaultState()
|
|
||||||
const status = makeMockStatus({ id: '1' })
|
|
||||||
|
|
||||||
mutations.addNewStatuses(state, {
|
|
||||||
statuses: [status],
|
|
||||||
timeline: 'public',
|
|
||||||
})
|
|
||||||
mutations.addNewStatuses(state, {
|
|
||||||
statuses: [status],
|
|
||||||
timeline: 'friends',
|
|
||||||
})
|
|
||||||
|
|
||||||
expect(state.allStatuses).to.eql([status])
|
|
||||||
expect(state.timelines.public.statuses).to.eql([status])
|
|
||||||
expect(state.timelines.public.visibleStatuses).to.eql([])
|
|
||||||
expect(state.timelines.public.newStatusCount).to.equal(1)
|
|
||||||
|
|
||||||
expect(state.allStatuses).to.eql([status])
|
|
||||||
expect(state.timelines.friends.statuses).to.eql([status])
|
|
||||||
expect(state.timelines.friends.visibleStatuses).to.eql([])
|
|
||||||
expect(state.timelines.friends.newStatusCount).to.equal(1)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('add the statuses to allStatuses if no timeline is given', () => {
|
|
||||||
const state = defaultState()
|
|
||||||
const status = makeMockStatus({ id: '1' })
|
|
||||||
|
|
||||||
mutations.addNewStatuses(state, { statuses: [status] })
|
|
||||||
|
|
||||||
expect(state.allStatuses).to.eql([status])
|
|
||||||
expect(state.timelines.public.statuses).to.eql([])
|
|
||||||
expect(state.timelines.public.visibleStatuses).to.eql([])
|
|
||||||
expect(state.timelines.public.newStatusCount).to.equal(0)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('adds the status to allStatuses and to the given timeline, directly visible', () => {
|
|
||||||
const state = defaultState()
|
|
||||||
const status = makeMockStatus({ id: '1' })
|
|
||||||
|
|
||||||
mutations.addNewStatuses(state, {
|
|
||||||
statuses: [status],
|
|
||||||
showImmediately: true,
|
|
||||||
timeline: 'public',
|
|
||||||
})
|
|
||||||
|
|
||||||
expect(state.allStatuses).to.eql([status])
|
|
||||||
expect(state.timelines.public.statuses).to.eql([status])
|
|
||||||
expect(state.timelines.public.visibleStatuses).to.eql([status])
|
|
||||||
expect(state.timelines.public.newStatusCount).to.equal(0)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('does not update the maxId when the noIdUpdate flag is set', () => {
|
|
||||||
const state = defaultState()
|
|
||||||
const status = makeMockStatus({ id: '1' })
|
|
||||||
const secondStatus = makeMockStatus({ id: '2' })
|
|
||||||
|
|
||||||
mutations.addNewStatuses(state, {
|
|
||||||
statuses: [status],
|
|
||||||
showImmediately: true,
|
|
||||||
timeline: 'public',
|
|
||||||
})
|
|
||||||
expect(state.timelines.public.maxId).to.equal('1')
|
|
||||||
|
|
||||||
mutations.addNewStatuses(state, {
|
|
||||||
statuses: [secondStatus],
|
|
||||||
showImmediately: true,
|
|
||||||
timeline: 'public',
|
|
||||||
noIdUpdate: true,
|
|
||||||
})
|
|
||||||
expect(state.timelines.public.statuses).to.eql([secondStatus, status])
|
|
||||||
expect(state.timelines.public.visibleStatuses).to.eql([
|
|
||||||
secondStatus,
|
|
||||||
status,
|
|
||||||
])
|
|
||||||
expect(state.timelines.public.maxId).to.equal('1')
|
|
||||||
})
|
|
||||||
|
|
||||||
it('keeps a descending by id order in timeline.visibleStatuses and timeline.statuses', () => {
|
|
||||||
const state = defaultState()
|
|
||||||
const nonVisibleStatus = makeMockStatus({ id: '1' })
|
|
||||||
const status = makeMockStatus({ id: '3' })
|
|
||||||
const statusTwo = makeMockStatus({ id: '2' })
|
|
||||||
const statusThree = makeMockStatus({ id: '4' })
|
|
||||||
|
|
||||||
mutations.addNewStatuses(state, {
|
|
||||||
statuses: [nonVisibleStatus],
|
|
||||||
showImmediately: false,
|
|
||||||
timeline: 'public',
|
|
||||||
})
|
|
||||||
|
|
||||||
mutations.addNewStatuses(state, {
|
|
||||||
statuses: [status],
|
|
||||||
showImmediately: true,
|
|
||||||
timeline: 'public',
|
|
||||||
})
|
|
||||||
mutations.addNewStatuses(state, {
|
|
||||||
statuses: [statusTwo],
|
|
||||||
showImmediately: true,
|
|
||||||
timeline: 'public',
|
|
||||||
})
|
|
||||||
|
|
||||||
expect(state.timelines.public.minVisibleId).to.equal('2')
|
|
||||||
|
|
||||||
mutations.addNewStatuses(state, {
|
|
||||||
statuses: [statusThree],
|
|
||||||
showImmediately: true,
|
|
||||||
timeline: 'public',
|
|
||||||
})
|
|
||||||
|
|
||||||
expect(state.timelines.public.statuses).to.eql([
|
|
||||||
statusThree,
|
|
||||||
status,
|
|
||||||
statusTwo,
|
|
||||||
nonVisibleStatus,
|
|
||||||
])
|
|
||||||
expect(state.timelines.public.visibleStatuses).to.eql([
|
|
||||||
statusThree,
|
|
||||||
status,
|
|
||||||
statusTwo,
|
|
||||||
])
|
|
||||||
})
|
|
||||||
|
|
||||||
it('splits retweets from their status and links them', () => {
|
|
||||||
const state = defaultState()
|
|
||||||
const status = makeMockStatus({ id: '1' })
|
|
||||||
const retweet = makeMockStatus({ id: '2', type: 'retweet' })
|
|
||||||
const modStatus = makeMockStatus({ id: '1', text: 'something else' })
|
|
||||||
|
|
||||||
retweet.retweeted_status = status
|
|
||||||
|
|
||||||
// It adds both statuses, but only the retweet to visible.
|
|
||||||
mutations.addNewStatuses(state, {
|
|
||||||
statuses: [retweet],
|
|
||||||
timeline: 'public',
|
|
||||||
showImmediately: true,
|
|
||||||
})
|
|
||||||
expect(state.timelines.public.visibleStatuses).to.have.length(1)
|
|
||||||
expect(state.timelines.public.statuses).to.have.length(1)
|
|
||||||
expect(state.allStatuses).to.have.length(2)
|
|
||||||
expect(state.allStatuses[0].id).to.equal('1')
|
|
||||||
expect(state.allStatuses[1].id).to.equal('2')
|
|
||||||
|
|
||||||
// It refers to the modified status.
|
|
||||||
mutations.addNewStatuses(state, {
|
|
||||||
statuses: [modStatus],
|
|
||||||
timeline: 'public',
|
|
||||||
})
|
|
||||||
expect(state.allStatuses).to.have.length(2)
|
|
||||||
expect(state.allStatuses[0].id).to.equal('1')
|
|
||||||
expect(state.allStatuses[0].text).to.equal(modStatus.text)
|
|
||||||
expect(state.allStatuses[1].id).to.equal('2')
|
|
||||||
expect(retweet.retweeted_status.text).to.eql(modStatus.text)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('replaces existing statuses with the same id', () => {
|
|
||||||
const state = defaultState()
|
|
||||||
const status = makeMockStatus({ id: '1' })
|
|
||||||
const modStatus = makeMockStatus({ id: '1', text: 'something else' })
|
|
||||||
|
|
||||||
// Add original status
|
|
||||||
mutations.addNewStatuses(state, {
|
|
||||||
statuses: [status],
|
|
||||||
showImmediately: true,
|
|
||||||
timeline: 'public',
|
|
||||||
})
|
|
||||||
expect(state.timelines.public.visibleStatuses).to.have.length(1)
|
|
||||||
expect(state.allStatuses).to.have.length(1)
|
|
||||||
|
|
||||||
// Add new version of status
|
|
||||||
mutations.addNewStatuses(state, {
|
|
||||||
statuses: [modStatus],
|
|
||||||
showImmediately: true,
|
|
||||||
timeline: 'public',
|
|
||||||
})
|
|
||||||
expect(state.timelines.public.visibleStatuses).to.have.length(1)
|
|
||||||
expect(state.allStatuses).to.have.length(1)
|
|
||||||
expect(state.allStatuses[0].text).to.eql(modStatus.text)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('replaces existing statuses with the same id, coming from a retweet', () => {
|
|
||||||
const state = defaultState()
|
|
||||||
const status = makeMockStatus({ id: '1' })
|
|
||||||
const modStatus = makeMockStatus({ id: '1', text: 'something else' })
|
|
||||||
const retweet = makeMockStatus({ id: '2', type: 'retweet' })
|
|
||||||
retweet.retweeted_status = modStatus
|
|
||||||
|
|
||||||
// Add original status
|
|
||||||
mutations.addNewStatuses(state, {
|
|
||||||
statuses: [status],
|
|
||||||
showImmediately: true,
|
|
||||||
timeline: 'public',
|
|
||||||
})
|
|
||||||
expect(state.timelines.public.visibleStatuses).to.have.length(1)
|
|
||||||
expect(state.allStatuses).to.have.length(1)
|
|
||||||
|
|
||||||
// Add new version of status
|
|
||||||
mutations.addNewStatuses(state, {
|
|
||||||
statuses: [retweet],
|
|
||||||
showImmediately: false,
|
|
||||||
timeline: 'public',
|
|
||||||
})
|
|
||||||
expect(state.timelines.public.visibleStatuses).to.have.length(1)
|
|
||||||
// Don't add the retweet itself if the tweet is visible
|
|
||||||
expect(state.timelines.public.statuses).to.have.length(1)
|
|
||||||
expect(state.allStatuses).to.have.length(2)
|
|
||||||
expect(state.allStatuses[0].text).to.eql(modStatus.text)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('handles favorite actions', () => {
|
|
||||||
const state = defaultState()
|
|
||||||
const status = makeMockStatus({ id: '1' })
|
|
||||||
|
|
||||||
const favorite = {
|
|
||||||
id: '2',
|
|
||||||
type: 'favorite',
|
|
||||||
in_reply_to_status_id: '1', // The API uses strings here...
|
|
||||||
uri: 'tag:shitposter.club,2016-08-21:fave:3895:note:773501:2016-08-21T16:52:15+00:00',
|
|
||||||
text: 'a favorited something by b',
|
|
||||||
user: { id: '99' },
|
|
||||||
}
|
|
||||||
|
|
||||||
mutations.addNewStatuses(state, {
|
|
||||||
statuses: [status],
|
|
||||||
showImmediately: true,
|
|
||||||
timeline: 'public',
|
|
||||||
})
|
|
||||||
mutations.addNewStatuses(state, {
|
|
||||||
statuses: [favorite],
|
|
||||||
showImmediately: true,
|
|
||||||
timeline: 'public',
|
|
||||||
})
|
|
||||||
|
|
||||||
expect(state.timelines.public.visibleStatuses).to.have.length(1)
|
|
||||||
expect(state.timelines.public.visibleStatuses[0].fave_num).to.eql(1)
|
|
||||||
expect(state.timelines.public.maxId).to.eq(favorite.id)
|
|
||||||
|
|
||||||
// Adding it again does nothing
|
|
||||||
mutations.addNewStatuses(state, {
|
|
||||||
statuses: [favorite],
|
|
||||||
showImmediately: true,
|
|
||||||
timeline: 'public',
|
|
||||||
})
|
|
||||||
|
|
||||||
expect(state.timelines.public.visibleStatuses).to.have.length(1)
|
|
||||||
expect(state.timelines.public.visibleStatuses[0].fave_num).to.eql(1)
|
|
||||||
expect(state.timelines.public.maxId).to.eq(favorite.id)
|
|
||||||
|
|
||||||
// If something is favorited by the current user, it also sets the 'favorited' property but does not increment counter to avoid over-counting. Counter is incremented (updated, really) via response to the favorite request.
|
|
||||||
const user = {
|
|
||||||
id: '1',
|
|
||||||
}
|
|
||||||
|
|
||||||
const ownFavorite = {
|
|
||||||
id: '3',
|
|
||||||
type: 'favorite',
|
|
||||||
in_reply_to_status_id: '1', // The API uses strings here...
|
|
||||||
uri: 'tag:shitposter.club,2016-08-21:fave:3895:note:773501:2016-08-21T16:52:15+00:00',
|
|
||||||
text: 'a favorited something by b',
|
|
||||||
user,
|
|
||||||
}
|
|
||||||
|
|
||||||
mutations.addNewStatuses(state, {
|
|
||||||
statuses: [ownFavorite],
|
|
||||||
showImmediately: true,
|
|
||||||
timeline: 'public',
|
|
||||||
user,
|
|
||||||
})
|
|
||||||
|
|
||||||
expect(state.timelines.public.visibleStatuses).to.have.length(1)
|
|
||||||
expect(state.timelines.public.visibleStatuses[0].fave_num).to.eql(1)
|
|
||||||
expect(state.timelines.public.visibleStatuses[0].favorited).to.eql(true)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('emojiReactions', () => {
|
|
||||||
it('increments count in existing reaction', () => {
|
|
||||||
const state = defaultState()
|
|
||||||
const status = makeMockStatus({ id: '1' })
|
|
||||||
status.emoji_reactions = [{ name: '😂', count: 1, accounts: [] }]
|
|
||||||
|
|
||||||
mutations.addNewStatuses(state, {
|
|
||||||
statuses: [status],
|
|
||||||
showImmediately: true,
|
|
||||||
timeline: 'public',
|
|
||||||
})
|
|
||||||
mutations.addOwnReaction(state, {
|
|
||||||
id: '1',
|
|
||||||
emoji: '😂',
|
|
||||||
currentUser: { id: 'me' },
|
|
||||||
})
|
|
||||||
expect(state.allStatusesObject['1'].emoji_reactions[0].count).to.eql(2)
|
|
||||||
expect(state.allStatusesObject['1'].emoji_reactions[0].me).to.eql(true)
|
|
||||||
expect(
|
|
||||||
state.allStatusesObject['1'].emoji_reactions[0].accounts[0].id,
|
|
||||||
).to.equal('me')
|
|
||||||
})
|
|
||||||
|
|
||||||
it('adds a new reaction', () => {
|
|
||||||
const state = defaultState()
|
|
||||||
const status = makeMockStatus({ id: '1' })
|
|
||||||
status.emoji_reactions = []
|
|
||||||
|
|
||||||
mutations.addNewStatuses(state, {
|
|
||||||
statuses: [status],
|
|
||||||
showImmediately: true,
|
|
||||||
timeline: 'public',
|
|
||||||
})
|
|
||||||
mutations.addOwnReaction(state, {
|
|
||||||
id: '1',
|
|
||||||
emoji: '😂',
|
|
||||||
currentUser: { id: 'me' },
|
|
||||||
})
|
|
||||||
expect(state.allStatusesObject['1'].emoji_reactions[0].count).to.eql(1)
|
|
||||||
expect(state.allStatusesObject['1'].emoji_reactions[0].me).to.eql(true)
|
|
||||||
expect(
|
|
||||||
state.allStatusesObject['1'].emoji_reactions[0].accounts[0].id,
|
|
||||||
).to.equal('me')
|
|
||||||
})
|
|
||||||
|
|
||||||
it('decreases count in existing reaction', () => {
|
|
||||||
const state = defaultState()
|
|
||||||
const status = makeMockStatus({ id: '1' })
|
|
||||||
status.emoji_reactions = [
|
|
||||||
{ name: '😂', count: 2, accounts: [{ id: 'me' }] },
|
|
||||||
]
|
|
||||||
|
|
||||||
mutations.addNewStatuses(state, {
|
|
||||||
statuses: [status],
|
|
||||||
showImmediately: true,
|
|
||||||
timeline: 'public',
|
|
||||||
})
|
|
||||||
mutations.removeOwnReaction(state, {
|
|
||||||
id: '1',
|
|
||||||
emoji: '😂',
|
|
||||||
currentUser: { id: 'me' },
|
|
||||||
})
|
|
||||||
expect(state.allStatusesObject['1'].emoji_reactions[0].count).to.eql(1)
|
|
||||||
expect(state.allStatusesObject['1'].emoji_reactions[0].me).to.eql(false)
|
|
||||||
expect(state.allStatusesObject['1'].emoji_reactions[0].accounts).to.eql(
|
|
||||||
[],
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('removes a reaction', () => {
|
|
||||||
const state = defaultState()
|
|
||||||
const status = makeMockStatus({ id: '1' })
|
|
||||||
status.emoji_reactions = [
|
|
||||||
{ name: '😂', count: 1, accounts: [{ id: 'me' }] },
|
|
||||||
]
|
|
||||||
|
|
||||||
mutations.addNewStatuses(state, {
|
|
||||||
statuses: [status],
|
|
||||||
showImmediately: true,
|
|
||||||
timeline: 'public',
|
|
||||||
})
|
|
||||||
mutations.removeOwnReaction(state, {
|
|
||||||
id: '1',
|
|
||||||
emoji: '😂',
|
|
||||||
currentUser: { id: 'me' },
|
|
||||||
})
|
|
||||||
expect(state.allStatusesObject['1'].emoji_reactions).to.have.length(0)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('showNewStatuses', () => {
|
|
||||||
it('resets the minId to the min of the visible statuses when adding new to visible statuses', () => {
|
|
||||||
const state = defaultState()
|
|
||||||
const status = makeMockStatus({ id: '10' })
|
|
||||||
mutations.addNewStatuses(state, {
|
|
||||||
statuses: [status],
|
|
||||||
showImmediately: true,
|
|
||||||
timeline: 'public',
|
|
||||||
})
|
|
||||||
const newStatus = makeMockStatus({ id: '20' })
|
|
||||||
mutations.addNewStatuses(state, {
|
|
||||||
statuses: [newStatus],
|
|
||||||
showImmediately: false,
|
|
||||||
timeline: 'public',
|
|
||||||
})
|
|
||||||
state.timelines.public.minId = '5'
|
|
||||||
mutations.showNewStatuses(state, { timeline: 'public' })
|
|
||||||
|
|
||||||
expect(state.timelines.public.visibleStatuses).to.have.length(2)
|
|
||||||
expect(state.timelines.public.minVisibleId).to.equal('10')
|
|
||||||
expect(state.timelines.public.minId).to.equal('10')
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('clearTimeline', () => {
|
|
||||||
it('keeps userId when clearing user timeline when excludeUserId param is true', () => {
|
|
||||||
const state = defaultState()
|
|
||||||
state.timelines.user.userId = 123
|
|
||||||
|
|
||||||
mutations.clearTimeline(state, { timeline: 'user', excludeUserId: true })
|
|
||||||
|
|
||||||
expect(state.timelines.user.userId).to.eql(123)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
603
test/unit/specs/stores/statuses.spec.js
Normal file
603
test/unit/specs/stores/statuses.spec.js
Normal file
|
|
@ -0,0 +1,603 @@
|
||||||
|
import { createTestingPinia } from '@pinia/testing'
|
||||||
|
import { snakeCase } from 'lodash'
|
||||||
|
import { setActivePinia } from 'pinia'
|
||||||
|
|
||||||
|
import { useStatusesStore } from 'src/stores/statuses.js'
|
||||||
|
import { useUsersStore } from 'src/stores/users.js'
|
||||||
|
|
||||||
|
import * as PUBLIC_API from 'src/api/public.js'
|
||||||
|
import * as USER_API from 'src/api/user.js'
|
||||||
|
|
||||||
|
const userId = '1'
|
||||||
|
const userScreenName = 'user'
|
||||||
|
const userName = 'Guy'
|
||||||
|
const userUrl = 'http://localhost/user'
|
||||||
|
|
||||||
|
const mockMastoAPIUser = ({
|
||||||
|
screen_name = userScreenName,
|
||||||
|
name = userName,
|
||||||
|
url = userUrl,
|
||||||
|
id = userId,
|
||||||
|
} = {}) => ({
|
||||||
|
id,
|
||||||
|
acct: screen_name,
|
||||||
|
display_name: name,
|
||||||
|
fields: [],
|
||||||
|
avatar: '',
|
||||||
|
url,
|
||||||
|
pleroma: {
|
||||||
|
emoji_reactions: [],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const mockUser = ({
|
||||||
|
screen_name = userScreenName,
|
||||||
|
id = userId,
|
||||||
|
name = userName,
|
||||||
|
url = userUrl,
|
||||||
|
} = {}) => ({
|
||||||
|
_original: mockMastoAPIUser({
|
||||||
|
screen_name,
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
url,
|
||||||
|
}),
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
screen_name,
|
||||||
|
url,
|
||||||
|
relationship: undefined,
|
||||||
|
})
|
||||||
|
|
||||||
|
const mockStatus = ({
|
||||||
|
id = '1',
|
||||||
|
text,
|
||||||
|
type = 'status',
|
||||||
|
statusUser = mockUser(),
|
||||||
|
} = {}) => ({
|
||||||
|
id,
|
||||||
|
user: statusUser,
|
||||||
|
name: 'status',
|
||||||
|
text: text ?? `Text number ${id}`,
|
||||||
|
uri: '',
|
||||||
|
type,
|
||||||
|
attentions: [],
|
||||||
|
statusnet_conversation_id: 'c1',
|
||||||
|
emoji_reactions: [],
|
||||||
|
})
|
||||||
|
|
||||||
|
const mockMastoAPIStatus = ({
|
||||||
|
id = '1',
|
||||||
|
text,
|
||||||
|
type = 'status',
|
||||||
|
statusUser = mockMastoAPIUser(),
|
||||||
|
} = {}) => ({
|
||||||
|
id,
|
||||||
|
account: statusUser,
|
||||||
|
name: 'status',
|
||||||
|
content: text ?? `Text number ${id}`,
|
||||||
|
uri: '',
|
||||||
|
type,
|
||||||
|
attentions: [],
|
||||||
|
statusnet_conversation_id: 'c1',
|
||||||
|
})
|
||||||
|
|
||||||
|
const DEFAULT_OPTIONS = (method = 'GET') => ({
|
||||||
|
method,
|
||||||
|
credentials: 'same-origin',
|
||||||
|
headers: {
|
||||||
|
Accept: 'application/json',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Statuses store', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
setActivePinia(createTestingPinia({ stubActions: false }))
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('addNewStatuses', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
const usersStore = useUsersStore()
|
||||||
|
usersStore.addNewUsers = vi.fn().mockReturnValue([mockUser()])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('adds the status to allStatuses', () => {
|
||||||
|
const store = useStatusesStore()
|
||||||
|
const usersStore = useUsersStore()
|
||||||
|
const status = mockStatus({ id: '1' })
|
||||||
|
|
||||||
|
store.addNewStatuses({
|
||||||
|
statuses: [status],
|
||||||
|
timestamp: 1,
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(store.allStatuses).to.eql(new Map([['1', status]]))
|
||||||
|
expect(store.conversations).to.eql(new Map([['c1', new Set(['1'])]]))
|
||||||
|
expect(usersStore.addNewUsers).to.have.callCount(1)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('splits retweets from their status and links them', () => {
|
||||||
|
const store = useStatusesStore()
|
||||||
|
const usersStore = useUsersStore()
|
||||||
|
const status = mockStatus({ id: '1' })
|
||||||
|
const retweet = mockStatus({
|
||||||
|
id: '2',
|
||||||
|
type: 'retweet',
|
||||||
|
user: mockUser({ id: '2' }),
|
||||||
|
})
|
||||||
|
retweet.type = 'retweet'
|
||||||
|
retweet.retweeted_status = status
|
||||||
|
|
||||||
|
store.addNewStatuses({
|
||||||
|
statuses: [retweet],
|
||||||
|
timestamp: 1,
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(store.allStatuses).to.eql(
|
||||||
|
new Map([
|
||||||
|
['1', status],
|
||||||
|
['2', retweet],
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
expect(usersStore.addNewUsers).to.have.callCount(2)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('splits quotes from their status and links them', () => {
|
||||||
|
const store = useStatusesStore()
|
||||||
|
const usersStore = useUsersStore()
|
||||||
|
const status = mockStatus({ id: '1' })
|
||||||
|
const quote = mockStatus({ id: '2' })
|
||||||
|
quote.quote = status
|
||||||
|
|
||||||
|
store.addNewStatuses({
|
||||||
|
statuses: [quote],
|
||||||
|
timestamp: 1,
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(store.allStatuses).to.eql(
|
||||||
|
new Map([
|
||||||
|
['1', status],
|
||||||
|
['2', quote],
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
expect(usersStore.addNewUsers).to.have.callCount(2)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('replaces existing statuses with the same id', () => {
|
||||||
|
const store = useStatusesStore()
|
||||||
|
const usersStore = useUsersStore()
|
||||||
|
const status = mockStatus({ id: '1' })
|
||||||
|
const modStatus = mockStatus({ id: '1', text: 'something else' })
|
||||||
|
|
||||||
|
store.addNewStatuses({
|
||||||
|
statuses: [status],
|
||||||
|
timestamp: 1991,
|
||||||
|
})
|
||||||
|
expect(store.allStatuses).to.eql(new Map([['1', status]]))
|
||||||
|
|
||||||
|
store.addNewStatuses({
|
||||||
|
statuses: [modStatus],
|
||||||
|
timestamp: 2000,
|
||||||
|
})
|
||||||
|
expect(store.allStatuses).to.eql(new Map([['1', modStatus]]))
|
||||||
|
expect(usersStore.addNewUsers).to.have.callCount(2)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('handles edits', () => {
|
||||||
|
const store = useStatusesStore()
|
||||||
|
const usersStore = useUsersStore()
|
||||||
|
const status = mockStatus({ id: '1' })
|
||||||
|
const modStatus = mockStatus({
|
||||||
|
id: '1',
|
||||||
|
text: 'something else',
|
||||||
|
type: 'edit',
|
||||||
|
})
|
||||||
|
|
||||||
|
store.addNewStatuses({
|
||||||
|
statuses: [status],
|
||||||
|
timestamp: 1991,
|
||||||
|
})
|
||||||
|
expect(store.allStatuses).to.eql(new Map([['1', status]]))
|
||||||
|
|
||||||
|
store.addNewStatuses({
|
||||||
|
statuses: [modStatus],
|
||||||
|
timestamp: 2000,
|
||||||
|
})
|
||||||
|
expect(store.allStatuses).to.eql(new Map([['1', modStatus]]))
|
||||||
|
expect(usersStore.addNewUsers).to.have.callCount(2)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('ignores updates with older timestamp', () => {
|
||||||
|
const store = useStatusesStore()
|
||||||
|
const usersStore = useUsersStore()
|
||||||
|
const status = mockStatus({ id: '1' })
|
||||||
|
const modStatus = mockStatus({ id: '1', text: 'something else' })
|
||||||
|
|
||||||
|
store.addNewStatuses({
|
||||||
|
statuses: [status],
|
||||||
|
timestamp: 2000,
|
||||||
|
})
|
||||||
|
expect(store.allStatuses).to.eql(new Map([['1', status]]))
|
||||||
|
|
||||||
|
store.addNewStatuses({
|
||||||
|
statuses: [modStatus],
|
||||||
|
timestamp: 1991,
|
||||||
|
})
|
||||||
|
expect(store.allStatuses).to.eql(new Map([['1', status]]))
|
||||||
|
expect(usersStore.addNewUsers).to.have.callCount(2)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('calls useUsersStore().addNewUsers() even on older timestamp', () => {
|
||||||
|
const store = useStatusesStore()
|
||||||
|
const usersStore = useUsersStore()
|
||||||
|
const status = mockStatus({ id: '1' })
|
||||||
|
const modStatus = mockStatus({ id: '1', text: 'something else' })
|
||||||
|
|
||||||
|
store.addNewStatuses({
|
||||||
|
statuses: [status],
|
||||||
|
timestamp: 2000,
|
||||||
|
})
|
||||||
|
store.addNewStatuses({
|
||||||
|
statuses: [modStatus],
|
||||||
|
timestamp: 1991,
|
||||||
|
})
|
||||||
|
expect(usersStore.addNewUsers).to.have.callCount(2)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('fetchers', () => {
|
||||||
|
it.each([
|
||||||
|
[
|
||||||
|
'StatusSource',
|
||||||
|
{
|
||||||
|
content_type: 'text/plain',
|
||||||
|
text: 'Text',
|
||||||
|
spoiler_text: 'Text',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'EmojiReactions',
|
||||||
|
[
|
||||||
|
{
|
||||||
|
accounts: [mockMastoAPIUser()],
|
||||||
|
count: 1,
|
||||||
|
me: false,
|
||||||
|
name: 'cofe',
|
||||||
|
url: '',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
],
|
||||||
|
['Favs', [mockMastoAPIUser()]],
|
||||||
|
['Repeats', [mockMastoAPIUser()]],
|
||||||
|
])('fetch%s', async (group, mockedResponse) => {
|
||||||
|
const mockFetch = vi.fn()
|
||||||
|
mockFetch.mockResolvedValueOnce(
|
||||||
|
new Response(JSON.stringify(mockedResponse), {
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
vi.stubGlobal('fetch', mockFetch)
|
||||||
|
|
||||||
|
let urlKey
|
||||||
|
let prefix = 'MASTODON'
|
||||||
|
if (group === 'Favs') {
|
||||||
|
urlKey = 'STATUS_FAVORITEDBY'
|
||||||
|
} else if (group === 'Repeats') {
|
||||||
|
urlKey = 'STATUS_REBLOGGEDBY'
|
||||||
|
} else {
|
||||||
|
urlKey = snakeCase(group).toUpperCase()
|
||||||
|
}
|
||||||
|
if (group === 'EmojiReactions') {
|
||||||
|
prefix = 'PLEROMA'
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = PUBLIC_API[`${prefix}_${urlKey}_URL`]('id')
|
||||||
|
|
||||||
|
const store = useStatusesStore()
|
||||||
|
const status = mockStatus({ id: 'id' })
|
||||||
|
store.addNewStatuses({
|
||||||
|
statuses: [status],
|
||||||
|
timestamp: 2000,
|
||||||
|
})
|
||||||
|
|
||||||
|
const result = await store[`fetch${group}`]('id')
|
||||||
|
const updated = store.allStatuses.get('id')
|
||||||
|
|
||||||
|
expect(mockFetch).to.have.been.calledWith(url, DEFAULT_OPTIONS())
|
||||||
|
if (group === 'Favs') {
|
||||||
|
expect(updated.favoritedBy).to.have.length(1)
|
||||||
|
expect(updated.fave_num).to.eql(1)
|
||||||
|
} else if (group === 'Repeats') {
|
||||||
|
expect(updated.rebloggedBy).to.have.length(1)
|
||||||
|
expect(updated.repeat_num).to.eql(1)
|
||||||
|
} else if (group === 'EmojiReactions') {
|
||||||
|
expect(updated.emoji_reactions).to.have.length(mockedResponse.length)
|
||||||
|
expect(updated.emoji_reactions[0].name).to.eql(mockedResponse[0].name)
|
||||||
|
} else {
|
||||||
|
expect(result).to.eql(mockedResponse)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('fetchFavsAndRepeats', async () => {
|
||||||
|
const store = useStatusesStore()
|
||||||
|
store.fetchFavs = vi.fn().mockResolvedValue(async () => {
|
||||||
|
/* no-op */
|
||||||
|
})
|
||||||
|
store.fetchRepeats = vi.fn().mockResolvedValue(async () => {
|
||||||
|
/* no-op */
|
||||||
|
})
|
||||||
|
|
||||||
|
await store.fetchFavsAndRepeats('id')
|
||||||
|
expect(store.fetchFavs).to.have.been.calledWith('id')
|
||||||
|
expect(store.fetchRepeats).to.have.been.calledWith('id')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('fetchStatus', async () => {
|
||||||
|
const mockFetch = vi.fn()
|
||||||
|
mockFetch.mockResolvedValueOnce(
|
||||||
|
new Response(JSON.stringify(mockMastoAPIStatus()), {
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
vi.stubGlobal('fetch', mockFetch)
|
||||||
|
|
||||||
|
const store = useStatusesStore()
|
||||||
|
await store.fetchStatus('id')
|
||||||
|
|
||||||
|
expect(mockFetch).to.have.been.calledWith(
|
||||||
|
PUBLIC_API.MASTODON_STATUS_URL('id'),
|
||||||
|
DEFAULT_OPTIONS(),
|
||||||
|
)
|
||||||
|
expect(store.allStatuses).to.have.length(1)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('interactions', () => {
|
||||||
|
it.each([
|
||||||
|
['favorite', 'MASTODON_FAVORITE_URL'],
|
||||||
|
['unfavorite', 'MASTODON_UNFAVORITE_URL'],
|
||||||
|
['retweet', 'MASTODON_RETWEET_URL'],
|
||||||
|
['unretweet', 'MASTODON_UNRETWEET_URL'],
|
||||||
|
['reactWithEmoji', 'PLEROMA_EMOJI_REACT_URL', 'PUT'],
|
||||||
|
['unreactWithEmoji', 'PLEROMA_EMOJI_UNREACT_URL', 'DELETE'],
|
||||||
|
[
|
||||||
|
'bookmark',
|
||||||
|
'MASTODON_BOOKMARK_STATUS_URL',
|
||||||
|
undefined,
|
||||||
|
{ folder_id: 'argument' },
|
||||||
|
],
|
||||||
|
['unbookmark', 'MASTODON_UNBOOKMARK_STATUS_URL'],
|
||||||
|
['pinStatus', 'MASTODON_PIN_OWN_STATUS_URL'],
|
||||||
|
['unpinStatus', 'MASTODON_UNPIN_OWN_STATUS_URL'],
|
||||||
|
['muteConversation', 'MASTODON_MUTE_CONVERSATION_URL'],
|
||||||
|
['unmuteConversation', 'MASTODON_UNMUTE_CONVERSATION_URL'],
|
||||||
|
['deleteStatus', 'MASTODON_DELETE_URL', 'DELETE'],
|
||||||
|
])('%s - api call', async (interaction, urlKey, method = 'POST', body) => {
|
||||||
|
const url = USER_API[urlKey]('1', 'argument')
|
||||||
|
|
||||||
|
const status = mockStatus()
|
||||||
|
const store = useStatusesStore()
|
||||||
|
store.addNewStatuses({
|
||||||
|
statuses: [status],
|
||||||
|
timestamp: 1,
|
||||||
|
})
|
||||||
|
|
||||||
|
const mockFetch = vi.fn()
|
||||||
|
mockFetch.mockResolvedValueOnce(
|
||||||
|
new Response(JSON.stringify(mockMastoAPIStatus({ text: 'Updated' })), {
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
vi.stubGlobal('fetch', mockFetch)
|
||||||
|
await store[interaction]('1', 'argument')
|
||||||
|
const expectedArg = DEFAULT_OPTIONS(method)
|
||||||
|
|
||||||
|
if (body) {
|
||||||
|
expectedArg.body = JSON.stringify(body)
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(mockFetch).to.have.been.calledWith(url, expectedArg)
|
||||||
|
if (interaction === 'deleteStatus') {
|
||||||
|
expect(store.allStatuses.get('1').deleted).to.be.true
|
||||||
|
} else {
|
||||||
|
expect(store.allStatuses.get('1').text).to.eql('Updated')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const optimismInteractions = [
|
||||||
|
['favorite', 'favorited', 'fave_num'],
|
||||||
|
['retweet', 'repeated', 'repeat_num'],
|
||||||
|
['bookmark', 'bookmarked'],
|
||||||
|
['muteConversation', 'thread_muted'],
|
||||||
|
]
|
||||||
|
.map(([method, property, count]) => [
|
||||||
|
[method, property, count],
|
||||||
|
['un' + method, property, count],
|
||||||
|
])
|
||||||
|
.flat()
|
||||||
|
|
||||||
|
it.each(
|
||||||
|
optimismInteractions,
|
||||||
|
)('%s - optimism call', async (method, property, count) => {
|
||||||
|
// Prepare our status
|
||||||
|
const status = mockStatus()
|
||||||
|
const negate = method.startsWith('un')
|
||||||
|
const oldCount = 9
|
||||||
|
const newCount = negate ? 8 : 10
|
||||||
|
status[property] = negate
|
||||||
|
if (count) {
|
||||||
|
status[count] = oldCount
|
||||||
|
}
|
||||||
|
if (method === 'unbookmark') {
|
||||||
|
status.bookmark_folder_id = 'argument'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert it
|
||||||
|
const store = useStatusesStore()
|
||||||
|
store.addNewStatuses({
|
||||||
|
statuses: [status],
|
||||||
|
timestamp: 1,
|
||||||
|
})
|
||||||
|
|
||||||
|
const mockFetch = vi.fn()
|
||||||
|
mockFetch.mockResolvedValueOnce(
|
||||||
|
new Response(JSON.stringify(mockMastoAPIStatus({ text: 'Updated' })), {
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(store.allStatuses.get('1')).to.have.property(property, negate)
|
||||||
|
if (count) {
|
||||||
|
expect(store.allStatuses.get('1')).to.have.property(count, oldCount)
|
||||||
|
}
|
||||||
|
vi.stubGlobal('fetch', mockFetch)
|
||||||
|
|
||||||
|
store[method]('1', 'argument')
|
||||||
|
expect(store.allStatuses.get('1')).to.have.property(property, !negate)
|
||||||
|
if (count) {
|
||||||
|
expect(store.allStatuses.get('1')).to.have.property(count, newCount)
|
||||||
|
}
|
||||||
|
if (property === 'bookmarked') {
|
||||||
|
expect(store.allStatuses.get('1')).to.have.property(
|
||||||
|
'bookmark_folder_id',
|
||||||
|
'argument',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it.each(
|
||||||
|
optimismInteractions,
|
||||||
|
)('%s - optimism fail', async (method, property, count) => {
|
||||||
|
// Prepare our status
|
||||||
|
const status = mockStatus()
|
||||||
|
const negate = method.startsWith('un')
|
||||||
|
const oldCount = 9
|
||||||
|
status[property] = negate
|
||||||
|
if (count) {
|
||||||
|
status[count] = oldCount
|
||||||
|
}
|
||||||
|
if (method === 'unbookmark') {
|
||||||
|
status.bookmark_folder_id = 'argument'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert it
|
||||||
|
const store = useStatusesStore()
|
||||||
|
store.addNewStatuses({
|
||||||
|
statuses: [status],
|
||||||
|
timestamp: 1,
|
||||||
|
})
|
||||||
|
|
||||||
|
const mockFetch = vi.fn()
|
||||||
|
mockFetch.mockRejectedValueOnce(new Error('Failure!'))
|
||||||
|
|
||||||
|
expect(store.allStatuses.get('1')).to.have.property(property, negate)
|
||||||
|
if (count) {
|
||||||
|
expect(store.allStatuses.get('1')).to.have.property(count, oldCount)
|
||||||
|
}
|
||||||
|
vi.stubGlobal('fetch', mockFetch)
|
||||||
|
|
||||||
|
await store[method]('1', 'argument')
|
||||||
|
expect(store.allStatuses.get('1')).to.have.property(property, negate)
|
||||||
|
if (count) {
|
||||||
|
expect(store.allStatuses.get('1')).to.have.property(count, oldCount)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Failing 'bookmark' method SHOULD clear folder id
|
||||||
|
if (method === 'unbookmark') {
|
||||||
|
expect(store.allStatuses.get('1')).to.have.property(
|
||||||
|
'bookmark_folder_id',
|
||||||
|
'argument',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it.each([
|
||||||
|
['reactWithEmoji', 0],
|
||||||
|
['unreactWithEmoji', 1],
|
||||||
|
['reactWithEmoji', 1],
|
||||||
|
['unreactWithEmoji', 2],
|
||||||
|
])('%s count: %s - optimism call', async (method, oldCount) => {
|
||||||
|
// Prepare our status
|
||||||
|
const status = mockStatus()
|
||||||
|
const negate = method.startsWith('un')
|
||||||
|
const newCount = negate ? oldCount - 1 : oldCount + 1
|
||||||
|
|
||||||
|
useUsersStore().currentUser = mockUser()
|
||||||
|
|
||||||
|
if (oldCount > 0) {
|
||||||
|
const reactors = [...new Array(oldCount)].map((empty, index) =>
|
||||||
|
mockUser({ id: 'o' + index }),
|
||||||
|
)
|
||||||
|
if (negate) {
|
||||||
|
// Replace one of reactors with ourselves
|
||||||
|
reactors[0] = useUsersStore().currentUser
|
||||||
|
}
|
||||||
|
status.emoji_reactions = [
|
||||||
|
{
|
||||||
|
name: 'hyperlol',
|
||||||
|
count: oldCount,
|
||||||
|
accounts: reactors,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
} else {
|
||||||
|
status.emoji_reactions = []
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert it
|
||||||
|
const store = useStatusesStore()
|
||||||
|
store.addNewStatuses({
|
||||||
|
statuses: [status],
|
||||||
|
timestamp: 1,
|
||||||
|
})
|
||||||
|
|
||||||
|
const mockFetch = vi.fn()
|
||||||
|
mockFetch.mockResolvedValueOnce(
|
||||||
|
new Response(JSON.stringify(mockMastoAPIStatus({ text: 'Updated' })), {
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
vi.stubGlobal('fetch', mockFetch)
|
||||||
|
const expected = store.allStatuses.get('1')
|
||||||
|
|
||||||
|
expect(expected.emoji_reactions).to.have.length(oldCount === 0 ? 0 : 1)
|
||||||
|
if (oldCount !== 0) {
|
||||||
|
expect(expected.emoji_reactions[0].name).to.eql('hyperlol')
|
||||||
|
expect(expected.emoji_reactions[0].count).to.eql(oldCount)
|
||||||
|
expect(expected.emoji_reactions[0].accounts).to.have.length(oldCount)
|
||||||
|
}
|
||||||
|
|
||||||
|
store[method]('1', 'hyperlol')
|
||||||
|
|
||||||
|
expect(expected.emoji_reactions).to.have.length(newCount === 0 ? 0 : 1)
|
||||||
|
if (newCount !== 0) {
|
||||||
|
expect(expected.emoji_reactions[0].name).to.eql('hyperlol')
|
||||||
|
expect(expected.emoji_reactions[0].count).to.eql(newCount)
|
||||||
|
expect(expected.emoji_reactions[0].accounts).to.have.length(newCount)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('wipeUserStatuses', () => {
|
||||||
|
const store = useStatusesStore()
|
||||||
|
const statuses = [...new Array(20)].map((empty, index) =>
|
||||||
|
mockStatus({
|
||||||
|
id: 's' + index,
|
||||||
|
statusUser: mockUser({ id: 'u' + index }),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
store.addNewStatuses({
|
||||||
|
statuses,
|
||||||
|
timestamp: 1,
|
||||||
|
})
|
||||||
|
|
||||||
|
store.wipeUserStatuses('u19')
|
||||||
|
|
||||||
|
expect(store.allStatuses).to.have.length(19)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
@ -43,47 +43,47 @@ const actionKeys = (action) => {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('The users store', () => {
|
const userId = '1'
|
||||||
beforeEach(() => {
|
const userScreenName = 'user'
|
||||||
setActivePinia(createTestingPinia({ stubActions: false }))
|
const userName = 'Guy'
|
||||||
})
|
const userUrl = 'http://localhost/user'
|
||||||
|
|
||||||
const userId = '1'
|
const mockMastoAPIUser = ({
|
||||||
const userScreenName = 'user'
|
screen_name = userScreenName,
|
||||||
const userName = 'Guy'
|
name = userName,
|
||||||
const userUrl = 'http://localhost/user'
|
url = userUrl,
|
||||||
|
id = userId,
|
||||||
|
} = {}) => ({
|
||||||
|
id,
|
||||||
|
acct: screen_name,
|
||||||
|
display_name: name,
|
||||||
|
fields: [],
|
||||||
|
avatar: '',
|
||||||
|
url,
|
||||||
|
})
|
||||||
|
|
||||||
const mastoApiUser = ({
|
const mockUser = ({
|
||||||
screen_name = userScreenName,
|
screen_name = userScreenName,
|
||||||
name = userName,
|
id = userId,
|
||||||
url = userUrl,
|
name = userName,
|
||||||
id = userId,
|
url = userUrl,
|
||||||
} = {}) => ({
|
} = {}) => ({
|
||||||
id,
|
_original: mockMastoAPIUser({
|
||||||
acct: screen_name,
|
screen_name,
|
||||||
display_name: name,
|
|
||||||
fields: [],
|
|
||||||
avatar: '',
|
|
||||||
url,
|
|
||||||
})
|
|
||||||
|
|
||||||
const user = ({
|
|
||||||
screen_name = userScreenName,
|
|
||||||
id = userId,
|
|
||||||
name = userName,
|
|
||||||
url = userUrl,
|
|
||||||
} = {}) => ({
|
|
||||||
_original: mastoApiUser({
|
|
||||||
screen_name,
|
|
||||||
id,
|
|
||||||
name,
|
|
||||||
url,
|
|
||||||
}),
|
|
||||||
id,
|
id,
|
||||||
name,
|
name,
|
||||||
screen_name,
|
|
||||||
url,
|
url,
|
||||||
relationship: undefined,
|
}),
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
screen_name,
|
||||||
|
url,
|
||||||
|
relationship: undefined,
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Users store', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
setActivePinia(createTestingPinia({ stubActions: false }))
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('addNewUsers', () => {
|
describe('addNewUsers', () => {
|
||||||
|
|
@ -91,9 +91,9 @@ describe('The users store', () => {
|
||||||
it('adds new users to the set, merging in new information for old users', () => {
|
it('adds new users to the set, merging in new information for old users', () => {
|
||||||
const store = useUsersStore()
|
const store = useUsersStore()
|
||||||
|
|
||||||
const modUser = user({ name: 'Dude' })
|
const modUser = mockUser({ name: 'Dude' })
|
||||||
|
|
||||||
store.addNewUsers({ data: [user()], timestamp: 1 })
|
store.addNewUsers({ data: [mockUser()], timestamp: 1 })
|
||||||
expect(store.users).to.have.length(1)
|
expect(store.users).to.have.length(1)
|
||||||
expect(store.users).to.have.all.keys(userId)
|
expect(store.users).to.have.all.keys(userId)
|
||||||
|
|
||||||
|
|
@ -106,9 +106,9 @@ describe('The users store', () => {
|
||||||
it('ignores new users if timestamp is older', () => {
|
it('ignores new users if timestamp is older', () => {
|
||||||
const store = useUsersStore()
|
const store = useUsersStore()
|
||||||
|
|
||||||
const modUser = user({ name: 'Old guy' })
|
const modUser = mockUser({ name: 'Old guy' })
|
||||||
|
|
||||||
store.addNewUsers({ data: [user()], timestamp: 2000 })
|
store.addNewUsers({ data: [mockUser()], timestamp: 2000 })
|
||||||
expect(store.users).to.have.length(1)
|
expect(store.users).to.have.length(1)
|
||||||
expect(store.users).to.have.all.keys(userId)
|
expect(store.users).to.have.all.keys(userId)
|
||||||
expect(store.users.get(userId).name).to.eql('Guy')
|
expect(store.users.get(userId).name).to.eql('Guy')
|
||||||
|
|
@ -123,18 +123,18 @@ describe('The users store', () => {
|
||||||
const store = useUsersStore()
|
const store = useUsersStore()
|
||||||
|
|
||||||
const userFields = {
|
const userFields = {
|
||||||
...user(),
|
...mockUser(),
|
||||||
fields: [{ name: 'Label 1', value: 'Content 1' }],
|
fields: [{ name: 'Label 1', value: 'Content 1' }],
|
||||||
}
|
}
|
||||||
const firstModUser = {
|
const firstModUser = {
|
||||||
...user(),
|
...mockUser(),
|
||||||
fields: [
|
fields: [
|
||||||
{ name: 'Label 2', value: 'Content 2' },
|
{ name: 'Label 2', value: 'Content 2' },
|
||||||
{ name: 'Label 3', value: 'Content 3' },
|
{ name: 'Label 3', value: 'Content 3' },
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
const secondModUser = {
|
const secondModUser = {
|
||||||
...user(),
|
...mockUser(),
|
||||||
fields: [{ name: 'Label 4', value: 'Content 4' }],
|
fields: [{ name: 'Label 4', value: 'Content 4' }],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -159,14 +159,14 @@ describe('The users store', () => {
|
||||||
const store = useUsersStore()
|
const store = useUsersStore()
|
||||||
|
|
||||||
const modUser = {
|
const modUser = {
|
||||||
...user(),
|
...mockUser(),
|
||||||
relationship: {
|
relationship: {
|
||||||
id: userId,
|
id: userId,
|
||||||
following: true,
|
following: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
store.addNewUsers({ data: [user()], timestamp: 1 })
|
store.addNewUsers({ data: [mockUser()], timestamp: 1 })
|
||||||
store.addNewUsers({ data: [modUser], timestamp: 2 })
|
store.addNewUsers({ data: [modUser], timestamp: 2 })
|
||||||
|
|
||||||
expect(store.relationships).to.have.length(1)
|
expect(store.relationships).to.have.length(1)
|
||||||
|
|
@ -179,14 +179,14 @@ describe('The users store', () => {
|
||||||
const store = useUsersStore()
|
const store = useUsersStore()
|
||||||
|
|
||||||
const modUser = {
|
const modUser = {
|
||||||
...user({ name: 'Old Dude' }),
|
...mockUser({ name: 'Old Dude' }),
|
||||||
relationship: {
|
relationship: {
|
||||||
id: userId,
|
id: userId,
|
||||||
following: true,
|
following: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
store.addNewUsers({ data: [user()], timestamp: 2000 })
|
store.addNewUsers({ data: [mockUser()], timestamp: 2000 })
|
||||||
store.addNewUsers({ data: [modUser], timestamp: 1991 })
|
store.addNewUsers({ data: [modUser], timestamp: 1991 })
|
||||||
|
|
||||||
expect(store.relationships).to.have.length(1)
|
expect(store.relationships).to.have.length(1)
|
||||||
|
|
@ -198,10 +198,12 @@ describe('The users store', () => {
|
||||||
it("doesn't erase relationship information if new data has it missing", () => {
|
it("doesn't erase relationship information if new data has it missing", () => {
|
||||||
const store = useUsersStore()
|
const store = useUsersStore()
|
||||||
|
|
||||||
const modUser = user({ name: 'Dude' })
|
const modUser = mockUser({ name: 'Dude' })
|
||||||
|
|
||||||
store.addNewUsers({
|
store.addNewUsers({
|
||||||
data: [{ ...user(), relationship: { id: userId, following: true } }],
|
data: [
|
||||||
|
{ ...mockUser(), relationship: { id: userId, following: true } },
|
||||||
|
],
|
||||||
timestamp: 1,
|
timestamp: 1,
|
||||||
})
|
})
|
||||||
store.addNewUsers({ data: [modUser], timestamp: 2 })
|
store.addNewUsers({ data: [modUser], timestamp: 2 })
|
||||||
|
|
@ -219,7 +221,7 @@ describe('The users store', () => {
|
||||||
const store = useUsersStore()
|
const store = useUsersStore()
|
||||||
const relationship = { id: userId, following: true }
|
const relationship = { id: userId, following: true }
|
||||||
|
|
||||||
store.addNewUsers({ data: [user()], timestamp: 1 })
|
store.addNewUsers({ data: [mockUser()], timestamp: 1 })
|
||||||
store.updateUserRelationships({ data: relationship, timestamp: 2 })
|
store.updateUserRelationships({ data: relationship, timestamp: 2 })
|
||||||
|
|
||||||
expect(store.relationship(userId)).to.eql({ id: userId, following: true })
|
expect(store.relationship(userId)).to.eql({ id: userId, following: true })
|
||||||
|
|
@ -240,7 +242,7 @@ describe('The users store', () => {
|
||||||
const relationship = { id: userId, following: true }
|
const relationship = { id: userId, following: true }
|
||||||
|
|
||||||
store.updateUserRelationships({ data: relationship, timestamp: 1 })
|
store.updateUserRelationships({ data: relationship, timestamp: 1 })
|
||||||
store.addNewUsers({ data: [user()], timestamp: 2 })
|
store.addNewUsers({ data: [mockUser()], timestamp: 2 })
|
||||||
|
|
||||||
expect(store.relationship(userId)).to.eql({ id: userId, following: true })
|
expect(store.relationship(userId)).to.eql({ id: userId, following: true })
|
||||||
expect(store.findUser(userId).relationship).to.eql({
|
expect(store.findUser(userId).relationship).to.eql({
|
||||||
|
|
@ -255,7 +257,7 @@ describe('The users store', () => {
|
||||||
const newRelationship = { id: userId, following: false }
|
const newRelationship = { id: userId, following: false }
|
||||||
|
|
||||||
store.addNewUsers({
|
store.addNewUsers({
|
||||||
data: [{ ...user(), relationship: newRelationship }],
|
data: [{ ...mockUser(), relationship: newRelationship }],
|
||||||
timestamp: 2000,
|
timestamp: 2000,
|
||||||
})
|
})
|
||||||
store.updateUserRelationships({ data: oldRelationship, timestamp: 1991 })
|
store.updateUserRelationships({ data: oldRelationship, timestamp: 1991 })
|
||||||
|
|
@ -274,13 +276,13 @@ describe('The users store', () => {
|
||||||
vi.stubGlobal(
|
vi.stubGlobal(
|
||||||
'fetch',
|
'fetch',
|
||||||
vi.fn().mockResolvedValueOnce(
|
vi.fn().mockResolvedValueOnce(
|
||||||
new Response(JSON.stringify(mastoApiUser()), {
|
new Response(JSON.stringify(mockMastoAPIUser()), {
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
const expected = user()
|
const expected = mockUser()
|
||||||
const store = useUsersStore()
|
const store = useUsersStore()
|
||||||
const resultUser = await store.fetchUserIfMissing({ id: '1' })
|
const resultUser = await store.fetchUserIfMissing({ id: '1' })
|
||||||
|
|
||||||
|
|
@ -300,14 +302,14 @@ describe('The users store', () => {
|
||||||
)
|
)
|
||||||
// fetch by name yields user id which we request next
|
// fetch by name yields user id which we request next
|
||||||
.mockResolvedValueOnce(
|
.mockResolvedValueOnce(
|
||||||
new Response(JSON.stringify(mastoApiUser()), {
|
new Response(JSON.stringify(mockMastoAPIUser()), {
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.mockThrowOnce(new Error("Shouldn't be called more than once")),
|
.mockThrowOnce(new Error("Shouldn't be called more than once")),
|
||||||
)
|
)
|
||||||
|
|
||||||
const expected = user()
|
const expected = mockUser()
|
||||||
const store = useUsersStore()
|
const store = useUsersStore()
|
||||||
const resultUser1 = await store.fetchUserIfMissing({ name: 'user' })
|
const resultUser1 = await store.fetchUserIfMissing({ name: 'user' })
|
||||||
const resultUser2 = await store.fetchUserIfMissing({ id: '1' })
|
const resultUser2 = await store.fetchUserIfMissing({ id: '1' })
|
||||||
|
|
@ -323,11 +325,11 @@ describe('The users store', () => {
|
||||||
vi.fn().mockThrowOnce(new Error("Shouldn't be called at all")),
|
vi.fn().mockThrowOnce(new Error("Shouldn't be called at all")),
|
||||||
)
|
)
|
||||||
const store = useUsersStore()
|
const store = useUsersStore()
|
||||||
store.addNewUsers({ data: [user()], timestamp: 1 })
|
store.addNewUsers({ data: [mockUser()], timestamp: 1 })
|
||||||
|
|
||||||
const resultUser1 = await store.fetchUserIfMissing({ id: '1' })
|
const resultUser1 = await store.fetchUserIfMissing({ id: '1' })
|
||||||
const resultUser2 = await store.fetchUserIfMissing({ name: 'user' })
|
const resultUser2 = await store.fetchUserIfMissing({ name: 'user' })
|
||||||
const expected = user()
|
const expected = mockUser()
|
||||||
|
|
||||||
expect(resultUser1).to.deep.include(expected)
|
expect(resultUser1).to.deep.include(expected)
|
||||||
expect(resultUser2).to.deep.include(expected)
|
expect(resultUser2).to.deep.include(expected)
|
||||||
|
|
@ -338,7 +340,7 @@ describe('The users store', () => {
|
||||||
vi.stubGlobal(
|
vi.stubGlobal(
|
||||||
'fetch',
|
'fetch',
|
||||||
vi.fn().mockResolvedValueOnce(
|
vi.fn().mockResolvedValueOnce(
|
||||||
new Response(JSON.stringify(mastoApiUser()), {
|
new Response(JSON.stringify(mockMastoAPIUser()), {
|
||||||
status: 404,
|
status: 404,
|
||||||
statusText: 'Not Found',
|
statusText: 'Not Found',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
|
@ -371,8 +373,12 @@ describe('The users store', () => {
|
||||||
.mockResolvedValueOnce(
|
.mockResolvedValueOnce(
|
||||||
new Response(
|
new Response(
|
||||||
JSON.stringify([
|
JSON.stringify([
|
||||||
mastoApiUser({ screen_name: 'snake', name: 'John', id: '2' }),
|
mockMastoAPIUser({
|
||||||
mastoApiUser({
|
screen_name: 'snake',
|
||||||
|
name: 'John',
|
||||||
|
id: '2',
|
||||||
|
}),
|
||||||
|
mockMastoAPIUser({
|
||||||
screen_name: 'zero',
|
screen_name: 'zero',
|
||||||
name: 'David Oh',
|
name: 'David Oh',
|
||||||
id: '3',
|
id: '3',
|
||||||
|
|
@ -386,12 +392,12 @@ describe('The users store', () => {
|
||||||
.mockResolvedValueOnce(
|
.mockResolvedValueOnce(
|
||||||
new Response(
|
new Response(
|
||||||
JSON.stringify([
|
JSON.stringify([
|
||||||
mastoApiUser({
|
mockMastoAPIUser({
|
||||||
screen_name: 'sigint',
|
screen_name: 'sigint',
|
||||||
name: 'Mr.Anderson',
|
name: 'Mr.Anderson',
|
||||||
id: '4',
|
id: '4',
|
||||||
}),
|
}),
|
||||||
mastoApiUser({
|
mockMastoAPIUser({
|
||||||
screen_name: 'paramedic',
|
screen_name: 'paramedic',
|
||||||
name: 'Dr.Clark',
|
name: 'Dr.Clark',
|
||||||
id: '5',
|
id: '5',
|
||||||
|
|
@ -406,7 +412,7 @@ describe('The users store', () => {
|
||||||
vi.stubGlobal('fetch', mockFetch)
|
vi.stubGlobal('fetch', mockFetch)
|
||||||
|
|
||||||
const store = useUsersStore()
|
const store = useUsersStore()
|
||||||
store.addNewUsers({ timestamp: 1, data: user() })
|
store.addNewUsers({ timestamp: 1, data: mockUser() })
|
||||||
|
|
||||||
const urlGroup = group === 'Friends' ? 'Following' : group
|
const urlGroup = group === 'Friends' ? 'Following' : group
|
||||||
const us = store.users.get(userId)
|
const us = store.users.get(userId)
|
||||||
|
|
@ -443,8 +449,12 @@ describe('The users store', () => {
|
||||||
.mockResolvedValueOnce(
|
.mockResolvedValueOnce(
|
||||||
new Response(
|
new Response(
|
||||||
JSON.stringify([
|
JSON.stringify([
|
||||||
mastoApiUser({ screen_name: 'snake', name: 'John', id: '2' }),
|
mockMastoAPIUser({
|
||||||
mastoApiUser({
|
screen_name: 'snake',
|
||||||
|
name: 'John',
|
||||||
|
id: '2',
|
||||||
|
}),
|
||||||
|
mockMastoAPIUser({
|
||||||
screen_name: 'zero',
|
screen_name: 'zero',
|
||||||
name: 'David Oh',
|
name: 'David Oh',
|
||||||
id: '3',
|
id: '3',
|
||||||
|
|
@ -458,12 +468,12 @@ describe('The users store', () => {
|
||||||
.mockResolvedValueOnce(
|
.mockResolvedValueOnce(
|
||||||
new Response(
|
new Response(
|
||||||
JSON.stringify([
|
JSON.stringify([
|
||||||
mastoApiUser({
|
mockMastoAPIUser({
|
||||||
screen_name: 'sigint',
|
screen_name: 'sigint',
|
||||||
name: 'Mr.Anderson',
|
name: 'Mr.Anderson',
|
||||||
id: '4',
|
id: '4',
|
||||||
}),
|
}),
|
||||||
mastoApiUser({
|
mockMastoAPIUser({
|
||||||
screen_name: 'paramedic',
|
screen_name: 'paramedic',
|
||||||
name: 'Dr.Clark',
|
name: 'Dr.Clark',
|
||||||
id: '5',
|
id: '5',
|
||||||
|
|
@ -478,7 +488,7 @@ describe('The users store', () => {
|
||||||
vi.stubGlobal('fetch', mockFetch)
|
vi.stubGlobal('fetch', mockFetch)
|
||||||
|
|
||||||
const store = useUsersStore()
|
const store = useUsersStore()
|
||||||
store.addNewUsers({ timestamp: 1, data: user() })
|
store.addNewUsers({ timestamp: 1, data: mockUser() })
|
||||||
|
|
||||||
const us = store.users.get(userId)
|
const us = store.users.get(userId)
|
||||||
|
|
||||||
|
|
@ -514,7 +524,7 @@ describe('The users store', () => {
|
||||||
vi.stubGlobal('fetch', mockFetch)
|
vi.stubGlobal('fetch', mockFetch)
|
||||||
|
|
||||||
const store = useUsersStore()
|
const store = useUsersStore()
|
||||||
store.addNewUsers({ timestamp: 1, data: user() })
|
store.addNewUsers({ timestamp: 1, data: mockUser() })
|
||||||
|
|
||||||
const us = store.users.get(userId)
|
const us = store.users.get(userId)
|
||||||
store.currentUser = us
|
store.currentUser = us
|
||||||
|
|
@ -548,9 +558,9 @@ describe('The users store', () => {
|
||||||
store.addNewUsers({
|
store.addNewUsers({
|
||||||
timestamp: 1,
|
timestamp: 1,
|
||||||
data: [
|
data: [
|
||||||
user(),
|
mockUser(),
|
||||||
{ ...user({ name: 'John', screen_name: 'snake', id: '2' }) },
|
{ ...mockUser({ name: 'John', screen_name: 'snake', id: '2' }) },
|
||||||
{ ...user({ name: 'David Oh', screen_name: 'zero', id: '3' }) },
|
{ ...mockUser({ name: 'David Oh', screen_name: 'zero', id: '3' }) },
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -572,7 +582,7 @@ describe('The users store', () => {
|
||||||
describe('misc updates', () => {
|
describe('misc updates', () => {
|
||||||
it('updateUserAdminData', () => {
|
it('updateUserAdminData', () => {
|
||||||
const store = useUsersStore()
|
const store = useUsersStore()
|
||||||
store.addNewUsers({ data: [user()], timestamp: 1 })
|
store.addNewUsers({ data: [mockUser()], timestamp: 1 })
|
||||||
const adminData = { is_active: true, tags: ['one', 'two'] }
|
const adminData = { is_active: true, tags: ['one', 'two'] }
|
||||||
store.updateUserAdminData(userId, adminData)
|
store.updateUserAdminData(userId, adminData)
|
||||||
|
|
||||||
|
|
@ -583,7 +593,7 @@ describe('The users store', () => {
|
||||||
|
|
||||||
it('updateRight', () => {
|
it('updateRight', () => {
|
||||||
const store = useUsersStore()
|
const store = useUsersStore()
|
||||||
store.addNewUsers({ data: [user()], timestamp: 1 })
|
store.addNewUsers({ data: [mockUser()], timestamp: 1 })
|
||||||
store.updateRight(userId, 'right1', true)
|
store.updateRight(userId, 'right1', true)
|
||||||
store.updateRight(userId, 'right2', false)
|
store.updateRight(userId, 'right2', false)
|
||||||
|
|
||||||
|
|
@ -594,7 +604,7 @@ describe('The users store', () => {
|
||||||
|
|
||||||
it('clearFollowLists', () => {
|
it('clearFollowLists', () => {
|
||||||
const store = useUsersStore()
|
const store = useUsersStore()
|
||||||
store.addNewUsers({ data: [user()], timestamp: 1 })
|
store.addNewUsers({ data: [mockUser()], timestamp: 1 })
|
||||||
const userData = store.users.get(userId)
|
const userData = store.users.get(userId)
|
||||||
store.relationshipsLists.friends.get(userData).add('2')
|
store.relationshipsLists.friends.get(userData).add('2')
|
||||||
store.relationshipsLists.friends.get(userData).add('3')
|
store.relationshipsLists.friends.get(userData).add('3')
|
||||||
|
|
@ -613,7 +623,7 @@ describe('The users store', () => {
|
||||||
vi.stubGlobal(
|
vi.stubGlobal(
|
||||||
'fetch',
|
'fetch',
|
||||||
vi.fn().mockResolvedValueOnce(
|
vi.fn().mockResolvedValueOnce(
|
||||||
new Response(JSON.stringify(mastoApiUser()), {
|
new Response(JSON.stringify(mockMastoAPIUser()), {
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
|
|
@ -653,9 +663,9 @@ describe('The users store', () => {
|
||||||
// Adding some users to verify they are getting cleaned afterwards
|
// Adding some users to verify they are getting cleaned afterwards
|
||||||
store.addNewUsers({
|
store.addNewUsers({
|
||||||
data: [
|
data: [
|
||||||
user(),
|
mockUser(),
|
||||||
{ ...user({ name: 'John', screen_name: 'snake' }) },
|
{ ...mockUser({ name: 'John', screen_name: 'snake' }) },
|
||||||
{ ...user({ name: 'David Oh', screen_name: 'zero' }) },
|
{ ...mockUser({ name: 'David Oh', screen_name: 'zero' }) },
|
||||||
],
|
],
|
||||||
timestamp: 2000,
|
timestamp: 2000,
|
||||||
})
|
})
|
||||||
|
|
@ -679,7 +689,7 @@ describe('The users store', () => {
|
||||||
vi.stubGlobal(
|
vi.stubGlobal(
|
||||||
'fetch',
|
'fetch',
|
||||||
vi.fn().mockResolvedValueOnce(
|
vi.fn().mockResolvedValueOnce(
|
||||||
new Response(JSON.stringify(mastoApiUser()), {
|
new Response(JSON.stringify(mockMastoAPIUser()), {
|
||||||
status: 403,
|
status: 403,
|
||||||
statusText: 'Forbidden',
|
statusText: 'Forbidden',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
|
@ -756,17 +766,17 @@ describe('The users store', () => {
|
||||||
useMergedConfigStore().mergedConfig = { useStreamingApi: true }
|
useMergedConfigStore().mergedConfig = { useStreamingApi: true }
|
||||||
|
|
||||||
const store = useUsersStore()
|
const store = useUsersStore()
|
||||||
store.currentUser = user()
|
store.currentUser = mockUser()
|
||||||
|
|
||||||
// Adding some users to verify they are getting cleaned afterwards
|
// Adding some users to verify they are getting cleaned afterwards
|
||||||
store.addNewUsers({
|
store.addNewUsers({
|
||||||
data: [
|
data: [
|
||||||
user(),
|
mockUser(),
|
||||||
{
|
{
|
||||||
...user({ name: 'John', screen_name: 'snake' }),
|
...mockUser({ name: 'John', screen_name: 'snake' }),
|
||||||
relationship: { id: userId, following: true },
|
relationship: { id: userId, following: true },
|
||||||
},
|
},
|
||||||
{ ...user({ name: 'David Oh', screen_name: 'zero' }) },
|
{ ...mockUser({ name: 'David Oh', screen_name: 'zero' }) },
|
||||||
],
|
],
|
||||||
timestamp: 2000,
|
timestamp: 2000,
|
||||||
})
|
})
|
||||||
|
|
@ -1168,7 +1178,7 @@ describe('The users store', () => {
|
||||||
vi.stubGlobal('fetch', mockFetch)
|
vi.stubGlobal('fetch', mockFetch)
|
||||||
|
|
||||||
const store = useUsersStore()
|
const store = useUsersStore()
|
||||||
store.currentUser = user()
|
store.currentUser = mockUser()
|
||||||
store.currentUser.domainMutes = new Set()
|
store.currentUser.domainMutes = new Set()
|
||||||
if (action === 'unmute') {
|
if (action === 'unmute') {
|
||||||
store.currentUser.domainMutes.add('example.com')
|
store.currentUser.domainMutes.add('example.com')
|
||||||
|
|
@ -1198,14 +1208,6 @@ describe('The users store', () => {
|
||||||
'blockUser',
|
'blockUser',
|
||||||
'unblockUser',
|
'unblockUser',
|
||||||
])('%ss', async (action) => {
|
])('%ss', async (action) => {
|
||||||
const mockFetch = vi.fn().mockResolvedValueOnce(
|
|
||||||
new Response(JSON.stringify({ id: userId }), {
|
|
||||||
headers: { 'Content-Type': 'application/json' },
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
|
|
||||||
vi.stubGlobal('fetch', mockFetch)
|
|
||||||
|
|
||||||
const store = useUsersStore()
|
const store = useUsersStore()
|
||||||
store[action] = vi.fn().mockResolvedValue(async () => {
|
store[action] = vi.fn().mockResolvedValue(async () => {
|
||||||
/* no-op */
|
/* no-op */
|
||||||
|
|
@ -1226,30 +1228,30 @@ describe('The users store', () => {
|
||||||
|
|
||||||
it('relationship returns a placeholder if relationship info is missing while user is present', () => {
|
it('relationship returns a placeholder if relationship info is missing while user is present', () => {
|
||||||
const store = useUsersStore()
|
const store = useUsersStore()
|
||||||
store.addNewUsers({ data: [user()], timestamp: 1 })
|
store.addNewUsers({ data: [mockUser()], timestamp: 1 })
|
||||||
|
|
||||||
expect(store.relationship(userId)).to.eql({ id: userId, loading: true })
|
expect(store.relationship(userId)).to.eql({ id: userId, loading: true })
|
||||||
})
|
})
|
||||||
|
|
||||||
it('findUser returns user with matching id', () => {
|
it('findUser returns user with matching id', () => {
|
||||||
const store = useUsersStore()
|
const store = useUsersStore()
|
||||||
store.addNewUsers({ data: [user()], timestamp: 1 })
|
store.addNewUsers({ data: [mockUser()], timestamp: 1 })
|
||||||
|
|
||||||
expect(store.findUser(userId).id).to.eql(userId)
|
expect(store.findUser(userId).id).to.eql(userId)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('findUserByName returns user with matching screen_name', () => {
|
it('findUserByName returns user with matching screen_name', () => {
|
||||||
const store = useUsersStore()
|
const store = useUsersStore()
|
||||||
store.addNewUsers({ data: [user()], timestamp: 1 })
|
store.addNewUsers({ data: [mockUser()], timestamp: 1 })
|
||||||
|
|
||||||
expect(store.findUserByName(user().screen_name).id).to.eql(userId)
|
expect(store.findUserByName(mockUser().screen_name).id).to.eql(userId)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('findUserByName returns user with matching url', () => {
|
it('findUserByName returns user with matching url', () => {
|
||||||
const store = useUsersStore()
|
const store = useUsersStore()
|
||||||
store.addNewUsers({ data: [user()], timestamp: 1 })
|
store.addNewUsers({ data: [mockUser()], timestamp: 1 })
|
||||||
|
|
||||||
expect(store.findUserByUrl(user().url).id).to.eql(userId)
|
expect(store.findUserByUrl(mockUser().url).id).to.eql(userId)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue