mirror of https://github.com/djteang/OrangeTV.git
Hide optional frontend entries
This commit is contained in:
parent
12d88d3991
commit
6d1ada87b8
|
|
@ -199,6 +199,45 @@ export const Card = Object.assign(
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const Link = ({
|
||||||
|
children,
|
||||||
|
href,
|
||||||
|
...props
|
||||||
|
}: React.AnchorHTMLAttributes<HTMLAnchorElement>) => (
|
||||||
|
<a href={href} {...props}>
|
||||||
|
{children}
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
|
||||||
|
export const Tooltip = Object.assign(
|
||||||
|
({ children, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
|
||||||
|
<div {...props}>{children}</div>
|
||||||
|
),
|
||||||
|
{
|
||||||
|
Trigger: ({ children, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
|
||||||
|
<div {...props}>{children}</div>
|
||||||
|
),
|
||||||
|
Content: ({ children, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
|
||||||
|
<div {...props}>{children}</div>
|
||||||
|
),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
export const Badge = Object.assign(
|
||||||
|
({ children, ...props }: React.HTMLAttributes<HTMLSpanElement>) => (
|
||||||
|
<span {...props}>{children}</span>
|
||||||
|
),
|
||||||
|
{
|
||||||
|
Label: ({ children, ...props }: React.HTMLAttributes<HTMLSpanElement>) => (
|
||||||
|
<span {...props}>{children}</span>
|
||||||
|
),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
export const Separator = (props: React.HTMLAttributes<HTMLHRElement>) => (
|
||||||
|
<hr {...props} />
|
||||||
|
);
|
||||||
|
|
||||||
const ModalRoot = ({
|
const ModalRoot = ({
|
||||||
children,
|
children,
|
||||||
state,
|
state,
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,6 @@ import {
|
||||||
} from '@heroui/react';
|
} from '@heroui/react';
|
||||||
import { Suspense, useEffect, useState } from 'react';
|
import { Suspense, useEffect, useState } from 'react';
|
||||||
|
|
||||||
import {
|
|
||||||
BangumiCalendarData,
|
|
||||||
GetBangumiCalendarData,
|
|
||||||
} from '@/lib/bangumi.client';
|
|
||||||
// 客户端收藏 API
|
// 客户端收藏 API
|
||||||
import {
|
import {
|
||||||
clearAllFavorites,
|
clearAllFavorites,
|
||||||
|
|
@ -38,9 +34,6 @@ function HomeClient() {
|
||||||
const [hotMovies, setHotMovies] = useState<DoubanItem[]>([]);
|
const [hotMovies, setHotMovies] = useState<DoubanItem[]>([]);
|
||||||
const [hotTvShows, setHotTvShows] = useState<DoubanItem[]>([]);
|
const [hotTvShows, setHotTvShows] = useState<DoubanItem[]>([]);
|
||||||
const [hotVarietyShows, setHotVarietyShows] = useState<DoubanItem[]>([]);
|
const [hotVarietyShows, setHotVarietyShows] = useState<DoubanItem[]>([]);
|
||||||
const [bangumiCalendarData, setBangumiCalendarData] = useState<
|
|
||||||
BangumiCalendarData[]
|
|
||||||
>([]);
|
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const { announcement } = useSite();
|
const { announcement } = useSite();
|
||||||
|
|
||||||
|
|
@ -79,7 +72,7 @@ function HomeClient() {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
|
||||||
// 并行获取热门电影、热门剧集和热门综艺
|
// 并行获取热门电影、热门剧集和热门综艺
|
||||||
const [moviesData, tvShowsData, varietyShowsData, bangumiCalendarData] =
|
const [moviesData, tvShowsData, varietyShowsData] =
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
getDoubanCategories({
|
getDoubanCategories({
|
||||||
kind: 'movie',
|
kind: 'movie',
|
||||||
|
|
@ -88,7 +81,6 @@ function HomeClient() {
|
||||||
}),
|
}),
|
||||||
getDoubanCategories({ kind: 'tv', category: 'tv', type: 'tv' }),
|
getDoubanCategories({ kind: 'tv', category: 'tv', type: 'tv' }),
|
||||||
getDoubanCategories({ kind: 'tv', category: 'show', type: 'show' }),
|
getDoubanCategories({ kind: 'tv', category: 'show', type: 'show' }),
|
||||||
GetBangumiCalendarData(),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (moviesData.code === 200) {
|
if (moviesData.code === 200) {
|
||||||
|
|
@ -102,8 +94,6 @@ function HomeClient() {
|
||||||
if (varietyShowsData.code === 200) {
|
if (varietyShowsData.code === 200) {
|
||||||
setHotVarietyShows(varietyShowsData.list);
|
setHotVarietyShows(varietyShowsData.list);
|
||||||
}
|
}
|
||||||
|
|
||||||
setBangumiCalendarData(bangumiCalendarData);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('获取推荐数据失败:', error);
|
console.error('获取推荐数据失败:', error);
|
||||||
} finally {
|
} finally {
|
||||||
|
|
@ -322,75 +312,6 @@ function HomeClient() {
|
||||||
</ScrollableRow>
|
</ScrollableRow>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
{/* 每日新番放送 */}
|
|
||||||
<Card>
|
|
||||||
<Card.Header className='flex-row items-end justify-between gap-4'>
|
|
||||||
<div>
|
|
||||||
<Card.Description>Bangumi</Card.Description>
|
|
||||||
<Card.Title>新番放送</Card.Title>
|
|
||||||
</div>
|
|
||||||
<HeroLink href='/douban?type=anime'>查看更多</HeroLink>
|
|
||||||
</Card.Header>
|
|
||||||
<ScrollableRow>
|
|
||||||
{loading
|
|
||||||
? // 加载状态显示灰色占位数据
|
|
||||||
Array.from({ length: 8 }).map((_, index) => (
|
|
||||||
<div
|
|
||||||
key={index}
|
|
||||||
className='min-w-[96px] w-24 sm:min-w-[180px] sm:w-44'
|
|
||||||
>
|
|
||||||
<Skeleton className='aspect-[2/3] w-full' />
|
|
||||||
<Skeleton className='mt-3 h-4' />
|
|
||||||
</div>
|
|
||||||
))
|
|
||||||
: // 展示当前日期的番剧
|
|
||||||
(() => {
|
|
||||||
// 获取当前日期对应的星期
|
|
||||||
const today = new Date();
|
|
||||||
const weekdays = [
|
|
||||||
'Sun',
|
|
||||||
'Mon',
|
|
||||||
'Tue',
|
|
||||||
'Wed',
|
|
||||||
'Thu',
|
|
||||||
'Fri',
|
|
||||||
'Sat',
|
|
||||||
];
|
|
||||||
const currentWeekday = weekdays[today.getDay()];
|
|
||||||
|
|
||||||
// 找到当前星期对应的番剧数据
|
|
||||||
const todayAnimes =
|
|
||||||
bangumiCalendarData.find(
|
|
||||||
(item) => item.weekday.en === currentWeekday
|
|
||||||
)?.items || [];
|
|
||||||
|
|
||||||
return todayAnimes.map((anime, index) => (
|
|
||||||
<div
|
|
||||||
key={`${anime.id || 0}-${index}`}
|
|
||||||
className='min-w-[96px] w-24 sm:min-w-[180px] sm:w-44'
|
|
||||||
>
|
|
||||||
<VideoCard
|
|
||||||
from='douban'
|
|
||||||
title={anime.name_cn || anime.name || '未知标题'}
|
|
||||||
poster={
|
|
||||||
anime.images?.large ||
|
|
||||||
anime.images?.common ||
|
|
||||||
anime.images?.medium ||
|
|
||||||
anime.images?.small ||
|
|
||||||
anime.images?.grid ||
|
|
||||||
'' // 空字符串,让 VideoCard 组件处理图片加载失败
|
|
||||||
}
|
|
||||||
douban_id={anime.id || 0}
|
|
||||||
rate={anime.rating?.score?.toFixed(1) || ''}
|
|
||||||
year={anime.air_date?.split('-')?.[0] || ''}
|
|
||||||
isBangumi={true}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
));
|
|
||||||
})()}
|
|
||||||
</ScrollableRow>
|
|
||||||
</Card>
|
|
||||||
|
|
||||||
{/* 热门综艺 */}
|
{/* 热门综艺 */}
|
||||||
<Card>
|
<Card>
|
||||||
<Card.Header className='flex-row items-end justify-between gap-4'>
|
<Card.Header className='flex-row items-end justify-between gap-4'>
|
||||||
|
|
|
||||||
|
|
@ -1037,7 +1037,7 @@ function SearchPageClient() {
|
||||||
value={searchQuery}
|
value={searchQuery}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
onFocus={handleInputFocus}
|
onFocus={handleInputFocus}
|
||||||
placeholder='搜索电影、电视剧、短剧...'
|
placeholder='搜索电影、电视剧...'
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
fullWidth
|
fullWidth
|
||||||
className='pl-10 pr-12'
|
className='pl-10 pr-12'
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { Cat, Clover, Film, Home, Play, Radio, Star, Tv } from 'lucide-react';
|
import { Clover, Film, Home, Star, Tv } from 'lucide-react';
|
||||||
import { Button, Card, ScrollShadow } from '@heroui/react';
|
import { Button, Card, ScrollShadow } from '@heroui/react';
|
||||||
import { usePathname, useRouter } from 'next/navigation';
|
import { usePathname, useRouter } from 'next/navigation';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
|
|
@ -33,26 +33,11 @@ const MobileBottomNav = ({ activePath }: MobileBottomNavProps) => {
|
||||||
label: '剧集',
|
label: '剧集',
|
||||||
href: '/douban?type=tv',
|
href: '/douban?type=tv',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
icon: Play,
|
|
||||||
label: '短剧',
|
|
||||||
href: '/shortdrama',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: Cat,
|
|
||||||
label: '动漫',
|
|
||||||
href: '/douban?type=anime',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
icon: Clover,
|
icon: Clover,
|
||||||
label: '综艺',
|
label: '综艺',
|
||||||
href: '/douban?type=show',
|
href: '/douban?type=show',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
icon: Radio,
|
|
||||||
label: '直播',
|
|
||||||
href: '/live',
|
|
||||||
},
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -81,11 +66,6 @@ const MobileBottomNav = ({ activePath }: MobileBottomNavProps) => {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 短剧页面的特殊处理
|
|
||||||
if (href === '/shortdrama' && decodedActive.startsWith('/shortdrama')) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 豆瓣页面的类型匹配
|
// 豆瓣页面的类型匹配
|
||||||
if (decodedActive.startsWith('/douban') && typeMatch &&
|
if (decodedActive.startsWith('/douban') && typeMatch &&
|
||||||
decodedActive.includes(`type=${typeMatch}`)) {
|
decodedActive.includes(`type=${typeMatch}`)) {
|
||||||
|
|
|
||||||
|
|
@ -3,14 +3,11 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Cat,
|
|
||||||
Clover,
|
Clover,
|
||||||
ExternalLink,
|
ExternalLink,
|
||||||
Film,
|
Film,
|
||||||
Home,
|
Home,
|
||||||
Menu,
|
Menu,
|
||||||
PlayCircle,
|
|
||||||
Radio,
|
|
||||||
Search,
|
Search,
|
||||||
Star,
|
Star,
|
||||||
Tv,
|
Tv,
|
||||||
|
|
@ -176,31 +173,16 @@ const Sidebar = ({ onToggle, activePath = '/' }: SidebarProps) => {
|
||||||
label: '电影',
|
label: '电影',
|
||||||
href: '/douban?type=movie',
|
href: '/douban?type=movie',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
icon: PlayCircle,
|
|
||||||
label: '短剧',
|
|
||||||
href: '/shortdrama',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
icon: Tv,
|
icon: Tv,
|
||||||
label: '剧集',
|
label: '剧集',
|
||||||
href: '/douban?type=tv',
|
href: '/douban?type=tv',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
icon: Cat,
|
|
||||||
label: '动漫',
|
|
||||||
href: '/douban?type=anime',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
icon: Clover,
|
icon: Clover,
|
||||||
label: '综艺',
|
label: '综艺',
|
||||||
href: '/douban?type=show',
|
href: '/douban?type=show',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
icon: Radio,
|
|
||||||
label: '直播',
|
|
||||||
href: '/live',
|
|
||||||
},
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -327,8 +309,7 @@ const Sidebar = ({ onToggle, activePath = '/' }: SidebarProps) => {
|
||||||
const isActive =
|
const isActive =
|
||||||
decodedActive === decodedItemHref ||
|
decodedActive === decodedItemHref ||
|
||||||
(decodedActive.startsWith('/douban') &&
|
(decodedActive.startsWith('/douban') &&
|
||||||
decodedActive.includes(`type=${typeMatch}`)) ||
|
decodedActive.includes(`type=${typeMatch}`));
|
||||||
(item.href === '/shortdrama' && decodedActive.startsWith('/shortdrama'));
|
|
||||||
const Icon = item.icon;
|
const Icon = item.icon;
|
||||||
return (
|
return (
|
||||||
<div key={item.label}>
|
<div key={item.label}>
|
||||||
|
|
|
||||||
|
|
@ -1,48 +1,20 @@
|
||||||
/* eslint-disable @typescript-eslint/no-explicit-any,react-hooks/exhaustive-deps */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
|
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { MessageCircle, Moon, Sun } from 'lucide-react';
|
import { Moon, Sun } from 'lucide-react';
|
||||||
import { usePathname } from 'next/navigation';
|
import { usePathname } from 'next/navigation';
|
||||||
import { useTheme } from 'next-themes';
|
import { useTheme } from 'next-themes';
|
||||||
import { useEffect, useState, useCallback } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { Badge } from '@heroui/react';
|
|
||||||
import { ChatModal } from './ChatModal';
|
|
||||||
import { AppIconButton } from './ui/HeroPrimitives';
|
import { AppIconButton } from './ui/HeroPrimitives';
|
||||||
import { useWebSocket } from '../hooks/useWebSocket';
|
|
||||||
import { WebSocketMessage } from '../lib/types';
|
|
||||||
|
|
||||||
export function ThemeToggle() {
|
export function ThemeToggle() {
|
||||||
const [mounted, setMounted] = useState(false);
|
const [mounted, setMounted] = useState(false);
|
||||||
const [isChatModalOpen, setIsChatModalOpen] = useState(false);
|
|
||||||
const [messageCount, setMessageCount] = useState(0);
|
|
||||||
const [chatCount, setChatCount] = useState(0);
|
|
||||||
const [friendRequestCount, setFriendRequestCount] = useState(0);
|
|
||||||
const [isMobile, setIsMobile] = useState(false);
|
const [isMobile, setIsMobile] = useState(false);
|
||||||
const { setTheme, resolvedTheme } = useTheme();
|
const { setTheme, resolvedTheme } = useTheme();
|
||||||
const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
|
|
||||||
// 不再在ThemeToggle中创建独立的WebSocket连接
|
|
||||||
// 改为依赖ChatModal传递的消息计数
|
|
||||||
|
|
||||||
// 直接使用ChatModal传来的消息计数
|
|
||||||
const handleMessageCountFromModal = useCallback((totalCount: number) => {
|
|
||||||
console.log('📊 [ThemeToggle] 收到ChatModal传来的消息计数:', totalCount);
|
|
||||||
setMessageCount(totalCount);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
// 处理聊天消息计数重置(当用户查看对话时)
|
|
||||||
const handleChatCountReset = useCallback((resetCount: number) => {
|
|
||||||
console.log('💬 [ThemeToggle] 重置聊天计数:', resetCount);
|
|
||||||
// 这些回调函数现在主要用于同步状态,实际计数由ChatModal管理
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
// 处理好友请求计数重置(当用户查看好友请求时)
|
|
||||||
const handleFriendRequestCountReset = useCallback((resetCount: number) => {
|
|
||||||
console.log('👥 [ThemeToggle] 重置好友请求计数:', resetCount);
|
|
||||||
// 这些回调函数现在主要用于同步状态,实际计数由ChatModal管理
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const setThemeColor = (theme?: string) => {
|
const setThemeColor = (theme?: string) => {
|
||||||
const meta = document.querySelector('meta[name="theme-color"]');
|
const meta = document.querySelector('meta[name="theme-color"]');
|
||||||
if (!meta) {
|
if (!meta) {
|
||||||
|
|
@ -96,28 +68,9 @@ export function ThemeToggle() {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// 检查是否在登录页面
|
|
||||||
const isLoginPage = pathname === '/login';
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className={`flex items-center ${isMobile ? 'space-x-1' : 'space-x-2'}`}>
|
<div className={`flex items-center ${isMobile ? 'space-x-1' : 'space-x-2'}`}>
|
||||||
{/* 聊天按钮 - 在登录页面不显示 */}
|
|
||||||
{!isLoginPage && (
|
|
||||||
<AppIconButton
|
|
||||||
onPress={() => setIsChatModalOpen(true)}
|
|
||||||
size={isMobile ? 'sm' : 'md'}
|
|
||||||
aria-label='Open chat'
|
|
||||||
>
|
|
||||||
{messageCount > 0 && (
|
|
||||||
<Badge size='sm' color='accent' variant='primary' className='absolute -right-1 -top-1'>
|
|
||||||
<Badge.Label>{messageCount > 99 ? '99+' : messageCount}</Badge.Label>
|
|
||||||
</Badge>
|
|
||||||
)}
|
|
||||||
<MessageCircle className='h-5 w-5' />
|
|
||||||
</AppIconButton>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* 主题切换按钮 */}
|
{/* 主题切换按钮 */}
|
||||||
<AppIconButton
|
<AppIconButton
|
||||||
onPress={toggleTheme}
|
onPress={toggleTheme}
|
||||||
|
|
@ -131,17 +84,6 @@ export function ThemeToggle() {
|
||||||
)}
|
)}
|
||||||
</AppIconButton>
|
</AppIconButton>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 聊天模态框 - 在登录页面不渲染 */}
|
|
||||||
{!isLoginPage && (
|
|
||||||
<ChatModal
|
|
||||||
isOpen={isChatModalOpen}
|
|
||||||
onClose={() => setIsChatModalOpen(false)}
|
|
||||||
onMessageCountChange={handleMessageCountFromModal}
|
|
||||||
onChatCountReset={handleChatCountReset}
|
|
||||||
onFriendRequestCountReset={handleFriendRequestCountReset}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
import { render, screen, waitFor } from '@testing-library/react';
|
||||||
|
|
||||||
|
import MobileBottomNav from '../MobileBottomNav';
|
||||||
|
import Sidebar from '../Sidebar';
|
||||||
|
import { ThemeToggle } from '../ThemeToggle';
|
||||||
|
|
||||||
|
const push = jest.fn();
|
||||||
|
|
||||||
|
jest.mock('next/navigation', () => ({
|
||||||
|
usePathname: () => '/',
|
||||||
|
useRouter: () => ({ push }),
|
||||||
|
useSearchParams: () => new URLSearchParams(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
jest.mock('next-themes', () => ({
|
||||||
|
useTheme: () => ({
|
||||||
|
resolvedTheme: 'dark',
|
||||||
|
setTheme: jest.fn(),
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
|
||||||
|
jest.mock('../ChatModal', () => ({
|
||||||
|
ChatModal: () => <div role='dialog'>聊天</div>,
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('hidden front-end options', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
push.mockClear();
|
||||||
|
localStorage.clear();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not render manga, short drama, or live in desktop navigation', () => {
|
||||||
|
render(<Sidebar activePath='/' />);
|
||||||
|
|
||||||
|
expect(screen.queryByRole('button', { name: '动漫' })).not.toBeInTheDocument();
|
||||||
|
expect(screen.queryByRole('button', { name: '短剧' })).not.toBeInTheDocument();
|
||||||
|
expect(screen.queryByRole('button', { name: '直播' })).not.toBeInTheDocument();
|
||||||
|
expect(screen.getByRole('button', { name: '电影' })).toBeInTheDocument();
|
||||||
|
expect(screen.getByRole('button', { name: '剧集' })).toBeInTheDocument();
|
||||||
|
expect(screen.getByRole('button', { name: '综艺' })).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not render manga, short drama, or live in mobile navigation', () => {
|
||||||
|
render(<MobileBottomNav activePath='/' />);
|
||||||
|
|
||||||
|
expect(screen.queryByRole('button', { name: '动漫' })).not.toBeInTheDocument();
|
||||||
|
expect(screen.queryByRole('button', { name: '短剧' })).not.toBeInTheDocument();
|
||||||
|
expect(screen.queryByRole('button', { name: '直播' })).not.toBeInTheDocument();
|
||||||
|
expect(screen.getByRole('button', { name: '电影' })).toBeInTheDocument();
|
||||||
|
expect(screen.getByRole('button', { name: '剧集' })).toBeInTheDocument();
|
||||||
|
expect(screen.getByRole('button', { name: '综艺' })).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not render the chat entry point or chat modal', async () => {
|
||||||
|
render(<ThemeToggle />);
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(screen.getByRole('button', { name: 'Toggle theme' })).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(screen.queryByRole('button', { name: 'Open chat' })).not.toBeInTheDocument();
|
||||||
|
expect(screen.queryByRole('dialog', { name: '聊天' })).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
Loading…
Reference in New Issue