misoai-web 1.0.5 → 1.5.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +9 -353
- package/bin/midscene-playground +2 -2
- package/dist/es/agent.js +9 -191
- package/dist/es/agent.js.map +1 -1
- package/dist/es/bridge-mode-browser.js +3 -3
- package/dist/es/bridge-mode-browser.js.map +1 -1
- package/dist/es/bridge-mode.js +11 -193
- package/dist/es/bridge-mode.js.map +1 -1
- package/dist/es/chrome-extension.js +10 -192
- package/dist/es/chrome-extension.js.map +1 -1
- package/dist/es/index.js +13 -195
- package/dist/es/index.js.map +1 -1
- package/dist/es/midscene-playground.js +9 -191
- package/dist/es/midscene-playground.js.map +1 -1
- package/dist/es/midscene-server.js.map +1 -1
- package/dist/es/playground.js +9 -191
- package/dist/es/playground.js.map +1 -1
- package/dist/es/playwright-report.js.map +1 -1
- package/dist/es/playwright.js +10 -192
- package/dist/es/playwright.js.map +1 -1
- package/dist/es/puppeteer-agent-launcher.js +13 -195
- package/dist/es/puppeteer-agent-launcher.js.map +1 -1
- package/dist/es/puppeteer.js +13 -195
- package/dist/es/puppeteer.js.map +1 -1
- package/dist/es/ui-utils.js.map +1 -1
- package/dist/es/utils.js.map +1 -1
- package/dist/es/yaml.js +5 -3
- package/dist/es/yaml.js.map +1 -1
- package/dist/lib/agent.js +9 -191
- package/dist/lib/agent.js.map +1 -1
- package/dist/lib/bridge-mode-browser.js +3 -3
- package/dist/lib/bridge-mode-browser.js.map +1 -1
- package/dist/lib/bridge-mode.js +11 -193
- package/dist/lib/bridge-mode.js.map +1 -1
- package/dist/lib/chrome-extension.js +10 -192
- package/dist/lib/chrome-extension.js.map +1 -1
- package/dist/lib/index.js +13 -195
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/midscene-playground.js +9 -191
- package/dist/lib/midscene-playground.js.map +1 -1
- package/dist/lib/midscene-server.js.map +1 -1
- package/dist/lib/playground.js +9 -191
- package/dist/lib/playground.js.map +1 -1
- package/dist/lib/playwright-report.js.map +1 -1
- package/dist/lib/playwright.js +10 -192
- package/dist/lib/playwright.js.map +1 -1
- package/dist/lib/puppeteer-agent-launcher.js +13 -195
- package/dist/lib/puppeteer-agent-launcher.js.map +1 -1
- package/dist/lib/puppeteer.js +13 -195
- package/dist/lib/puppeteer.js.map +1 -1
- package/dist/lib/ui-utils.js.map +1 -1
- package/dist/lib/utils.js.map +1 -1
- package/dist/lib/yaml.js +5 -3
- package/dist/lib/yaml.js.map +1 -1
- package/dist/types/agent.d.ts +1 -27
- package/dist/types/bridge-mode-browser.d.ts +2 -2
- package/dist/types/bridge-mode.d.ts +2 -2
- package/dist/types/{browser-a1877d18.d.ts → browser-aec1055d.d.ts} +1 -1
- package/dist/types/chrome-extension.d.ts +2 -2
- package/dist/types/index.d.ts +1 -1
- package/dist/types/midscene-server.d.ts +1 -1
- package/dist/types/{page-663ece08.d.ts → page-86ab0fe1.d.ts} +34 -34
- package/dist/types/playground.d.ts +2 -2
- package/dist/types/playwright.d.ts +1 -1
- package/dist/types/puppeteer-agent-launcher.d.ts +1 -1
- package/dist/types/puppeteer.d.ts +1 -1
- package/dist/types/utils.d.ts +1 -1
- package/dist/types/yaml.d.ts +1 -1
- package/iife-script/htmlElement.js +2 -2
- package/iife-script/htmlElementDebug.js +2 -2
- package/package.json +3 -3
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"mappings":"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","names":[],"ignoreList":[],"sources":["../../src/common/utils.ts","../../src/playwright/reporter/index.ts"],"sourcesContent":["import type { StaticPage } from '@/playground';\r\nimport type {\r\n BaseElement,\r\n ElementTreeNode,\r\n PlanningLocateParam,\r\n PlaywrightParserOpt,\r\n UIContext,\r\n} from 'misoai-core';\r\nimport { elementByPositionWithElementInfo } from 'misoai-core/ai-model';\r\nimport { uploadTestInfoToServer } from 'misoai-core/utils';\r\nimport { MIDSCENE_REPORT_TAG_NAME, getAIConfig } from 'misoai-shared/env';\r\nimport type { ElementInfo } from 'misoai-shared/extractor';\r\nimport {\r\n generateElementByPosition,\r\n getNodeFromCacheList,\r\n traverseTree,\r\n treeToList,\r\n} from 'misoai-shared/extractor';\r\nimport { resizeImgBase64 } from 'misoai-shared/img';\r\nimport type { DebugFunction } from 'misoai-shared/logger';\r\nimport { assert, logMsg, uuid } from 'misoai-shared/utils';\r\nimport dayjs from 'dayjs';\r\nimport type { Page as PlaywrightPage } from 'playwright';\r\nimport type { Page as PuppeteerPage } from 'puppeteer';\r\nimport { WebElementInfo } from '../web-element';\r\nimport type { WebPage } from './page';\r\n\r\nexport type WebUIContext = UIContext<WebElementInfo> & {\r\n url: string;\r\n};\r\n\r\nexport async function parseContextFromWebPage(\r\n page: WebPage,\r\n _opt?: PlaywrightParserOpt,\r\n): Promise<WebUIContext> {\r\n assert(page, 'page is required');\r\n if ((page as StaticPage)._forceUsePageContext) {\r\n return await (page as any)._forceUsePageContext();\r\n }\r\n const url = await page.url();\r\n uploadTestInfoToServer({ testUrl: url });\r\n\r\n let screenshotBase64: string;\r\n let tree: ElementTreeNode<ElementInfo>;\r\n\r\n await Promise.all([\r\n page.screenshotBase64().then((base64) => {\r\n screenshotBase64 = base64;\r\n }),\r\n page.getElementsNodeTree().then(async (treeRoot) => {\r\n tree = treeRoot;\r\n }),\r\n ]);\r\n\r\n const webTree = traverseTree(tree!, (elementInfo) => {\r\n const { rect, id, content, attributes, locator, indexId } = elementInfo;\r\n return new WebElementInfo({\r\n rect,\r\n locator,\r\n id,\r\n content,\r\n attributes,\r\n indexId,\r\n });\r\n });\r\n\r\n assert(screenshotBase64!, 'screenshotBase64 is required');\r\n\r\n const elementsInfo = treeToList(webTree);\r\n const size = await page.size();\r\n\r\n if (size.dpr && size.dpr > 1) {\r\n // console.time('resizeImgBase64');\r\n screenshotBase64 = await resizeImgBase64(screenshotBase64, {\r\n width: size.width,\r\n height: size.height,\r\n });\r\n // console.timeEnd('resizeImgBase64');\r\n }\r\n\r\n return {\r\n content: elementsInfo!,\r\n tree: webTree,\r\n size,\r\n screenshotBase64: screenshotBase64!,\r\n url,\r\n };\r\n}\r\n\r\nexport function reportFileName(tag = 'web') {\r\n const reportTagName = getAIConfig(MIDSCENE_REPORT_TAG_NAME);\r\n const dateTimeInFileName = dayjs().format('YYYY-MM-DD_HH-mm-ss');\r\n // ensure uniqueness at the same time\r\n const uniqueId = uuid().substring(0, 8);\r\n return `${reportTagName || tag}-${dateTimeInFileName}-${uniqueId}`;\r\n}\r\n\r\nexport function printReportMsg(filepath: string) {\r\n logMsg(`Midscene - report file updated: ${filepath}`);\r\n}\r\n\r\n/**\r\n * Get the current execution file name\r\n * @returns The name of the current execution file\r\n */\r\nexport function getCurrentExecutionFile(trace?: string): string | false {\r\n const error = new Error();\r\n const stackTrace = trace || error.stack;\r\n const pkgDir = process.cwd() || '';\r\n if (stackTrace) {\r\n const stackLines = stackTrace.split('\\n');\r\n for (const line of stackLines) {\r\n if (\r\n line.includes('.spec.') ||\r\n line.includes('.test.') ||\r\n line.includes('.ts') ||\r\n line.includes('.js')\r\n ) {\r\n const match = line.match(/(?:at\\s+)?(.*?\\.(?:spec|test)\\.[jt]s)/);\r\n if (match?.[1]) {\r\n const targetFileName = match[1]\r\n .replace(pkgDir, '')\r\n .trim()\r\n .replace('at ', '');\r\n return targetFileName;\r\n }\r\n }\r\n }\r\n }\r\n return false;\r\n}\r\n\r\nconst testFileIndex = new Map<string, number>();\r\n\r\nexport function generateCacheId(fileName?: string): string {\r\n let taskFile = fileName || getCurrentExecutionFile();\r\n if (!taskFile) {\r\n taskFile = uuid();\r\n console.warn(\r\n 'Midscene - using random UUID for cache id. Cache may be invalid.',\r\n );\r\n }\r\n\r\n if (testFileIndex.has(taskFile)) {\r\n const currentIndex = testFileIndex.get(taskFile);\r\n if (currentIndex !== undefined) {\r\n testFileIndex.set(taskFile, currentIndex + 1);\r\n }\r\n } else {\r\n testFileIndex.set(taskFile, 1);\r\n }\r\n return `${taskFile}-${testFileIndex.get(taskFile)}`;\r\n}\r\n\r\nexport const ERROR_CODE_NOT_IMPLEMENTED_AS_DESIGNED =\r\n 'NOT_IMPLEMENTED_AS_DESIGNED';\r\n\r\nexport function replaceIllegalPathCharsAndSpace(str: string) {\r\n return str.replace(/[/\\\\:*?\"<>| ]/g, '-');\r\n}\r\n\r\nexport function forceClosePopup(\r\n page: PuppeteerPage | PlaywrightPage,\r\n debug: DebugFunction,\r\n) {\r\n page.on('popup', async (popup) => {\r\n if (!popup) {\r\n console.warn('got a popup event, but the popup is not ready yet, skip');\r\n return;\r\n }\r\n const url = await (popup as PuppeteerPage).url();\r\n console.log(`Popup opened: ${url}`);\r\n if (!(popup as PuppeteerPage).isClosed()) {\r\n try {\r\n await (popup as PuppeteerPage).close(); // Close the newly opened TAB\r\n } catch (error) {\r\n debug(`failed to close popup ${url}, error: ${error}`);\r\n }\r\n } else {\r\n debug(`popup is already closed, skip close ${url}`);\r\n }\r\n\r\n if (!page.isClosed()) {\r\n try {\r\n await page.goto(url);\r\n } catch (error) {\r\n debug(`failed to goto ${url}, error: ${error}`);\r\n }\r\n } else {\r\n debug(`page is already closed, skip goto ${url}`);\r\n }\r\n });\r\n}\r\n\r\nexport function matchElementFromPlan(\r\n planLocateParam: PlanningLocateParam,\r\n tree: ElementTreeNode<BaseElement>,\r\n) {\r\n if (!planLocateParam) {\r\n return undefined;\r\n }\r\n if (planLocateParam.id) {\r\n return getNodeFromCacheList(planLocateParam.id);\r\n }\r\n\r\n if (planLocateParam.bbox) {\r\n const centerPosition = {\r\n x: Math.floor((planLocateParam.bbox[0] + planLocateParam.bbox[2]) / 2),\r\n y: Math.floor((planLocateParam.bbox[1] + planLocateParam.bbox[3]) / 2),\r\n };\r\n let element = elementByPositionWithElementInfo(tree, centerPosition);\r\n\r\n if (!element) {\r\n element = generateElementByPosition(centerPosition) as BaseElement;\r\n }\r\n\r\n return element;\r\n }\r\n\r\n return undefined;\r\n}\r\n","import {\r\n printReportMsg,\r\n replaceIllegalPathCharsAndSpace,\r\n reportFileName,\r\n} from '@/common/utils';\r\nimport type { ReportDumpWithAttributes } from 'misoai-core';\r\nimport { writeDumpReport } from 'misoai-core/utils';\r\nimport type {\r\n FullConfig,\r\n FullResult,\r\n Reporter,\r\n Suite,\r\n TestCase,\r\n TestResult,\r\n} from '@playwright/test/reporter';\r\n\r\nfunction logger(...message: any[]) {\r\n if (process.env.DEBUG === 'true') {\r\n console.log('Midscene e2e report:', ...message);\r\n }\r\n}\r\n\r\nconst testDataList: Array<ReportDumpWithAttributes> = [];\r\nlet mergedFilename: string;\r\nconst testTitleToFilename: Map<string, string> = new Map();\r\n\r\nfunction getStableFilename(testTitle: string): string {\r\n if (!testTitleToFilename.has(testTitle)) {\r\n // use reportFileName to generate the base filename\r\n // only replace the illegal characters in the file system: /, \\, :, *, ?, \", <, >, |\r\n const baseTag = `playwright-${replaceIllegalPathCharsAndSpace(testTitle)}`;\r\n const generatedFilename = reportFileName(baseTag);\r\n testTitleToFilename.set(testTitle, generatedFilename);\r\n }\r\n return testTitleToFilename.get(testTitle)!;\r\n}\r\n\r\nfunction updateReport(mode: 'merged' | 'separate', testId?: string) {\r\n if (mode === 'separate') {\r\n // in separate mode, find the data for the corresponding testID and generate a separate report\r\n const testData = testDataList.find(\r\n (data) => data.attributes?.playwright_test_id === testId,\r\n );\r\n\r\n if (testData) {\r\n // use the stable filename\r\n const stableFilename = getStableFilename(\r\n testData.attributes?.playwright_test_title,\r\n );\r\n\r\n const reportPath = writeDumpReport(stableFilename, [testData]);\r\n reportPath && printReportMsg(reportPath);\r\n }\r\n } else if (mode === 'merged') {\r\n // in merged mode, write all test data into one file\r\n if (!mergedFilename) {\r\n mergedFilename = reportFileName('playwright-merged');\r\n }\r\n\r\n const reportPath = writeDumpReport(mergedFilename, testDataList);\r\n reportPath && printReportMsg(reportPath);\r\n } else {\r\n throw new Error(\r\n `Unknown reporter type in playwright config: ${mode}, only support 'merged' or 'separate'`,\r\n );\r\n }\r\n}\r\n\r\nfunction getMode(reporterType: string) {\r\n if (!reporterType) {\r\n return 'merged';\r\n }\r\n\r\n if (reporterType !== 'merged' && reporterType !== 'separate') {\r\n throw new Error(\r\n `Unknown reporter type in playwright config: ${reporterType}, only support 'merged' or 'separate'`,\r\n );\r\n }\r\n\r\n return reporterType;\r\n}\r\n\r\nclass MidsceneReporter implements Reporter {\r\n mode?: 'merged' | 'separate';\r\n\r\n async onBegin(config: FullConfig, suite: Suite) {\r\n const reporterType = config.reporter?.[1]?.[1]?.type;\r\n\r\n this.mode = getMode(reporterType);\r\n\r\n // const suites = suite.allTests();\r\n // logger(`Starting the run with ${suites.length} tests`);\r\n }\r\n\r\n onTestBegin(test: TestCase, _result: TestResult) {\r\n // logger(`Starting test ${test.title}`);\r\n }\r\n\r\n onTestEnd(test: TestCase, result: TestResult) {\r\n const dumpAnnotation = test.annotations.find((annotation) => {\r\n return annotation.type === 'MIDSCENE_DUMP_ANNOTATION';\r\n });\r\n if (!dumpAnnotation?.description) return;\r\n const retry = result.retry ? `(retry #${result.retry})` : '';\r\n const testId = `${test.id}${retry}`;\r\n const testData: ReportDumpWithAttributes = {\r\n dumpString: dumpAnnotation.description,\r\n attributes: {\r\n playwright_test_id: testId,\r\n playwright_test_title: `${test.title}${retry}`,\r\n playwright_test_status: result.status,\r\n playwright_test_duration: result.duration,\r\n },\r\n };\r\n\r\n testDataList.push(testData);\r\n\r\n updateReport(this.mode!, testId);\r\n\r\n test.annotations = test.annotations.filter(\r\n (annotation) => annotation.type !== 'MIDSCENE_DUMP_ANNOTATION',\r\n );\r\n }\r\n\r\n onEnd(result: FullResult) {\r\n updateReport(this.mode!);\r\n\r\n logger(`Finished the run: ${result.status}`);\r\n }\r\n}\r\n\r\nexport default MidsceneReporter;\r\n"]}
|
1
|
+
{"version":3,"mappings":"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","names":[],"ignoreList":[],"sources":["../../src/common/utils.ts","../../src/playwright/reporter/index.ts"],"sourcesContent":["import type { StaticPage } from '@/playground';\nimport type {\n BaseElement,\n ElementTreeNode,\n PlanningLocateParam,\n PlaywrightParserOpt,\n UIContext,\n} from 'misoai-core';\nimport { elementByPositionWithElementInfo } from 'misoai-core/ai-model';\nimport { uploadTestInfoToServer } from 'misoai-core/utils';\nimport { MIDSCENE_REPORT_TAG_NAME, getAIConfig } from 'misoai-shared/env';\nimport type { ElementInfo } from 'misoai-shared/extractor';\nimport {\n generateElementByPosition,\n getNodeFromCacheList,\n traverseTree,\n treeToList,\n} from 'misoai-shared/extractor';\nimport { resizeImgBase64 } from 'misoai-shared/img';\nimport type { DebugFunction } from 'misoai-shared/logger';\nimport { assert, logMsg, uuid } from 'misoai-shared/utils';\nimport dayjs from 'dayjs';\nimport type { Page as PlaywrightPage } from 'playwright';\nimport type { Page as PuppeteerPage } from 'puppeteer';\nimport { WebElementInfo } from '../web-element';\nimport type { WebPage } from './page';\n\nexport type WebUIContext = UIContext<WebElementInfo> & {\n url: string;\n};\n\nexport async function parseContextFromWebPage(\n page: WebPage,\n _opt?: PlaywrightParserOpt,\n): Promise<WebUIContext> {\n assert(page, 'page is required');\n if ((page as StaticPage)._forceUsePageContext) {\n return await (page as any)._forceUsePageContext();\n }\n const url = await page.url();\n uploadTestInfoToServer({ testUrl: url });\n\n let screenshotBase64: string;\n let tree: ElementTreeNode<ElementInfo>;\n\n await Promise.all([\n page.screenshotBase64().then((base64) => {\n screenshotBase64 = base64;\n }),\n page.getElementsNodeTree().then(async (treeRoot) => {\n tree = treeRoot;\n }),\n ]);\n\n const webTree = traverseTree(tree!, (elementInfo) => {\n const { rect, id, content, attributes, locator, indexId } = elementInfo;\n return new WebElementInfo({\n rect,\n locator,\n id,\n content,\n attributes,\n indexId,\n });\n });\n\n assert(screenshotBase64!, 'screenshotBase64 is required');\n\n const elementsInfo = treeToList(webTree);\n const size = await page.size();\n\n if (size.dpr && size.dpr > 1) {\n // console.time('resizeImgBase64');\n screenshotBase64 = await resizeImgBase64(screenshotBase64, {\n width: size.width,\n height: size.height,\n });\n // console.timeEnd('resizeImgBase64');\n }\n\n return {\n content: elementsInfo!,\n tree: webTree,\n size,\n screenshotBase64: screenshotBase64!,\n url,\n };\n}\n\nexport function reportFileName(tag = 'web') {\n const reportTagName = getAIConfig(MIDSCENE_REPORT_TAG_NAME);\n const dateTimeInFileName = dayjs().format('YYYY-MM-DD_HH-mm-ss');\n // ensure uniqueness at the same time\n const uniqueId = uuid().substring(0, 8);\n return `${reportTagName || tag}-${dateTimeInFileName}-${uniqueId}`;\n}\n\nexport function printReportMsg(filepath: string) {\n logMsg(`Midscene - report file updated: ${filepath}`);\n}\n\n/**\n * Get the current execution file name\n * @returns The name of the current execution file\n */\nexport function getCurrentExecutionFile(trace?: string): string | false {\n const error = new Error();\n const stackTrace = trace || error.stack;\n const pkgDir = process.cwd() || '';\n if (stackTrace) {\n const stackLines = stackTrace.split('\\n');\n for (const line of stackLines) {\n if (\n line.includes('.spec.') ||\n line.includes('.test.') ||\n line.includes('.ts') ||\n line.includes('.js')\n ) {\n const match = line.match(/(?:at\\s+)?(.*?\\.(?:spec|test)\\.[jt]s)/);\n if (match?.[1]) {\n const targetFileName = match[1]\n .replace(pkgDir, '')\n .trim()\n .replace('at ', '');\n return targetFileName;\n }\n }\n }\n }\n return false;\n}\n\nconst testFileIndex = new Map<string, number>();\n\nexport function generateCacheId(fileName?: string): string {\n let taskFile = fileName || getCurrentExecutionFile();\n if (!taskFile) {\n taskFile = uuid();\n console.warn(\n 'Midscene - using random UUID for cache id. Cache may be invalid.',\n );\n }\n\n if (testFileIndex.has(taskFile)) {\n const currentIndex = testFileIndex.get(taskFile);\n if (currentIndex !== undefined) {\n testFileIndex.set(taskFile, currentIndex + 1);\n }\n } else {\n testFileIndex.set(taskFile, 1);\n }\n return `${taskFile}-${testFileIndex.get(taskFile)}`;\n}\n\nexport const ERROR_CODE_NOT_IMPLEMENTED_AS_DESIGNED =\n 'NOT_IMPLEMENTED_AS_DESIGNED';\n\nexport function replaceIllegalPathCharsAndSpace(str: string) {\n return str.replace(/[/\\\\:*?\"<>| ]/g, '-');\n}\n\nexport function forceClosePopup(\n page: PuppeteerPage | PlaywrightPage,\n debug: DebugFunction,\n) {\n page.on('popup', async (popup) => {\n if (!popup) {\n console.warn('got a popup event, but the popup is not ready yet, skip');\n return;\n }\n const url = await (popup as PuppeteerPage).url();\n console.log(`Popup opened: ${url}`);\n if (!(popup as PuppeteerPage).isClosed()) {\n try {\n await (popup as PuppeteerPage).close(); // Close the newly opened TAB\n } catch (error) {\n debug(`failed to close popup ${url}, error: ${error}`);\n }\n } else {\n debug(`popup is already closed, skip close ${url}`);\n }\n\n if (!page.isClosed()) {\n try {\n await page.goto(url);\n } catch (error) {\n debug(`failed to goto ${url}, error: ${error}`);\n }\n } else {\n debug(`page is already closed, skip goto ${url}`);\n }\n });\n}\n\nexport function matchElementFromPlan(\n planLocateParam: PlanningLocateParam,\n tree: ElementTreeNode<BaseElement>,\n) {\n if (!planLocateParam) {\n return undefined;\n }\n if (planLocateParam.id) {\n return getNodeFromCacheList(planLocateParam.id);\n }\n\n if (planLocateParam.bbox) {\n const centerPosition = {\n x: Math.floor((planLocateParam.bbox[0] + planLocateParam.bbox[2]) / 2),\n y: Math.floor((planLocateParam.bbox[1] + planLocateParam.bbox[3]) / 2),\n };\n let element = elementByPositionWithElementInfo(tree, centerPosition);\n\n if (!element) {\n element = generateElementByPosition(centerPosition) as BaseElement;\n }\n\n return element;\n }\n\n return undefined;\n}\n","import {\n printReportMsg,\n replaceIllegalPathCharsAndSpace,\n reportFileName,\n} from '@/common/utils';\nimport type { ReportDumpWithAttributes } from 'misoai-core';\nimport { writeDumpReport } from 'misoai-core/utils';\nimport type {\n FullConfig,\n FullResult,\n Reporter,\n Suite,\n TestCase,\n TestResult,\n} from '@playwright/test/reporter';\n\nfunction logger(...message: any[]) {\n if (process.env.DEBUG === 'true') {\n console.log('Midscene e2e report:', ...message);\n }\n}\n\nconst testDataList: Array<ReportDumpWithAttributes> = [];\nlet mergedFilename: string;\nconst testTitleToFilename: Map<string, string> = new Map();\n\nfunction getStableFilename(testTitle: string): string {\n if (!testTitleToFilename.has(testTitle)) {\n // use reportFileName to generate the base filename\n // only replace the illegal characters in the file system: /, \\, :, *, ?, \", <, >, |\n const baseTag = `playwright-${replaceIllegalPathCharsAndSpace(testTitle)}`;\n const generatedFilename = reportFileName(baseTag);\n testTitleToFilename.set(testTitle, generatedFilename);\n }\n return testTitleToFilename.get(testTitle)!;\n}\n\nfunction updateReport(mode: 'merged' | 'separate', testId?: string) {\n if (mode === 'separate') {\n // in separate mode, find the data for the corresponding testID and generate a separate report\n const testData = testDataList.find(\n (data) => data.attributes?.playwright_test_id === testId,\n );\n\n if (testData) {\n // use the stable filename\n const stableFilename = getStableFilename(\n testData.attributes?.playwright_test_title,\n );\n\n const reportPath = writeDumpReport(stableFilename, [testData]);\n reportPath && printReportMsg(reportPath);\n }\n } else if (mode === 'merged') {\n // in merged mode, write all test data into one file\n if (!mergedFilename) {\n mergedFilename = reportFileName('playwright-merged');\n }\n\n const reportPath = writeDumpReport(mergedFilename, testDataList);\n reportPath && printReportMsg(reportPath);\n } else {\n throw new Error(\n `Unknown reporter type in playwright config: ${mode}, only support 'merged' or 'separate'`,\n );\n }\n}\n\nfunction getMode(reporterType: string) {\n if (!reporterType) {\n return 'merged';\n }\n\n if (reporterType !== 'merged' && reporterType !== 'separate') {\n throw new Error(\n `Unknown reporter type in playwright config: ${reporterType}, only support 'merged' or 'separate'`,\n );\n }\n\n return reporterType;\n}\n\nclass MidsceneReporter implements Reporter {\n mode?: 'merged' | 'separate';\n\n async onBegin(config: FullConfig, suite: Suite) {\n const reporterType = config.reporter?.[1]?.[1]?.type;\n\n this.mode = getMode(reporterType);\n\n // const suites = suite.allTests();\n // logger(`Starting the run with ${suites.length} tests`);\n }\n\n onTestBegin(test: TestCase, _result: TestResult) {\n // logger(`Starting test ${test.title}`);\n }\n\n onTestEnd(test: TestCase, result: TestResult) {\n const dumpAnnotation = test.annotations.find((annotation) => {\n return annotation.type === 'MIDSCENE_DUMP_ANNOTATION';\n });\n if (!dumpAnnotation?.description) return;\n const retry = result.retry ? `(retry #${result.retry})` : '';\n const testId = `${test.id}${retry}`;\n const testData: ReportDumpWithAttributes = {\n dumpString: dumpAnnotation.description,\n attributes: {\n playwright_test_id: testId,\n playwright_test_title: `${test.title}${retry}`,\n playwright_test_status: result.status,\n playwright_test_duration: result.duration,\n },\n };\n\n testDataList.push(testData);\n\n updateReport(this.mode!, testId);\n\n test.annotations = test.annotations.filter(\n (annotation) => annotation.type !== 'MIDSCENE_DUMP_ANNOTATION',\n );\n }\n\n onEnd(result: FullResult) {\n updateReport(this.mode!);\n\n logger(`Finished the run: ${result.status}`);\n }\n}\n\nexport default MidsceneReporter;\n"]}
|
package/dist/es/playwright.js
CHANGED
@@ -17,10 +17,11 @@ var ScriptPlayer = class {
|
|
17
17
|
this.unnamedResultIndex = 0;
|
18
18
|
this.pageAgent = null;
|
19
19
|
this.result = {};
|
20
|
+
const target = script.target || script.web || script.android;
|
20
21
|
if (ifInBrowser) {
|
21
22
|
this.output = void 0;
|
22
|
-
} else if (
|
23
|
-
this.output = resolve(process.cwd(),
|
23
|
+
} else if (target?.output) {
|
24
|
+
this.output = resolve(process.cwd(), target.output);
|
24
25
|
} else {
|
25
26
|
this.output = join(getMidsceneRunSubDir("output"), `${process.pid}.json`);
|
26
27
|
}
|
@@ -94,12 +95,13 @@ var ScriptPlayer = class {
|
|
94
95
|
} else if ("aiAssert" in flowItem) {
|
95
96
|
const assertTask = flowItem;
|
96
97
|
const prompt = assertTask.aiAssert;
|
98
|
+
const msg = assertTask.errorMessage;
|
97
99
|
assert(prompt, "missing prompt for aiAssert");
|
98
100
|
assert(
|
99
101
|
typeof prompt === "string",
|
100
102
|
"prompt for aiAssert must be a string"
|
101
103
|
);
|
102
|
-
await agent.aiAssert(prompt);
|
104
|
+
await agent.aiAssert(prompt, msg);
|
103
105
|
} else if ("aiQuery" in flowItem) {
|
104
106
|
const queryTask = flowItem;
|
105
107
|
const prompt = queryTask.aiQuery;
|
@@ -1688,7 +1690,7 @@ import yaml3 from "js-yaml";
|
|
1688
1690
|
import semver from "semver";
|
1689
1691
|
|
1690
1692
|
// package.json
|
1691
|
-
var version = "1.
|
1693
|
+
var version = "1.5.6";
|
1692
1694
|
|
1693
1695
|
// src/common/task-cache.ts
|
1694
1696
|
var debug3 = getDebug3("cache");
|
@@ -1870,13 +1872,10 @@ var PageAgent = class {
|
|
1870
1872
|
generateReport: true,
|
1871
1873
|
autoPrintReportMsg: true,
|
1872
1874
|
groupName: "Midscene Report",
|
1873
|
-
groupDescription: ""
|
1874
|
-
enableCumulativeContext: true,
|
1875
|
-
autoClearContext: false
|
1875
|
+
groupDescription: ""
|
1876
1876
|
},
|
1877
1877
|
opts || {}
|
1878
1878
|
);
|
1879
|
-
this.initializeContextStore();
|
1880
1879
|
if (this.page.pageType === "puppeteer" || this.page.pageType === "playwright") {
|
1881
1880
|
this.page.waitForNavigationTimeout = this.opts.waitForNavigationTimeout || DEFAULT_WAIT_FOR_NAVIGATION_TIMEOUT;
|
1882
1881
|
this.page.waitForNetworkIdleTimeout = this.opts.waitForNetworkIdleTimeout || DEFAULT_WAIT_FOR_NETWORK_IDLE_TIMEOUT;
|
@@ -1903,69 +1902,6 @@ var PageAgent = class {
|
|
1903
1902
|
opts?.testId || this.page.pageType || "web"
|
1904
1903
|
);
|
1905
1904
|
}
|
1906
|
-
/**
|
1907
|
-
* Initialize context store for cumulative context functionality
|
1908
|
-
*/
|
1909
|
-
async initializeContextStore() {
|
1910
|
-
if (!this.opts.enableCumulativeContext) {
|
1911
|
-
debug4("Cumulative context disabled via options");
|
1912
|
-
return;
|
1913
|
-
}
|
1914
|
-
try {
|
1915
|
-
const aiModel = await import("misoai-core/ai-model");
|
1916
|
-
this.contextStore = aiModel.getContextStore();
|
1917
|
-
debug4("Context store initialized successfully", {
|
1918
|
-
autoClearContext: this.opts.autoClearContext,
|
1919
|
-
testId: this.opts.testId
|
1920
|
-
});
|
1921
|
-
if (this.opts.autoClearContext) {
|
1922
|
-
this.contextStore.clear();
|
1923
|
-
debug4("Context store cleared due to autoClearContext option");
|
1924
|
-
} else {
|
1925
|
-
const existingData = this.contextStore.getAllData();
|
1926
|
-
const existingSteps = this.contextStore.getRecentSteps(100).length;
|
1927
|
-
debug4("Context store preserving existing data", {
|
1928
|
-
existingDataKeys: Object.keys(existingData),
|
1929
|
-
existingStepsCount: existingSteps
|
1930
|
-
});
|
1931
|
-
}
|
1932
|
-
} catch (error) {
|
1933
|
-
debug4("Failed to initialize context store:", error);
|
1934
|
-
console.warn("⚠️ Could not initialize context store:", error);
|
1935
|
-
}
|
1936
|
-
}
|
1937
|
-
/**
|
1938
|
-
* Get the context store instance
|
1939
|
-
*/
|
1940
|
-
getContextStore() {
|
1941
|
-
return this.contextStore;
|
1942
|
-
}
|
1943
|
-
/**
|
1944
|
-
* Clear the context store
|
1945
|
-
*/
|
1946
|
-
clearContext() {
|
1947
|
-
if (this.contextStore) {
|
1948
|
-
this.contextStore.clear();
|
1949
|
-
}
|
1950
|
-
}
|
1951
|
-
/**
|
1952
|
-
* Get all stored data from context store
|
1953
|
-
*/
|
1954
|
-
getStoredData() {
|
1955
|
-
if (this.contextStore) {
|
1956
|
-
return this.contextStore.getAllData();
|
1957
|
-
}
|
1958
|
-
return {};
|
1959
|
-
}
|
1960
|
-
/**
|
1961
|
-
* Get step summary from context store
|
1962
|
-
*/
|
1963
|
-
getStepSummary() {
|
1964
|
-
if (this.contextStore) {
|
1965
|
-
return this.contextStore.getStepSummary();
|
1966
|
-
}
|
1967
|
-
return "";
|
1968
|
-
}
|
1969
1905
|
async getUIContext(action) {
|
1970
1906
|
if (action && (action === "extract" || action === "assert" || action === "captcha")) {
|
1971
1907
|
return await parseContextFromWebPage(this.page, {
|
@@ -2201,31 +2137,6 @@ var PageAgent = class {
|
|
2201
2137
|
};
|
2202
2138
|
}
|
2203
2139
|
async aiAction(taskPrompt, opt) {
|
2204
|
-
if (this.opts.enableCumulativeContext && this.contextStore) {
|
2205
|
-
try {
|
2206
|
-
const originalPrompt = taskPrompt;
|
2207
|
-
const processedPrompt = this.contextStore.replaceAllReferences(taskPrompt, "action");
|
2208
|
-
if (originalPrompt !== processedPrompt) {
|
2209
|
-
debug4("Context replacement in aiAction:", {
|
2210
|
-
original: originalPrompt,
|
2211
|
-
processed: processedPrompt,
|
2212
|
-
storedData: this.contextStore.getAllData()
|
2213
|
-
});
|
2214
|
-
}
|
2215
|
-
this.contextStore.addStep({
|
2216
|
-
type: "action",
|
2217
|
-
summary: `Action: ${processedPrompt}`,
|
2218
|
-
prompt: processedPrompt
|
2219
|
-
});
|
2220
|
-
debug4("Added action step to context store:", {
|
2221
|
-
stepNumber: this.contextStore.getRecentSteps(1)[0]?.stepNumber,
|
2222
|
-
totalSteps: this.contextStore.getRecentSteps(100).length
|
2223
|
-
});
|
2224
|
-
taskPrompt = processedPrompt;
|
2225
|
-
} catch (error) {
|
2226
|
-
debug4("Context store operation failed:", error);
|
2227
|
-
}
|
2228
|
-
}
|
2229
2140
|
const cacheable = opt?.cacheable;
|
2230
2141
|
const isVlmUiTars = vlLocateMode() === "vlm-ui-tars";
|
2231
2142
|
const matchedCache = isVlmUiTars || cacheable === false ? void 0 : this.taskCache?.matchPlanCache(taskPrompt);
|
@@ -2272,75 +2183,7 @@ var PageAgent = class {
|
|
2272
2183
|
};
|
2273
2184
|
}
|
2274
2185
|
async aiQuery(demand) {
|
2275
|
-
|
2276
|
-
let storageKey;
|
2277
|
-
try {
|
2278
|
-
const aiModel = await import("misoai-core/ai-model");
|
2279
|
-
const contextStore = aiModel.getContextStore();
|
2280
|
-
if (typeof demand === "string") {
|
2281
|
-
const storageInstruction = contextStore.parseStorageInstruction(demand);
|
2282
|
-
if (storageInstruction) {
|
2283
|
-
storageKey = storageInstruction.key;
|
2284
|
-
processedDemand = storageInstruction.cleanText;
|
2285
|
-
contextStore._pendingAliases = storageInstruction.aliases;
|
2286
|
-
} else {
|
2287
|
-
const storageMatch = demand.match(/store\s+(?:as\s+)?(\w+)/i);
|
2288
|
-
if (storageMatch) {
|
2289
|
-
storageKey = storageMatch[1];
|
2290
|
-
processedDemand = demand.replace(/,?\s*store\s+(?:as\s+)?\w+/i, "").trim();
|
2291
|
-
}
|
2292
|
-
}
|
2293
|
-
}
|
2294
|
-
} catch (error) {
|
2295
|
-
debug4("Context store not available:", error);
|
2296
|
-
}
|
2297
|
-
const { output, executor } = await this.taskExecutor.query(processedDemand);
|
2298
|
-
if (this.opts.enableCumulativeContext && this.contextStore) {
|
2299
|
-
if (storageKey && output) {
|
2300
|
-
try {
|
2301
|
-
const pendingAliases = this.contextStore._pendingAliases;
|
2302
|
-
if (pendingAliases) {
|
2303
|
-
this.contextStore.storeDataWithAliases(storageKey, output, pendingAliases, typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand));
|
2304
|
-
delete this.contextStore._pendingAliases;
|
2305
|
-
debug4("Stored query result with aliases:", {
|
2306
|
-
key: storageKey,
|
2307
|
-
value: output,
|
2308
|
-
aliases: pendingAliases
|
2309
|
-
});
|
2310
|
-
} else {
|
2311
|
-
this.contextStore.storeData(storageKey, output);
|
2312
|
-
debug4("Stored query result:", {
|
2313
|
-
key: storageKey,
|
2314
|
-
value: output
|
2315
|
-
});
|
2316
|
-
}
|
2317
|
-
this.contextStore.addStep({
|
2318
|
-
type: "query",
|
2319
|
-
summary: `Query: ${typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)} (stored as ${storageKey})`,
|
2320
|
-
data: output,
|
2321
|
-
prompt: typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)
|
2322
|
-
});
|
2323
|
-
debug4("Added query step to context store:", {
|
2324
|
-
storageKey,
|
2325
|
-
totalStoredItems: Object.keys(this.contextStore.getAllData()).length,
|
2326
|
-
totalSteps: this.contextStore.getRecentSteps(100).length
|
2327
|
-
});
|
2328
|
-
} catch (error) {
|
2329
|
-
debug4("Failed to store query result:", error);
|
2330
|
-
}
|
2331
|
-
} else {
|
2332
|
-
try {
|
2333
|
-
this.contextStore.addStep({
|
2334
|
-
type: "query",
|
2335
|
-
summary: `Query: ${typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)}`,
|
2336
|
-
data: output,
|
2337
|
-
prompt: typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)
|
2338
|
-
});
|
2339
|
-
} catch (error) {
|
2340
|
-
debug4("Failed to add query step:", error);
|
2341
|
-
}
|
2342
|
-
}
|
2343
|
-
}
|
2186
|
+
const { output, executor } = await this.taskExecutor.query(demand);
|
2344
2187
|
const metadata = this.afterTaskRunning(executor);
|
2345
2188
|
return {
|
2346
2189
|
result: output,
|
@@ -2450,31 +2293,6 @@ var PageAgent = class {
|
|
2450
2293
|
};
|
2451
2294
|
}
|
2452
2295
|
async aiAssert(assertion, msg, opt) {
|
2453
|
-
let processedAssertion = assertion;
|
2454
|
-
if (this.opts.enableCumulativeContext && this.contextStore) {
|
2455
|
-
try {
|
2456
|
-
const originalAssertion = assertion;
|
2457
|
-
processedAssertion = this.contextStore.replaceAllReferences(assertion, "assertion");
|
2458
|
-
if (originalAssertion !== processedAssertion) {
|
2459
|
-
debug4("Context replacement in aiAssert:", {
|
2460
|
-
original: originalAssertion,
|
2461
|
-
processed: processedAssertion,
|
2462
|
-
context: "assertion",
|
2463
|
-
storedData: this.contextStore.getAllData()
|
2464
|
-
});
|
2465
|
-
}
|
2466
|
-
this.contextStore.addStep({
|
2467
|
-
type: "assertion",
|
2468
|
-
summary: `Assertion: ${processedAssertion}`,
|
2469
|
-
prompt: processedAssertion
|
2470
|
-
});
|
2471
|
-
debug4("Added assertion step to context store:", {
|
2472
|
-
totalSteps: this.contextStore.getRecentSteps(100).length
|
2473
|
-
});
|
2474
|
-
} catch (error) {
|
2475
|
-
debug4("Context store operation failed:", error);
|
2476
|
-
}
|
2477
|
-
}
|
2478
2296
|
let currentUrl = "";
|
2479
2297
|
if (this.page.url) {
|
2480
2298
|
try {
|
@@ -2482,7 +2300,7 @@ var PageAgent = class {
|
|
2482
2300
|
} catch (e) {
|
2483
2301
|
}
|
2484
2302
|
}
|
2485
|
-
const assertionWithContext = currentUrl ? `For the page at URL "${currentUrl}", ${
|
2303
|
+
const assertionWithContext = currentUrl ? `For the page at URL "${currentUrl}", ${assertion}` : assertion;
|
2486
2304
|
const { output, executor } = await this.taskExecutor.assert(assertionWithContext);
|
2487
2305
|
const metadata = this.afterTaskRunning(executor, true);
|
2488
2306
|
if (output && opt?.keepRawResponse) {
|
@@ -2714,7 +2532,7 @@ var Page = class {
|
|
2714
2532
|
this.everMoved = false;
|
2715
2533
|
this.underlyingPage = underlyingPage;
|
2716
2534
|
this.pageType = pageType;
|
2717
|
-
this.waitForNavigationTimeout = opts?.waitForNavigationTimeout
|
2535
|
+
this.waitForNavigationTimeout = opts?.waitForNavigationTimeout ?? DEFAULT_WAIT_FOR_NAVIGATION_TIMEOUT2;
|
2718
2536
|
}
|
2719
2537
|
async evaluate(pageFunction, arg) {
|
2720
2538
|
let result;
|