reacts and custom emoji reacts

This commit is contained in:
Moon.eth
2026-07-30 17:38:23 +09:00
parent 5b7b4360d2
commit b814d79f19
7 changed files with 384 additions and 3 deletions
+113 -3
View File
@@ -1,7 +1,7 @@
import { fireEvent, render } from '@testing-library/svelte'
import { describe, expect, it } from 'vitest'
import { fireEvent, render, waitFor } from '@testing-library/svelte'
import { describe, expect, it, vi } from 'vitest'
import { APP_SERVICES } from '$lib/app-services'
import { status, testServices } from '$test/fixtures'
import { account, session, status, testServices } from '$test/fixtures'
import BlogEntry from './BlogEntry.svelte'
function renderEntry(overrides: Parameters<typeof status>[0]) {
@@ -66,3 +66,113 @@ describe('BlogEntry MFM rendering', () => {
})
})
})
describe('BlogEntry emoji reactions', () => {
it('collapses the reaction bar when the entry has no reactions', () => {
const view = renderEntry({ pleroma: { emoji_reactions: [] } })
expect(view.queryByLabelText('Emoji reactions')).not.toBeInTheDocument()
})
it('shows counts for Unicode and custom Pleroma/Akkoma reactions', () => {
const view = renderEntry({
pleroma: {
emoji_reactions: [
{ name: '🎉', count: 2, me: false },
{
name: 'party_blob@remote.example',
count: 3,
me: true,
url: 'https://cdn.example/emoji/party_blob.png',
},
],
},
})
expect(view.getByLabelText('Emoji reactions')).toBeInTheDocument()
expect(
view.getByRole('button', { name: 'Add 🎉 reaction, 2 reactions' }),
).toHaveTextContent('2')
expect(
view.getByRole('button', {
name: 'Remove :party_blob@remote.example: reaction, 3 reactions',
}),
).toHaveAttribute('aria-pressed', 'true')
expect(view.getByAltText(':party_blob@remote.example:')).toHaveAttribute(
'src',
'https://cdn.example/emoji/party_blob.png',
)
})
it('optimistically adds an existing reaction and applies the returned status', async () => {
const original = status({
pleroma: { emoji_reactions: [{ name: '🎉', count: 2, me: false }] },
})
const confirmed = status({
pleroma: { emoji_reactions: [{ name: '🎉', count: 3, me: true }] },
})
const onupdate = vi.fn()
const setEmojiReaction = vi.fn().mockResolvedValue(confirmed)
const services = testServices({
session: session({ signedIn: true, me: account() }),
endpoints: { setEmojiReaction },
})
const view = render(BlogEntry, {
props: { status: original, onupdate },
context: new Map([[APP_SERVICES, services]]),
})
await fireEvent.click(
view.getByRole('button', { name: 'Add 🎉 reaction, 2 reactions' }),
)
expect(setEmojiReaction).toHaveBeenCalledWith(
services.session.api,
original.id,
'🎉',
true,
)
expect(onupdate.mock.calls[0][0].pleroma?.emoji_reactions).toEqual([
{ name: '🎉', count: 3, me: true },
])
await waitFor(() => expect(onupdate).toHaveBeenLastCalledWith(confirmed))
})
it('removes the viewers existing custom reaction', async () => {
const customReaction = {
name: 'party_blob@remote.example',
count: 1,
me: true,
url: 'https://cdn.example/emoji/party_blob.png',
}
const original = status({
pleroma: { emoji_reactions: [customReaction] },
})
const confirmed = status({ pleroma: { emoji_reactions: [] } })
const onupdate = vi.fn()
const setEmojiReaction = vi.fn().mockResolvedValue(confirmed)
const services = testServices({
session: session({ signedIn: true, me: account() }),
endpoints: { setEmojiReaction },
})
const view = render(BlogEntry, {
props: { status: original, onupdate },
context: new Map([[APP_SERVICES, services]]),
})
await fireEvent.click(
view.getByRole('button', {
name: 'Remove :party_blob@remote.example: reaction, 1 reaction',
}),
)
expect(setEmojiReaction).toHaveBeenCalledWith(
services.session.api,
original.id,
customReaction.name,
false,
)
expect(onupdate.mock.calls[0][0].pleroma?.emoji_reactions).toEqual([])
await waitFor(() => expect(onupdate).toHaveBeenLastCalledWith(confirmed))
})
})