mirror of
https://git.shipoclu.com/moon/plspace.git
synced 2026-08-13 02:42:30 +00:00
208 lines
7.0 KiB
TypeScript
208 lines
7.0 KiB
TypeScript
import { fireEvent, render, waitFor } from '@testing-library/svelte'
|
|
import { describe, expect, it, vi } from 'vitest'
|
|
import { APP_SERVICES } from '$lib/app-services'
|
|
import { account, session, status, testServices } from '$test/fixtures'
|
|
import Composer from './Composer.svelte'
|
|
|
|
describe('Composer', () => {
|
|
it('posts through an in-memory endpoint double', async () => {
|
|
const postStatus = vi.fn().mockResolvedValue(status())
|
|
const services = testServices({
|
|
session: session({ token: 'token', me: account(), signedIn: true }),
|
|
endpoints: { postStatus },
|
|
})
|
|
const view = render(Composer, {
|
|
props: { initialText: 'A backend-free component test' },
|
|
context: new Map([[APP_SERVICES, services]]),
|
|
})
|
|
|
|
await fireEvent.click(view.getByRole('button', { name: 'Post Entry' }))
|
|
|
|
await waitFor(() => expect(postStatus).toHaveBeenCalledOnce())
|
|
expect(postStatus.mock.calls[0][1]).toMatchObject({
|
|
status: 'A backend-free component test',
|
|
visibility: 'public',
|
|
})
|
|
})
|
|
|
|
it('can submit a structured quote without commentary', async () => {
|
|
const quoted = status({
|
|
id: 'quoted-entry',
|
|
content: '<p>The original thought</p>',
|
|
})
|
|
const postStatus = vi.fn().mockResolvedValue(status({ id: 'new-quote' }))
|
|
const services = testServices({
|
|
session: session({ token: 'token', me: account(), signedIn: true }),
|
|
endpoints: { postStatus },
|
|
})
|
|
const view = render(Composer, {
|
|
props: { quote: quoted, submitLabel: 'Post Quote' },
|
|
context: new Map([[APP_SERVICES, services]]),
|
|
})
|
|
|
|
expect(view.getByText('The original thought')).toBeInTheDocument()
|
|
await fireEvent.click(view.getByRole('button', { name: 'Post Quote' }))
|
|
|
|
await waitFor(() => expect(postStatus).toHaveBeenCalledOnce())
|
|
expect(postStatus.mock.calls[0][1]).toMatchObject({
|
|
status: '',
|
|
quoted_status_id: 'quoted-entry',
|
|
})
|
|
})
|
|
|
|
it('composes a multiple-choice poll without a backend', async () => {
|
|
const postStatus = vi.fn().mockResolvedValue(status())
|
|
const services = testServices({
|
|
session: session({
|
|
token: 'token',
|
|
me: account(),
|
|
signedIn: true,
|
|
instance: {
|
|
title: 'Pleroma',
|
|
version: '2.9.0',
|
|
configuration: {
|
|
polls: {
|
|
max_options: 4,
|
|
max_characters_per_option: 30,
|
|
min_expiration: 300,
|
|
max_expiration: 604_800,
|
|
},
|
|
},
|
|
},
|
|
}),
|
|
endpoints: { postStatus },
|
|
})
|
|
const view = render(Composer, {
|
|
props: { initialText: 'Which old web feature should return?' },
|
|
context: new Map([[APP_SERVICES, services]]),
|
|
})
|
|
|
|
await fireEvent.click(view.getByRole('button', { name: 'Poll' }))
|
|
await fireEvent.input(view.getByRole('textbox', { name: 'Poll option 1' }), {
|
|
target: { value: 'Guestbooks' },
|
|
})
|
|
await fireEvent.input(view.getByRole('textbox', { name: 'Poll option 2' }), {
|
|
target: { value: 'Webrings' },
|
|
})
|
|
await fireEvent.click(view.getByRole('button', { name: 'Add option' }))
|
|
await fireEvent.input(view.getByRole('textbox', { name: 'Poll option 3' }), {
|
|
target: { value: 'Blink tags' },
|
|
})
|
|
await fireEvent.click(view.getByRole('checkbox', { name: 'Allow multiple choices' }))
|
|
await fireEvent.change(view.getByLabelText('Keep open for'), {
|
|
target: { value: '3600' },
|
|
})
|
|
await fireEvent.click(view.getByRole('button', { name: 'Post Entry' }))
|
|
|
|
await waitFor(() => expect(postStatus).toHaveBeenCalledOnce())
|
|
expect(postStatus.mock.calls[0][1]).toMatchObject({
|
|
status: 'Which old web feature should return?',
|
|
poll: {
|
|
options: ['Guestbooks', 'Webrings', 'Blink tags'],
|
|
expires_in: 3600,
|
|
multiple: true,
|
|
},
|
|
})
|
|
})
|
|
|
|
it.each([
|
|
['Command+Enter', { metaKey: true }],
|
|
['Ctrl+Enter', { ctrlKey: true }],
|
|
])('submits with %s from the focused compose field', async (_label, modifier) => {
|
|
const postStatus = vi.fn().mockResolvedValue(status())
|
|
const services = testServices({
|
|
session: session({ token: 'token', me: account(), signedIn: true }),
|
|
endpoints: { postStatus },
|
|
})
|
|
const view = render(Composer, {
|
|
props: { initialText: 'Keyboard-posted entry' },
|
|
context: new Map([[APP_SERVICES, services]]),
|
|
})
|
|
|
|
await fireEvent.keyDown(view.getByRole('textbox', { name: 'Entry text' }), {
|
|
key: 'Enter',
|
|
...modifier,
|
|
})
|
|
|
|
await waitFor(() => expect(postStatus).toHaveBeenCalledOnce())
|
|
expect(postStatus.mock.calls[0][1].status).toBe('Keyboard-posted entry')
|
|
})
|
|
|
|
it('uploads a pasted clipboard image and attaches it to the post', async () => {
|
|
const pastedImage = new File(['image bytes'], 'pasted-image.png', { type: 'image/png' })
|
|
const uploadMedia = vi.fn().mockResolvedValue({
|
|
id: 'pasted-media',
|
|
type: 'image',
|
|
url: 'https://media.example/pasted-image.png',
|
|
preview_url: 'https://media.example/pasted-image-preview.png',
|
|
description: null,
|
|
})
|
|
const postStatus = vi.fn().mockResolvedValue(status())
|
|
const services = testServices({
|
|
session: session({
|
|
token: 'token',
|
|
me: account(),
|
|
signedIn: true,
|
|
instance: {
|
|
title: 'Test server',
|
|
version: '1.0.0',
|
|
configuration: { statuses: { max_media_attachments: 4 } },
|
|
},
|
|
}),
|
|
endpoints: { uploadMedia, postStatus },
|
|
})
|
|
const view = render(Composer, {
|
|
props: { initialText: 'A pasted picture' },
|
|
context: new Map([[APP_SERVICES, services]]),
|
|
})
|
|
const textarea = view.getByRole('textbox', { name: 'Entry text' })
|
|
|
|
await fireEvent.paste(textarea, {
|
|
clipboardData: {
|
|
items: [
|
|
{
|
|
kind: 'file',
|
|
type: 'image/png',
|
|
getAsFile: () => pastedImage,
|
|
},
|
|
],
|
|
files: [pastedImage],
|
|
},
|
|
})
|
|
|
|
await waitFor(() => expect(uploadMedia).toHaveBeenCalledOnce())
|
|
expect(uploadMedia.mock.calls[0][1]).toBe(pastedImage)
|
|
expect(view.container.querySelector('.composer-attachment img')).toHaveAttribute(
|
|
'src',
|
|
'https://media.example/pasted-image-preview.png',
|
|
)
|
|
|
|
await fireEvent.click(view.getByRole('button', { name: 'Post Entry' }))
|
|
|
|
await waitFor(() => expect(postStatus).toHaveBeenCalledOnce())
|
|
expect(postStatus.mock.calls[0][1].media_ids).toEqual(['pasted-media'])
|
|
})
|
|
|
|
it('leaves ordinary text-only paste alone', async () => {
|
|
const uploadMedia = vi.fn()
|
|
const services = testServices({
|
|
session: session({ token: 'token', me: account(), signedIn: true }),
|
|
endpoints: { uploadMedia },
|
|
})
|
|
const view = render(Composer, {
|
|
context: new Map([[APP_SERVICES, services]]),
|
|
})
|
|
const textarea = view.getByRole('textbox', { name: 'Entry text' })
|
|
|
|
const wasNotCancelled = await fireEvent.paste(textarea, {
|
|
clipboardData: {
|
|
items: [{ kind: 'string', type: 'text/plain', getAsFile: () => null }],
|
|
files: [],
|
|
},
|
|
})
|
|
|
|
expect(wasNotCancelled).toBe(true)
|
|
expect(uploadMedia).not.toHaveBeenCalled()
|
|
})
|
|
})
|