移动端仅保留我的页签
移动端底部导航只展示我的页签 隐藏移动端活动页签时回落到我的页 更新首页页签相关组件测试
This commit is contained in:
@@ -1142,14 +1142,19 @@ function renderStatefulLoggedOutHomeView(
|
||||
>
|
||||
> = {},
|
||||
isDesktopLayout = false,
|
||||
options: {
|
||||
initialActiveTab?: RpgEntryHomeViewProps['activeTab'];
|
||||
allowHiddenActiveTab?: boolean;
|
||||
} = {},
|
||||
) {
|
||||
const authSpies = {
|
||||
openLoginModal: vi.fn(),
|
||||
};
|
||||
|
||||
function StatefulLoggedOutHomeView() {
|
||||
const [activeTab, setActiveTab] =
|
||||
useState<RpgEntryHomeViewProps['activeTab']>('category');
|
||||
const [activeTab, setActiveTab] = useState<
|
||||
RpgEntryHomeViewProps['activeTab']
|
||||
>(options.initialActiveTab ?? 'category');
|
||||
|
||||
return (
|
||||
<AuthUiContext.Provider
|
||||
@@ -1175,6 +1180,7 @@ function renderStatefulLoggedOutHomeView(
|
||||
activeTab={activeTab}
|
||||
isDesktopLayout={isDesktopLayout}
|
||||
onTabChange={setActiveTab}
|
||||
allowHiddenActiveTab={options.allowHiddenActiveTab ?? true}
|
||||
hasSavedGame={false}
|
||||
savedSnapshot={null}
|
||||
saveEntries={[]}
|
||||
@@ -3782,22 +3788,23 @@ test('shows a reachable login entry outside mobile recommend tab', async () => {
|
||||
expect(openLoginModal).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test('logged out bottom nav turns active recommend tab into next action', () => {
|
||||
const { container } = renderLoggedOutHomeView(vi.fn());
|
||||
test('logged out mobile bottom nav only shows profile tab', () => {
|
||||
const { container } = renderLoggedOutHomeView(vi.fn(), {}, 'profile');
|
||||
|
||||
const nav = container.querySelector('.platform-bottom-nav');
|
||||
expect(nav).toBeTruthy();
|
||||
expect(nav?.classList.contains('platform-bottom-nav')).toBe(true);
|
||||
expect(nav?.classList.contains('grid-cols-1')).toBe(true);
|
||||
const buttons = within(nav as HTMLElement).getAllByRole('button');
|
||||
|
||||
expect(buttons.map((button) => button.textContent)).toEqual([
|
||||
'下一个',
|
||||
'发现',
|
||||
'我的',
|
||||
]);
|
||||
expect(buttons[0]?.querySelector('.lucide-chevron-down')).toBeTruthy();
|
||||
expect(buttons[1]?.querySelector('.lucide-compass')).toBeTruthy();
|
||||
expect(buttons[2]?.querySelector('.lucide-user-round')).toBeTruthy();
|
||||
expect(buttons.map((button) => button.textContent)).toEqual(['我的']);
|
||||
expect(buttons[0]?.querySelector('.lucide-user-round')).toBeTruthy();
|
||||
expect(
|
||||
within(nav as HTMLElement).queryByRole('button', { name: '推荐' }),
|
||||
).toBeNull();
|
||||
expect(
|
||||
within(nav as HTMLElement).queryByRole('button', { name: '发现' }),
|
||||
).toBeNull();
|
||||
expect(
|
||||
within(nav as HTMLElement).queryByRole('button', { name: '创作' }),
|
||||
).toBeNull();
|
||||
@@ -3809,24 +3816,24 @@ test('logged out bottom nav turns active recommend tab into next action', () =>
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
test('logged in mobile bottom nav hides draft and project entries', () => {
|
||||
test('logged in mobile bottom nav only shows profile tab', () => {
|
||||
const { container } = renderLoggedInHomeView({
|
||||
activeTab: 'profile',
|
||||
hasUnreadDraftUpdate: true,
|
||||
draftTabContent: <div>草稿内容</div>,
|
||||
});
|
||||
|
||||
const nav = container.querySelector('.platform-bottom-nav');
|
||||
expect(nav).toBeTruthy();
|
||||
expect(nav?.classList.contains('grid-cols-1')).toBe(true);
|
||||
const buttons = within(nav as HTMLElement).getAllByRole('button');
|
||||
expect(buttons.map((button) => button.textContent)).toEqual(['我的']);
|
||||
expect(
|
||||
within(nav as HTMLElement).getByRole('button', { name: '推荐' }),
|
||||
).toBeTruthy();
|
||||
within(nav as HTMLElement).queryByRole('button', { name: '推荐' }),
|
||||
).toBeNull();
|
||||
expect(
|
||||
within(nav as HTMLElement).getByRole('button', { name: '发现' }),
|
||||
).toBeTruthy();
|
||||
expect(
|
||||
within(nav as HTMLElement).getByRole('button', { name: '我的' }),
|
||||
).toBeTruthy();
|
||||
|
||||
within(nav as HTMLElement).queryByRole('button', { name: '发现' }),
|
||||
).toBeNull();
|
||||
expect(
|
||||
within(nav as HTMLElement).queryByRole('button', {
|
||||
name: '草稿,有新草稿',
|
||||
@@ -4106,7 +4113,6 @@ test('mobile discover search submits public work code', async () => {
|
||||
const onSearchPublicCode = vi.fn();
|
||||
|
||||
renderStatefulLoggedOutHomeView({ onSearchPublicCode });
|
||||
await user.click(screen.getByRole('button', { name: '发现' }));
|
||||
|
||||
const searchInput =
|
||||
screen.getByPlaceholderText('搜索作品号、名称、作者、描述');
|
||||
@@ -4145,7 +4151,6 @@ test('discover search fuzzy matches public work id, name, author and description
|
||||
onOpenGalleryDetail,
|
||||
onSearchPublicCode,
|
||||
});
|
||||
await user.click(screen.getByRole('button', { name: '发现' }));
|
||||
const discoverPanel = document.getElementById('platform-tab-panel-category');
|
||||
if (!discoverPanel) {
|
||||
throw new Error('缺少发现面板');
|
||||
@@ -4212,7 +4217,6 @@ test('mobile discover keeps edutainment works in the last dedicated channel only
|
||||
onOpenChildMotionDemo,
|
||||
onSearchPublicCode,
|
||||
});
|
||||
await user.click(screen.getByRole('button', { name: '发现' }));
|
||||
const discoverPanel = document.getElementById('platform-tab-panel-category');
|
||||
if (!discoverPanel) {
|
||||
throw new Error('缺少发现面板');
|
||||
@@ -4285,10 +4289,12 @@ test('desktop discover shows child motion demo in edutainment channel', async ()
|
||||
const user = userEvent.setup();
|
||||
const onOpenChildMotionDemo = vi.fn();
|
||||
|
||||
renderStatefulLoggedOutHomeView({
|
||||
onOpenChildMotionDemo,
|
||||
});
|
||||
await user.click(screen.getByRole('button', { name: '发现' }));
|
||||
renderStatefulLoggedOutHomeView(
|
||||
{
|
||||
onOpenChildMotionDemo,
|
||||
},
|
||||
true,
|
||||
);
|
||||
await user.click(screen.getByRole('tab', { name: '寓教于乐' }));
|
||||
|
||||
const warmupButton = screen.getByRole('button', { name: /热身关卡/u });
|
||||
@@ -4316,7 +4322,6 @@ test('mobile discover hides edutainment channel and work when switch is disabled
|
||||
latestEntries: [edutainmentEntry],
|
||||
onSearchPublicCode,
|
||||
});
|
||||
await user.click(screen.getByRole('button', { name: '发现' }));
|
||||
const discoverPanel = document.getElementById('platform-tab-panel-category');
|
||||
if (!discoverPanel) {
|
||||
throw new Error('缺少发现面板');
|
||||
@@ -4353,7 +4358,6 @@ test('mobile discover keeps baby object match works in edutainment channel only'
|
||||
onOpenGalleryDetail,
|
||||
onSearchPublicCode,
|
||||
});
|
||||
await user.click(screen.getByRole('button', { name: '发现' }));
|
||||
const discoverPanel = document.getElementById('platform-tab-panel-category');
|
||||
if (!discoverPanel) {
|
||||
throw new Error('缺少发现面板');
|
||||
@@ -4388,7 +4392,6 @@ test('discover search keeps public code fallback when local works do not match',
|
||||
latestEntries: [puzzlePublicEntry],
|
||||
onSearchPublicCode,
|
||||
});
|
||||
await user.click(screen.getByRole('button', { name: '发现' }));
|
||||
|
||||
const searchInput =
|
||||
screen.getByPlaceholderText('搜索作品号、名称、作者、描述');
|
||||
@@ -4406,7 +4409,6 @@ test('public gallery cards hide work code until detail is opened', async () => {
|
||||
latestEntries: [puzzlePublicEntry],
|
||||
onOpenGalleryDetail,
|
||||
});
|
||||
await user.click(screen.getByRole('button', { name: '发现' }));
|
||||
|
||||
expect(screen.queryByText('PZ-EPUBLIC1')).toBeNull();
|
||||
expect(
|
||||
@@ -4436,26 +4438,34 @@ test('public gallery cards hide phone masked author and public user code', async
|
||||
},
|
||||
true,
|
||||
);
|
||||
await user.click(screen.getByRole('button', { name: '发现' }));
|
||||
|
||||
const card = screen.getByRole('button', { name: /喜气洋洋/u });
|
||||
expect(card).toBeTruthy();
|
||||
expect(within(card).getByText('公开作者')).toBeTruthy();
|
||||
expect(await within(card).findByText('公开作者')).toBeTruthy();
|
||||
expect(within(card).queryByText('158****3533 · SY-00000003')).toBeNull();
|
||||
expect(within(card).queryByText('158****3533')).toBeNull();
|
||||
expect(within(card).queryByText('SY-00000003')).toBeNull();
|
||||
});
|
||||
|
||||
test('logged out mobile shell defaults to discover tab', () => {
|
||||
const { container } = renderStatefulLoggedOutHomeView({
|
||||
latestEntries: [puzzlePublicEntry],
|
||||
});
|
||||
test('logged out mobile shell defaults to profile tab when active tab is hidden', async () => {
|
||||
const { container } = renderStatefulLoggedOutHomeView(
|
||||
{
|
||||
latestEntries: [puzzlePublicEntry],
|
||||
},
|
||||
false,
|
||||
{
|
||||
allowHiddenActiveTab: false,
|
||||
},
|
||||
);
|
||||
|
||||
const activePanel = container.querySelector('.platform-tab-panel--active');
|
||||
expect(activePanel?.id).toBe('platform-tab-panel-category');
|
||||
await waitFor(() => {
|
||||
expect(container.querySelector('.platform-tab-panel--active')?.id).toBe(
|
||||
'platform-tab-panel-profile',
|
||||
);
|
||||
});
|
||||
expect(
|
||||
screen.getByPlaceholderText('搜索作品号、名称、作者、描述'),
|
||||
).toBeTruthy();
|
||||
screen.queryByPlaceholderText('搜索作品号、名称、作者、描述'),
|
||||
).toBeNull();
|
||||
expect(container.querySelector('.platform-mobile-topbar')).toBeTruthy();
|
||||
expect(
|
||||
container.querySelector('.platform-mobile-entry-shell--recommend'),
|
||||
@@ -4463,18 +4473,15 @@ test('logged out mobile shell defaults to discover tab', () => {
|
||||
});
|
||||
|
||||
test('logged out recommend tab opens embedded runtime without login modal', async () => {
|
||||
const user = userEvent.setup();
|
||||
const { container, openLoginModal } = renderStatefulLoggedOutHomeView({
|
||||
latestEntries: [puzzlePublicEntry],
|
||||
activeRecommendEntryKey: 'puzzle:user-2:puzzle-profile-public-1',
|
||||
});
|
||||
const bottomNav = container.querySelector('.platform-bottom-nav');
|
||||
if (!bottomNav) {
|
||||
throw new Error('缺少底部导航');
|
||||
}
|
||||
|
||||
await user.click(
|
||||
within(bottomNav as HTMLElement).getByRole('button', { name: '推荐' }),
|
||||
const { container, openLoginModal } = renderStatefulLoggedOutHomeView(
|
||||
{
|
||||
latestEntries: [puzzlePublicEntry],
|
||||
activeRecommendEntryKey: 'puzzle:user-2:puzzle-profile-public-1',
|
||||
},
|
||||
false,
|
||||
{
|
||||
initialActiveTab: 'home',
|
||||
},
|
||||
);
|
||||
|
||||
expect(openLoginModal).not.toHaveBeenCalled();
|
||||
@@ -4489,20 +4496,17 @@ test('logged out recommend tab opens embedded runtime without login modal', asyn
|
||||
});
|
||||
|
||||
test('logged out recommend runtime keeps detail callback idle', async () => {
|
||||
const user = userEvent.setup();
|
||||
const onOpenGalleryDetail = vi.fn();
|
||||
const { openLoginModal } = renderStatefulLoggedOutHomeView({
|
||||
latestEntries: [puzzlePublicEntry],
|
||||
activeRecommendEntryKey: 'puzzle:user-2:puzzle-profile-public-1',
|
||||
onOpenGalleryDetail,
|
||||
});
|
||||
const bottomNav = document.querySelector('.platform-bottom-nav');
|
||||
if (!bottomNav) {
|
||||
throw new Error('缺少底部导航');
|
||||
}
|
||||
|
||||
await user.click(
|
||||
within(bottomNav as HTMLElement).getByRole('button', { name: '推荐' }),
|
||||
const { openLoginModal } = renderStatefulLoggedOutHomeView(
|
||||
{
|
||||
latestEntries: [puzzlePublicEntry],
|
||||
activeRecommendEntryKey: 'puzzle:user-2:puzzle-profile-public-1',
|
||||
onOpenGalleryDetail,
|
||||
},
|
||||
false,
|
||||
{
|
||||
initialActiveTab: 'home',
|
||||
},
|
||||
);
|
||||
|
||||
expect(openLoginModal).not.toHaveBeenCalled();
|
||||
@@ -4596,9 +4600,8 @@ test('mobile recommend meta matches active wooden fish runtime entry', () => {
|
||||
expect(within(meta).getByText('莲台木鱼')).toBeTruthy();
|
||||
});
|
||||
|
||||
test('logged out desktop recommend rail enters runtime without login modal', async () => {
|
||||
test('logged out desktop rail hides recommend entry', () => {
|
||||
mockDesktopLayout();
|
||||
const user = userEvent.setup();
|
||||
const openLoginModal = vi.fn();
|
||||
|
||||
const { container } = renderLoggedOutHomeView(
|
||||
@@ -4616,10 +4619,11 @@ test('logged out desktop recommend rail enters runtime without login modal', asy
|
||||
throw new Error('缺少桌面侧边栏');
|
||||
}
|
||||
|
||||
await user.click(
|
||||
within(desktopRail as HTMLElement).getByRole('button', { name: '推荐' }),
|
||||
);
|
||||
|
||||
expect(
|
||||
within(desktopRail as HTMLElement).queryByRole('button', {
|
||||
name: '推荐',
|
||||
}),
|
||||
).toBeNull();
|
||||
expect(openLoginModal).not.toHaveBeenCalled();
|
||||
expect(screen.queryByTestId('recommend-runtime')).toBeNull();
|
||||
expect(container.querySelector('.platform-desktop-shell')).toBeTruthy();
|
||||
@@ -5379,8 +5383,7 @@ test('logged in recommend runtime preloads adjacent work previews and drag switc
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
test('logged out active recommend bottom tab selects next work without login', async () => {
|
||||
const user = userEvent.setup();
|
||||
test('logged out active recommend bottom nav hides next action', () => {
|
||||
const onSelectNextRecommendEntry = vi.fn();
|
||||
const openLoginModal = vi.fn();
|
||||
|
||||
@@ -5390,9 +5393,8 @@ test('logged out active recommend bottom tab selects next work without login', a
|
||||
onSelectNextRecommendEntry,
|
||||
});
|
||||
|
||||
await user.click(screen.getByRole('button', { name: '下一个' }));
|
||||
|
||||
expect(onSelectNextRecommendEntry).toHaveBeenCalledTimes(1);
|
||||
expect(screen.queryByRole('button', { name: '下一个' })).toBeNull();
|
||||
expect(onSelectNextRecommendEntry).not.toHaveBeenCalled();
|
||||
expect(openLoginModal).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -5487,9 +5489,6 @@ test('mobile discover recommend feed only rotates the card closest to screen cen
|
||||
renderStatefulLoggedOutHomeView({
|
||||
latestEntries: [firstEntry, secondEntry],
|
||||
});
|
||||
act(() => {
|
||||
screen.getByRole('button', { name: '发现' }).click();
|
||||
});
|
||||
|
||||
const tabPanel = document.querySelector('.platform-tab-panel--active');
|
||||
const firstCard = screen.getByRole('button', { name: /中心拼图一/u });
|
||||
@@ -5662,7 +5661,6 @@ test('mobile today channel only shows newly published works from today', async (
|
||||
latestEntries: [yesterdayEntry, updatedTodayEntry, todayEntry],
|
||||
});
|
||||
|
||||
await user.click(screen.getByRole('button', { name: '发现' }));
|
||||
await user.click(screen.getByRole('tab', { name: '今日' }));
|
||||
const discoverPanel = document.getElementById('platform-tab-panel-category');
|
||||
if (!discoverPanel) {
|
||||
@@ -5816,7 +5814,6 @@ test('mobile home moves category shelf into game category channel', async () =>
|
||||
expect(screen.queryByRole('button', { name: 'PC游戏' })).toBeNull();
|
||||
expect(screen.queryByRole('button', { name: '即点即玩' })).toBeNull();
|
||||
|
||||
await user.click(screen.getByRole('button', { name: '发现' }));
|
||||
await user.click(screen.getByRole('tab', { name: '分类' }));
|
||||
|
||||
expect(screen.getAllByText('分类').length).toBeGreaterThan(0);
|
||||
@@ -5842,7 +5839,6 @@ test('mobile game category list orders works by composite public metric', async
|
||||
latestEntries: [puzzlePublicEntry, hotRankEntry],
|
||||
});
|
||||
|
||||
await user.click(screen.getByRole('button', { name: '发现' }));
|
||||
await user.click(screen.getByRole('tab', { name: '分类' }));
|
||||
await user.click(screen.getByRole('button', { name: '奇幻' }));
|
||||
|
||||
@@ -5874,7 +5870,6 @@ test('mobile game category filter dialog filters by play type', async () => {
|
||||
latestEntries: [puzzlePublicEntry, match3dEntry],
|
||||
});
|
||||
|
||||
await user.click(screen.getByRole('button', { name: '发现' }));
|
||||
await user.click(screen.getByRole('tab', { name: '分类' }));
|
||||
await user.click(screen.getByRole('button', { name: '奇幻' }));
|
||||
|
||||
@@ -5909,7 +5904,6 @@ test('mobile game category keeps filter controls when current filter becomes emp
|
||||
latestEntries: [puzzlePublicEntry],
|
||||
});
|
||||
|
||||
await user.click(screen.getByRole('button', { name: '发现' }));
|
||||
await user.click(screen.getByRole('tab', { name: '分类' }));
|
||||
await user.click(screen.getByRole('button', { name: '奇幻' }));
|
||||
await user.click(screen.getByRole('button', { name: /筛选/u }));
|
||||
@@ -5955,7 +5949,6 @@ test('bottom category tab becomes ranking and switches ranking metrics', async (
|
||||
latestEntries: [remixRankEntry, hotRankEntry, newRankEntry],
|
||||
});
|
||||
|
||||
await user.click(screen.getByRole('button', { name: '发现' }));
|
||||
await user.click(screen.getByRole('tab', { name: '排行' }));
|
||||
|
||||
expect(await screen.findByRole('tab', { name: '热门榜' })).toBeTruthy();
|
||||
@@ -5989,7 +5982,6 @@ test('ranking rows limit displayed work name and show two short tags on the thir
|
||||
latestEntries: [longTextRankEntry],
|
||||
});
|
||||
|
||||
await user.click(screen.getByRole('button', { name: '发现' }));
|
||||
await user.click(screen.getByRole('tab', { name: '排行' }));
|
||||
|
||||
const rankingPanel = document.getElementById('platform-tab-panel-category');
|
||||
|
||||
@@ -2899,13 +2899,7 @@ export function RpgEntryHomeView({
|
||||
hasManualCategoryTagSelectionRef.current = true;
|
||||
setSelectedCategoryTag(tag);
|
||||
}, []);
|
||||
const visibleMobileTabs = useMemo<PlatformHomeTab[]>(
|
||||
() =>
|
||||
isAuthenticated
|
||||
? ['home', 'category', 'profile']
|
||||
: ['home', 'category', 'profile'],
|
||||
[isAuthenticated],
|
||||
);
|
||||
const visibleMobileTabs = useMemo<PlatformHomeTab[]>(() => ['profile'], []);
|
||||
const visibleDesktopNavTabs = useMemo<PlatformNavTab[]>(
|
||||
() =>
|
||||
(isAuthenticated
|
||||
@@ -2962,12 +2956,11 @@ export function RpgEntryHomeView({
|
||||
return;
|
||||
}
|
||||
if (!visibleMobileTabs.includes(activeTab) && !isDesktopLayout) {
|
||||
onTabChange(isAuthenticated ? 'home' : 'category');
|
||||
onTabChange('profile');
|
||||
}
|
||||
}, [
|
||||
activeTab,
|
||||
allowHiddenActiveTab,
|
||||
isAuthenticated,
|
||||
isDesktopLayout,
|
||||
onTabChange,
|
||||
visibleMobileTabs,
|
||||
@@ -5115,7 +5108,7 @@ export function RpgEntryHomeView({
|
||||
|
||||
<div className="platform-mobile-bottom-dock min-w-0 shrink-0">
|
||||
<div
|
||||
className={`platform-bottom-nav grid ${visibleMobileTabs.length === 5 ? 'grid-cols-5' : visibleMobileTabs.length === 4 ? 'grid-cols-4' : visibleMobileTabs.length === 3 ? 'grid-cols-3' : 'grid-cols-2'}`}
|
||||
className={`platform-bottom-nav grid ${visibleMobileTabs.length === 5 ? 'grid-cols-5' : visibleMobileTabs.length === 4 ? 'grid-cols-4' : visibleMobileTabs.length === 3 ? 'grid-cols-3' : visibleMobileTabs.length === 2 ? 'grid-cols-2' : 'grid-cols-1'}`}
|
||||
>
|
||||
{visibleMobileTabs.map((tab) => (
|
||||
<PlatformTabButton
|
||||
|
||||
Reference in New Issue
Block a user