Files
gym-manage/gym-manage-coach-uniapp/e2e/pages/CourseDetailPage.js
T

200 lines
5.6 KiB
JavaScript

const { sleep } = require('../helpers/automator');
class CourseDetailPage {
/**
* @param {object} miniProgram - miniprogram-automator 实例
*/
constructor(miniProgram) {
this.mp = miniProgram;
}
/**
* 等待课程详情页加载完成
*/
async waitForLoad() {
const page = await this.mp.currentPage();
await page.waitFor('.detail-page', { timeout: 10000 });
await sleep(1500); // 等待异步数据加载
return page;
}
/**
* 获取课程基本信息
* @returns {Promise<{courseName: string, status: string, time: string, location: string, memberCount: string}>}
*/
async getCourseInfo() {
const page = await this.mp.currentPage();
const info = {};
try {
// 课程名
const titleEl = await page.$('.detail-title');
info.courseName = titleEl ? (await titleEl.text()).trim() : '';
// 状态标签
const statusEl = await page.$('.cover-status text');
info.status = statusEl ? (await statusEl.text()).trim() : '';
// 信息项
const infoItems = await page.$$('.info-item');
for (const item of infoItems) {
try {
const labelEl = await item.$('.info-label');
const valueEl = await item.$('.info-value');
if (labelEl && valueEl) {
const label = (await labelEl.text()).trim();
const value = (await valueEl.text()).trim();
if (label === '时间') info.time = value;
if (label === '地点') info.location = value;
if (label === '人数') info.memberCount = value;
}
} catch (e) {
// 跳过
}
}
} catch (e) {
// 忽略
}
return info;
}
/**
* 点击开课按钮
* 仅当 course.status == 0 (待开课) 时可用
*/
async startCourse() {
const page = await this.mp.currentPage();
const startBtn = await page.$('.start-btn');
if (!startBtn) {
throw new Error('未找到开课按钮(课程可能不是"待开课"状态)');
}
// 检查按钮是否被禁用
const isDisabled = await this._isButtonDisabled(startBtn);
if (isDisabled) {
throw new Error('开课按钮被禁用(尚未到开课时间)');
}
await startBtn.tap();
await sleep(3000); // 等待开课请求完成
}
/**
* 点击结课按钮
* 仅当 course.status == 3 || 7 (进行中) 时可用
*/
async endCourse() {
const page = await this.mp.currentPage();
const endBtn = await page.$('.end-btn');
if (!endBtn) {
throw new Error('未找到结课按钮(课程可能不是"进行中"状态)');
}
const isDisabled = await this._isButtonDisabled(endBtn);
if (isDisabled) {
throw new Error('结课按钮被禁用(尚未到结课时间)');
}
await endBtn.tap();
await sleep(3000); // 等待结课请求完成
}
/**
* 获取学员列表
* 注意:当前课程详情页设计中没有独立的学员列表区域,
* 学员人数信息在 info-card 中展示。
* @returns {Promise<{count: number, max: number}>}
*/
async getStudentList() {
const info = await this.getCourseInfo();
if (info.memberCount) {
const match = info.memberCount.match(/(\d+)\s*\/\s*(\d+)/);
if (match) {
return {
count: parseInt(match[1], 10),
max: parseInt(match[2], 10)
};
}
}
return { count: 0, max: 0 };
}
/**
* 生成签到二维码
* 注意:当前课程详情页没有直接的生成二维码按钮。
* 二维码通常通过后端 API 生成,MiniTest 中可通过 evaluate 调用 API。
*/
async generateQRCode() {
const page = await this.mp.currentPage();
// 通过 evaluate 在小程序环境中生成二维码
// 实际二维码生成逻辑取决于后端 API
try {
const qrData = await this.mp.evaluate(() => {
// 尝试获取当前课程的签到信息
const pages = getCurrentPages();
const currentPage = pages[pages.length - 1];
return {
courseId: currentPage.courseId || '',
timestamp: Date.now()
};
});
return qrData;
} catch (e) {
console.warn('[CourseDetailPage] 生成二维码失败:', e.message);
return null;
}
}
/**
* 获取操作按钮状态
*/
async getActionButtonStatus() {
const page = await this.mp.currentPage();
try {
const startBtn = await page.$('.start-btn');
if (startBtn) {
const text = (await startBtn.text()).trim();
const isDisabled = await this._isButtonDisabled(startBtn);
return { type: 'start', text, disabled: isDisabled };
}
const endBtn = await page.$('.end-btn');
if (endBtn) {
const text = (await endBtn.text()).trim();
const isDisabled = await this._isButtonDisabled(endBtn);
return { type: 'end', text, disabled: isDisabled };
}
const disabledBtn = await page.$('.disabled-btn');
if (disabledBtn) {
const text = (await disabledBtn.text()).trim();
return { type: 'disabled', text, disabled: true };
}
} catch (e) {
// 忽略
}
return null;
}
/**
* 内部方法:检查按钮是否被禁用
*/
async _isButtonDisabled(btnElement) {
try {
const disabled = await btnElement.attribute('disabled');
if (disabled === 'true' || disabled === true || disabled === '') {
return true;
}
// 也检查 CSS class
const className = await btnElement.attribute('class');
return (className || '').includes('disabled');
} catch (e) {
return false;
}
}
}
module.exports = CourseDetailPage;