diff --git a/frontend/tests/unit/renderShell.smoke.test.tsx b/frontend/tests/unit/renderShell.smoke.test.tsx
new file mode 100644
index 0000000..04ea35e
--- /dev/null
+++ b/frontend/tests/unit/renderShell.smoke.test.tsx
@@ -0,0 +1,17 @@
+// REQ-USR-003: renderShell 共享渲染工具自带冒烟用例(T0)
+import { describe, it, expect } from 'vitest';
+import { screen } from '@testing-library/react';
+import { renderShell } from './renderShell';
+
+describe('renderShell', () => {
+ it('renderShell mounts a route element', () => {
+ renderShell(
shell-ok
, {
+ initialEntries: ['/'],
+ preloadedAuth: {
+ token: 't',
+ user: { id: 1, sUserName: '朱子纯', sUserType: '超级管理员', sLanguage: '中文' },
+ },
+ });
+ expect(screen.getByText('shell-ok')).toBeInTheDocument();
+ });
+});
diff --git a/frontend/tests/unit/renderShell.tsx b/frontend/tests/unit/renderShell.tsx
new file mode 100644
index 0000000..1a8ac40
--- /dev/null
+++ b/frontend/tests/unit/renderShell.tsx
@@ -0,0 +1,46 @@
+// REQ-USR-003: 外壳 / 路由测试共享渲染工具(Provider + 真实 store + MemoryRouter + AntD App)
+// 复用 FE-01 renderLogin.tsx 模式,扩展为可注入 auth 预置态(token/user)。
+import type { ReactElement } from 'react';
+import { render } from '@testing-library/react';
+import { Provider } from 'react-redux';
+import { MemoryRouter } from 'react-router-dom';
+import { App as AntdApp, ConfigProvider } from 'antd';
+import { configureStore } from '@reduxjs/toolkit';
+import authReducer, { type AuthState } from '../../src/store/slices/authSlice';
+import type { RootState } from '../../src/store/store';
+
+/** 构建带 auth slice 的测试 store,可注入 token/user 预置态 */
+export function makeShellStore(preloadedAuth?: Partial) {
+ return configureStore({
+ reducer: { auth: authReducer },
+ preloadedState: preloadedAuth
+ ? { auth: { token: null, user: null, ...preloadedAuth } }
+ : undefined,
+ });
+}
+
+export interface RenderShellOptions {
+ initialEntries?: string[];
+ preloadedAuth?: Partial;
+ store?: ReturnType;
+}
+
+export function renderShell(ui: ReactElement, options?: RenderShellOptions) {
+ const store = options?.store ?? makeShellStore(options?.preloadedAuth);
+ const result = render(
+
+
+
+
+ {ui}
+
+
+
+ ,
+ );
+ return {
+ ...result,
+ store,
+ getState: () => store.getState() as RootState,
+ };
+}