新增e2e测试脚本,修复部分问题

This commit was merged in pull request #51.
This commit is contained in:
2026-07-22 20:00:13 +08:00
parent 53d1ce6fb2
commit 4c07ec5455
105 changed files with 21700 additions and 318 deletions
@@ -0,0 +1,162 @@
/**
* CourseDetailPage - 课程详情页 Page Object
* 对应页面: pages/course-detail/course-detail
*/
class CourseDetailPage {
constructor(miniProgram) {
this.mp = miniProgram;
}
/**
* 等待课程详情页加载完成
*/
async waitForLoad() {
const { waitForPage } = require('../helpers/automator');
return waitForPage(this.mp, 'pages/course-detail/course-detail');
}
/**
* 获取课程名称
* @returns {Promise<string>}
*/
async getCourseName() {
const page = await this.mp.currentPage();
try {
const nameEl = await page.$('.course-name');
if (nameEl) {
return await nameEl.text();
}
} catch (e) {
console.warn('[CourseDetailPage] 获取课程名称异常:', e.message);
}
return '';
}
/**
* 获取教练名称
* @returns {Promise<string>}
*/
async getCoachName() {
const page = await this.mp.currentPage();
try {
const coachEl = await page.$('.coach-name');
if (coachEl) {
return await coachEl.text();
}
} catch (e) {
console.warn('[CourseDetailPage] 获取教练名称异常:', e.message);
}
return '';
}
/**
* 获取课程详情信息
* @returns {Promise<Object>}
*/
async getCourseInfo() {
const page = await this.mp.currentPage();
const info = {
name: '',
coach: '',
time: '',
location: ''
};
try {
info.name = await this.getCourseName();
info.coach = await this.getCoachName();
const timeEl = await page.$('.course-time');
if (timeEl) {
info.time = await timeEl.text();
}
const locationEl = await page.$('.course-location');
if (locationEl) {
info.location = await locationEl.text();
}
} catch (e) {
console.warn('[CourseDetailPage] 获取课程信息异常:', e.message);
}
return info;
}
/**
* 点击预约按钮
* @returns {Promise<boolean>} 是否点击成功
*/
async bookCourse() {
const page = await this.mp.currentPage();
console.log('[CourseDetailPage] 点击预约按钮');
try {
const bookBtn = await page.$('.book-btn');
if (bookBtn) {
await bookBtn.tap();
await this.mp.waitFor(2000);
return true;
}
// 尝试其他可能的按钮选择器
const confirmBtn = await page.$('.confirm-btn');
if (confirmBtn) {
await confirmBtn.tap();
await this.mp.waitFor(2000);
return true;
}
} catch (e) {
console.warn('[CourseDetailPage] 预约按钮点击异常:', e.message);
}
return false;
}
/**
* 验证预约成功提示
* @returns {Promise<boolean>}
*/
async verifyBookingSuccess() {
console.log('[CourseDetailPage] 验证预约成功...');
await this.mp.waitFor(1000);
const page = await this.mp.currentPage();
try {
// 检查 toast 提示
const toast = await page.$('.uni-toast');
if (toast) {
const toastText = await toast.text();
console.log(`[CourseDetailPage] Toast 内容: "${toastText}"`);
return toastText.includes('成功') || toastText.includes('预约');
}
} catch (e) {
console.warn('[CourseDetailPage] 验证 toast 异常:', e.message);
}
// 如果页面跳转到"我的课程",也视为成功
try {
const currentPage = await this.mp.currentPage();
if (currentPage.path && currentPage.path.includes('my-courses')) {
return true;
}
} catch (e) {
// ignore
}
return false;
}
/**
* 返回上一页
*/
async goBack() {
try {
await this.mp.navigateBack();
await this.mp.waitFor(1000);
} catch (e) {
console.warn('[CourseDetailPage] 返回异常:', e.message);
}
}
}
module.exports = CourseDetailPage;
+101
View File
@@ -0,0 +1,101 @@
/**
* HomePage - 首页 Page Object
* 对应页面: pages/index/index
*/
class HomePage {
constructor(miniProgram) {
this.mp = miniProgram;
}
/**
* 等待首页加载完成
*/
async waitForLoad() {
const { waitForPage } = require('../helpers/automator');
return waitForPage(this.mp, 'pages/index/index');
}
/**
* 获取首页关键元素
* @returns {Promise<Object>} 包含轮播图、导航等元素信息
*/
async getElements() {
const page = await this.mp.currentPage();
const elements = {};
try {
// 尝试获取轮播图
const swiperItems = await page.$$('swiper-item');
elements.bannerCount = swiperItems ? swiperItems.length : 0;
} catch (e) {
elements.bannerCount = 0;
}
try {
// 获取课程列表卡片
const courseCards = await page.$$('.course-card');
elements.courseCardCount = courseCards ? courseCards.length : 0;
} catch (e) {
elements.courseCardCount = 0;
}
try {
// 获取导航按钮
const navButtons = await page.$$('.nav-item');
elements.navButtonCount = navButtons ? navButtons.length : 0;
} catch (e) {
elements.navButtonCount = 0;
}
return elements;
}
/**
* 获取轮播图信息
* @returns {Promise<Array>} 轮播图列表
*/
async getBanners() {
const page = await this.mp.currentPage();
try {
const swiperItems = await page.$$('swiper-item');
if (!swiperItems || swiperItems.length === 0) {
return [];
}
const banners = [];
for (let i = 0; i < swiperItems.length; i++) {
try {
const image = await swiperItems[i].$('image');
if (image) {
const src = await image.attribute('src');
banners.push({ index: i, src });
}
} catch (e) {
banners.push({ index: i, src: null });
}
}
return banners;
} catch (e) {
return [];
}
}
/**
* 通过 TabBar 切换到搜索页
*/
async navigateToSearch() {
const { switchTab } = require('../helpers/automator');
await switchTab(this.mp, 1);
}
/**
* 下拉刷新
*/
async pullDownRefresh() {
const page = await this.mp.currentPage();
// 触发下拉刷新
await this.mp.callWxMethod('startPullDownRefresh', {});
await this.mp.waitFor(2000);
}
}
module.exports = HomePage;
@@ -0,0 +1,117 @@
/**
* MyCoursesPage - 我的课程页 Page Object
* 对应页面: pages/my-courses/my-courses
*/
class MyCoursesPage {
constructor(miniProgram) {
this.mp = miniProgram;
}
/**
* 等待我的课程页加载完成
*/
async waitForLoad() {
const { waitForPage } = require('../helpers/automator');
return waitForPage(this.mp, 'pages/my-courses/my-courses');
}
/**
* 获取预约列表
* @returns {Promise<Array>} 预约课程列表
*/
async getBookingList() {
const page = await this.mp.currentPage();
try {
const bookingCards = await page.$$('.booking-card');
return bookingCards || [];
} catch (e) {
console.warn('[MyCoursesPage] 获取预约列表异常:', e.message);
return [];
}
}
/**
* 获取预约数量
* @returns {Promise<number>}
*/
async getBookingCount() {
const list = await this.getBookingList();
return list.length;
}
/**
* 取消指定索引的预约
* @param {number} index - 预约索引(从0开始)
* @returns {Promise<boolean>}
*/
async cancelBooking(index = 0) {
const page = await this.mp.currentPage();
console.log(`[MyCoursesPage] 取消第 ${index} 个预约`);
try {
const bookingCards = await page.$$('.booking-card');
if (!bookingCards || !bookingCards[index]) {
console.warn('[MyCoursesPage] 未找到预约卡片');
return false;
}
// 点击取消按钮
const cancelBtn = await bookingCards[index].$('.cancel-btn');
if (cancelBtn) {
await cancelBtn.tap();
await this.mp.waitFor(500);
return true;
}
} catch (e) {
console.warn('[MyCoursesPage] 取消预约异常:', e.message);
}
return false;
}
/**
* 签到
* @param {string|number} courseId - 课程ID
* @returns {Promise<boolean>}
*/
async signIn(courseId) {
const page = await this.mp.currentPage();
console.log(`[MyCoursesPage] 签到课程: ${courseId}`);
try {
const signInBtn = await page.$('.sign-in-btn');
if (signInBtn) {
await signInBtn.tap();
await this.mp.waitFor(1500);
return true;
}
} catch (e) {
console.warn('[MyCoursesPage] 签到操作异常:', e.message);
}
return false;
}
/**
* 下拉刷新列表
*/
async pullDownRefresh() {
const page = await this.mp.currentPage();
try {
await this.mp.callWxMethod('startPullDownRefresh', {});
await this.mp.waitFor(2000);
} catch (e) {
console.warn('[MyCoursesPage] 下拉刷新异常:', e.message);
}
}
/**
* 通过 TabBar 切换到个人中心
*/
async navigateToProfile() {
const { switchTab } = require('../helpers/automator');
await switchTab(this.mp, 3);
}
}
module.exports = MyCoursesPage;
+122
View File
@@ -0,0 +1,122 @@
/**
* ProfilePage - 个人中心页 Page Object
* 对应页面: pages/profile/profile
*/
class ProfilePage {
constructor(miniProgram) {
this.mp = miniProgram;
}
/**
* 等待个人中心页加载完成
*/
async waitForLoad() {
const { waitForPage } = require('../helpers/automator');
return waitForPage(this.mp, 'pages/profile/profile');
}
/**
* 获取会员名称
* @returns {Promise<string>}
*/
async getMemberName() {
const page = await this.mp.currentPage();
try {
const nameEl = await page.$('.member-name');
if (nameEl) {
return await nameEl.text();
}
// 尝试其他可能的选择器
const nickEl = await page.$('.nickname');
if (nickEl) {
return await nickEl.text();
}
const userEl = await page.$('.user-name');
if (userEl) {
return await userEl.text();
}
} catch (e) {
console.warn('[ProfilePage] 获取会员名称异常:', e.message);
}
return '';
}
/**
* 获取个人中心所有信息
* @returns {Promise<Object>}
*/
async getProfileInfo() {
const page = await this.mp.currentPage();
const info = {
name: '',
phone: '',
email: ''
};
try {
info.name = await this.getMemberName();
const phoneEl = await page.$('.member-phone');
if (phoneEl) {
info.phone = await phoneEl.text();
}
const emailEl = await page.$('.member-email');
if (emailEl) {
info.email = await emailEl.text();
}
} catch (e) {
console.warn('[ProfilePage] 获取个人信息异常:', e.message);
}
return info;
}
/**
* 跳转到我的课程页
*/
async navigateToMyCourses() {
const { switchTab } = require('../helpers/automator');
await switchTab(this.mp, 2);
}
/**
* 跳转到首页
*/
async navigateToHome() {
const { switchTab } = require('../helpers/automator');
await switchTab(this.mp, 0);
}
/**
* 获取菜单项列表
* @returns {Promise<Array>}
*/
async getMenuItems() {
const page = await this.mp.currentPage();
try {
const menuItems = await page.$$('.menu-item');
return menuItems || [];
} catch (e) {
console.warn('[ProfilePage] 获取菜单项异常:', e.message);
return [];
}
}
/**
* 下拉刷新
*/
async pullDownRefresh() {
const page = await this.mp.currentPage();
try {
await this.mp.callWxMethod('startPullDownRefresh', {});
await this.mp.waitFor(2000);
} catch (e) {
console.warn('[ProfilePage] 下拉刷新异常:', e.message);
}
}
}
module.exports = ProfilePage;
+140
View File
@@ -0,0 +1,140 @@
/**
* SearchPage - 团课搜索页 Page Object
* 对应页面: pages/search/search
*/
class SearchPage {
constructor(miniProgram) {
this.mp = miniProgram;
}
/**
* 等待搜索页加载完成
*/
async waitForLoad() {
const { waitForPage } = require('../helpers/automator');
return waitForPage(this.mp, 'pages/search/search');
}
/**
* 输入搜索关键词
* @param {string} keyword - 搜索关键词
*/
async searchCourses(keyword) {
const page = await this.mp.currentPage();
console.log(`[SearchPage] 搜索课程: "${keyword}"`);
try {
// 查找搜索输入框并输入
const searchInput = await page.$('input');
if (searchInput) {
await searchInput.input(keyword);
}
// 查找搜索按钮并点击
const searchBtn = await page.$('.search-btn');
if (searchBtn) {
await searchBtn.tap();
}
} catch (e) {
console.warn('[SearchPage] 搜索操作异常:', e.message);
}
await this.mp.waitFor(1500);
}
/**
* 选择日期范围
* @param {string} start - 开始日期 YYYY-MM-DD
* @param {string} end - 结束日期 YYYY-MM-DD
*/
async selectDateRange(start, end) {
console.log(`[SearchPage] 选择日期范围: ${start} ~ ${end}`);
// 日期选择通常由 picker 组件实现,通过触发 change 事件模拟
const page = await this.mp.currentPage();
try {
const pickerElements = await page.$$('picker');
if (pickerElements && pickerElements.length >= 2) {
// 假设第一个是开始日期,第二个是结束日期
await pickerElements[0].tap();
await this.mp.waitFor(500);
await pickerElements[1].tap();
await this.mp.waitFor(500);
}
} catch (e) {
console.warn('[SearchPage] 日期选择异常:', e.message);
}
}
/**
* 选择时间段
* @param {string} value - 时间段值(如 'morning', 'afternoon', 'evening'
*/
async selectPeriod(value) {
console.log(`[SearchPage] 选择时间段: ${value}`);
const page = await this.mp.currentPage();
try {
const periodBtn = await page.$(`.period-${value}`);
if (periodBtn) {
await periodBtn.tap();
await this.mp.waitFor(1000);
}
} catch (e) {
console.warn('[SearchPage] 时间段选择异常:', e.message);
}
}
/**
* 获取课程列表
* @returns {Promise<Array>} 课程列表
*/
async getCourseList() {
const page = await this.mp.currentPage();
try {
const courseCards = await page.$$('.course-card');
if (!courseCards || courseCards.length === 0) {
return [];
}
return courseCards;
} catch (e) {
return [];
}
}
/**
* 获取课程列表中的课程数量
* @returns {Promise<number>}
*/
async getCourseCount() {
const list = await this.getCourseList();
return list.length;
}
/**
* 点击指定索引的课程卡片
* @param {number} index - 课程索引(从0开始)
*/
async clickCourse(index = 0) {
const page = await this.mp.currentPage();
console.log(`[SearchPage] 点击第 ${index} 个课程`);
try {
const courseCards = await page.$$('.course-card');
if (courseCards && courseCards[index]) {
await courseCards[index].tap();
await this.mp.waitFor(1500);
}
} catch (e) {
console.warn('[SearchPage] 点击课程异常:', e.message);
}
}
/**
* 通过 TabBar 切换到首页
*/
async navigateToHome() {
const { switchTab } = require('../helpers/automator');
await switchTab(this.mp, 0);
}
}
module.exports = SearchPage;