広場投稿追加画面の刷新 (#399) #413
@@ -1,4 +1,4 @@
|
||||
import { render, screen } from '@testing-library/react'
|
||||
import { fireEvent, render, screen } from '@testing-library/react'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
|
||||
import PostThumbnailPreview from '@/components/posts/PostThumbnailPreview'
|
||||
@@ -9,4 +9,28 @@ describe ('PostThumbnailPreview', () => {
|
||||
|
||||
expect (screen.getByRole ('img')).toHaveAttribute ('src', 'blob:preview')
|
||||
})
|
||||
|
||||
it ('renders an empty thumbnail frame without text when the URL is empty', () => {
|
||||
const { container } = render (
|
||||
<PostThumbnailPreview url="" className="h-10 w-10"/>)
|
||||
|
||||
expect (screen.queryByRole ('img')).toBeNull ()
|
||||
expect (screen.queryByText ('サムネールを表示できません')).toBeNull ()
|
||||
expect (screen.queryByText ('なし')).toBeNull ()
|
||||
expect (container.querySelector ('div.rounded.border.bg-muted')).not.toBeNull ()
|
||||
expect (container.textContent).toBe ('')
|
||||
})
|
||||
|
||||
it ('renders an empty thumbnail frame without text when image loading fails', () => {
|
||||
const { container } = render (
|
||||
<PostThumbnailPreview url="blob:preview" className="h-10 w-10"/>)
|
||||
|
||||
fireEvent.error (screen.getByRole ('img'))
|
||||
|
||||
expect (screen.queryByRole ('img')).toBeNull ()
|
||||
expect (screen.queryByText ('サムネールを表示できません')).toBeNull ()
|
||||
expect (screen.queryByText ('なし')).toBeNull ()
|
||||
expect (container.querySelector ('div.rounded.border.bg-muted')).not.toBeNull ()
|
||||
expect (container.textContent).toBe ('')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -19,30 +19,13 @@ const PostThumbnailPreview: FC<Props> = (
|
||||
setFailed (false)
|
||||
}, [url])
|
||||
|
||||
if (!(url))
|
||||
if (!(url) || failed)
|
||||
{
|
||||
return (
|
||||
<div
|
||||
className={cn (
|
||||
className,
|
||||
'flex items-center justify-center rounded border',
|
||||
'border-border bg-muted text-xs text-muted-foreground')}>
|
||||
なし
|
||||
</div>)
|
||||
}
|
||||
|
||||
if (failed)
|
||||
{
|
||||
return (
|
||||
<div
|
||||
className={cn (
|
||||
className,
|
||||
'flex items-center justify-center rounded border',
|
||||
'border-amber-300 bg-amber-50 p-2 text-center text-xs',
|
||||
'text-amber-700 dark:border-amber-900 dark:bg-amber-950',
|
||||
'dark:text-amber-200')}>
|
||||
サムネールを表示できません
|
||||
</div>)
|
||||
'rounded border border-border bg-muted')}/>)
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -38,12 +38,18 @@ describe ('PostImportThumbnailPreview', () => {
|
||||
it ('does not render the unsafe URL directly when preview fetching fails', async () => {
|
||||
api.apiGet.mockRejectedValueOnce (new Error ('unsafe'))
|
||||
|
||||
render (
|
||||
const { container } = render (
|
||||
<PostImportThumbnailPreview
|
||||
url="http://127.0.0.1/private.png"
|
||||
className="h-10 w-10"/>)
|
||||
|
||||
expect (await screen.findByText ('サムネールを表示できません')).toBeInTheDocument ()
|
||||
await waitFor (() => {
|
||||
expect (screen.queryByRole ('img')).toBeNull ()
|
||||
})
|
||||
expect (screen.queryByText ('サムネールを表示できません')).toBeNull ()
|
||||
expect (screen.queryByText ('なし')).toBeNull ()
|
||||
expect (container.querySelector ('div.rounded.border.bg-muted')).not.toBeNull ()
|
||||
expect (container.textContent).toBe ('')
|
||||
expect (screen.queryByRole ('img')).toBeNull ()
|
||||
})
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ import { useEffect, useRef, useState } from 'react'
|
||||
|
||||
import PostThumbnailPreview from '@/components/posts/PostThumbnailPreview'
|
||||
import { apiGet } from '@/lib/api'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
import type { FC } from 'react'
|
||||
|
||||
@@ -18,7 +17,6 @@ const PostImportThumbnailPreview: FC<Props> = (
|
||||
className = 'h-16 w-16' },
|
||||
) => {
|
||||
const [previewUrl, setPreviewUrl] = useState ('')
|
||||
const [unavailable, setUnavailable] = useState (false)
|
||||
const previewUrlRef = useRef ('')
|
||||
|
||||
useEffect (() => {
|
||||
@@ -28,7 +26,6 @@ const PostImportThumbnailPreview: FC<Props> = (
|
||||
previewUrlRef.current = ''
|
||||
}
|
||||
setPreviewUrl ('')
|
||||
setUnavailable (false)
|
||||
|
||||
if (!(url))
|
||||
return
|
||||
@@ -51,7 +48,7 @@ const PostImportThumbnailPreview: FC<Props> = (
|
||||
catch
|
||||
{
|
||||
if (active)
|
||||
setUnavailable (true)
|
||||
setPreviewUrl ('')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,20 +64,6 @@ const PostImportThumbnailPreview: FC<Props> = (
|
||||
}
|
||||
}, [url])
|
||||
|
||||
if (unavailable)
|
||||
{
|
||||
return (
|
||||
<div
|
||||
className={cn (
|
||||
className,
|
||||
'flex items-center justify-center rounded border',
|
||||
'border-amber-300 bg-amber-50 p-2 text-center text-xs',
|
||||
'text-amber-700 dark:border-amber-900 dark:bg-amber-950',
|
||||
'dark:text-amber-200')}>
|
||||
サムネールを表示できません
|
||||
</div>)
|
||||
}
|
||||
|
||||
return (
|
||||
<PostThumbnailPreview
|
||||
url={previewUrl}
|
||||
|
||||
新しい課題から参照
ユーザをブロックする