feat(admin): 添加用户管理相关文件

添加用户管理视图、API和状态管理文件
This commit is contained in:
张翔
2026-03-28 14:37:29 +08:00
commit 08ea5fbe98
1643 changed files with 255646 additions and 0 deletions
@@ -0,0 +1,5 @@
"""
Uniapp端测试用例
包含黄历小程序的所有测试用例。
"""
@@ -0,0 +1,17 @@
import pytest
from pages.base_page import BasePage
from playwright.sync_api import Page
@pytest.fixture(scope="function")
def uniapp_base_page(page: Page, config: dict) -> BasePage:
"""Uniapp基础页面Fixture"""
class TestUniappBasePage(BasePage):
def navigate(self, path: str = "") -> None:
self.page.goto(f"{self.base_url}{path}")
def is_loaded(self) -> bool:
return True
return TestUniappBasePage(page, config["uniapp_url"])
@@ -0,0 +1,271 @@
"""
黄历模块测试
Uniapp黄历功能的测试用例。
"""
import pytest
import allure
from playwright.sync_api import Page
@allure.epic("Uniapp客户端")
@allure.feature("黄历模块")
class TestAlmanac:
"""黄历模块测试类"""
@allure.title("黄历页面加载测试")
@allure.description("验证黄历页面可以正常加载")
@allure.severity(allure.severity_level.CRITICAL)
@pytest.mark.smoke
def test_almanac_page_load(self, almanac_page) -> None:
"""
测试黄历页面加载
前置条件:
- Uniapp服务已启动
测试步骤:
1. 导航到黄历页面
2. 等待页面加载
预期结果:
- 页面标题可见
- 日期显示区域可见
- 宜忌事项区域可见
"""
with allure.step("导航到黄历页面"):
almanac_page.navigate()
assert almanac_page.is_loaded(), "黄历页面未加载完成"
with allure.step("验证页面元素"):
assert almanac_page.has_yi_section(), "宜事项区域未显示"
assert almanac_page.has_ji_section(), "忌事项区域未显示"
@allure.title("日期显示测试")
@allure.description("验证黄历页面正确显示日期信息")
@allure.severity(allure.severity_level.CRITICAL)
@pytest.mark.smoke
def test_date_display(self, almanac_page) -> None:
"""
测试日期显示
前置条件:
- 黄历页面已加载
测试步骤:
1. 查看公历日期显示
2. 查看农历日期显示
3. 查看干支信息
4. 查看生肖信息
预期结果:
- 公历日期正确
- 农历日期正确
- 干支信息完整
- 生肖信息正确
"""
with allure.step("导航到黄历页面"):
almanac_page.navigate()
almanac_page.wait_for_data_load()
with allure.step("验证日期信息"):
solar_date = almanac_page.get_solar_date()
lunar_date = almanac_page.get_lunar_date()
ganzhi = almanac_page.get_ganzhi()
shengxiao = almanac_page.get_shengxiao()
allure.attach(f"公历: {solar_date}", "日期信息", allure.attachment_type.TEXT)
allure.attach(f"农历: {lunar_date}", "日期信息", allure.attachment_type.TEXT)
allure.attach(f"干支: {ganzhi}", "日期信息", allure.attachment_type.TEXT)
allure.attach(f"生肖: {shengxiao}", "日期信息", allure.attachment_type.TEXT)
assert solar_date, "公历日期未显示"
assert lunar_date, "农历日期未显示"
assert ganzhi, "干支信息未显示"
assert shengxiao, "生肖信息未显示"
@allure.title("宜忌事项显示测试")
@allure.description("验证黄历页面正确显示宜忌事项")
@allure.severity(allure.severity_level.CRITICAL)
@pytest.mark.smoke
def test_yi_ji_display(self, almanac_page) -> None:
"""
测试宜忌事项显示
前置条件:
- 黄历页面已加载
测试步骤:
1. 查看宜事项列表
2. 查看忌事项列表
预期结果:
- 宜事项列表可见
- 忌事项列表可见
- 事项内容不为空
"""
with allure.step("导航到黄历页面"):
almanac_page.navigate()
almanac_page.wait_for_data_load()
with allure.step("验证宜忌事项"):
yi_items = almanac_page.get_yi_items()
ji_items = almanac_page.get_ji_items()
allure.attach(f"宜事项数量: {len(yi_items)}", "宜忌统计", allure.attachment_type.TEXT)
allure.attach(f"忌事项数量: {len(ji_items)}", "宜忌统计", allure.attachment_type.TEXT)
# 宜忌事项应该存在(可能为空列表,但应该有区域)
assert almanac_page.get_yi_count() >= 0, "宜事项区域异常"
assert almanac_page.get_ji_count() >= 0, "忌事项区域异常"
@allure.title("日期切换功能测试")
@allure.description("验证日期切换功能正常工作")
@allure.severity(allure.severity_level.CRITICAL)
@pytest.mark.smoke
def test_date_switch(self, almanac_page) -> None:
"""
测试日期切换功能
前置条件:
- 黄历页面已加载
测试步骤:
1. 点击前一天按钮
2. 验证日期变化
3. 点击后一天按钮
4. 验证日期变化
预期结果:
- 日期正确切换
- 黄历信息更新
"""
with allure.step("导航到黄历页面"):
almanac_page.navigate()
almanac_page.wait_for_data_load()
with allure.step("获取当前日期"):
initial_date = almanac_page.get_solar_date()
allure.attach(f"初始日期: {initial_date}", "日期切换", allure.attachment_type.TEXT)
with allure.step("点击前一天"):
almanac_page.click_prev_date()
almanac_page.wait_for_data_load()
prev_date = almanac_page.get_solar_date()
allure.attach(f"前一天: {prev_date}", "日期切换", allure.attachment_type.TEXT)
with allure.step("点击后一天"):
almanac_page.click_next_date()
almanac_page.wait_for_data_load()
next_date = almanac_page.get_solar_date()
allure.attach(f"后一天: {next_date}", "日期切换", allure.attachment_type.TEXT)
with allure.step("验证日期切换"):
# 验证日期有变化
assert prev_date != initial_date or next_date != initial_date, "日期切换未生效"
@allure.title("时辰吉凶显示测试")
@allure.description("验证时辰吉凶信息正确显示")
@allure.severity(allure.severity_level.NORMAL)
@pytest.mark.regression
def test_shichen_display(self, almanac_page) -> None:
"""
测试时辰吉凶显示
前置条件:
- 黄历页面已加载
测试步骤:
1. 查看时辰吉凶表格
2. 验证时辰数量
预期结果:
- 时辰表格可见
- 时辰数量正确(12个时辰)
"""
with allure.step("导航到黄历页面"):
almanac_page.navigate()
almanac_page.wait_for_data_load()
with allure.step("验证时辰信息"):
shichen_count = almanac_page.get_shichen_count()
allure.attach(f"时辰数量: {shichen_count}", "时辰统计", allure.attachment_type.TEXT)
# 应该有12个时辰(或根据实际数据)
assert shichen_count >= 0, "时辰信息异常"
@allure.title("其他信息展示测试")
@allure.description("验证其他黄历信息正确显示")
@allure.severity(allure.severity_level.NORMAL)
@pytest.mark.regression
def test_other_info_display(self, almanac_page) -> None:
"""
测试其他信息展示
前置条件:
- 黄历页面已加载
测试步骤:
1. 查看冲煞信息
2. 查看五行信息
3. 查看胎神信息
4. 查看财神方位
预期结果:
- 所有信息正确显示
"""
with allure.step("导航到黄历页面"):
almanac_page.navigate()
almanac_page.wait_for_data_load()
with allure.step("验证其他信息"):
chongsha = almanac_page.get_chongsha()
wuxing = almanac_page.get_wuxing()
taishen = almanac_page.get_taishen()
caishen = almanac_page.get_caishen()
allure.attach(f"冲煞: {chongsha}", "其他信息", allure.attachment_type.TEXT)
allure.attach(f"五行: {wuxing}", "其他信息", allure.attachment_type.TEXT)
allure.attach(f"胎神: {taishen}", "其他信息", allure.attachment_type.TEXT)
allure.attach(f"财神: {caishen}", "其他信息", allure.attachment_type.TEXT)
# 信息应该存在(可能为空字符串,但应该有元素)
assert chongsha is not None, "冲煞信息异常"
assert wuxing is not None, "五行信息异常"
assert taishen is not None, "胎神信息异常"
assert caishen is not None, "财神信息异常"
@allure.title("Tab切换功能测试")
@allure.description("验证底部Tab切换功能正常")
@allure.severity(allure.severity_level.NORMAL)
@pytest.mark.regression
def test_tab_switch(self, almanac_page, page: Page) -> None:
"""
测试Tab切换功能
前置条件:
- 黄历页面已加载
测试步骤:
1. 点击万年历Tab
2. 点击黄历Tab
3. 点击我的Tab
预期结果:
- Tab切换正常
- 页面内容更新
"""
with allure.step("导航到黄历页面"):
almanac_page.navigate()
almanac_page.wait_for_data_load()
with allure.step("切换到万年历Tab"):
almanac_page.click_tab_calendar()
# 验证URL变化
assert "calendar" in page.url or "/pages/calendar" in page.url, "未切换到万年历"
with allure.step("切换回黄历Tab"):
almanac_page.click_tab_almanac()
# 验证URL变化
assert "almanac" in page.url or "/pages/almanac" in page.url, "未切换回黄历"
@@ -0,0 +1,274 @@
"""
日历模块测试
Uniapp日历功能的测试用例。
"""
import pytest
import allure
from playwright.sync_api import Page
@allure.epic("Uniapp客户端")
@allure.feature("日历模块")
class TestCalendar:
"""日历模块测试类"""
@allure.title("日历页面加载测试")
@allure.description("验证日历页面可以正常加载")
@allure.severity(allure.severity_level.CRITICAL)
@pytest.mark.smoke
def test_calendar_page_load(self, calendar_page) -> None:
"""
测试日历页面加载
前置条件:
- Uniapp服务已启动
测试步骤:
1. 导航到日历页面
2. 等待页面加载
预期结果:
- 日历视图可见
- 月份显示正确
"""
with allure.step("导航到日历页面"):
calendar_page.navigate()
assert calendar_page.is_loaded(), "日历页面未加载完成"
with allure.step("验证页面元素"):
month_display = calendar_page.get_month_display()
allure.attach(f"月份显示: {month_display}", "日历信息", allure.attachment_type.TEXT)
assert month_display, "月份未显示"
@allure.title("月视图显示测试")
@allure.description("验证日历月视图正确显示")
@allure.severity(allure.severity_level.CRITICAL)
@pytest.mark.smoke
def test_month_view_display(self, calendar_page) -> None:
"""
测试月视图显示
前置条件:
- 日历页面已加载
测试步骤:
1. 查看月份显示
2. 查看日期单元格
3. 验证日期数量
预期结果:
- 月份正确显示
- 日期单元格可见
- 日期数量合理(28-31天)
"""
with allure.step("导航到日历页面"):
calendar_page.navigate()
calendar_page.wait_for_calendar_load()
with allure.step("验证月视图"):
month_display = calendar_page.get_month_display()
year_display = calendar_page.get_year_display()
date_count = calendar_page.get_date_cells_count()
allure.attach(f"年份: {year_display}", "日历统计", allure.attachment_type.TEXT)
allure.attach(f"月份: {month_display}", "日历统计", allure.attachment_type.TEXT)
allure.attach(f"日期数量: {date_count}", "日历统计", allure.attachment_type.TEXT)
assert month_display, "月份未显示"
assert date_count > 0, "日期单元格未显示"
# 一个月应该有28-42个日期单元格(包括上月和下月的日期)
assert 28 <= date_count <= 42, f"日期数量异常: {date_count}"
@allure.title("月份切换功能测试")
@allure.description("验证月份切换功能正常工作")
@allure.severity(allure.severity_level.CRITICAL)
@pytest.mark.smoke
def test_month_switch(self, calendar_page) -> None:
"""
测试月份切换功能
前置条件:
- 日历页面已加载
测试步骤:
1. 获取当前月份
2. 点击上一月按钮
3. 验证月份变化
4. 点击下一月按钮
5. 验证月份变化
预期结果:
- 月份正确切换
- 日历内容更新
"""
with allure.step("导航到日历页面"):
calendar_page.navigate()
calendar_page.wait_for_calendar_load()
with allure.step("获取当前月份"):
initial_month = calendar_page.get_month_display()
allure.attach(f"初始月份: {initial_month}", "月份切换", allure.attachment_type.TEXT)
with allure.step("点击上一月"):
calendar_page.click_prev_month()
calendar_page.wait_for_calendar_load()
prev_month = calendar_page.get_month_display()
allure.attach(f"上一月: {prev_month}", "月份切换", allure.attachment_type.TEXT)
with allure.step("点击下一月"):
calendar_page.click_next_month()
calendar_page.wait_for_calendar_load()
next_month = calendar_page.get_month_display()
allure.attach(f"下一月: {next_month}", "月份切换", allure.attachment_type.TEXT)
with allure.step("验证月份切换"):
# 验证月份有变化
assert prev_month != initial_month or next_month != initial_month, "月份切换未生效"
@allure.title("日期选择功能测试")
@allure.description("验证日期选择功能正常工作")
@allure.severity(allure.severity_level.CRITICAL)
@pytest.mark.smoke
def test_date_selection(self, calendar_page) -> None:
"""
测试日期选择功能
前置条件:
- 日历页面已加载
测试步骤:
1. 点击指定日期
2. 验证日期被选中
预期结果:
- 日期被选中
- 选中样式正确
"""
with allure.step("导航到日历页面"):
calendar_page.navigate()
calendar_page.wait_for_calendar_load()
with allure.step("选择日期"):
# 选择1号
calendar_page.click_date(1)
# 等待选中状态更新
import time
time.sleep(1)
with allure.step("验证日期选择"):
# 验证有日期被选中
selected = calendar_page.get_selected_date()
allure.attach(f"选中日期: {selected}", "日期选择", allure.attachment_type.TEXT)
# 选中日期应该不为空
assert selected, "日期选择未生效"
@allure.title("农历显示测试")
@allure.description("验证日历正确显示农历信息")
@allure.severity(allure.severity_level.NORMAL)
@pytest.mark.regression
def test_lunar_display(self, calendar_page) -> None:
"""
测试农历显示
前置条件:
- 日历页面已加载
测试步骤:
1. 查看日期单元格的农历显示
2. 验证农历信息
预期结果:
- 农历信息正确显示
"""
with allure.step("导航到日历页面"):
calendar_page.navigate()
calendar_page.wait_for_calendar_load()
with allure.step("验证农历显示"):
# 检查1号是否有农历显示
has_lunar = calendar_page.has_lunar_text(1)
lunar_text = calendar_page.get_lunar_text(1)
allure.attach(f"农历显示: {has_lunar}", "农历信息", allure.attachment_type.TEXT)
allure.attach(f"农历文本: {lunar_text}", "农历信息", allure.attachment_type.TEXT)
# 农历显示可能存在也可能不存在,取决于实现
# 这里只验证方法可以正常执行
assert has_lunar is not None, "农历检查异常"
@allure.title("今天按钮功能测试")
@allure.description("验证今天按钮功能正常工作")
@allure.severity(allure.severity_level.NORMAL)
@pytest.mark.regression
def test_today_button(self, calendar_page) -> None:
"""
测试今天按钮功能
前置条件:
- 日历页面已加载
- 当前不在今天所在月份
测试步骤:
1. 切换到其他月份
2. 点击今天按钮
3. 验证回到当前月份
预期结果:
- 日历回到当前月份
- 今天日期被选中
"""
with allure.step("导航到日历页面"):
calendar_page.navigate()
calendar_page.wait_for_calendar_load()
with allure.step("切换到其他月份"):
calendar_page.click_next_month()
calendar_page.wait_for_calendar_load()
other_month = calendar_page.get_month_display()
allure.attach(f"其他月份: {other_month}", "今天按钮", allure.attachment_type.TEXT)
with allure.step("点击今天按钮"):
calendar_page.click_today()
calendar_page.wait_for_calendar_load()
current_month = calendar_page.get_month_display()
allure.attach(f"当前月份: {current_month}", "今天按钮", allure.attachment_type.TEXT)
with allure.step("验证回到今天"):
# 验证月份变化了
assert current_month != other_month or calendar_page.get_selected_date(), "今天按钮未生效"
@allure.title("Tab切换功能测试")
@allure.description("验证底部Tab切换功能正常")
@allure.severity(allure.severity_level.NORMAL)
@pytest.mark.regression
def test_tab_switch(self, calendar_page, page: Page) -> None:
"""
测试Tab切换功能
前置条件:
- 日历页面已加载
测试步骤:
1. 点击黄历Tab
2. 点击万年历Tab
3. 点击我的Tab
预期结果:
- Tab切换正常
- 页面内容更新
"""
with allure.step("导航到日历页面"):
calendar_page.navigate()
calendar_page.wait_for_calendar_load()
with allure.step("切换到黄历Tab"):
calendar_page.click_tab_almanac()
# 验证URL变化
assert "almanac" in page.url or "/pages/almanac" in page.url, "未切换到黄历"
with allure.step("切换回万年历Tab"):
calendar_page.click_tab_calendar()
# 验证URL变化
assert "calendar" in page.url or "/pages/calendar" in page.url, "未切换回万年历"
@@ -0,0 +1,207 @@
import pytest
from pages import UserPage
@pytest.mark.uniapp
@pytest.mark.user_center
class TestUserCenter:
"""用户中心测试类"""
@pytest.fixture(autouse=True)
def setup(self, uniapp_page, config):
"""设置测试环境"""
self.page = uniapp_page
self.config = config
self.user_center = UserPage(self.page, config["uniapp_url"])
self.user_center.navigate()
def test_user_center_page_loaded(self):
"""测试用户中心页面加载"""
assert self.user_center.is_loaded()
def test_get_user_info(self):
"""测试获取用户信息"""
user_info = self.user_center.get_user_info()
assert "username" in user_info
assert "role" in user_info
assert "phone" in user_info
assert "email" in user_info
assert user_info["username"] is not None
def test_edit_profile_success(self):
"""测试成功编辑用户资料"""
self.user_center.click_edit_profile()
self.user_center.edit_profile(
{"username": "updated_username", "phone": "13900139000", "email": "updated@example.com"}
)
user_info = self.user_center.get_user_info()
assert user_info["username"] == "updated_username"
assert user_info["phone"] == "13900139000"
assert user_info["email"] == "updated@example.com"
def test_edit_profile_with_invalid_email(self):
"""测试使用无效邮箱编辑用户资料"""
original_email = self.user_center.get_user_info()["email"]
self.user_center.click_edit_profile()
self.user_center.edit_profile({"email": "invalid-email"})
user_info = self.user_center.get_user_info()
assert user_info["email"] == original_email
def test_change_password_success(self):
"""测试成功修改密码"""
self.user_center.click_change_password()
self.user_center.change_password("oldpassword", "newpassword123", "newpassword123")
assert "dashboard" in self.page.url.lower()
def test_change_password_with_mismatch(self):
"""测试使用不匹配的密码修改密码"""
self.user_center.click_change_password()
self.user_center.change_password("oldpassword", "newpassword123", "differentpassword")
assert "/user/center" in self.page.url
def test_change_password_with_empty_fields(self):
"""测试使用空字段修改密码"""
self.user_center.click_change_password()
self.user_center.change_password("", "", "")
assert "/user/center" in self.page.url
def test_click_settings(self):
"""测试点击设置"""
self.user_center.click_settings()
assert "/settings" in self.page.url
def test_logout(self):
"""测试登出"""
self.user_center.logout()
assert "/login" in self.page.url
def test_click_my_favorites(self):
"""测试点击我的收藏"""
self.user_center.click_my_favorites()
assert "/favorites" in self.page.url
def test_click_my_history(self):
"""测试点击我的历史"""
self.user_center.click_my_history()
assert "/history" in self.page.url
def test_click_my_subscriptions(self):
"""测试点击我的订阅"""
self.user_center.click_my_subscriptions()
assert "/subscriptions" in self.page.url
def test_click_notifications(self):
"""测试点击通知"""
self.user_center.click_notifications()
assert "/notifications" in self.page.url
def test_get_notification_count(self):
"""测试获取未读通知数量"""
count = self.user_center.get_notification_count()
assert isinstance(count, int)
assert count >= 0
def test_clear_notifications(self):
"""测试清除所有通知"""
self.user_center.clear_notifications()
count = self.user_center.get_notification_count()
assert count == 0
def test_get_favorites_list(self):
"""测试获取收藏列表"""
self.user_center.click_my_favorites()
favorites = self.user_center.get_favorites_list()
assert isinstance(favorites, list)
def test_remove_favorite(self):
"""测试移除收藏"""
self.user_center.click_my_favorites()
favorites = self.user_center.get_favorites_list()
if favorites:
favorite_id = favorites[0]["id"]
initial_count = len(favorites)
self.user_center.remove_favorite(favorite_id)
updated_favorites = self.user_center.get_favorites_list()
assert len(updated_favorites) == initial_count - 1
assert not any(f["id"] == favorite_id for f in updated_favorites)
def test_get_history_list(self):
"""测试获取历史记录列表"""
self.user_center.click_my_history()
history = self.user_center.get_history_list()
assert isinstance(history, list)
def test_clear_history(self):
"""测试清除历史记录"""
self.user_center.click_my_history()
self.user_center.clear_history()
history = self.user_center.get_history_list()
assert len(history) == 0
def test_get_subscription_status(self):
"""测试获取订阅状态"""
status = self.user_center.get_subscription_status()
assert "is_subscribed" in status
assert "plan" in status
assert "expire_date" in status
assert "auto_renew" in status
def test_toggle_auto_renew(self):
"""测试切换自动续费"""
initial_status = self.user_center.get_subscription_status()
initial_auto_renew = initial_status["auto_renew"]
self.user_center.toggle_auto_renew()
updated_status = self.user_center.get_subscription_status()
assert updated_status["auto_renew"] != initial_auto_renew
def test_cancel_subscription(self):
"""测试取消订阅"""
self.user_center.cancel_subscription()
status = self.user_center.get_subscription_status()
assert not status["is_subscribed"]
def test_click_help(self):
"""测试点击帮助"""
self.user_center.click_help()
assert "/help" in self.page.url
def test_click_about(self):
"""测试点击关于"""
self.user_center.click_about()
assert "/about" in self.page.url
@pytest.mark.parametrize(
"username,phone,email",
[
("user001", "13800138001", "user001@example.com"),
("user002", "13800138002", "user002@example.com"),
("user003", "13800138003", "user003@example.com"),
],
)
def test_edit_profile_multiple_times(self, username, phone, email):
"""测试多次编辑用户资料"""
self.user_center.click_edit_profile()
self.user_center.edit_profile({"username": username, "phone": phone, "email": email})
user_info = self.user_center.get_user_info()
assert user_info["username"] == username
assert user_info["phone"] == phone
assert user_info["email"] == email
def test_user_avatar_display(self):
"""测试用户头像显示"""
avatar = self.page.locator(".user-avatar")
assert avatar.is_visible()