90 lines
4.7 KiB
TypeScript
90 lines
4.7 KiB
TypeScript
import { describe, it, beforeAll, afterAll, beforeEach, expect } from 'vitest';
|
|
import { DeviceDriver } from '../../drivers/types';
|
|
import { createDriver } from '../../drivers/factory';
|
|
import { TestReporter } from '../../utils/test-reporter';
|
|
import { sleep } from '../../utils/common';
|
|
import * as dotenv from 'dotenv';
|
|
import * as path from 'path';
|
|
|
|
dotenv.config({ path: path.resolve(__dirname, '../../.env') });
|
|
|
|
// 摄像头录屏/回放(普通功能用例,非 P0)。manifest 摄像头控制 P0 只有 15974「出流」,无单列录屏 step → 不挂 P0/ONES。
|
|
// 流程:进功能页 → 底部 Playback tab → 校验三区块(Cloud Videos / microSD Card Videos / Recordings and Screenshots)
|
|
// → 进 Recordings and Screenshots(本地录屏+截图画廊) → 校验进入(All Types 筛选/标题)。
|
|
// 全用真实文本节点定位。⚠️ 事件/录屏列表为空属当前设备问题(无 SD 卡/未触发录制),不判用例失败——只校验页面可达。
|
|
// 与已保留的 iOS 骨架 camera_recording.test.ts 并存(那份后续单独调 iOS/相册删除等细分动作)。
|
|
interface CamCfg { name: string; }
|
|
const CAMERAS: CamCfg[] = [
|
|
{ name: 'Pan/Tilt Cam 2K oy' },
|
|
];
|
|
const ONLY = process.env.CAMERA_NAME || '';
|
|
const TARGETS = ONLY ? CAMERAS.filter((c) => c.name.includes(ONLY)) : CAMERAS;
|
|
|
|
describe('Camera Record/Playback - 摄像头录屏回放(Playback)', () => {
|
|
let driver: DeviceDriver;
|
|
let reporter: TestReporter;
|
|
|
|
beforeAll(async () => {
|
|
driver = createDriver();
|
|
await driver.createSession();
|
|
reporter = new TestReporter('Camera_Recording', driver.platform.toUpperCase());
|
|
});
|
|
afterAll(async () => { reporter.generate(); await driver.destroySession(); });
|
|
beforeEach(async () => { await driver.dismissPopupIfPresent(); await driver.goBackToHomepage(); await driver.dismissPopupIfPresent(); });
|
|
|
|
async function enterCamera(name: string): Promise<boolean> {
|
|
for (let i = 0; i < 8; i++) {
|
|
const el = await driver.findElementRaw('-android uiautomator', `new UiSelector().textContains("${name}")`).catch(() => null);
|
|
if (el) {
|
|
const r = await driver.getElementRect(el);
|
|
await driver.tap(r.x + Math.min(r.width / 2, 120), Math.max(r.y - 40, r.y + 20));
|
|
await sleep(7000); return true;
|
|
}
|
|
await driver.scrollDown(500); await sleep(800);
|
|
}
|
|
return false;
|
|
}
|
|
const tapText = async (t: string): Promise<boolean> => {
|
|
const el = await driver.findElementRaw('-android uiautomator', `new UiSelector().textContains("${t}")`).catch(() => null);
|
|
if (el) { await driver.tapElement(el); return true; }
|
|
return false;
|
|
};
|
|
const srcHas = async (t: string): Promise<boolean> => (await driver.getSource()).includes(t);
|
|
|
|
for (const cam of TARGETS) {
|
|
it(`[Camera] ${cam.name} 录屏回放(Playback)`, { timeout: 120000 }, async () => {
|
|
const start = Date.now();
|
|
const label = `录屏回放${cam.name}`;
|
|
try {
|
|
if (!(await enterCamera(cam.name))) throw new Error(`首页找不到摄像头卡片 "${cam.name}"`);
|
|
if (!(await tapText('Playback'))) throw new Error('功能页底部无 Playback tab');
|
|
await sleep(4000);
|
|
const hasMicroSD = await srcHas('microSD Card Videos');
|
|
const hasRec = await srcHas('Recordings and Screenshots');
|
|
const hasCloud = await srcHas('Cloud Videos');
|
|
if (!hasRec || !hasMicroSD) {
|
|
const ss = await driver.screenshot().catch(() => '');
|
|
reporter.record(label, 'FAIL', Date.now() - start, `Playback 页区块缺失(microSD=${hasMicroSD} Recordings=${hasRec} Cloud=${hasCloud})`, ss);
|
|
throw new Error('未进入 Playback 页');
|
|
}
|
|
console.log(`${cam.name} Playback 就绪: Cloud=${hasCloud} microSD=${hasMicroSD} Recordings=${hasRec}`);
|
|
if (!(await tapText('Recordings and Screenshots'))) throw new Error('点不到 Recordings and Screenshots');
|
|
await sleep(4000);
|
|
const inGallery = (await srcHas('All Types')) || (await srcHas('Recordings and Screenshots'));
|
|
if (!inGallery) {
|
|
const ss = await driver.screenshot().catch(() => '');
|
|
reporter.record(label, 'FAIL', Date.now() - start, '未进入录屏/截图画廊页', ss);
|
|
throw new Error('未进入画廊页');
|
|
}
|
|
const elapsed = ((Date.now() - start) / 1000).toFixed(1);
|
|
reporter.record(label, 'PASS', Date.now() - start, `Playback 三区块齐+进入录屏截图画廊(列表空=设备无录制,非用例失败), 耗时${elapsed}s`);
|
|
expect(inGallery).toBe(true);
|
|
} catch (e: any) {
|
|
const ss = await driver.screenshot().catch(() => '');
|
|
reporter.record(label, 'FAIL', Date.now() - start, e.message, ss);
|
|
throw e;
|
|
}
|
|
});
|
|
}
|
|
});
|