more tests
This commit is contained in:
parent
307297f836
commit
d0b00db195
8 changed files with 384 additions and 103 deletions
|
|
@ -25,7 +25,8 @@ export const MASTODON_FOLLOWERS_URL = (
|
||||||
`/api/v1/accounts/${id}/followers${paramsString({ minId, maxId, sinceId, limit, withRelationships })}`
|
`/api/v1/accounts/${id}/followers${paramsString({ minId, maxId, sinceId, limit, withRelationships })}`
|
||||||
|
|
||||||
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`
|
export const MASTODON_STATUS_CONTEXT_URL = (id) =>
|
||||||
|
`/api/v1/statuses/${id}/context`
|
||||||
export const MASTODON_STATUS_SOURCE_URL = (id) =>
|
export const MASTODON_STATUS_SOURCE_URL = (id) =>
|
||||||
`/api/v1/statuses/${id}/source`
|
`/api/v1/statuses/${id}/source`
|
||||||
export const MASTODON_STATUS_HISTORY_URL = (id) =>
|
export const MASTODON_STATUS_HISTORY_URL = (id) =>
|
||||||
|
|
|
||||||
|
|
@ -114,16 +114,9 @@ export default {
|
||||||
const conversationLite = computed(() =>
|
const conversationLite = computed(() =>
|
||||||
conversation.value.map(({ id }) => ({ id })),
|
conversation.value.map(({ id }) => ({ id })),
|
||||||
)
|
)
|
||||||
|
provide('focusedId', focusedId)
|
||||||
watch(
|
provide('conversation', conversation)
|
||||||
expanded,
|
provide('replies', replies)
|
||||||
(value) => {
|
|
||||||
if (value) {
|
|
||||||
fetchConversation()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ flush: 'post' },
|
|
||||||
)
|
|
||||||
|
|
||||||
// Component created
|
// Component created
|
||||||
if (isPage.value) {
|
if (isPage.value) {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { storeToRefs } from 'pinia'
|
import { storeToRefs } from 'pinia'
|
||||||
import { computed, nextTick, provide, ref, watch } from 'vue'
|
import { computed, nextTick, ref, watch, toValue } from 'vue'
|
||||||
|
|
||||||
import { useMergedConfigStore } from 'src/stores/merged_config.js'
|
import { useMergedConfigStore } from 'src/stores/merged_config.js'
|
||||||
import { useOAuthStore } from 'src/stores/oauth.js'
|
import { useOAuthStore } from 'src/stores/oauth.js'
|
||||||
|
|
@ -52,7 +52,7 @@ export function useConversation(statusId, expanded) {
|
||||||
}
|
}
|
||||||
const fullyLoaded = ref(false)
|
const fullyLoaded = ref(false)
|
||||||
const conversationId = computed(
|
const conversationId = computed(
|
||||||
() => mainStatus.value?.statusnet_conversation_id,
|
() => mainStatus.value?.statusnet_conversation_id ?? null,
|
||||||
)
|
)
|
||||||
watch(conversationId, (neu, old) => {
|
watch(conversationId, (neu, old) => {
|
||||||
if (neu !== old) fullyLoaded.value = false
|
if (neu !== old) fullyLoaded.value = false
|
||||||
|
|
@ -62,7 +62,7 @@ export function useConversation(statusId, expanded) {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!expanded.value || !fullyLoaded.value) {
|
if (!toValue(expanded) || !fullyLoaded.value) {
|
||||||
return [currentStatus.value]
|
return [currentStatus.value]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -124,8 +124,6 @@ export function useConversation(statusId, expanded) {
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
const getReplies = (id) => replies.value.get(id) ?? new Set()
|
const getReplies = (id) => replies.value.get(id) ?? new Set()
|
||||||
provide('conversation', conversation)
|
|
||||||
provide('replies', replies)
|
|
||||||
|
|
||||||
const fetchConversation = async () => {
|
const fetchConversation = async () => {
|
||||||
if (currentStatus.value) {
|
if (currentStatus.value) {
|
||||||
|
|
@ -133,7 +131,7 @@ export function useConversation(statusId, expanded) {
|
||||||
data: { ancestors, descendants },
|
data: { ancestors, descendants },
|
||||||
timestamp,
|
timestamp,
|
||||||
} = await apiFetchConversation({
|
} = await apiFetchConversation({
|
||||||
id: statusId.value,
|
id: toValue(statusId),
|
||||||
credentials: useOAuthStore().token,
|
credentials: useOAuthStore().token,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -150,7 +148,7 @@ export function useConversation(statusId, expanded) {
|
||||||
loadError.value = null
|
loadError.value = null
|
||||||
|
|
||||||
const { data: status } = await apiFetchStatus({
|
const { data: status } = await apiFetchStatus({
|
||||||
id: statusId.value,
|
id: toValue(statusId),
|
||||||
credentials: useOAuthStore().token,
|
credentials: useOAuthStore().token,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -164,6 +162,16 @@ export function useConversation(statusId, expanded) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
expanded,
|
||||||
|
(value) => {
|
||||||
|
if (value) {
|
||||||
|
fetchConversation()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ flush: 'post' },
|
||||||
|
)
|
||||||
|
|
||||||
// # Focus
|
// # Focus
|
||||||
const focused = ref(null)
|
const focused = ref(null)
|
||||||
const { mainStatus: focusedStatus } = useMainStatus(focused)
|
const { mainStatus: focusedStatus } = useMainStatus(focused)
|
||||||
|
|
@ -173,29 +181,28 @@ export function useConversation(statusId, expanded) {
|
||||||
watch(statusId, (val) => setFocused(val), { immediate: true })
|
watch(statusId, (val) => setFocused(val), { immediate: true })
|
||||||
|
|
||||||
const focusedId = computed(() =>
|
const focusedId = computed(() =>
|
||||||
expanded.value && fullyLoaded.value ? focusedStatus.value?.id : null,
|
(toValue(expanded) && fullyLoaded.value) ? focusedStatus.value?.id : null,
|
||||||
)
|
)
|
||||||
provide('focusedId', focusedId)
|
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
focusedStatus,
|
focusedId,
|
||||||
(newVal, oldVal) => {
|
(newVal, oldVal) => {
|
||||||
if (!newVal) return
|
if (!newVal) return
|
||||||
if (newVal?.id === oldVal?.id) return // prevents infinite loop
|
if (newVal === oldVal) return // prevents infinite loop
|
||||||
if (!streamingEnabled.value) {
|
if (!streamingEnabled.value) {
|
||||||
useStatusesStore().fetchStatus(newVal.id)
|
useStatusesStore().fetchStatus(newVal)
|
||||||
}
|
}
|
||||||
|
|
||||||
useStatusesStore().fetchFavsAndRepeats(newVal.id)
|
useStatusesStore().fetchFavsAndRepeats(newVal)
|
||||||
useStatusesStore().fetchEmojiReactions(newVal.id)
|
useStatusesStore().fetchEmojiReactions(newVal)
|
||||||
},
|
},
|
||||||
{ immediate: true },
|
{ immediate: true },
|
||||||
)
|
)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
focusedId,
|
focusedId,
|
||||||
conversationId,
|
|
||||||
setFocused,
|
setFocused,
|
||||||
|
conversationId,
|
||||||
currentStatus,
|
currentStatus,
|
||||||
mainStatus,
|
mainStatus,
|
||||||
conversation,
|
conversation,
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ export function useMainStatus(statusId) {
|
||||||
const statusesStore = useStatusesStore()
|
const statusesStore = useStatusesStore()
|
||||||
const getStatusObject = (id) => statusesStore.allStatuses.get(id)
|
const getStatusObject = (id) => statusesStore.allStatuses.get(id)
|
||||||
|
|
||||||
const status = computed(() => getStatusObject(toValue(statusId)))
|
const status = computed(() => getStatusObject(toValue(statusId)) ?? null)
|
||||||
|
|
||||||
const mainStatus = computed(() => {
|
const mainStatus = computed(() => {
|
||||||
if (!status.value) return null
|
if (!status.value) return null
|
||||||
|
|
|
||||||
93
test/fixtures/masto_api.js
vendored
Normal file
93
test/fixtures/masto_api.js
vendored
Normal file
|
|
@ -0,0 +1,93 @@
|
||||||
|
export const userId = '1'
|
||||||
|
export const userScreenName = 'user'
|
||||||
|
export const userName = 'Guy'
|
||||||
|
export const userUrl = 'http://localhost/user'
|
||||||
|
|
||||||
|
export const fetchOptions = (url, method = 'GET') => [
|
||||||
|
url,
|
||||||
|
{
|
||||||
|
method,
|
||||||
|
credentials: 'same-origin',
|
||||||
|
headers: {
|
||||||
|
Accept: 'application/json',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
export const mockMastoAPIUser = ({
|
||||||
|
screen_name = userScreenName,
|
||||||
|
name = userName,
|
||||||
|
url = userUrl,
|
||||||
|
id = userId,
|
||||||
|
} = {}) => ({
|
||||||
|
id,
|
||||||
|
acct: screen_name,
|
||||||
|
display_name: name,
|
||||||
|
fields: [],
|
||||||
|
avatar: '',
|
||||||
|
url,
|
||||||
|
pleroma: {
|
||||||
|
emoji_reactions: [],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
export const mockMastoAPIStatus = ({
|
||||||
|
id = '1',
|
||||||
|
text,
|
||||||
|
type = 'status',
|
||||||
|
statusUser = mockMastoAPIUser(),
|
||||||
|
in_reply_to_status_id = null,
|
||||||
|
statusnet_conversation_id = 'c1',
|
||||||
|
} = {}) => ({
|
||||||
|
id,
|
||||||
|
account: statusUser,
|
||||||
|
name: 'status',
|
||||||
|
content: text ?? `Text number ${id}`,
|
||||||
|
uri: '',
|
||||||
|
type,
|
||||||
|
attentions: [],
|
||||||
|
pleroma: {
|
||||||
|
conversation_id: statusnet_conversation_id,
|
||||||
|
},
|
||||||
|
in_reply_to_id: in_reply_to_status_id,
|
||||||
|
})
|
||||||
|
|
||||||
|
export 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,
|
||||||
|
})
|
||||||
|
|
||||||
|
export const mockStatus = ({
|
||||||
|
id = '1',
|
||||||
|
text,
|
||||||
|
type = 'status',
|
||||||
|
statusUser = mockUser(),
|
||||||
|
in_reply_to_status_id = null,
|
||||||
|
statusnet_conversation_id = 'c1',
|
||||||
|
} = {}) => ({
|
||||||
|
id,
|
||||||
|
user: statusUser,
|
||||||
|
name: 'status',
|
||||||
|
text: text ?? `Text number ${id}`,
|
||||||
|
uri: '',
|
||||||
|
type,
|
||||||
|
attentions: [],
|
||||||
|
statusnet_conversation_id,
|
||||||
|
emoji_reactions: [],
|
||||||
|
in_reply_to_status_id,
|
||||||
|
})
|
||||||
251
test/unit/specs/composables/useConversation.spec.js
Normal file
251
test/unit/specs/composables/useConversation.spec.js
Normal file
|
|
@ -0,0 +1,251 @@
|
||||||
|
import { createTestingPinia } from '@pinia/testing'
|
||||||
|
import { flushPromises, mount } from '@vue/test-utils'
|
||||||
|
import { setActivePinia } from 'pinia'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import {
|
||||||
|
mockMastoAPIStatus,
|
||||||
|
|
||||||
|
mockMastoAPIUser,
|
||||||
|
mockStatus,
|
||||||
|
mockUser,
|
||||||
|
userId,
|
||||||
|
userName,
|
||||||
|
userScreenName,
|
||||||
|
userUrl,
|
||||||
|
} from 'test/fixtures/masto_api.js'
|
||||||
|
|
||||||
|
import { useMergedConfigStore } from 'src/stores/merged_config.js'
|
||||||
|
import { useOAuthStore } from 'src/stores/oauth.js'
|
||||||
|
import { useStatusesStore } from 'src/stores/statuses.js'
|
||||||
|
import { useStreamingStore } from 'src/stores/streaming.js'
|
||||||
|
|
||||||
|
import { useConversation } from 'src/composables/useConversation.js'
|
||||||
|
|
||||||
|
import {
|
||||||
|
MASTODON_STATUS_CONTEXT_URL,
|
||||||
|
MASTODON_STATUS_URL,
|
||||||
|
MASTODON_STATUS_FAVORITEDBY_URL,
|
||||||
|
MASTODON_STATUS_REBLOGGEDBY_URL,
|
||||||
|
PLEROMA_EMOJI_REACTIONS_URL,
|
||||||
|
} from 'src/api/public.js'
|
||||||
|
|
||||||
|
describe('useConversation', () => {
|
||||||
|
const constructStatus = (index, convoId = '1000') => {
|
||||||
|
const stringId = index.toString()
|
||||||
|
const object = { id: stringId, statusnet_conversation_id: convoId }
|
||||||
|
if (index > 0) {
|
||||||
|
object.in_reply_to_status_id = (index - 1).toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
return mockStatus(object)
|
||||||
|
}
|
||||||
|
const constructStatusAPI = (index, convoId = '1000') => {
|
||||||
|
const stringId = index.toString()
|
||||||
|
const object = { id: stringId, statusnet_conversation_id: convoId }
|
||||||
|
if (index > 0) {
|
||||||
|
object.in_reply_to_status_id = (index - 1).toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
return mockMastoAPIStatus(object)
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
setActivePinia(createTestingPinia({ stubActions: false }))
|
||||||
|
vi.useFakeTimers()
|
||||||
|
useStatusesStore().resetStatuses()
|
||||||
|
})
|
||||||
|
afterEach(() => {
|
||||||
|
vi.useRealTimers()
|
||||||
|
vi.resetAllMocks()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should work if status is unknown yet', () => {
|
||||||
|
useStatusesStore().allStatuses = new Map()
|
||||||
|
|
||||||
|
const result = useConversation(ref('1'), ref(false))
|
||||||
|
|
||||||
|
expect(result.focusedId.value).to.eql(null)
|
||||||
|
expect(result.currentStatus.value).to.eql(null)
|
||||||
|
expect(result.mainStatus.value).to.eql(null)
|
||||||
|
expect(result.replies.value).to.eql(new Map())
|
||||||
|
expect(result.conversationId.value).to.eql(null)
|
||||||
|
expect(result.conversation.value).to.eql([])
|
||||||
|
expect(result.loadError.value).to.eql(null)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should return single item that is already known when not expanded', () => {
|
||||||
|
useStatusesStore().allStatuses = new Map(
|
||||||
|
[...new Array(20)].map((i, index) => [index.toString(), constructStatus(index)])
|
||||||
|
)
|
||||||
|
|
||||||
|
const result = useConversation(ref('1'), ref(false))
|
||||||
|
const expectedStatus = constructStatus(1)
|
||||||
|
|
||||||
|
expect(result.focusedId.value).to.eql(null)
|
||||||
|
expect(result.currentStatus.value).to.eql(expectedStatus)
|
||||||
|
expect(result.mainStatus.value).to.eql(expectedStatus)
|
||||||
|
expect(result.conversation.value).to.eql([expectedStatus])
|
||||||
|
expect(result.conversationId.value).to.eql('1000')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should return entire conversation when fethed', async () => {
|
||||||
|
const convo = [...new Array(20)].map((i, index) => constructStatus(index))
|
||||||
|
const convoAPI = [...new Array(20)].map((i, index) => constructStatusAPI(index))
|
||||||
|
|
||||||
|
const mockFetch = vi.fn()
|
||||||
|
vi.when(mockFetch, { onUnmatched: 'throw' })
|
||||||
|
.calledWith(MASTODON_STATUS_URL('4'), expect.anything())
|
||||||
|
.thenResolveOnce(new Response(JSON.stringify(convoAPI[4]), {
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
}))
|
||||||
|
.calledWith(MASTODON_STATUS_CONTEXT_URL('4'), expect.anything())
|
||||||
|
.thenResolveOnce(new Response(JSON.stringify({
|
||||||
|
ancestors: convoAPI.slice(0,4),
|
||||||
|
descendants: convoAPI.slice(5),
|
||||||
|
}), {
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
}))
|
||||||
|
vi.stubGlobal('fetch', mockFetch)
|
||||||
|
|
||||||
|
const result = useConversation(ref('4'), ref(true))
|
||||||
|
await result.fetchConversation()
|
||||||
|
|
||||||
|
expect(mockFetch).to.have.been.calledWith(MASTODON_STATUS_URL('4'), expect.anything())
|
||||||
|
expect(result.conversation.value).to.have.length(1)
|
||||||
|
expect(result.conversation.value[0]).to.have.property('id', '4')
|
||||||
|
expect(result.conversationId.value).to.have.eql('1000')
|
||||||
|
|
||||||
|
await vi.advanceTimersToNextTimerAsync()
|
||||||
|
expect(mockFetch).to.have.been.calledWith(MASTODON_STATUS_CONTEXT_URL('4'), expect.anything())
|
||||||
|
expect(result.conversation.value).to.have.length(20)
|
||||||
|
expect(result.conversation.value[0]).to.have.property('id', '0')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should fetch entire conversation when expanded', async () => {
|
||||||
|
const convo = [...new Array(20)].map((i, index) => constructStatus(index))
|
||||||
|
const convoAPI = [...new Array(20)].map((i, index) => constructStatusAPI(index))
|
||||||
|
useStatusesStore().addNewStatuses({ statuses: [convo[4]], timestamp: Date.now() })
|
||||||
|
|
||||||
|
const mockFetch = vi.fn()
|
||||||
|
vi.when(mockFetch)
|
||||||
|
.calledWith(MASTODON_STATUS_CONTEXT_URL('4'), expect.anything())
|
||||||
|
.thenResolveOnce(new Response(JSON.stringify({
|
||||||
|
ancestors: convoAPI.slice(0,4),
|
||||||
|
descendants: convoAPI.slice(5),
|
||||||
|
}), {
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
}))
|
||||||
|
vi.stubGlobal('fetch', mockFetch)
|
||||||
|
|
||||||
|
const expanded = ref(false)
|
||||||
|
const result = useConversation(ref('4'), expanded)
|
||||||
|
expect(result.conversation.value).to.have.length(1)
|
||||||
|
expect(result.conversation.value[0]).to.have.property('id', '4')
|
||||||
|
expect(result.focusedId.value).to.eql(null)
|
||||||
|
expanded.value = true
|
||||||
|
await vi.advanceTimersToNextTimerAsync()
|
||||||
|
expect(mockFetch).to.have.been.calledWith(MASTODON_STATUS_CONTEXT_URL('4'), expect.anything())
|
||||||
|
await vi.advanceTimersToNextTimerAsync()
|
||||||
|
expect(result.focusedId.value).to.eql('4')
|
||||||
|
expect(mockFetch).to.have.been.calledWith(MASTODON_STATUS_FAVORITEDBY_URL('4'), expect.anything())
|
||||||
|
expect(mockFetch).to.have.been.calledWith(MASTODON_STATUS_REBLOGGEDBY_URL('4'), expect.anything())
|
||||||
|
expect(mockFetch).to.have.been.calledWith(PLEROMA_EMOJI_REACTIONS_URL('4'), expect.anything())
|
||||||
|
await vi.advanceTimersToNextTimerAsync()
|
||||||
|
expect(result.conversation.value).to.have.length(20)
|
||||||
|
expect(result.conversation.value[0]).to.have.property('id', '0')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should reset and fetch another conversation when statusId changes', async () => {
|
||||||
|
const aConvo = [...new Array(20)].map((i, index) => constructStatus(index + 'a', '1000'))
|
||||||
|
const aConvoAPI = [...new Array(20)].map((i, index) => constructStatusAPI(index + 'a', '1000'))
|
||||||
|
const bConvo = [...new Array(20)].map((i, index) => constructStatus(index + 'b', '2000'))
|
||||||
|
const bConvoAPI = [...new Array(20)].map((i, index) => constructStatusAPI(index + 'b', '2000'))
|
||||||
|
|
||||||
|
const mockFetch = vi.fn()
|
||||||
|
vi.when(mockFetch, { onUnmatched: 'throw' })
|
||||||
|
.calledWith(MASTODON_STATUS_URL('4a'), expect.anything())
|
||||||
|
.thenResolveOnce(new Response(JSON.stringify(aConvoAPI[4]), {
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
}))
|
||||||
|
.calledWith(MASTODON_STATUS_CONTEXT_URL('4a'), expect.anything())
|
||||||
|
.thenResolveOnce(new Response(JSON.stringify({
|
||||||
|
ancestors: aConvoAPI.slice(0,4),
|
||||||
|
descendants: aConvoAPI.slice(5),
|
||||||
|
}), {
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
}))
|
||||||
|
.calledWith(MASTODON_STATUS_URL('4b'), expect.anything())
|
||||||
|
.thenResolveOnce(new Response(JSON.stringify(bConvoAPI[4]), {
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
}))
|
||||||
|
.calledWith(MASTODON_STATUS_CONTEXT_URL('4b'), expect.anything())
|
||||||
|
.thenResolveOnce(new Response(JSON.stringify({
|
||||||
|
ancestors: bConvoAPI.slice(0,4),
|
||||||
|
descendants: bConvoAPI.slice(5),
|
||||||
|
}), {
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
}))
|
||||||
|
vi.stubGlobal('fetch', mockFetch)
|
||||||
|
|
||||||
|
const statusId = ref('4a')
|
||||||
|
|
||||||
|
const result = useConversation(statusId, true)
|
||||||
|
await result.fetchConversation()
|
||||||
|
|
||||||
|
expect(mockFetch).to.have.been.calledWith(MASTODON_STATUS_URL('4a'), expect.anything())
|
||||||
|
expect(result.conversation.value).to.have.length(1)
|
||||||
|
expect(result.conversation.value[0]).to.have.property('id', '4a')
|
||||||
|
expect(result.conversationId.value).to.have.eql('1000')
|
||||||
|
|
||||||
|
await vi.advanceTimersToNextTimerAsync()
|
||||||
|
expect(mockFetch).to.have.been.calledWith(MASTODON_STATUS_CONTEXT_URL('4a'), expect.anything())
|
||||||
|
expect(result.conversation.value).to.have.length(20)
|
||||||
|
expect(result.conversation.value[0]).to.have.property('id', '0a')
|
||||||
|
|
||||||
|
statusId.value = '4b'
|
||||||
|
|
||||||
|
await vi.advanceTimersToNextTimerAsync()
|
||||||
|
expect(result.conversation.value).to.have.length(0)
|
||||||
|
|
||||||
|
await vi.advanceTimersToNextTimerAsync()
|
||||||
|
expect(mockFetch).to.have.been.calledWith(MASTODON_STATUS_URL('4b'), expect.anything())
|
||||||
|
expect(result.conversation.value).to.have.length(1)
|
||||||
|
expect(result.conversation.value[0]).to.have.property('id', '4b')
|
||||||
|
expect(result.conversationId.value).to.have.eql('2000')
|
||||||
|
|
||||||
|
await vi.advanceTimersToNextTimerAsync()
|
||||||
|
expect(mockFetch).to.have.been.calledWith(MASTODON_STATUS_CONTEXT_URL('4b'), expect.anything())
|
||||||
|
expect(result.conversation.value).to.have.length(20)
|
||||||
|
expect(result.conversation.value[0]).to.have.property('id', '0b')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should form replies object', async () => {
|
||||||
|
const convo = [...new Array(4)].map((i, index) => constructStatus(index))
|
||||||
|
const convoAPI = [...new Array(4)].map((i, index) => constructStatusAPI(index))
|
||||||
|
useStatusesStore().addNewStatuses({ statuses: convo, timestamp: Date.now() })
|
||||||
|
|
||||||
|
const mockFetch = vi.fn()
|
||||||
|
vi.when(mockFetch)
|
||||||
|
.calledWith(MASTODON_STATUS_CONTEXT_URL('2'), expect.anything())
|
||||||
|
.thenResolveOnce(new Response(JSON.stringify({
|
||||||
|
ancestors: convoAPI.slice(0,1),
|
||||||
|
descendants: convoAPI.slice(2),
|
||||||
|
}), {
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
}))
|
||||||
|
vi.stubGlobal('fetch', mockFetch)
|
||||||
|
|
||||||
|
const result = useConversation('2', true)
|
||||||
|
await result.fetchConversation()
|
||||||
|
|
||||||
|
await vi.advanceTimersToNextTimerAsync()
|
||||||
|
await vi.advanceTimersToNextTimerAsync()
|
||||||
|
await vi.advanceTimersToNextTimerAsync()
|
||||||
|
expect(result.conversation.value).to.have.length(4)
|
||||||
|
expect(result.replies.value).to.eql(new Map([
|
||||||
|
['0', new Set([{ name: '#1', id: '1' }])],
|
||||||
|
['1', new Set([{ name: '#2', id: '2' }])],
|
||||||
|
['2', new Set([{ name: '#3', id: '3' }])],
|
||||||
|
]))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
@ -10,7 +10,7 @@ describe('useMainStatus', () => {
|
||||||
setActivePinia(createTestingPinia())
|
setActivePinia(createTestingPinia())
|
||||||
useStatusesStore().allStatuses = new Map([
|
useStatusesStore().allStatuses = new Map([
|
||||||
[1, { id: 1 }],
|
[1, { id: 1 }],
|
||||||
[2, { id: 2, retweeted_status: { id: 1 }}],
|
[2, { id: 2, retweeted_status: { id: 1 } }],
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -24,7 +24,7 @@ describe('useMainStatus', () => {
|
||||||
it('repeat', () => {
|
it('repeat', () => {
|
||||||
const { status, mainStatus } = useMainStatus(2)
|
const { status, mainStatus } = useMainStatus(2)
|
||||||
|
|
||||||
expect(status.value).to.eql({ id: 2, retweeted_status: { id: 1 }})
|
expect(status.value).to.eql({ id: 2, retweeted_status: { id: 1 } })
|
||||||
expect(mainStatus.value).to.eql({ id: 1 })
|
expect(mainStatus.value).to.eql({ id: 1 })
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,16 @@
|
||||||
import { createTestingPinia } from '@pinia/testing'
|
import { createTestingPinia } from '@pinia/testing'
|
||||||
import { snakeCase } from 'lodash-es'
|
import { snakeCase } from 'lodash-es'
|
||||||
import { setActivePinia } from 'pinia'
|
import { setActivePinia } from 'pinia'
|
||||||
|
import {
|
||||||
|
mockMastoAPIStatus,
|
||||||
|
mockMastoAPIUser,
|
||||||
|
mockStatus,
|
||||||
|
mockUser,
|
||||||
|
userId,
|
||||||
|
userName,
|
||||||
|
userScreenName,
|
||||||
|
userUrl,
|
||||||
|
} from 'test/fixtures/masto_api.js'
|
||||||
|
|
||||||
import { useStatusesStore } from 'src/stores/statuses.js'
|
import { useStatusesStore } from 'src/stores/statuses.js'
|
||||||
import { useStreamingStore } from 'src/stores/streaming.js'
|
import { useStreamingStore } from 'src/stores/streaming.js'
|
||||||
|
|
@ -9,80 +19,6 @@ import { useUsersStore } from 'src/stores/users.js'
|
||||||
import * as PUBLIC_API from 'src/api/public.js'
|
import * as PUBLIC_API from 'src/api/public.js'
|
||||||
import * as USER_API from 'src/api/user.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') => ({
|
const DEFAULT_OPTIONS = (method = 'GET') => ({
|
||||||
method,
|
method,
|
||||||
credentials: 'same-origin',
|
credentials: 'same-origin',
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue