Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: fix e2e test #316

Merged
merged 16 commits into from
Jan 24, 2025
4 changes: 3 additions & 1 deletion .github/workflows/ai.yml
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,10 @@ jobs:
if-no-files-found: ignore

- name: Check if script failed
if: steps.test-ai.outcome == 'failure'
if: steps.test-ai.outcome == 'failure' || steps.e2e-tests.outcome == 'failure' || steps.e2e-tests-cache.outcome == 'failure' || steps.e2e-tests-report.outcome == 'failure'
run: exit 1





3 changes: 2 additions & 1 deletion packages/midscene/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,9 @@
"computer": "TEST_COMPUTER=true npm run test:ai -- tests/ai/evaluate/computer.test.ts",
"evaluate": "npm run test:ai -- tests/ai/evaluate/inspect.test.ts",
"evaluate:assertion": "npm run test:ai -- tests/ai/evaluate/assertion.test.ts",
"prompt": "npm run test:ai -- tests/ai/parse-action.test.ts",
"evaluate:plan": "npm run test:ai -- tests/ai/evaluate/plan/planning.test.ts",
"evaluate:update": "UPDATE_AI_DATA=true npm run test:ai -- tests/ai/evaluate/inspect.test.ts",
"prompt": "npm run test:ai -- tests/ai/parse-action.test.ts",
"prepublishOnly": "npm run build"
},
"dependencies": {
Expand Down
2 changes: 1 addition & 1 deletion packages/midscene/tests/ai/evaluate/assertion.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import {
repeatFile,
} from './test-suite/util';
import 'dotenv/config';
import { repeatTime } from '../util';

const repeatTime = 2;
const testSources = [
// 'todo',
'online_order',
Expand Down
2 changes: 1 addition & 1 deletion packages/midscene/tests/ai/evaluate/inspect.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ import {
runTestCases,
} from './test-suite/util';
import 'dotenv/config';
import { repeatTime } from '../util';

const repeatTime = 2;
const relocateAfterPlanning = false;
const failCaseThreshold = process.env.CI ? 1 : 0;
const testSources = [
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`automation - planning input > input value 1`] = `
[
{
"locate": {
"id": "fbc2d002",
"prompt": "the input field with placeholder 'What needs to be done?'",
},
"param": {
"value": "learning english",
},
"thought": undefined,
"type": "Input",
},
]
`;

exports[`automation - planning input > input value 2`] = `
[
{
"locate": {
"id": "fbc2d002",
"prompt": "the input field labeled 'What needs to be done?'",
},
"param": {
"value": "learning english",
},
"thought": undefined,
"type": "Input",
},
{
"locate": null,
"param": {
"value": "Enter",
},
"thought": undefined,
"type": "KeyboardPress",
},
]
`;

exports[`automation - planning input > input value Add, delete, correct and check 1`] = `
[
{
"locate": {
"id": "fbc2d002",
"prompt": "the task input box with the content 'Learn English'",
},
"param": {
"value": "Learn English tomorrow",
},
"thought": undefined,
"type": "Input",
},
]
`;

exports[`automation - planning input > input value Add, delete, correct and check 2`] = `
[
{
"locate": {
"id": "fbc2d002",
"prompt": "the input box containing 'Learn English'",
},
"param": {
"value": "Learn Skiing",
},
"thought": undefined,
"type": "Input",
},
]
`;

exports[`automation - planning input > input value Add, delete, correct and check 3`] = `
[
{
"locate": {
"id": "fbc2d002",
"prompt": "the task input box containing 'Learn English'",
},
"param": {
"value": "Learn",
},
"thought": undefined,
"type": "Input",
},
]
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`automation - planning > basic run 1`] = `
{
"timeMs": 3500,
}
`;

exports[`automation - planning > basic run 2`] = `
{
"value": "Enter",
}
`;
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { plan } from '@/ai-model';
/* eslint-disable max-lines-per-function */
import { describe, expect, it, vi } from 'vitest';
import { makePlanResultStable } from '../../util';
import { makePlanResultStable, repeatTime } from '../../util';
import { getPageDataOfTestName, repeat } from './../test-suite/util';

vi.setConfig({
Expand All @@ -10,7 +10,7 @@ vi.setConfig({
});

describe('automation - planning input', () => {
repeat(5, () =>
repeat(repeatTime, () =>
it('input value', async () => {
const { context } = await getPageDataOfTestName('todo');
const instructions = [
Expand All @@ -26,7 +26,7 @@ describe('automation - planning input', () => {
}),
);

repeat(5, () =>
repeat(repeatTime, () =>
it('input value Add, delete, correct and check', async () => {
const { context } = await getPageDataOfTestName('todo-input-with-value');
const instructions = [
Expand Down
2 changes: 1 addition & 1 deletion packages/midscene/tests/ai/evaluate/plan/planning.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ describe('automation - planning', () => {
it('scroll some element', async () => {
const { context } = await getPageDataOfTestName('todo');
const { actions } = await plan(
'Scroll left the status filters (with a button named "complete")',
'Scroll left the status filters (with a button named "completed")',
{
context,
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`assert openAI > online order 1`] = `
exports[`extract > online order 1`] = `
{
"data": [
{
Expand All @@ -17,7 +17,7 @@ exports[`assert openAI > online order 1`] = `
}
`;

exports[`assert openAI > todo 1`] = `
exports[`extract > todo 1`] = `
{
"data": [
"Learn Python",
Expand All @@ -29,7 +29,7 @@ exports[`assert openAI > todo 1`] = `
}
`;

exports[`assert openAI > todo obj 1`] = `
exports[`extract > todo obj 1`] = `
{
"data": [
{
Expand Down
97 changes: 50 additions & 47 deletions packages/midscene/tests/ai/plan/plan-to-target.test.ts
Original file line number Diff line number Diff line change
@@ -1,58 +1,61 @@
import path from 'node:path';
import { vlmPlanning } from '@/ai-model/ui-tars-planning';
import { savePositionImg } from '@midscene/shared/img';
import { expect, test } from 'vitest';
import { expect, it, test } from 'vitest';
import { getPageTestData } from '../evaluate/test-suite/util';

test('inspect with quick answer', async () => {
const { context } = await getPageTestData(
path.join(__dirname, '../evaluate/test-data/todo'),
);
const isUiTars = process.env.MIDSCENE_USE_VLM_UI_TARS === '1';

const { width, height } = context.size;
const startTime = Date.now();
const { realActions } = await vlmPlanning({
userInstruction: '删除第二条任务',
conversationHistory: [
{
role: 'user',
content: [
{
type: 'image_url',
image_url: {
url: context.originalScreenshotBase64,
test.skipIf(!isUiTars)('only run in ui-tars', () => {
it('plan to target', async () => {
const { context } = await getPageTestData(
path.join(__dirname, '../evaluate/test-data/todo'),
);

const { width, height } = context.size;
const startTime = Date.now();
const { realActions } = await vlmPlanning({
userInstruction: '删除第二条任务',
conversationHistory: [
{
role: 'user',
content: [
{
type: 'image_url',
image_url: {
url: context.originalScreenshotBase64,
},
},
},
],
],
},
],
size: {
width,
height,
},
],
size: {
width,
height,
},
});
});

const endTime = Date.now();
const cost = (endTime - startTime) / 1000;
const start_box =
'start_box' in realActions[0].action_inputs
? realActions[0].action_inputs.start_box
: '[]';
const box = JSON.parse(start_box);
console.log('plan to target content:', {
box,
size: {
width,
height,
},
cost: `${cost}s`,
});
// expect(box).toEqual([0.397, 0.218, 0.397, 0.218]);
expect(true).toBe(true);
await savePositionImg({
inputImgBase64: context.originalScreenshotBase64,
rect: { x: box[0] * width, y: box[1] * height },
outputPath: path.join(__dirname, 'output.png'),
const endTime = Date.now();
const cost = (endTime - startTime) / 1000;
const start_box =
'start_box' in realActions[0].action_inputs
? realActions[0].action_inputs.start_box
: '[]';
const box = JSON.parse(start_box);
console.log('plan to target content:', {
box,
size: {
width,
height,
},
cost: `${cost}s`,
});
// expect(box).toEqual([0.397, 0.218, 0.397, 0.218]);
expect(true).toBe(true);
await savePositionImg({
inputImgBase64: context.originalScreenshotBase64,
rect: { x: box[0] * width, y: box[1] * height },
outputPath: path.join(__dirname, 'output.png'),
});
});
// expect(cost).toBeLessThan(100);
});
9 changes: 6 additions & 3 deletions packages/midscene/tests/ai/util.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import type { PlanningAction } from '@/types';

export const repeatTime = 1;
export function makePlanResultStable(plans: PlanningAction[]) {
return plans.map((plan) => {
// Removing thinking makes the results stable for snapshot testing
plan.thought = undefined;
if (plan.param?.prompt) {
plan.param.prompt = '';
}
if (plan.quickAnswer) {
plan.quickAnswer.reason = '';
plan.quickAnswer.text = '';
if ('quickAnswer' in plan && plan.quickAnswer) {
plan.quickAnswer = {
reason: '',
text: '',
};
}
return plan;
});
Expand Down
1 change: 1 addition & 0 deletions packages/web-integration/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@
"test": "vitest --run",
"test:u": "vitest --run -u",
"test:ai": "AI_TEST_TYPE=web npm run test",
"test:ai:bridge": "BRIDGE_MODE=true npm run test --inspect packages/web-integration/tests/ai/bridge/agent.test.ts",
"test:ai:cache": "MIDSCENE_CACHE=true AI_TEST_TYPE=web npm run test",
"test:ai:all": "npm run test:ai:web && npm run test:ai:native",
"test:ai:native": "MIDSCENE_CACHE=true AI_TEST_TYPE=native npm run test",
Expand Down
8 changes: 6 additions & 2 deletions packages/web-integration/src/common/tasks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -349,9 +349,13 @@ export class PageTaskExecutor {
} else if (scrollToEventName === 'untilLeft') {
await this.page.scrollUntilLeft(startingPoint);
} else if (scrollToEventName === 'once' || !scrollToEventName) {
if (taskParam.direction === 'down' || !taskParam.direction) {
if (
taskParam?.direction === 'down' ||
!taskParam ||
!taskParam.direction
) {
await this.page.scrollDown(
taskParam.distance || undefined,
taskParam?.distance || undefined,
startingPoint,
);
} else if (taskParam.direction === 'up') {
Expand Down
3 changes: 2 additions & 1 deletion packages/web-integration/tests/ai/bridge/agent.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ vi.setConfig({
testTimeout: 60 * 1000,
});
const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
describe.skipIf(process.env.CI)(

describe.skipIf(!process.env.BRIDGE_MODE)(
'fully functional agent in server(cli) side',
() => {
it('basic', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,7 @@ test('ai todo', async ({ ai, aiQuery }) => {
}

await ai('Enter "Happy Birthday" in the task box');
await ai('Enter "Learn" in the task box');

await ai(
'Add "JS today" to base on the existing content(important) of the task box, then press enter',
);
await ai('Enter "Learn JS today"in the task box, then press Enter to create');

await ai(
'Enter "Learn Rust tomorrow" in the task box, then press Enter to create',
Expand All @@ -27,6 +23,7 @@ test('ai todo', async ({ ai, aiQuery }) => {
);

const allTaskList = await aiQuery<string[]>('string[], tasks in the list');
console.log('allTaskList', allTaskList);
expect(allTaskList.length).toBe(3);
expect(allTaskList).toContain('Learn JS today');
expect(allTaskList).toContain('Learn Rust tomorrow');
Expand Down
Loading
Loading