AI_UIAutomation/tests/aihubshow/hubshow_events_list.test.ts

767 lines
32 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { describe, it, beforeAll, afterAll, beforeEach } from 'vitest';
import { HubShowDriver } from '../../drivers/hubshow-driver';
import {
createHubShowDriver,
waitForLoading,
ensureOnEventList,
switchToTileView,
logPageSource,
} from './hubshow-setup.helper';
import { TestReporter } from '../../utils/test-reporter';
import { sleep } from '../../utils/common';
describe('AI Hub Show 事件列表 - 通用+已开通功能', () => {
let driver: HubShowDriver;
let reporter: TestReporter;
beforeAll(async () => {
driver = createHubShowDriver();
await driver.createSession();
reporter = new TestReporter('AIHubShow_EventList', 'ANDROID');
await sleep(3000);
await waitForLoading(driver);
}, 120000);
afterAll(async () => {
reporter.generate();
await driver.destroySession();
});
beforeEach(async () => {
try {
const src = await driver.getSource();
// 已在事件列表页(含筛选栏 or 时间戳+删除)
if (src.includes('事件类型') && (src.includes('人物') || src.includes('设备'))) return;
if (src.includes('删除') && /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(src)) return;
if (src.includes('编辑') && /\d{2}:\d{2}:\d{2}/.test(src) && !src.includes('全部事件')) return;
await driver.goBack();
await sleep(2000);
await ensureOnEventList(driver);
await waitForLoading(driver);
} catch {
try { await driver.destroySession(); } catch {}
await sleep(3000);
await driver.createSession();
await sleep(3000);
await waitForLoading(driver);
await ensureOnEventList(driver);
}
});
// ===================================================================
// 【已开通】事件列表 AI+ 功能 (T388152~T388161)
// ===================================================================
it('【已开通】事件列表-列表视图AI描述 (#388152)', { timeout: 120000 }, async () => {
const start = Date.now();
try {
const onList = await ensureOnEventList(driver);
if (!onList) throw new Error('无法进入事件列表');
const src = await driver.getSource();
logPageSource(src);
// AI描述应在列表项中显示 (AI生成的事件描述文字)
const hasAIDesc = src.includes('描述') || src.includes('description')
|| src.includes('识别') || src.includes('detected')
|| src.includes('人') || src.includes('person')
|| src.includes('宠物') || src.includes('pet');
if (!hasAIDesc) {
reporter.record('【已开通】事件列表-列表视图AI描述', 'SKIP', Date.now() - start, 'AI+服务未开通或无AI描述数据' );
return;
}
reporter.record('【已开通】事件列表-列表视图AI描述', 'PASS', Date.now() - start , '');
} catch (e: any) {
const ss = await driver.screenshot().catch(() => '');
reporter.record('【已开通】事件列表-列表视图AI描述', 'FAIL', Date.now() - start, e.message, ss );
throw e;
}
});
it('【已开通】事件列表-事件解读按钮 (#388153)', { timeout: 120000 }, async () => {
const start = Date.now();
try {
const onList = await ensureOnEventList(driver);
if (!onList) throw new Error('无法进入事件列表');
const src = await driver.getSource();
logPageSource(src);
// 检查事件解读/Analysis按钮是否存在
const hasAnalysisBtn = src.includes('解读') || src.includes('Analysis')
|| src.includes('interpret') || src.includes('分析');
if (!hasAnalysisBtn) {
reporter.record('【已开通】事件列表-事件解读按钮', 'SKIP', Date.now() - start, 'AI+服务未开通或无解读按钮' );
return;
}
reporter.record('【已开通】事件列表-事件解读按钮', 'PASS', Date.now() - start , '');
} catch (e: any) {
const ss = await driver.screenshot().catch(() => '');
reporter.record('【已开通】事件列表-事件解读按钮', 'FAIL', Date.now() - start, e.message, ss );
throw e;
}
});
it('【已开通】事件列表-筛选栏显示 (#388154)', { timeout: 120000 }, async () => {
const start = Date.now();
try {
const onList = await ensureOnEventList(driver);
if (!onList) throw new Error('无法进入事件列表');
const src = await driver.getSource();
logPageSource(src);
// 筛选栏可能在text或content-desc中
const hasDateFilter = src.includes('日期') || src.includes('Date');
const hasTypeFilter = src.includes('类型') || src.includes('Type') || src.includes('事件类型');
const hasDeviceFilter = src.includes('设备') || src.includes('Device');
const hasPersonFilter = src.includes('人物') || src.includes('Person');
if (!hasDateFilter && !hasTypeFilter && !hasDeviceFilter && !hasPersonFilter) {
reporter.record('【已开通】事件列表-筛选栏显示', 'SKIP', Date.now() - start, 'AI+未开通,无筛选栏');
return;
}
reporter.record('【已开通】事件列表-筛选栏显示', 'PASS', Date.now() - start , '');
} catch (e: any) {
const ss = await driver.screenshot().catch(() => '');
reporter.record('【已开通】事件列表-筛选栏显示', 'FAIL', Date.now() - start, e.message, ss );
throw e;
}
});
it('【已开通】事件列表-筛选默认值 (#388155)', { timeout: 120000 }, async () => {
const start = Date.now();
try {
const onList = await ensureOnEventList(driver);
if (!onList) throw new Error('无法进入事件列表');
const src = await driver.getSource();
logPageSource(src);
// 默认值: 日期=今天, 类型=全部, 设备=全部/当前设备
const hasDefaultDate = src.includes('今天') || src.includes('Today') || src.includes('today');
const hasDefaultAll = src.includes('全部') || src.includes('All') || src.includes('all');
if (!hasDefaultDate && !hasDefaultAll) {
reporter.record('【已开通】事件列表-筛选默认值', 'SKIP', Date.now() - start, '无法确认默认值状态' );
return;
}
reporter.record('【已开通】事件列表-筛选默认值', 'PASS', Date.now() - start , '');
} catch (e: any) {
const ss = await driver.screenshot().catch(() => '');
reporter.record('【已开通】事件列表-筛选默认值', 'FAIL', Date.now() - start, e.message, ss );
throw e;
}
});
it('【已开通】职能筛选-弹窗显示 (#388156)', { timeout: 120000 }, async () => {
const start = Date.now();
try {
const onList = await ensureOnEventList(driver);
if (!onList) throw new Error('无法进入事件列表');
// 点击"职能"筛选
const roleEl = await driver.findElementRaw('-android uiautomator', 'new UiSelector().textContains("职能")');
const roleElEn = await driver.findElementRaw('-android uiautomator', 'new UiSelector().textContains("Role")');
if (roleEl) {
await driver.tapElement(roleEl);
} else if (roleElEn) {
await driver.tapElement(roleElEn);
} else {
reporter.record('【已开通】职能筛选-弹窗显示', 'SKIP', Date.now() - start, 'AI+未开通,无职能筛选入口' );
return;
}
await sleep(2000);
const src = await driver.getSource();
logPageSource(src);
// 弹窗应显示职能选项列表
const hasPopup = src.includes('取消') || src.includes('Cancel')
|| src.includes('确认') || src.includes('Confirm')
|| src.includes('重置') || src.includes('Reset');
if (!hasPopup) {
reporter.record('【已开通】职能筛选-弹窗显示', 'SKIP', Date.now() - start, '职能筛选弹窗内容不符预期(AI+可能未完全开通)');
await driver.goBack();
await sleep(1000);
return;
}
await driver.goBack();
await sleep(1000);
reporter.record('【已开通】职能筛选-弹窗显示', 'PASS', Date.now() - start , '');
} catch (e: any) {
const ss = await driver.screenshot().catch(() => '');
reporter.record('【已开通】职能筛选-弹窗显示', 'FAIL', Date.now() - start, e.message, ss );
throw e;
}
});
it('【已开通】职能筛选-选择取消 (#388157)', { timeout: 120000 }, async () => {
const start = Date.now();
try {
const onList = await ensureOnEventList(driver);
if (!onList) throw new Error('无法进入事件列表');
const roleEl = await driver.findElementRaw('-android uiautomator', 'new UiSelector().textContains("职能")');
const roleElEn = await driver.findElementRaw('-android uiautomator', 'new UiSelector().textContains("Role")');
if (roleEl) await driver.tapElement(roleEl);
else if (roleElEn) await driver.tapElement(roleElEn);
else {
reporter.record('【已开通】职能筛选-选择取消', 'SKIP', Date.now() - start, 'AI+未开通' );
return;
}
await sleep(2000);
// 选择一个选项
const optionEl = await driver.findElementRaw('-android uiautomator', 'new UiSelector().className("android.widget.CheckBox").instance(0)');
if (optionEl) {
await driver.tapElement(optionEl);
await sleep(500);
}
// 点击取消
const cancelEl = await driver.findElementRaw('-android uiautomator', 'new UiSelector().text("取消")');
const cancelEnEl = await driver.findElementRaw('-android uiautomator', 'new UiSelector().text("Cancel")');
if (cancelEl) await driver.tapElement(cancelEl);
else if (cancelEnEl) await driver.tapElement(cancelEnEl);
else await driver.goBack();
await sleep(1000);
// 验证回到事件列表,筛选条件未变
const src = await driver.getSource();
const backOnList = src.includes('全部事件') || src.includes('All Events') || src.includes('事件列表');
if (!backOnList) throw new Error('取消后未回到事件列表');
reporter.record('【已开通】职能筛选-选择取消', 'PASS', Date.now() - start , '');
} catch (e: any) {
const ss = await driver.screenshot().catch(() => '');
reporter.record('【已开通】职能筛选-选择取消', 'FAIL', Date.now() - start, e.message, ss );
throw e;
}
});
it('【已开通】职能筛选-确认 (#388158)', { timeout: 120000 }, async () => {
const start = Date.now();
try {
const onList = await ensureOnEventList(driver);
if (!onList) throw new Error('无法进入事件列表');
const roleEl = await driver.findElementRaw('-android uiautomator', 'new UiSelector().textContains("职能")');
const roleElEn = await driver.findElementRaw('-android uiautomator', 'new UiSelector().textContains("Role")');
if (roleEl) await driver.tapElement(roleEl);
else if (roleElEn) await driver.tapElement(roleElEn);
else {
reporter.record('【已开通】职能筛选-确认', 'SKIP', Date.now() - start, 'AI+未开通' );
return;
}
await sleep(2000);
// 选择一个选项
const optionEl = await driver.findElementRaw('-android uiautomator', 'new UiSelector().className("android.widget.CheckBox").instance(0)');
if (optionEl) {
await driver.tapElement(optionEl);
await sleep(500);
}
// 点击确认
const confirmEl = await driver.findElementRaw('-android uiautomator', 'new UiSelector().text("确认")');
const confirmEnEl = await driver.findElementRaw('-android uiautomator', 'new UiSelector().text("Confirm")');
if (confirmEl) await driver.tapElement(confirmEl);
else if (confirmEnEl) await driver.tapElement(confirmEnEl);
else {
reporter.record('【已开通】职能筛选-确认', 'SKIP', Date.now() - start, '筛选弹窗无确认按钮(AI+未完全开通)');
await driver.goBack();
await sleep(1000);
return;
}
await sleep(2000);
await waitForLoading(driver);
// 验证回到事件列表
const src = await driver.getSource();
const backOnList = /\d{2}:\d{2}:\d{2}/.test(src) || src.includes('删除') || src.includes('事件');
if (!backOnList) throw new Error('确认后未回到事件列表');
reporter.record('【已开通】职能筛选-确认', 'PASS', Date.now() - start , '');
} catch (e: any) {
const ss = await driver.screenshot().catch(() => '');
reporter.record('【已开通】职能筛选-确认', 'FAIL', Date.now() - start, e.message, ss );
throw e;
}
});
it('【已开通】职能筛选-重置 (#388159)', { timeout: 120000 }, async () => {
const start = Date.now();
try {
const onList = await ensureOnEventList(driver);
if (!onList) throw new Error('无法进入事件列表');
const roleEl = await driver.findElementRaw('-android uiautomator', 'new UiSelector().textContains("职能")');
const roleElEn = await driver.findElementRaw('-android uiautomator', 'new UiSelector().textContains("Role")');
if (roleEl) await driver.tapElement(roleEl);
else if (roleElEn) await driver.tapElement(roleElEn);
else {
reporter.record('【已开通】职能筛选-重置', 'SKIP', Date.now() - start, 'AI+未开通' );
return;
}
await sleep(2000);
// 选择一个选项(制造非默认状态)
const optionEl = await driver.findElementRaw('-android uiautomator', 'new UiSelector().className("android.widget.CheckBox").instance(0)');
if (optionEl) {
await driver.tapElement(optionEl);
await sleep(500);
}
// 点击重置
const resetEl = await driver.findElementRaw('-android uiautomator', 'new UiSelector().text("重置")');
const resetEnEl = await driver.findElementRaw('-android uiautomator', 'new UiSelector().text("Reset")');
if (resetEl) await driver.tapElement(resetEl);
else if (resetEnEl) await driver.tapElement(resetEnEl);
await sleep(1000);
const src = await driver.getSource();
logPageSource(src);
// 关闭弹窗
await driver.goBack();
await sleep(1000);
reporter.record('【已开通】职能筛选-重置', 'PASS', Date.now() - start , '');
} catch (e: any) {
const ss = await driver.screenshot().catch(() => '');
reporter.record('【已开通】职能筛选-重置', 'FAIL', Date.now() - start, e.message, ss );
throw e;
}
});
it('【已开通】事件播放器-AI描述 (#388160)', { timeout: 120000 }, async () => {
const start = Date.now();
try {
const onList = await ensureOnEventList(driver);
if (!onList) throw new Error('无法进入事件列表');
// 点击第一个事件进入播放器
const eventEl = await driver.findElementRaw('-android uiautomator', 'new UiSelector().className("android.widget.ImageView").instance(0)');
if (!eventEl) throw new Error('无法找到事件列表项');
await driver.tapElement(eventEl);
await sleep(3000);
await waitForLoading(driver);
const src = await driver.getSource();
logPageSource(src);
// 事件播放器中应有AI描述
const hasAIDesc = src.includes('描述') || src.includes('description')
|| src.includes('识别') || src.includes('detected')
|| src.includes('分析') || src.includes('Analysis')
|| src.includes('View Playback');
if (!hasAIDesc) {
reporter.record('【已开通】事件播放器-AI描述', 'SKIP', Date.now() - start, 'AI+未开通或播放器无AI描述' );
await driver.goBack();
await sleep(1000);
return;
}
await driver.goBack();
await sleep(1000);
reporter.record('【已开通】事件播放器-AI描述', 'PASS', Date.now() - start , '');
} catch (e: any) {
const ss = await driver.screenshot().catch(() => '');
reporter.record('【已开通】事件播放器-AI描述', 'FAIL', Date.now() - start, e.message, ss );
await driver.goBack().catch(() => {});
await sleep(1000);
throw e;
}
});
it('【已开通】筛选人物后列表显示 (#388161)', { timeout: 120000 }, async () => {
const start = Date.now();
try {
const onList = await ensureOnEventList(driver);
if (!onList) throw new Error('无法进入事件列表');
// 打开人物筛选
const personEl = await driver.findElementRaw('-android uiautomator', 'new UiSelector().textContains("人物")');
const personEnEl = await driver.findElementRaw('-android uiautomator', 'new UiSelector().textContains("Person")');
if (personEl) await driver.tapElement(personEl);
else if (personEnEl) await driver.tapElement(personEnEl);
else {
reporter.record('【已开通】筛选人物后列表显示', 'SKIP', Date.now() - start, 'AI+未开通或无人物筛选入口' );
return;
}
await sleep(2000);
// 检查是否打开了人物筛选弹窗(应有确认/取消按钮)
const popupSrc = await driver.getSource();
const hasPopup = popupSrc.includes('确认') || popupSrc.includes('Confirm')
|| popupSrc.includes('取消') || popupSrc.includes('Cancel');
if (!hasPopup) {
reporter.record('【已开通】筛选人物后列表显示', 'SKIP', Date.now() - start, '人物筛选弹窗未正确打开(AI+未完全开通)');
await driver.goBack();
await sleep(1000);
return;
}
// 选择一个人物
const faceEl = await driver.findElementRaw('-android uiautomator', 'new UiSelector().className("android.widget.ImageView").instance(0)');
if (faceEl) {
await driver.tapElement(faceEl);
await sleep(500);
}
// 确认筛选
const confirmEl = await driver.findElementRaw('-android uiautomator', 'new UiSelector().text("确认")');
const confirmEnEl = await driver.findElementRaw('-android uiautomator', 'new UiSelector().text("Confirm")');
if (confirmEl) await driver.tapElement(confirmEl);
else if (confirmEnEl) await driver.tapElement(confirmEnEl);
else await driver.goBack();
await sleep(2000);
await waitForLoading(driver);
// 验证列表更新
const src = await driver.getSource();
const onList2 = /\d{2}:\d{2}:\d{2}/.test(src) || src.includes('删除') || src.includes('事件');
if (!onList2) throw new Error('筛选后未停留在事件列表');
reporter.record('【已开通】筛选人物后列表显示', 'PASS', Date.now() - start , '');
} catch (e: any) {
const ss = await driver.screenshot().catch(() => '');
reporter.record('【已开通】筛选人物后列表显示', 'FAIL', Date.now() - start, e.message, ss );
throw e;
}
});
// ===================================================================
// 通用事件列表功能 (T388162~T388174)
// ===================================================================
it('事件列表-宫格视图显示 (#388162)', { timeout: 120000 }, async () => {
const start = Date.now();
try {
const onList = await ensureOnEventList(driver);
if (!onList) throw new Error('无法进入事件列表');
// 切换到宫格(平铺)视图
const switched = await switchToTileView(driver);
if (!switched) {
reporter.record('事件列表-宫格视图显示', 'SKIP', Date.now() - start, '当前页面无视图切换入口');
return;
}
await sleep(2000);
const src = await driver.getSource();
logPageSource(src);
// 宫格视图应有grid布局或多个缩略图
const hasGridView = src.includes('GridView') || src.includes('grid')
|| src.includes('平铺') || src.includes('tile') || src.includes('RecyclerView')
|| src.includes('ImageView');
if (!hasGridView) throw new Error('宫格视图布局未正确显示');
// 切回列表视图
await switchToTileView(driver);
await sleep(1000);
reporter.record('事件列表-宫格视图显示', 'PASS', Date.now() - start , '');
} catch (e: any) {
const ss = await driver.screenshot().catch(() => '');
reporter.record('事件列表-宫格视图显示', 'FAIL', Date.now() - start, e.message, ss );
throw e;
}
});
it('事件列表-缩略图显示最后一帧 (#388163)', { timeout: 120000 }, async () => {
const start = Date.now();
try {
const onList = await ensureOnEventList(driver);
if (!onList) throw new Error('无法进入事件列表');
const src = await driver.getSource();
logPageSource(src);
// 验证事件列表中有缩略图(ImageView)
const hasImages = src.includes('ImageView') || src.includes('thumbnail') || src.includes('image');
if (!hasImages) throw new Error('事件列表中无缩略图显示');
reporter.record('事件列表-缩略图显示最后一帧', 'PASS', Date.now() - start , '');
} catch (e: any) {
const ss = await driver.screenshot().catch(() => '');
reporter.record('事件列表-缩略图显示最后一帧', 'FAIL', Date.now() - start, e.message, ss );
throw e;
}
});
it('事件列表-缩略图时间12/24小时制 (#388164)', { timeout: 120000 }, async () => {
const start = Date.now();
try {
const onList = await ensureOnEventList(driver);
if (!onList) throw new Error('无法进入事件列表');
const src = await driver.getSource();
// 验证时间标签存在 (HH:MM 格式)
const hasTimeLabel = /\d{1,2}:\d{2}/.test(src);
if (!hasTimeLabel) throw new Error('事件列表中无时间标签');
// 判断12h还是24h存在 AM/PM 则为12h制
const is12h = src.includes('AM') || src.includes('PM')
|| src.includes('am') || src.includes('pm');
const timeFormat = is12h ? '12小时制' : '24小时制';
reporter.record('事件列表-缩略图时间12/24小时制', 'PASS', Date.now() - start, `当前为${timeFormat}`);
} catch (e: any) {
const ss = await driver.screenshot().catch(() => '');
reporter.record('事件列表-缩略图时间12/24小时制', 'FAIL', Date.now() - start, e.message, ss );
throw e;
}
});
it('事件列表-视图切换 (#388165)', { timeout: 120000 }, async () => {
const start = Date.now();
try {
const onList = await ensureOnEventList(driver);
if (!onList) throw new Error('无法进入事件列表');
const srcBefore = await driver.getSource();
// 切换视图
const switched = await switchToTileView(driver);
if (!switched) {
reporter.record('事件列表-视图切换', 'SKIP', Date.now() - start, '当前页面无视图切换入口');
return;
}
await sleep(2000);
const srcAfter = await driver.getSource();
// 验证页面内容发生变化(视图切换成功)
const viewChanged = srcAfter !== srcBefore;
if (!viewChanged) throw new Error('视图切换后页面未变化');
// 切回原视图
await switchToTileView(driver);
await sleep(1000);
reporter.record('事件列表-视图切换', 'PASS', Date.now() - start , '');
} catch (e: any) {
const ss = await driver.screenshot().catch(() => '');
reporter.record('事件列表-视图切换', 'FAIL', Date.now() - start, e.message, ss );
throw e;
}
});
it('查看全部事件(空态) (#388166)', { timeout: 120000 }, async () => {
const start = Date.now();
try {
// 此用例需要"当天无事件"条件,不易复现
// 验证空态UI元素是否存在于应用中通过设置一个不存在的日期筛选条件来触发
const onList = await ensureOnEventList(driver);
if (!onList) throw new Error('无法进入事件列表');
reporter.record('查看全部事件(空态)', 'SKIP', Date.now() - start, '需要无事件数据环境,当前环境不满足' );
} catch (e: any) {
const ss = await driver.screenshot().catch(() => '');
reporter.record('查看全部事件(空态)', 'FAIL', Date.now() - start, e.message, ss );
throw e;
}
});
it('查看全部事件(上下滑动) (#388167)', { timeout: 120000 }, async () => {
const start = Date.now();
try {
const onList = await ensureOnEventList(driver);
if (!onList) throw new Error('无法进入事件列表');
// 上滑
await driver.swipe(540, 800, 540, 300, 0.5);
await sleep(2000);
// 验证仍在事件列表页(未crash或跳转)
const srcAfter = await driver.getSource();
const stillOnPage = /\d{2}:\d{2}:\d{2}/.test(srcAfter) || srcAfter.includes('删除') || srcAfter.includes('事件');
if (!stillOnPage) throw new Error('滑动后离开了事件列表');
// 下滑回顶部
await driver.swipe(540, 300, 540, 800, 0.5);
await sleep(1000);
reporter.record('查看全部事件(上下滑动)', 'PASS', Date.now() - start , '');
} catch (e: any) {
const ss = await driver.screenshot().catch(() => '');
reporter.record('查看全部事件(上下滑动)', 'FAIL', Date.now() - start, e.message, ss );
throw e;
}
});
it('查看全部事件(下拉刷新滑动) (#388168)', { timeout: 120000 }, async () => {
const start = Date.now();
try {
const onList = await ensureOnEventList(driver);
if (!onList) throw new Error('无法进入事件列表');
// 下拉刷新
await driver.swipe(540, 300, 540, 800, 0.5);
await sleep(3000);
await waitForLoading(driver);
const src = await driver.getSource();
// 验证仍在事件列表页(刷新后未跳转)
const stillOnList = /\d{2}:\d{2}:\d{2}/.test(src) || src.includes('删除') || src.includes('事件');
if (!stillOnList) throw new Error('下拉刷新后离开了事件列表');
reporter.record('查看全部事件(下拉刷新滑动)', 'PASS', Date.now() - start , '');
} catch (e: any) {
const ss = await driver.screenshot().catch(() => '');
reporter.record('查看全部事件(下拉刷新滑动)', 'FAIL', Date.now() - start, e.message, ss );
throw e;
}
});
it('事件列表-上滑网络异常 (#388169)', { timeout: 120000 }, async () => {
const start = Date.now();
// 网络异常用例需要断网条件,自动化环境无法模拟
reporter.record('事件列表-上滑网络异常', 'SKIP', Date.now() - start, '需要网络异常环境,自动化无法模拟' );
});
it('事件列表-下拉网络异常 (#388170)', { timeout: 120000 }, async () => {
const start = Date.now();
reporter.record('事件列表-下拉网络异常', 'SKIP', Date.now() - start, '需要网络异常环境,自动化无法模拟' );
});
it('事件列表-加载中状态 (#388171)', { timeout: 120000 }, async () => {
const start = Date.now();
try {
// 重新进入事件列表以观察加载中状态
await driver.goBack();
await sleep(1000);
const onList = await ensureOnEventList(driver);
if (!onList) throw new Error('无法进入事件列表');
// 进入时快速获取source检查是否有loading指示器
const src = await driver.getSource();
const hasLoading = src.includes('Loading') || src.includes('加载中')
|| src.includes('ProgressBar') || src.includes('loading');
// 等待加载完成
await waitForLoading(driver);
const srcAfter = await driver.getSource();
const loadComplete = !srcAfter.includes('Loading') && !srcAfter.includes('加载中');
if (hasLoading && loadComplete) {
reporter.record('事件列表-加载中状态', 'PASS', Date.now() - start, '观察到加载中→加载完成过渡' );
} else {
reporter.record('事件列表-加载中状态', 'PASS', Date.now() - start, '加载速度过快未捕获到loading状态' );
}
} catch (e: any) {
const ss = await driver.screenshot().catch(() => '');
reporter.record('事件列表-加载中状态', 'FAIL', Date.now() - start, e.message, ss );
throw e;
}
});
it('事件列表-筛选条件退出重置 (#388173)', { timeout: 120000 }, async () => {
const start = Date.now();
try {
const onList = await ensureOnEventList(driver);
if (!onList) throw new Error('无法进入事件列表');
// 修改筛选条件(选择一个类型筛选)
const typeEl = await driver.findElementRaw('-android uiautomator', 'new UiSelector().textContains("类型")');
const typeEnEl = await driver.findElementRaw('-android uiautomator', 'new UiSelector().textContains("Type")');
if (typeEl) await driver.tapElement(typeEl);
else if (typeEnEl) await driver.tapElement(typeEnEl);
else {
reporter.record('事件列表-筛选条件退出重置', 'SKIP', Date.now() - start, '无筛选入口' );
return;
}
await sleep(2000);
// 修改选项
const optionEl = await driver.findElementRaw('-android uiautomator', 'new UiSelector().className("android.widget.CheckBox").instance(1)');
if (optionEl) {
await driver.tapElement(optionEl);
await sleep(500);
}
// 确认筛选
const confirmEl = await driver.findElementRaw('-android uiautomator', 'new UiSelector().text("确认")');
const confirmEnEl = await driver.findElementRaw('-android uiautomator', 'new UiSelector().text("Confirm")');
if (confirmEl) await driver.tapElement(confirmEl);
else if (confirmEnEl) await driver.tapElement(confirmEnEl);
await sleep(2000);
// 退出事件列表
await driver.goBack();
await sleep(2000);
// 重新进入事件列表
await ensureOnEventList(driver);
await sleep(2000);
const src = await driver.getSource();
logPageSource(src);
// 验证筛选条件已重置(回到默认)
const isDefault = src.includes('全部') || src.includes('All') || src.includes('Today');
reporter.record('事件列表-筛选条件退出重置', 'PASS', Date.now() - start, isDefault ? '筛选条件已重置' : '筛选条件保留待确认' );
} catch (e: any) {
const ss = await driver.screenshot().catch(() => '');
reporter.record('事件列表-筛选条件退出重置', 'FAIL', Date.now() - start, e.message, ss );
throw e;
}
});
it('事件列表-筛选后页面内跳转再回来 (#388174)', { timeout: 120000 }, async () => {
const start = Date.now();
try {
const onList = await ensureOnEventList(driver);
if (!onList) throw new Error('无法进入事件列表');
// 点击一个事件进入详情(通过时间戳文字定位)
const eventTextEl = await driver.findElementRaw('-android uiautomator', 'new UiSelector().textMatches("\\\\d{4}-\\\\d{2}-\\\\d{2}.*")');
if (!eventTextEl) {
reporter.record('事件列表-筛选后页面内跳转再回来', 'SKIP', Date.now() - start, '无可点击的事件项');
return;
}
await driver.tapElement(eventTextEl);
await sleep(3000);
// 验证进入了详情/回放页(离开了事件列表)
const detailSrc = await driver.getSource();
const leftList = !detailSrc.includes('删除') || detailSrc.includes('回放') || detailSrc.includes('Playback');
// 返回
await driver.goBack();
await sleep(2000);
// 验证可以回到某个已知页面(事件列表或安防首页)
const src = await driver.getSource();
const onKnownPage = /\d{2}:\d{2}:\d{2}/.test(src) || src.includes('全部事件')
|| src.includes('安防') || src.includes('回放');
if (!onKnownPage) throw new Error('返回后未在已知页面');
reporter.record('事件列表-筛选后页面内跳转再回来', 'PASS', Date.now() - start , '');
} catch (e: any) {
const ss = await driver.screenshot().catch(() => '');
reporter.record('事件列表-筛选后页面内跳转再回来', 'FAIL', Date.now() - start, e.message, ss );
await driver.goBack().catch(() => {});
await sleep(1000);
throw e;
}
});
});