新增e2e测试脚本,修复部分问题
This commit was merged in pull request #51.
This commit is contained in:
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
Reference in New Issue
Block a user