{"version":3,"sources":["jsdelivr-header.js","/npm/node_modules/.pnpm/tslib@2.3.1/node_modules/tslib/tslib.es6.js","/npm/@idux/wetest-engine@0.1.3/src/expect.ts","/npm/@idux/wetest-engine@0.1.3/src/utils/fs.ts","/npm/@idux/wetest-engine@0.1.3/src/utils/pageSelector.ts","/npm/@idux/wetest-engine@0.1.3/src/utils/log.ts","/npm/@idux/wetest-engine@0.1.3/src/utils/common.ts","/npm/@idux/wetest-engine@0.1.3/src/assertor.ts","/npm/@idux/wetest-engine@0.1.3/src/caseManager.ts","/npm/@idux/wetest-engine@0.1.3/src/utils/uuid.ts","/npm/@idux/wetest-engine@0.1.3/src/mockProxy.ts","/npm/@idux/wetest-engine@0.1.3/src/hooks/useTrace.ts","/npm/@idux/wetest-engine@0.1.3/src/browserManager.ts","/npm/@idux/ai-selector/src/utils/util.ts","/npm/@idux/wetest-engine@0.1.3/src/recorder.ts","/npm/@idux/wetest-engine@0.1.3/src/utils/testInfoImpl.ts","/npm/@idux/wetest-engine@0.1.3/src/runner.ts"],"names":[],"mappings":"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","file":"/npm/@idux/wetest-engine@0.1.3/engine/index.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /npm/@idux/wetest-engine@0.1.3/engine/index.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","/*! *****************************************************************************\r\nCopyright (c) Microsoft Corporation.\r\n\r\nPermission to use, copy, modify, and/or distribute this software for any\r\npurpose with or without fee is hereby granted.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\r\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\r\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\r\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\r\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\r\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\r\nPERFORMANCE OF THIS SOFTWARE.\r\n***************************************************************************** */\r\n/* global Reflect, Promise */\r\n\r\nvar extendStatics = function(d, b) {\r\n    extendStatics = Object.setPrototypeOf ||\r\n        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n        function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };\r\n    return extendStatics(d, b);\r\n};\r\n\r\nexport function __extends(d, b) {\r\n    if (typeof b !== \"function\" && b !== null)\r\n        throw new TypeError(\"Class extends value \" + String(b) + \" is not a constructor or null\");\r\n    extendStatics(d, b);\r\n    function __() { this.constructor = d; }\r\n    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n}\r\n\r\nexport var __assign = function() {\r\n    __assign = Object.assign || function __assign(t) {\r\n        for (var s, i = 1, n = arguments.length; i < n; i++) {\r\n            s = arguments[i];\r\n            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\r\n        }\r\n        return t;\r\n    }\r\n    return __assign.apply(this, arguments);\r\n}\r\n\r\nexport function __rest(s, e) {\r\n    var t = {};\r\n    for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\r\n        t[p] = s[p];\r\n    if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\r\n        for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\r\n            if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\r\n                t[p[i]] = s[p[i]];\r\n        }\r\n    return t;\r\n}\r\n\r\nexport function __decorate(decorators, target, key, desc) {\r\n    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\r\n    if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\r\n    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\r\n    return c > 3 && r && Object.defineProperty(target, key, r), r;\r\n}\r\n\r\nexport function __param(paramIndex, decorator) {\r\n    return function (target, key) { decorator(target, key, paramIndex); }\r\n}\r\n\r\nexport function __metadata(metadataKey, metadataValue) {\r\n    if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(metadataKey, metadataValue);\r\n}\r\n\r\nexport function __awaiter(thisArg, _arguments, P, generator) {\r\n    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n    return new (P || (P = Promise))(function (resolve, reject) {\r\n        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n        function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n        step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n    });\r\n}\r\n\r\nexport function __generator(thisArg, body) {\r\n    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\r\n    return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n    function verb(n) { return function (v) { return step([n, v]); }; }\r\n    function step(op) {\r\n        if (f) throw new TypeError(\"Generator is already executing.\");\r\n        while (_) try {\r\n            if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n            if (y = 0, t) op = [op[0] & 2, t.value];\r\n            switch (op[0]) {\r\n                case 0: case 1: t = op; break;\r\n                case 4: _.label++; return { value: op[1], done: false };\r\n                case 5: _.label++; y = op[1]; op = [0]; continue;\r\n                case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n                default:\r\n                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n                    if (t[2]) _.ops.pop();\r\n                    _.trys.pop(); continue;\r\n            }\r\n            op = body.call(thisArg, _);\r\n        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n    }\r\n}\r\n\r\nexport var __createBinding = Object.create ? (function(o, m, k, k2) {\r\n    if (k2 === undefined) k2 = k;\r\n    Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });\r\n}) : (function(o, m, k, k2) {\r\n    if (k2 === undefined) k2 = k;\r\n    o[k2] = m[k];\r\n});\r\n\r\nexport function __exportStar(m, o) {\r\n    for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p);\r\n}\r\n\r\nexport function __values(o) {\r\n    var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\r\n    if (m) return m.call(o);\r\n    if (o && typeof o.length === \"number\") return {\r\n        next: function () {\r\n            if (o && i >= o.length) o = void 0;\r\n            return { value: o && o[i++], done: !o };\r\n        }\r\n    };\r\n    throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\r\n}\r\n\r\nexport function __read(o, n) {\r\n    var m = typeof Symbol === \"function\" && o[Symbol.iterator];\r\n    if (!m) return o;\r\n    var i = m.call(o), r, ar = [], e;\r\n    try {\r\n        while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\r\n    }\r\n    catch (error) { e = { error: error }; }\r\n    finally {\r\n        try {\r\n            if (r && !r.done && (m = i[\"return\"])) m.call(i);\r\n        }\r\n        finally { if (e) throw e.error; }\r\n    }\r\n    return ar;\r\n}\r\n\r\n/** @deprecated */\r\nexport function __spread() {\r\n    for (var ar = [], i = 0; i < arguments.length; i++)\r\n        ar = ar.concat(__read(arguments[i]));\r\n    return ar;\r\n}\r\n\r\n/** @deprecated */\r\nexport function __spreadArrays() {\r\n    for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\r\n    for (var r = Array(s), k = 0, i = 0; i < il; i++)\r\n        for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\r\n            r[k] = a[j];\r\n    return r;\r\n}\r\n\r\nexport function __spreadArray(to, from, pack) {\r\n    if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {\r\n        if (ar || !(i in from)) {\r\n            if (!ar) ar = Array.prototype.slice.call(from, 0, i);\r\n            ar[i] = from[i];\r\n        }\r\n    }\r\n    return to.concat(ar || Array.prototype.slice.call(from));\r\n}\r\n\r\nexport function __await(v) {\r\n    return this instanceof __await ? (this.v = v, this) : new __await(v);\r\n}\r\n\r\nexport function __asyncGenerator(thisArg, _arguments, generator) {\r\n    if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n    var g = generator.apply(thisArg, _arguments || []), i, q = [];\r\n    return i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i;\r\n    function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }\r\n    function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\r\n    function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\r\n    function fulfill(value) { resume(\"next\", value); }\r\n    function reject(value) { resume(\"throw\", value); }\r\n    function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\r\n}\r\n\r\nexport function __asyncDelegator(o) {\r\n    var i, p;\r\n    return i = {}, verb(\"next\"), verb(\"throw\", function (e) { throw e; }), verb(\"return\"), i[Symbol.iterator] = function () { return this; }, i;\r\n    function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === \"return\" } : f ? f(v) : v; } : f; }\r\n}\r\n\r\nexport function __asyncValues(o) {\r\n    if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n    var m = o[Symbol.asyncIterator], i;\r\n    return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\r\n    function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\r\n    function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\r\n}\r\n\r\nexport function __makeTemplateObject(cooked, raw) {\r\n    if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\r\n    return cooked;\r\n};\r\n\r\nvar __setModuleDefault = Object.create ? (function(o, v) {\r\n    Object.defineProperty(o, \"default\", { enumerable: true, value: v });\r\n}) : function(o, v) {\r\n    o[\"default\"] = v;\r\n};\r\n\r\nexport function __importStar(mod) {\r\n    if (mod && mod.__esModule) return mod;\r\n    var result = {};\r\n    if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\r\n    __setModuleDefault(result, mod);\r\n    return result;\r\n}\r\n\r\nexport function __importDefault(mod) {\r\n    return (mod && mod.__esModule) ? mod : { default: mod };\r\n}\r\n\r\nexport function __classPrivateFieldGet(receiver, state, kind, f) {\r\n    if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a getter\");\r\n    if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot read private member from an object whose class did not declare it\");\r\n    return kind === \"m\" ? f : kind === \"a\" ? f.call(receiver) : f ? f.value : state.get(receiver);\r\n}\r\n\r\nexport function __classPrivateFieldSet(receiver, state, value, kind, f) {\r\n    if (kind === \"m\") throw new TypeError(\"Private method is not writable\");\r\n    if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a setter\");\r\n    if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot write private member to an object whose class did not declare it\");\r\n    return (kind === \"a\" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;\r\n}\r\n","import expectLib from 'expect'\r\nimport { Step } from '../src'\r\nimport { getTestInfoImplState } from '@idux/wetest-share'\r\nimport type { Expect, MatcherState as JestMatcherState } from 'expect/build/types'\r\n\r\nfunction createExpect(actual: unknown) {\r\n  return new Proxy(expectLib(actual), {\r\n    get(target: any, matcherName: any, receiver: any) {\r\n      let matcher = Reflect.get(target, matcherName, receiver)\r\n\r\n      return (...args: any[]) => {\r\n        const step: Step = {\r\n          stepId: `expect:api@expect: ${actual || ''}  ${matcherName}  ${args[0] || ''}`,\r\n          startTime: Date.now(),\r\n          title: `断言:api@expect: ${actual || ''}  ${matcherName}  ${args[0] || ''}`,\r\n          status: 'pass',\r\n        }\r\n\r\n        const reportStepError = (error: Error) => {\r\n          step.error = error.toString()\r\n          step.status = 'fail'\r\n        }\r\n\r\n        try {\r\n          matcher.call(target, ...args)\r\n          step.endTime = Date.now()\r\n        } catch (e: any) {\r\n          reportStepError(e)\r\n          throw e\r\n        } finally {\r\n          createTestInfoStep(step)\r\n        }\r\n      }\r\n    },\r\n  })\r\n}\r\n\r\nexport const createTestInfoStep = (step: Step) => {\r\n  const testInfoImpl = getTestInfoImplState()\r\n\r\n  return testInfoImpl.addStep(step)\r\n}\r\n\r\nexport const expect: Expect<JestMatcherState> = new Proxy(expectLib as any, {\r\n  apply: function (target: any, thisArg: any, argumentsList: [actual: unknown]) {\r\n    const [actual] = argumentsList\r\n    return createExpect(actual)\r\n  },\r\n})\r\n","import { appendFileSync, existsSync, mkdirSync, readFileSync, writeFileSync, rmSync } from 'fs'\r\nimport path from 'path'\r\n\r\n/**\r\n *创建目录\r\n *\r\n * @export\r\n * @param {(string | string[])} paths\r\n */\r\nexport function createDir(paths: string | string[]) {\r\n  if (typeof paths === 'string') {\r\n    paths = [paths]\r\n  }\r\n  paths.forEach(path => {\r\n    if (!existsSync(path)) {\r\n      mkdirSync(path, { recursive: true })\r\n    }\r\n  })\r\n}\r\n\r\n/**\r\n * 刪除目录\r\n *\r\n * @export\r\n * @param {(string | string[])} paths\r\n */\r\nexport function rmDir(paths: string | string[]) {\r\n  if (typeof paths === 'string') {\r\n    paths = [paths]\r\n  }\r\n  paths.forEach(path => {\r\n    if (existsSync(path)) {\r\n\r\n      // 这里存在报错文件的时候，会删除失败\r\n      rmSync(path, {recursive: true})\r\n    }\r\n  })\r\n}\r\n\r\n/**\r\n * 写入json文件\r\n *\r\n * @export\r\n * @param {Record<string, any>} json\r\n * @param {string} output\r\n */\r\nexport function writeJson(json: Record<string, any>, output: string) {\r\n  createDir(path.dirname(output))\r\n  writeFileSync(output, JSON.stringify(json, null, 2), { encoding: 'utf-8' })\r\n}\r\n\r\n/**\r\n * 读取json文件内容\r\n *\r\n * @export\r\n * @template T\r\n * @param {string} path\r\n * @returns {*}  {T}\r\n */\r\nexport function readJson<T extends Record<string, any>>(path: string): T {\r\n  return JSON.parse(readFileSync(path, 'utf-8'))\r\n}\r\n\r\n/**\r\n * 向文件追加内容\r\n *\r\n * @export\r\n * @param {string} output\r\n * @param {string} content\r\n */\r\nexport function appendFile(output: string, content: string): void {\r\n  createDir(path.dirname(output))\r\n  if (existsSync(output)) {\r\n    appendFileSync(output, content, 'utf-8')\r\n  } else {\r\n    writeFileSync(output, content, { flag: 'a+' })\r\n  }\r\n}\r\n\r\n/**\r\n * 获取快照内容\r\n *\r\n * @export\r\n * @param {string} snapshotPath\r\n * @returns {*}  {Record<string, string>}\r\n */\r\nexport function getSnapshotData(snapshotPath: string): Record<string, string> {\r\n  const data = Object.create(null)\r\n  let snapshotContents = ''\r\n\r\n  if (existsSync(snapshotPath)) {\r\n    snapshotContents = readFileSync(snapshotPath, 'utf8')\r\n    const populate = new Function('exports', snapshotContents)\r\n    populate(data)\r\n  }\r\n\r\n  return data\r\n}\r\n","import { Page } from 'playwright'\r\nimport { SelectorMap, SelectorInfo } from '@idux/wetest-ai-selector/types'\r\n\r\nexport default class PageSelector {\r\n  private selectorInfo: SelectorInfo\r\n\r\n  private page: Page\r\n\r\n  constructor(selectorInfo: SelectorInfo, page: Page) {\r\n    this.selectorInfo = selectorInfo\r\n    this.page = page\r\n  }\r\n\r\n  private getSelectorIterator(selectorMap: SelectorMap) {\r\n    let keys = Object.keys(selectorMap).sort((a, b) => Number(a) - Number(b))\r\n    let idx = -1\r\n    let jumpArr: string[] = []\r\n    let jumpIdx = -1\r\n\r\n    return {\r\n      next() {\r\n        let selector = selectorMap[keys[++idx]]\r\n        return selector\r\n      },\r\n      jumpNext() {\r\n        let selector = selectorMap[jumpArr[++jumpIdx]]\r\n        return selector\r\n      },\r\n      saveJumpItem() {\r\n        jumpArr.push(keys[idx])\r\n      },\r\n    }\r\n  }\r\n\r\n  private async recursionMathEl(level: number, selector: string) {\r\n    if (this.selectorInfo.firstSelector.length > 2) {\r\n      return\r\n    }\r\n\r\n    let selectorMap = this.selectorInfo.levelSelectorMap[level]\r\n\r\n    if (!selectorMap) {\r\n      // 这里代表\r\n      // 整个levelSelectorMap是空的（level === 0 的时候）\r\n      // 已经递归完所有的levelSelectorMap，level-1级（也是最后一级递归）递归命中了多个，但没有找到唯一的元素（level > 0的时候）\r\n      //(这时候也给出去兜底，这种情况当前action的执行成功率在1/n,n是selector命中的元素个数)\r\n      // todo：这里后续可以加上命中概率显示在client\r\n      return\r\n    }\r\n\r\n    let iterator = this.getSelectorIterator(selectorMap)\r\n    let curSelector = iterator.next()\r\n\r\n    // 先遍历当前selectorMap iterator，快速找到唯一目标的selector，非唯一的存入JumpItem，后续再遍历与递归，加快算法效率\r\n    while (curSelector) {\r\n      let unionselector = selector ? `${curSelector} >> ${selector}` : curSelector\r\n\r\n      let curSelectorEles = await this.page.$$(curSelector)\r\n\r\n      // 如果当前层级的选择此是nth的，不能直接作为最终唯一匹配选择器，需要向上查找（也就是最终的结果，开头的元素选择器不能是nth的）\r\n      if (curSelector.includes('nth=') || curSelectorEles.length > 1) {\r\n        iterator.saveJumpItem()\r\n        curSelector = iterator.next()\r\n        continue\r\n      }\r\n\r\n      let result = await this.page.$$(unionselector)\r\n\r\n      if (!result.length) {\r\n        curSelector = iterator.next()\r\n        continue\r\n      }\r\n\r\n      if (result.length === 1) {\r\n        this.selectorInfo.firstSelector.push(unionselector)\r\n        curSelector = iterator.next()\r\n        continue\r\n      }\r\n\r\n      if (result.length > 1) {\r\n        iterator.saveJumpItem()\r\n        curSelector = iterator.next()\r\n        continue\r\n      }\r\n    }\r\n\r\n    // 这里开始处理selector匹配多个元素的情况\r\n    curSelector = iterator.jumpNext()\r\n\r\n    while (curSelector) {\r\n      let unionselector = selector ? `${curSelector} >> ${selector}` : curSelector\r\n\r\n      await this.recursionMathEl(level + 1, unionselector)\r\n\r\n      curSelector = iterator.jumpNext()\r\n    }\r\n  }\r\n\r\n  public async generateFirstSelector() {\r\n    await this.recursionMathEl(0, '')\r\n  }\r\n\r\n  public getFirstSelector() {\r\n    return this.selectorInfo.firstSelector\r\n  }\r\n}\r\n","import chalk from 'chalk'\r\n\r\n\r\nexport class Log {\r\n    static runnerActionLog(action:string) {\r\n        console.log(chalk.green(`[wetest] running action:${action}`))\r\n    }\r\n\r\n    static runneSelectorLog(selectors:string, index:number) {\r\n        console.log(chalk.yellow(`[wetest] target element ${index} selector: ${selectors}`))\r\n    }\r\n}","import { chromium, firefox, webkit, PageScreenshotOptions, Page, BrowserType } from 'playwright'\r\nimport { BrowserName } from '../types'\r\nimport pretty from 'pretty'\r\nimport PageSelector from './pageSelector'\r\nimport { SelectorInfo } from '@idux/wetest-ai-selector'\r\nimport { Log } from './log'\r\n\r\nexport function getBrowser(browser: BrowserName): BrowserType {\r\n  return {\r\n    chromium,\r\n    firefox,\r\n    webkit,\r\n  }[browser]\r\n}\r\n\r\n/**\r\n * 截图工具\r\n *\r\n * @export\r\n * @param {Page} page\r\n * @param {{\r\n *     path: string\r\n *     selector?: string\r\n *   }} options\r\n */\r\nexport async function screenshot(\r\n  page: Page,\r\n  options: {\r\n    path: string\r\n    selector?: string\r\n  },\r\n) {\r\n  const screenshotParams: PageScreenshotOptions = {}\r\n  if (options.selector) {\r\n    const boudingRect = await page.locator(options.selector).boundingBox()\r\n    if (boudingRect) {\r\n      screenshotParams.clip = boudingRect\r\n    }\r\n  }\r\n  // FIXME:odiff暂时不支持buffer对比和输出，官方近期会开始支持，这里先直接生成图片\r\n  await page.screenshot({\r\n    path: options.path,\r\n    ...screenshotParams,\r\n  })\r\n}\r\n\r\n/**\r\n * 获取\r\n *\r\n * @export\r\n * @param {Page} page\r\n * @param {{\r\n *     path: string\r\n *     selector: string\r\n *     filter?: (snap: string) => string\r\n *   }} {\r\n *     path,\r\n *     selector,\r\n *     filter = str => str,\r\n *   }\r\n */\r\nexport async function getSnapshot(\r\n  page: Page,\r\n  {\r\n    selector,\r\n    filter = str => str,\r\n  }: {\r\n    selector: string\r\n    filter?: (snap: string) => string\r\n  },\r\n) {\r\n  const snapshot = await page.locator(selector).evaluate(node => node.outerHTML)\r\n  return filter(pretty(snapshot))\r\n}\r\n\r\n/**\r\n * 删除对象中符合条件的项\r\n *\r\n * FIXME: 后续需要优化，不然太多JSON操作了，性能受影响\r\n *\r\n * @export\r\n * @param {Record<string, any>} obj\r\n * @param {(key: string, value: any) => boolean} deleteFn\r\n * @returns {Record<string, any>}\r\n */\r\nexport function deleteDeep(\r\n  obj: Record<string, any>,\r\n  omitParams: RegExp | ((key: string, value: string) => boolean),\r\n): Record<string, any> {\r\n  const deleteFn = (key: string, val: any) => {\r\n    if (omitParams instanceof RegExp) {\r\n      return omitParams.test(key)\r\n    }\r\n    return omitParams(key, val)\r\n  }\r\n  return JSON.parse(\r\n    JSON.stringify(obj, (key, value) => {\r\n      if (deleteFn(key, value)) {\r\n        return undefined\r\n      }\r\n      return value\r\n    }),\r\n  )\r\n}\r\n\r\nexport function sleep(timeout?: number) {\r\n  return new Promise(resolve => setTimeout(resolve, timeout))\r\n}\r\n\r\nexport async function autoTrySelector(\r\n  fn: Function,\r\n  selectorInfo: SelectorInfo,\r\n  page: Page,\r\n  allowFirstSelectorEmpty = false,\r\n) {\r\n  let firstSelector = selectorInfo.firstSelector\r\n\r\n  if (!firstSelector.length && !allowFirstSelectorEmpty) {\r\n    const pageSelector = new PageSelector(selectorInfo, page)\r\n    await pageSelector.generateFirstSelector()\r\n    firstSelector = pageSelector.getFirstSelector()\r\n  }\r\n\r\n  if (!firstSelector.length) {\r\n    throw new Error('[running]元素选择器缺失，请检查是否存在错误（改动引发）或者增加埋点属性后重新录制用例')\r\n  }\r\n\r\n  for (let i = 0; i < firstSelector.length; i++) {\r\n    try {\r\n      Log.runneSelectorLog(firstSelector[i], i + 1)\r\n      const result = await fn(firstSelector[i])\r\n      return result\r\n    } catch (error) {\r\n      if (i < firstSelector.length - 1) {\r\n        continue\r\n      }\r\n\r\n      throw error\r\n    }\r\n  }\r\n}\r\n","import { PNG } from 'pngjs'\r\nimport pixelmatch from 'pixelmatch'\r\nimport { Page, PageScreenshotOptions } from 'playwright'\r\nimport { expect, createTestInfoStep } from './expect'\r\nimport pretty from 'pretty'\r\nimport {\r\n  Assertion,\r\n  ScreenshotAssertion,\r\n  SnapshotAssertion,\r\n  UrlAssertion,\r\n  VisibleAssertion,\r\n  ValueAssertion,\r\n  isCheckedAssertion,\r\n} from './types'\r\nimport { readJson, createDir } from './utils/fs'\r\nimport { join } from 'path'\r\nimport chalk from 'chalk'\r\nimport { writeFileSync, readFileSync, copyFileSync, rmSync } from 'fs'\r\nimport { sleep } from './utils/common'\r\nimport { autoTrySelector } from './utils/common'\r\nimport { SelectorInfo } from '@idux/wetest-ai-selector/types'\r\n\r\nconst createDOMPurify = require('dompurify')\r\nconst { JSDOM } = require('jsdom')\r\n\r\n/**\r\n * 获取\r\n *\r\n * @export\r\n * @param {Page} page\r\n * @param {{\r\n *     path: string\r\n *     selectors: string[]\r\n *     filter?: (snap: string) => string\r\n *   }} {\r\n *     path,\r\n *     selector,\r\n *     filter = str => str,\r\n *   }\r\n */\r\nexport async function getSnapshot(\r\n  page: Page,\r\n  {\r\n    selectorInfo,\r\n    transfer = sanitizeSnapshot => sanitizeSnapshot,\r\n  }: {\r\n    selectorInfo: SelectorInfo\r\n    transfer?: (snap: string, raw: string) => string\r\n  },\r\n) {\r\n  const snapshot = await autoTrySelector(\r\n    (selector: string) => page.locator(selector).evaluate(node => node.outerHTML),\r\n    selectorInfo,\r\n    page,\r\n    true,\r\n  )\r\n  const rawSnapshot = pretty(snapshot)\r\n  const window = new JSDOM('').window\r\n  const DOMPurify = createDOMPurify(window)\r\n  const sanitizeSnapshot = DOMPurify.sanitize(snapshot, {\r\n    ALLOWED_ATTR: ['class'],\r\n    ALLOW_DATA_ATTR: false,\r\n  })\r\n  return transfer(sanitizeSnapshot, rawSnapshot)\r\n}\r\n\r\n/**\r\n * 截图工具\r\n *\r\n * @export\r\n * @param {Page} page\r\n * @param {{\r\n *     path: string\r\n *     selectors?: string[]\r\n *   }} options\r\n */\r\nasync function screenshot(\r\n  page: Page,\r\n  options: {\r\n    path: string\r\n    selectorInfo?: SelectorInfo\r\n  },\r\n) {\r\n  const screenshotParams: PageScreenshotOptions = {}\r\n  if (options.selectorInfo) {\r\n    const boudingRect = await autoTrySelector(\r\n      (selector: string) => page.locator(selector).boundingBox(),\r\n      options.selectorInfo,\r\n      page,\r\n      true,\r\n    )\r\n    if (boudingRect) {\r\n      screenshotParams.clip = boudingRect\r\n    }\r\n  }\r\n  // FIXME:odiff暂时不支持buffer对比和输出，官方近期会开始支持，这里先直接生成图片\r\n  await page.screenshot({\r\n    path: options.path,\r\n    ...screenshotParams,\r\n  })\r\n}\r\n\r\ninterface AssertorOptions {\r\n  runtimeDir?: string\r\n  snapshotFile: string\r\n  screenshotsDir: string\r\n  snapshotTransfer?: (snap: string, raw: string) => string\r\n  origin?: {\r\n    old: string\r\n    new?: string\r\n  }\r\n}\r\n\r\nexport class Assertor {\r\n  private options!: AssertorOptions\r\n  snapshots: Record<string, string> = {}\r\n\r\n  constructor(options: AssertorOptions) {\r\n    this.options = options\r\n  }\r\n\r\n  /**\r\n   * 加载本地的快照信息\r\n   *\r\n   * @memberof Assertor\r\n   */\r\n  loadSnapshots() {\r\n    this.snapshots = readJson(this.options.snapshotFile)\r\n  }\r\n\r\n  /**\r\n   * 断言,录制的时候，部分断言需要跑一遍获取对应的断言值得\r\n   *\r\n   * @param {Assertion} assertion\r\n   * @param {Page} page\r\n   * @memberof Assertor\r\n   */\r\n  async assert(assertion: Assertion, page: Page) {\r\n    switch (assertion.params.type) {\r\n      case 'snapshot':\r\n        await this.assertSnapshot(assertion as SnapshotAssertion, page)\r\n        break\r\n\r\n      case 'screenshot':\r\n        await this.assertScreenshot(assertion as ScreenshotAssertion, page)\r\n        break\r\n    }\r\n  }\r\n\r\n  /**\r\n   * 截图断言\r\n   *\r\n   * @param {ScreenshotAssertion} assertion\r\n   * @param {Page} page\r\n   * @memberof Assertor\r\n   */\r\n  async assertScreenshot(assertion: ScreenshotAssertion, page: Page) {\r\n    await page.evaluate('window.__wetest_toggleShowToolbar(false)')\r\n    await screenshot(page, {\r\n      path: join(this.options.screenshotsDir, assertion.params.name),\r\n      selectorInfo: assertion.params.selector,\r\n    })\r\n    await page.evaluate('window.__wetest_toggleShowToolbar(true)')\r\n  }\r\n\r\n  /**\r\n   * 快照断言\r\n   *\r\n   * @param {SnapshotAssertion} assertion\r\n   * @param {Page} page\r\n   * @memberof Assertor\r\n   */\r\n  async assertSnapshot(assertion: SnapshotAssertion, page: Page) {\r\n    const snapshot = await getSnapshot(page, {\r\n      selectorInfo: assertion.params.selector,\r\n      transfer: this.options.snapshotTransfer,\r\n    })\r\n    this.snapshots[assertion.params.name] = snapshot\r\n  }\r\n\r\n  /**\r\n   * 执行断言\r\n   *\r\n   * @param {Assertion} assertion\r\n   * @param {Page} page\r\n   * @memberof Assertor\r\n   */\r\n  async runAssertion(assertion: Assertion, page: Page) {\r\n    switch (assertion.params.type) {\r\n      case 'url':\r\n        await this.runUrlAssertion(assertion as UrlAssertion, page)\r\n        break\r\n\r\n      case 'visible':\r\n        await this.runVisibleAssertion(assertion as VisibleAssertion, page)\r\n        break\r\n\r\n      case 'screenshot':\r\n        // @XXX #15 等 1s 再断言，这里可以看下能不能优化下策略\r\n        await sleep(1500)\r\n        await this.runScreenshotAssertion(assertion as ScreenshotAssertion, page)\r\n        break\r\n\r\n      case 'snapshot':\r\n        await this.runSnapshotAssertion(assertion as SnapshotAssertion, page)\r\n        break\r\n\r\n      case 'value':\r\n        await this.runValueAssertion(assertion as ValueAssertion, page)\r\n        break\r\n      case 'isChecked':\r\n        await this.runIsCheckedAssertion(assertion as isCheckedAssertion, page)\r\n        break\r\n\r\n      default:\r\n        throw new Error('[Assertor] 不支持当前断言类型！')\r\n    }\r\n  }\r\n\r\n  /**\r\n   * 执行元素可见断言\r\n   *\r\n   * @param {VisibleAssertion} assertion\r\n   * @param {Page} page\r\n   * @memberof Assertor\r\n   */\r\n  async runVisibleAssertion(assertion: VisibleAssertion, page: Page) {\r\n    const pageFn = async (selector: string) => {\r\n      const result = await page.locator(selector).isVisible()\r\n      expect(result).toBeTruthy()\r\n    }\r\n    await autoTrySelector(pageFn, assertion.params.selector, page, true)\r\n  }\r\n\r\n  /**\r\n   * 执行url断言\r\n   *\r\n   * @param {UrlAssertion} assertion\r\n   * @param {Page} page\r\n   * @memberof Assertor\r\n   */\r\n  runUrlAssertion(assertion: UrlAssertion, page: Page) {\r\n    const url = this.options.origin?.new\r\n      ? assertion.params.url.replace(this.options.origin.old, this.options.origin.new)\r\n      : assertion.params.url\r\n    expect(page.url()).toBe(url)\r\n  }\r\n\r\n  /**\r\n   * 执行截图断言\r\n   *\r\n   * @param {ScreenshotAssertion} assertion\r\n   * @param {Page} page\r\n   * @memberof Assertor\r\n   */\r\n  async runScreenshotAssertion(assertion: ScreenshotAssertion, page: Page) {\r\n    const oldScreenshotPath = join(this.options.screenshotsDir, assertion.params.name)\r\n    const newScreenshotPath = join(this.options.screenshotsDir, `new_${assertion.params.name}`)\r\n    const diffScreenshotPath = join(this.options.screenshotsDir, `diff_${assertion.params.name}`)\r\n\r\n    await screenshot(page, {\r\n      path: newScreenshotPath,\r\n      selectorInfo: assertion.params.selector,\r\n    })\r\n\r\n    const testStep = createTestInfoStep({\r\n      stepId: `expect:api@expect: ${assertion.context || ''}  ${assertion.params.name}`,\r\n      startTime: Date.now(),\r\n      title: `断言:api@expect: ${assertion.context || ''}  ${assertion.params.name}`,\r\n      status: 'pass',\r\n    })\r\n\r\n    const oldScreenshotPng = PNG.sync.read(readFileSync(oldScreenshotPath))\r\n    const newScreenshotPng = PNG.sync.read(readFileSync(newScreenshotPath))\r\n    const { width, height } = oldScreenshotPng\r\n    const diff = new PNG({ width, height })\r\n\r\n    // 对比后像素点差异数量值 1px = 1\r\n    const pxDiffCount = pixelmatch(oldScreenshotPng.data, newScreenshotPng.data, diff.data, width, height, {\r\n      threshold: 0.2, // 色彩比较的阈值，越低越精确，这里给个不太低的值，防止浏览器渲染有的时候字体虚化导致问题\r\n    })\r\n\r\n    if (pxDiffCount > 1) {\r\n      // 对比不通过\r\n      const errorDir = this.options.runtimeDir ?? process.cwd()\r\n      createDir(errorDir)\r\n\r\n      writeFileSync(diffScreenshotPath, PNG.sync.write(diff))\r\n      copyFileSync(newScreenshotPath, join(errorDir, `new_${assertion.params.name}`))\r\n      copyFileSync(diffScreenshotPath, join(errorDir, `diff_${assertion.params.name}`))\r\n      rmSync(newScreenshotPath)\r\n      rmSync(diffScreenshotPath)\r\n\r\n      testStep.status = 'fail'\r\n      testStep.error = `screenshot ${assertion.params.name} compare fail! See ${errorDir}`\r\n      testStep.endTime = Date.now()\r\n      throw new Error(chalk.red(`screenshot ${assertion.params.name} compare fail! See ${errorDir}`))\r\n    } else {\r\n      rmSync(newScreenshotPath)\r\n      testStep.endTime = Date.now()\r\n    }\r\n  }\r\n\r\n  /**\r\n   * 执行快照断言\r\n   *\r\n   * @param {SnapshotAssertion} assertion\r\n   * @param {Page} page\r\n   * @param {string} expectSnap\r\n   * @memberof Assertor\r\n   */\r\n  async runSnapshotAssertion(assertion: SnapshotAssertion, page: Page) {\r\n    expect(\r\n      await getSnapshot(page, {\r\n        selectorInfo: assertion.params.selector,\r\n        transfer: this.options.snapshotTransfer,\r\n      }),\r\n    ).toBe(this.snapshots[assertion.params.name])\r\n  }\r\n\r\n  /**\r\n   * 执行快照断言\r\n   *\r\n   * @param {SnapshotAssertion} assertion\r\n   * @param {Page} page\r\n   * @param {string} expectSnap\r\n   * @memberof Assertor\r\n   */\r\n  async runValueAssertion(assertion: ValueAssertion, page: Page) {\r\n    expect(\r\n      await autoTrySelector((selector: string) => page.inputValue(selector), assertion.params.selector, page),\r\n    ).toBe(assertion.params.value)\r\n  }\r\n  /**\r\n   * 执行isChecked断言\r\n   *\r\n   * @param {SnapshotAssertion} assertion\r\n   * @param {Page} page\r\n   * @param {string} expectSnap\r\n   * @memberof Assertor\r\n   */\r\n  async runIsCheckedAssertion(assertion: isCheckedAssertion, page: Page) {\r\n    expect(await autoTrySelector((selector: string) => page.isChecked(selector), assertion.params.selector, page)).toBe(\r\n      assertion.params.checked,\r\n    )\r\n  }\r\n}\r\n","import { existsSync, readFileSync } from 'fs'\r\nimport { last, merge } from 'lodash'\r\nimport { join } from 'path'\r\nimport { Case, Action, Signal } from './types'\r\nimport { createDir, readJson, writeJson } from './utils/fs'\r\n\r\nfunction getInitialCase(): Case {\r\n  return {\r\n    name: '',\r\n    origin: '',\r\n    saveMock: true,\r\n    loginCase: false,\r\n    skip: false,\r\n    actions: [],\r\n  }\r\n}\r\n\r\n/**\r\n * 读取快照信息\r\n *\r\n * @param {string} snapshotPath\r\n * @returns {Record<string, string>}\r\n */\r\nfunction readSnapshots(snapshotPath: string): Record<string, string> {\r\n  const data = Object.create(null)\r\n  let snapshotContents = ''\r\n\r\n  if (existsSync(snapshotPath)) {\r\n    snapshotContents = readFileSync(snapshotPath, 'utf8')\r\n    const populate = new Function('exports', snapshotContents)\r\n    populate(data)\r\n  }\r\n\r\n  return data\r\n}\r\n\r\nexport class CaseManger {\r\n  caseDir: string = ''\r\n\r\n  case: Case = getInitialCase()\r\n  snapshots: Record<string, string> = {}\r\n\r\n  constructor(caseDir: string) {\r\n    this.caseDir = caseDir\r\n  }\r\n\r\n  get pathResolve() {\r\n    return {\r\n      caseDir: this.caseDir,\r\n      screenshotsDir: join(this.caseDir, 'screenshots'),\r\n      mockFile: join(this.caseDir, 'mock.json'),\r\n      snapshotFile: join(this.caseDir, 'snapshots.json'),\r\n      caseFile: join(this.caseDir, 'case.json'),\r\n    }\r\n  }\r\n\r\n  /**\r\n   * 创建新的用例\r\n   *\r\n   * @param {{ saveMock: boolean }} caseInfo\r\n   * @returns {('success' | 'exist' | 'fail')}\r\n   * @memberof CaseManger\r\n   */\r\n  create(caseInfo: { saveMock: boolean }): 'success' | 'exist' | 'fail' {\r\n    if (existsSync(this.caseDir)) {\r\n      return 'exist'\r\n    }\r\n\r\n    try {\r\n      createDir(this.caseDir)\r\n    } catch (error) {\r\n      console.error(error)\r\n      return 'fail'\r\n    }\r\n\r\n    merge(this.case, caseInfo)\r\n\r\n    return 'success'\r\n  }\r\n\r\n  /**\r\n   * 加载已有的用例信息\r\n   *\r\n   * @memberof CaseManger\r\n   */\r\n  load() {\r\n    this.case = readJson<Case>(join(this.caseDir, 'case.json'))\r\n    this.snapshots = readSnapshots(join(this.caseDir, 'snapshots.snap'))\r\n  }\r\n\r\n  /**\r\n   * 保存用例\r\n   *\r\n   * @memberof CaseManger\r\n   */\r\n  save() {\r\n    writeJson(this.case, this.pathResolve.caseFile)\r\n  }\r\n\r\n  /**\r\n   * 记录action\r\n   *\r\n   * @param {Action} action\r\n   * @memberof CaseManger\r\n   */\r\n  recordAction(action: Action) {\r\n    this.case.actions.push(action)\r\n  }\r\n\r\n  setSignal(signal: Signal) {\r\n    const { name, ...params } = signal\r\n    const lastAction = last(this.case.actions)\r\n\r\n    if (!lastAction) return\r\n\r\n    if (!lastAction.signals) {\r\n      lastAction.signals = {}\r\n    }\r\n    lastAction.signals[name] = params\r\n  }\r\n\r\n  reset() {\r\n    this.case = getInitialCase()\r\n    this.snapshots = {}\r\n  }\r\n}\r\n","let uuid = 1000\r\nexport function getUuid() {\r\n  return (++uuid).toString()\r\n}\r\n","import { Request, Page, Response, BrowserContext } from 'playwright'\r\nimport crypto from 'crypto'\r\nimport { readJson, writeJson } from './utils/fs'\r\nimport { get, set, last, merge } from 'lodash'\r\nimport qs from 'qs'\r\nimport { deleteDeep } from './utils/common'\r\nimport { CustomProxy } from './types'\r\n\r\ninterface ResponseInfo {\r\n  status: number\r\n  headers: Record<string, string>\r\n  body: string\r\n}\r\n\r\ninterface RequestInfo {\r\n  method: string\r\n  data?: string\r\n  params?: string\r\n  url: string\r\n}\r\n\r\ninterface RequestPool {\r\n  pages: {\r\n    [pageId: string]: {\r\n      [url: string]: {\r\n        [requestHash: string]: string[]\r\n      }\r\n    }\r\n  }\r\n  responses: {\r\n    [hash: string]: ResponseInfo\r\n  }\r\n  request: {\r\n    [hash: string]: Omit<RequestInfo, 'url'>\r\n  }\r\n  customData: {\r\n    [key: string]: any\r\n  }\r\n}\r\n\r\ninterface ProxyOptions {\r\n  omitParams: RegExp | ((key: string, value: string) => boolean)\r\n}\r\n\r\nfunction md5(str: string): string {\r\n  return crypto.createHash('md5').update(str).digest('hex')\r\n}\r\n\r\n/**\r\n * 获取删除了某些params的url\r\n *\r\n * @param {string} url\r\n * @param {ProxyOptions['omitParams']} omitParams\r\n * @returns {string}\r\n */\r\nfunction parseUrl(\r\n  url: string,\r\n  omitParams: ProxyOptions['omitParams'],\r\n): {\r\n  url: string\r\n  params: Record<string, any>\r\n} {\r\n  let [realUrl, urlParamsText] = url.split('?')\r\n  const urlParams = deleteDeep(urlParamsText ? qs.parse(urlParamsText) : {}, omitParams)\r\n\r\n  return {\r\n    url: realUrl,\r\n    params: urlParams,\r\n  }\r\n}\r\n\r\n/**\r\n * 获取删除了某些params的postData\r\n *\r\n * @param {string} data\r\n * @param {ProxyOptions['omitParams']} omitParams\r\n * @returns {string}\r\n */\r\nfunction getPostDataAfterOmit(data: string, omitParams: ProxyOptions['omitParams']): string {\r\n  let res = data\r\n  try {\r\n    res = JSON.stringify(deleteDeep(JSON.parse(data), omitParams))\r\n  } catch (error) {\r\n    error\r\n  }\r\n  return res\r\n}\r\n\r\nfunction getRequestInfo(request: Request, omitParams: ProxyOptions['omitParams']): RequestInfo {\r\n  const method = request.method()\r\n  const urlParsed = parseUrl(request.url(), omitParams)\r\n\r\n  return {\r\n    url: urlParsed.url,\r\n    method,\r\n    params: JSON.stringify(urlParsed.params),\r\n    data: getPostDataAfterOmit(request.postData() ?? '', omitParams),\r\n  }\r\n}\r\n\r\nasync function getResponseInfo(response: Response): Promise<ResponseInfo> {\r\n  return {\r\n    status: response.status(),\r\n    headers: await response.allHeaders(),\r\n    body: await response.text(),\r\n  }\r\n}\r\n\r\nexport class MockProxy {\r\n  requestPool: RequestPool = {\r\n    pages: {},\r\n    responses: {},\r\n    request: {},\r\n    customData: {},\r\n  }\r\n\r\n  monitoring = false\r\n\r\n  options: ProxyOptions = {\r\n    omitParams: () => false,\r\n  }\r\n\r\n  constructor(options?: Partial<ProxyOptions>) {\r\n    merge(this.options, options)\r\n  }\r\n\r\n  startMonitoring() {\r\n    this.monitoring = true\r\n  }\r\n\r\n  addCustomProxy(context: BrowserContext, proxy: CustomProxy) {\r\n    proxy(this).forEach(args => context.route(...args))\r\n  }\r\n\r\n  /**\r\n   * 监听page，记录接口数据\r\n   *\r\n   * @param {Page} page\r\n   * @param {string} pageId\r\n   * @memberof MockProxy\r\n   */\r\n  monitorPage(page: Page, pageId: string) {\r\n    page.on('response', async res => {\r\n      if (!this.monitoring) {\r\n        return\r\n      }\r\n\r\n      // 只拦截json的请求\r\n      if (res.request().resourceType() === 'xhr') {\r\n        console.log(`[MockProxy] 监听中 page[${pageId}], url[${res.url()}]`)\r\n        const resName = await this.storeResponse(res)\r\n        this.storeRequest(res.request(), resName, pageId)\r\n      }\r\n    })\r\n  }\r\n\r\n  /**\r\n   * 代理page，伪造接口数据\r\n   * TODO:需要考虑接口循环的场景怎么处理\r\n   *\r\n   * @param {{\r\n   *     page: Page\r\n   *     pageId: string\r\n   *     origin: string 接口的origin\r\n   *     originCurrent: string 当前接口环境的origin\r\n   *   }} {\r\n   *     page,\r\n   *     pageId,\r\n   *     origin,\r\n   *     originReplace,\r\n   *   }\r\n   * @memberof MockProxy\r\n   */\r\n  proxyPage({\r\n    page,\r\n    pageId,\r\n    origin,\r\n    originCurrent,\r\n  }: {\r\n    page: Page\r\n    pageId: string\r\n    origin?: string\r\n    originCurrent?: string\r\n  }) {\r\n    const urlPool = this.requestPool.pages[pageId]\r\n\r\n    if (!urlPool) return\r\n    Object.entries(urlPool).map(([url, requestContent]) => {\r\n      let index = 0\r\n      let urlCurrent = origin && originCurrent ? url.replace(origin, originCurrent) : url\r\n      page.route(new RegExp(`${urlCurrent}($|\\\\?)`), (route, request) => {\r\n        // eslint-disable-next-line no-unused-vars\r\n        const { url: _, ...requestInfo } = getRequestInfo(request, this.options.omitParams)\r\n        const requestHash = md5(JSON.stringify(requestInfo))\r\n        const responseHash = requestContent[requestHash]?.[index++] ?? last(requestContent[requestHash])\r\n        const response = this.requestPool.responses[responseHash]\r\n\r\n        if (response) {\r\n          route.fulfill(response)\r\n        } else {\r\n          route.continue()\r\n        }\r\n        console.log(\r\n          `[MockProxy] 代理${response ? '成功' : '失败'}！page[${pageId}], url[${url}], requestHash[${requestHash}]`,\r\n        )\r\n      })\r\n    })\r\n  }\r\n\r\n  /**\r\n   * 存储请求信息\r\n   *\r\n   * @param {Request} request\r\n   * @param {string} responseHash\r\n   * @param {string} pageId\r\n   * @memberof MockProxy\r\n   */\r\n  async storeRequest(request: Request, responseHash: string, pageId: string) {\r\n    const { url, ...requestInfo } = getRequestInfo(request, this.options.omitParams)\r\n    const requestHash = md5(JSON.stringify(requestInfo))\r\n\r\n    this.requestPool.request[requestHash] = requestInfo\r\n\r\n    const path = [pageId, url, requestHash]\r\n    const requestPool: string[] = get(this.requestPool.pages, path)\r\n    if (!requestPool) {\r\n      set(this.requestPool.pages, path, [responseHash])\r\n    } else {\r\n      requestPool.push(responseHash)\r\n    }\r\n  }\r\n\r\n  /**\r\n   * 存储响应信息\r\n   *\r\n   * @param {Response} response\r\n   * @returns {Promise<string>}\r\n   * @memberof MockProxy\r\n   */\r\n  async storeResponse(response: Response): Promise<string> {\r\n    const resInfo = await getResponseInfo(response)\r\n    const hash = md5(JSON.stringify(resInfo))\r\n    this.requestPool.responses[hash] = resInfo\r\n    return hash\r\n  }\r\n\r\n  save(output: string) {\r\n    writeJson(this.requestPool, output)\r\n  }\r\n\r\n  load(file: string) {\r\n    this.requestPool = readJson(file)\r\n  }\r\n\r\n  reset() {\r\n    this.requestPool = {\r\n      pages: {},\r\n      responses: {},\r\n      request: {},\r\n      customData: {},\r\n    }\r\n    this.monitoring = false\r\n  }\r\n}\r\n","import { BrowserContext } from 'playwright'\r\n\r\nexport async function useTraceStart(context: BrowserContext, option = {}) {\r\n    return await context.tracing.start(option);\r\n}\r\n\r\nexport async function useTracestop(context: BrowserContext, saveTracPath: string) {\r\n    if (saveTracPath) {\r\n        return await context.tracing.stop({path: saveTracPath});\r\n    }\r\n\r\n    return Promise.resolve()\r\n}","import { BrowserName } from '@idux/wetest-engine'\r\nimport {\r\n  chromium,\r\n  firefox,\r\n  webkit,\r\n  Browser,\r\n  BrowserContext,\r\n  Page,\r\n  BrowserType,\r\n  LaunchOptions,\r\n  BrowserContextOptions,\r\n} from 'playwright'\r\nimport { EventEmitter } from 'stream'\r\nimport { flattenDeep } from 'lodash'\r\nimport { useTraceStart, useTracestop } from './hooks/useTrace'\r\nimport type TestInfoImpl from './utils/testInfoImpl'\r\nimport { Step } from './types/testInfo'\r\nimport { getEngineIsRunning, getRunnerConfig } from '@idux/wetest-share'\r\n\r\nexport function getBrowser(browser: BrowserName): BrowserType {\r\n  return {\r\n    chromium,\r\n    firefox,\r\n    webkit,\r\n  }[browser]\r\n}\r\n\r\nexport class BrowserManger extends EventEmitter {\r\n  browser?: Browser\r\n\r\n  private contextIdMap: Map<string, BrowserContext> = new Map()\r\n  private contextMap: Map<BrowserContext, Map<string, Page>> = new Map()\r\n\r\n  initListener(testInfoImpl: TestInfoImpl) {\r\n    let stepIndex = 0\r\n    const createInstrumentationListener = () => {\r\n      return {\r\n        onApiCallBegin: (apiCall, stackTrace, userData) => {\r\n          // playwright api开始监听器\r\n          const stepId = `pw:api@${apiCall}@${stepIndex++}`\r\n\r\n          const step: Step = {\r\n            stepId,\r\n            startTime: Date.now(),\r\n            title: `操作浏览器api：${apiCall}`,\r\n            status: 'pass',\r\n          }\r\n\r\n          testInfoImpl.addStep(step)\r\n\r\n          userData.userObject = step\r\n        },\r\n        onApiCallEnd: (userData, error) => {\r\n          // playwright api结束监听器\r\n\r\n          const step = userData.userObject\r\n\r\n          if (step) {\r\n            step.endTime = Date.now()\r\n          }\r\n\r\n          if (error) {\r\n            step.error = error.toString()\r\n            step.status = 'fail'\r\n          }\r\n        },\r\n      }\r\n    }\r\n\r\n    const onDidCreateBrowserContext = async context => {\r\n      const listener = createInstrumentationListener()\r\n\r\n      context._instrumentation.addListener(listener)\r\n    }\r\n\r\n    for (const browserType of [chromium, firefox, webkit]) {\r\n      // 为个浏览器注册playwright api监听器\r\n      ;(browserType as any)._onDidCreateContext = onDidCreateBrowserContext\r\n    }\r\n  }\r\n\r\n  async launch(browserName: BrowserName, launchOptions: LaunchOptions) {\r\n    const browserType = getBrowser(browserName)\r\n    this.browser = await browserType.launch(launchOptions)\r\n    return this\r\n  }\r\n\r\n  getContext(cxtId: string) {\r\n    const context = this.contextIdMap.get(cxtId)\r\n    if (!context) {\r\n      throw new Error(`[BrowserManger] Context(${cxtId}) not found.`)\r\n    }\r\n    return context\r\n  }\r\n\r\n  async newContext(id: string, options?: BrowserContextOptions) {\r\n    if (!this.browser) {\r\n      throw new Error('[wetest: BrowserManager] you should launch a browser before create context')\r\n    }\r\n\r\n    if (getEngineIsRunning()) {\r\n      const runnerConfig = getRunnerConfig()\r\n\r\n      let userAgent = runnerConfig.userAgent\r\n\r\n      if (options && userAgent && userAgent[this.browser.browserType().name()]) {\r\n        options.userAgent = userAgent[this.browser.browserType().name()]\r\n      }\r\n    }\r\n\r\n    const context = await this.browser.newContext(options)\r\n    this.contextIdMap.set(id, context)\r\n\r\n    this.emit('newContext', context, id)\r\n    return context\r\n  }\r\n\r\n  getPage(cxtId: string, pageId: string) {\r\n    const page = this.contextMap.get(this.getContext(cxtId))?.get(pageId)\r\n    if (!page) {\r\n      throw new Error(`Page(${pageId}) under Context(${cxtId}) not found.`)\r\n    }\r\n    return page\r\n  }\r\n\r\n  setPage(page: Page, cxtId: string, pageId: string) {\r\n    const context = this.getContext(cxtId)\r\n    const pageMap = this.contextMap.get(context) ?? new Map()\r\n    pageMap.set(pageId, page)\r\n    this.contextMap.set(context, pageMap)\r\n    this.emit('newPage', page, pageId, cxtId)\r\n  }\r\n\r\n  async newPage(cxtId: string, pageId: string) {\r\n    const context = this.getContext(cxtId)\r\n    const page = await context.newPage()\r\n    this.setPage(page, cxtId, pageId)\r\n    return page\r\n  }\r\n\r\n  /**\r\n   * 广播page\r\n   * 遍历pages，执行evaluate\r\n   *\r\n   * @param {string} evaluate\r\n   * @param {string} [cxtId]\r\n   * @memberof BrowserManger\r\n   */\r\n  async broadcastPage(evaluate: string, cxtId?: string) {\r\n    const contexts = cxtId ? [this.getContext(cxtId)] : this.browser?.contexts() ?? []\r\n    const pages = flattenDeep(contexts.map(cxt => cxt.pages()))\r\n    await Promise.all(pages.map(page => page.evaluate(evaluate)))\r\n  }\r\n\r\n  async closeContext(id?: string | string[]) {\r\n    let contexts: BrowserContext[] = []\r\n    if (!id) {\r\n      contexts = this.browser?.contexts() ?? []\r\n    } else {\r\n      const ids = Array.isArray(id) ? id : [id]\r\n      contexts = ids.map(id => this.getContext(id))\r\n    }\r\n    return Promise.all(contexts.map(ctx => ctx.close()) ?? [])\r\n  }\r\n\r\n  async close() {\r\n    await this.closeContext()\r\n    await this.browser?.close()\r\n  }\r\n\r\n  async stopTracing(saveTracPath: string, id?: string | string[]) {\r\n    let contexts: BrowserContext[] = []\r\n    if (!id) {\r\n      contexts = this.browser?.contexts() ?? []\r\n    } else {\r\n      const ids = Array.isArray(id) ? id : [id]\r\n      contexts = ids.map(id => this.getContext(id))\r\n    }\r\n    return Promise.all(\r\n      contexts.map(async ctx => {\r\n        return await useTracestop(ctx, saveTracPath)\r\n      }) ?? [],\r\n    )\r\n  }\r\n\r\n  async startTracing(context: BrowserContext, options = {}) {\r\n    return await useTraceStart(context, options)\r\n  }\r\n}\r\n","export function getDefaultSelectorCfg () {\r\n    return {\r\n        buryingPoint: '',\r\n        excludeClass: [],\r\n        excludeClassModify: new RegExp(/./),\r\n        excludeAttr: new RegExp(/./),\r\n        excludeIdByVal: new RegExp(/./),\r\n    }\r\n}","import { Assertor } from './assertor'\r\nimport { merge } from 'lodash'\r\nimport { join } from 'path'\r\nimport { BrowserContext, Page, BrowserContextOptions } from 'playwright'\r\nimport { EventEmitter } from 'stream'\r\nimport { Action, EngineApis, RecorderConfig } from './types'\r\nimport { getUuid } from './utils/uuid'\r\nimport { CaseManger } from './caseManager'\r\nimport { MockProxy } from './mockProxy'\r\nimport { O } from 'ts-toolbelt'\r\nimport { BrowserManger } from './browserManager'\r\nimport { writeJson } from './utils/fs'\r\nimport { existsSync } from 'fs'\r\nimport { getRecordConfig, loginCaseFileName } from '@idux/wetest-share'\r\nimport { getDefaultSelectorCfg } from '@idux/wetest-ai-selector/utils/util'\r\n\r\nclass Recorder extends EventEmitter {\r\n  private browserManager = new BrowserManger()\r\n  private caseManger?: CaseManger\r\n  private assertor?: Assertor\r\n  private mockProxy!: MockProxy\r\n\r\n  private options: RecorderConfig = {\r\n    rootDir: process.cwd(),\r\n    optimization: true,\r\n    stateDir: join(process.cwd(), 'state.json'),\r\n    snapshotTransfer: getRecordConfig().snapshotTransfer,\r\n    browser: {\r\n      type: 'chromium',\r\n    },\r\n    selector: getDefaultSelectorCfg(),\r\n  }\r\n\r\n  private recording = false\r\n\r\n  constructor(options?: O.Partial<RecorderConfig, 'deep'>) {\r\n    super()\r\n    merge(this.options, options)\r\n    this.options.stateDir = join(this.options.rootDir, 'state.json')\r\n    this.mockProxy = new MockProxy({\r\n      omitParams: this.options.proxy?.omitParams,\r\n    })\r\n  }\r\n\r\n  private async prepareContext(context: BrowserContext, ctxId = getUuid()) {\r\n    context.on('page', page => {\r\n      this.onPage(page, ctxId)\r\n    })\r\n\r\n    context.on('close', () => {\r\n      this.recordAction({\r\n        action: 'closeContext',\r\n        params: {\r\n          id: ctxId,\r\n        },\r\n      })\r\n    })\r\n\r\n    await context.addInitScript({\r\n      path: join(__dirname, '../inject/index.js'),\r\n    })\r\n\r\n    const isRecording: EngineApis['__wetest_isRecording'] = () => this.recording\r\n\r\n    await context.exposeFunction('__wetest_isRecording', isRecording)\r\n    await context.exposeBinding('__wetest_recordAction', ({ page }, action: Action) => {\r\n      this.recordAction(action)\r\n\r\n      if (action.action === 'assertion') {\r\n        this.assertor?.assert(action, page)\r\n      }\r\n    })\r\n    await context.exposeFunction('__wetest_createCase', this.createCase)\r\n    await context.exposeFunction('__wetest_startRecord', this.startRecord)\r\n    await context.exposeFunction('__wetest_finishRecord', this.finishRecord)\r\n    await context.exposeFunction('__wetest_getwetestCfg', this.getwetestCfg)\r\n    await context.exposeFunction('__wetest_exit', this.exit)\r\n  }\r\n\r\n  private async onPage(page: Page, ctxId: string, pageId = getUuid()) {\r\n    this.browserManager.setPage(page, ctxId, pageId)\r\n\r\n    this.preparePage(page, ctxId, pageId)\r\n\r\n    if (await page.opener()) {\r\n      this.caseManger?.setSignal({\r\n        name: 'popup',\r\n        pageId: pageId,\r\n      })\r\n    } else {\r\n      await page.waitForEvent('domcontentloaded')\r\n      this.recordAction({\r\n        action: 'newPage',\r\n        context: ctxId,\r\n        params: {\r\n          url: page.url(),\r\n          id: pageId,\r\n        },\r\n      })\r\n    }\r\n  }\r\n\r\n  private preparePage(page: Page, ctxId: string, pageId = getUuid()) {\r\n    page.on('close', () => {\r\n      this.recordAction({\r\n        action: 'closePage',\r\n        context: ctxId,\r\n        params: {\r\n          id: pageId,\r\n        },\r\n      })\r\n    })\r\n\r\n    page.on('domcontentloaded', () => {\r\n      page.evaluate(`window.__wetest_contextId = '${ctxId}'`)\r\n      page.evaluate(`window.__wetest_pageId = '${pageId}'`)\r\n    })\r\n\r\n    this.mockProxy.monitorPage(page, pageId)\r\n  }\r\n\r\n  private async recordAction(action: Action) {\r\n    if (!this.recording) return\r\n    this.caseManger?.recordAction(action)\r\n  }\r\n\r\n  async start({ url = 'http://localhost:8080' }: { url: string }) {\r\n    await this.browserManager.launch(this.options.browser.type, { headless: false })\r\n    this.browserManager.browser?.on('disconnected', this.exit)\r\n\r\n    // 录制登录状态的  还要在看一下路径具体怎么保存和拿取\r\n    const contextId = getUuid()\r\n    const contextParams: BrowserContextOptions = {\r\n      ignoreHTTPSErrors: true,\r\n    }\r\n\r\n    if (existsSync(this.options.stateDir)) {\r\n      contextParams.storageState = this.options.stateDir\r\n    }\r\n    const context = await this.browserManager.newContext(contextId, contextParams)\r\n    await this.prepareContext(context, contextId)\r\n\r\n    const page = await context.newPage()\r\n    await page.goto(url, {\r\n      waitUntil: 'domcontentloaded',\r\n    })\r\n  }\r\n\r\n  private getwetestCfg: EngineApis['__wetest_getwetestCfg'] = () => {\r\n    return {\r\n      selectorCfg: getRecordConfig().selector,\r\n    }\r\n  }\r\n\r\n  private createCase: EngineApis['__wetest_createCase'] = caseInfo => {\r\n    // 如果是登录的用例，在文件名上打个标记，方便后面重新认证的时候快速找到\r\n    if (caseInfo.loginCase) {\r\n      caseInfo.name = `${loginCaseFileName}/${caseInfo.name}`\r\n    }\r\n    this.caseManger = new CaseManger(join(this.options.rootDir, caseInfo.name))\r\n    return this.caseManger.create(caseInfo)\r\n  }\r\n\r\n  private startRecord: EngineApis['__wetest_startRecord'] = ({ context, page, url }) => {\r\n    if (!this.caseManger) {\r\n      throw new Error('[wetest: Recorder] start record before create case!')\r\n    }\r\n\r\n    this.caseManger.case.viewport &&\r\n      this.browserManager.getPage(context, page).setViewportSize(this.caseManger.case.viewport)\r\n\r\n    this.assertor = new Assertor(\r\n      Object.assign({}, this.caseManger.pathResolve, { snapshotTransfer: this.options.snapshotTransfer }),\r\n    )\r\n\r\n    if (this.caseManger.case.saveMock) {\r\n      this.mockProxy.startMonitoring()\r\n      this.options.proxy?.customProxy &&\r\n        this.mockProxy.addCustomProxy(this.browserManager.getContext(context), this.options.proxy.customProxy)\r\n    }\r\n\r\n    this.options.beforeStartRecord?.({ page: this.browserManager.getPage(context, page), caseManager: this.caseManger })\r\n\r\n    this.recording = true\r\n\r\n    this.recordAction({\r\n      action: 'newContext',\r\n      params: {\r\n        id: context,\r\n      },\r\n    })\r\n    this.recordAction({\r\n      action: 'newPage',\r\n      context,\r\n      params: {\r\n        id: page,\r\n        url,\r\n      },\r\n    })\r\n\r\n    this.syncStatus()\r\n\r\n    this.options.afterStartRecord?.({ page: this.browserManager.getPage(context, page), caseManager: this.caseManger })\r\n  }\r\n\r\n  private finishRecord: EngineApis['__wetest_finishRecord'] = async ({ context }: { context: string }) => {\r\n    if (!this.caseManger) {\r\n      throw new Error(`[wetest: Recorder] don't have a case but calling finish record!`)\r\n    }\r\n\r\n    // 如果是登录用例，需要保存认证信息\r\n    if (this.caseManger.case.loginCase) {\r\n      this.recordAction({\r\n        action: 'saveStatus',\r\n        context: '1001',\r\n        page: '1002',\r\n        params: {},\r\n      })\r\n    }\r\n\r\n    this.recordAction({\r\n      action: 'closeContext',\r\n      params: {\r\n        id: context,\r\n      },\r\n    })\r\n\r\n    // 对 case.json 进行优化。如：input 会产生多个事件，过滤剩下一个\r\n    if (this.options.optimization) {\r\n      const rawActions = this.caseManger.case.actions\r\n      const optActions = rawActions.filter((item, index) => {\r\n        const nextActions = rawActions[index + 1]\r\n        return !(item.action === 'input' && nextActions.action === item.action)\r\n      })\r\n      this.caseManger.case.actions = optActions\r\n    }\r\n\r\n    this.options.beforeFinishRecord?.({ caseManager: this.caseManger })\r\n\r\n    this.recording = false\r\n    this.caseManger.save()\r\n    this.mockProxy.save(this.caseManger.pathResolve.mockFile)\r\n    this.mockProxy.reset()\r\n    this.assertor && writeJson(this.assertor?.snapshots, this.caseManger.pathResolve.snapshotFile)\r\n    this.syncStatus()\r\n\r\n    this.options.afterFinishRecord?.({ caseManager: this.caseManger })\r\n  }\r\n\r\n  private exit: EngineApis['__wetest_exit'] = async () => {\r\n    await this.browserManager.close()\r\n    this.emit('exit')\r\n  }\r\n\r\n  private syncStatus() {\r\n    this.browserManager.broadcastPage(`window.__wetest_syncStatus(${this.recording})`)\r\n  }\r\n}\r\n\r\nexport { Recorder }\r\n","import { Step, TestInfoImplParams, TestInfo, TestStatus } from '../types/testInfo'\r\nimport { getUuid } from './uuid'\r\n\r\n\r\nexport default class TestInfoImpl {\r\n    private testId: string\r\n    private name: string\r\n    private startTime: number\r\n    private endTime: number\r\n    private steps: Step[] = []\r\n    private errors: string[] = []\r\n    private status: TestStatus = 'pass'\r\n\r\n    constructor(params: TestInfoImplParams) {\r\n        this.name = params.name\r\n        this.startTime = this.endTime = Date.now()\r\n        this.testId = `testid@${getUuid()}@${this.startTime}`\r\n    }\r\n\r\n    public addStep (step: Step) : Step {\r\n        this.steps.push(step)\r\n        return step\r\n    }\r\n\r\n    public complete (status: TestStatus) {\r\n        this.status = status\r\n        this.endTime = Date.now()\r\n    }\r\n\r\n    public getTestInfo () : TestInfo {\r\n        this.procssData()\r\n\r\n        return {\r\n            testId: this.testId,\r\n            name: this.name,\r\n            startTime: this.startTime,\r\n            endTime: this.endTime,\r\n            errors: this.errors,\r\n            steps: this.steps,\r\n            status: this.status\r\n        }\r\n    }\r\n\r\n    private procssData () {\r\n        if (this.status === 'fail') {\r\n\r\n            this.steps.forEach(step => {\r\n                if (step.error) {\r\n                    this.errors.push(step.error)\r\n                }\r\n            })\r\n        }\r\n    }\r\n}","import { Assertor } from './assertor'\r\nimport { CaseManger } from './caseManager'\r\nimport { merge, pick } from 'lodash'\r\nimport { Page, BrowserContextOptions } from 'playwright'\r\nimport { Action, ManualAction } from './types'\r\nimport { EventEmitter } from 'stream'\r\nimport { BrowserManger } from './browserManager'\r\nimport { MockProxy } from './mockProxy'\r\nimport { RunnerConfig } from './types'\r\nimport { O } from 'ts-toolbelt'\r\nimport { join } from 'path'\r\nimport { rmDir, writeJson } from '@idux/wetest-share'\r\nimport { existsSync } from 'fs'\r\n// import NetworkHelper from './utils/networkHelper'\r\nimport TestInfoImpl from './utils/testInfoImpl'\r\nimport { autoTrySelector } from './utils/common'\r\nimport { Log } from './utils/log'\r\nimport { setTestInfoImplState, getRunnerConfig, getTestInfoImplState } from '@idux/wetest-share'\r\nimport dayjs from 'dayjs'\r\n\r\nclass Runner extends EventEmitter {\r\n  private options: RunnerConfig = {\r\n    errorsDir: join(process.cwd(), '__errors__'),\r\n    stateDir: join(process.cwd(), 'state.json'),\r\n    traceDir: join(process.cwd(), 'traceData'),\r\n    loginUrl: '',\r\n    cookies: [],\r\n    browser: {\r\n      type: 'chromium',\r\n      headless: true,\r\n    },\r\n    reporter: {\r\n      alwaysShowTracing: false,\r\n\r\n      tracingScreenshots: true,\r\n    },\r\n    userAgent: {},\r\n    timeout: 30000,\r\n  }\r\n  private caseName: string = ''\r\n  private traceMap = new Map()\r\n  // private networkHelper: any\r\n  private browserManager!: BrowserManger\r\n  private caseManager!: CaseManger\r\n  private assertor!: Assertor\r\n\r\n  constructor(options?: O.Partial<RunnerConfig, 'deep'>) {\r\n    super()\r\n    merge(this.options, options)\r\n  }\r\n\r\n  private async init(caseDir: string, fileName: string) {\r\n    if (!this.browserManager) {\r\n      this.browserManager = new BrowserManger()\r\n      await this.browserManager.launch(this.options.browser.type, {\r\n        headless: this.options.browser.headless,\r\n        slowMo: this.options.actionInterval,\r\n      })\r\n    }\r\n    this.caseManager = new CaseManger(caseDir)\r\n    this.caseManager.load()\r\n\r\n    const runnerConfig = getRunnerConfig()\r\n\r\n    this.assertor = new Assertor({\r\n      ...this.caseManager.pathResolve,\r\n      runtimeDir: join(this.options.errorsDir, fileName),\r\n      snapshotTransfer: runnerConfig.snapshotTransfer,\r\n      origin: {\r\n        old: this.caseManager.case.origin,\r\n        new: this.options.origin,\r\n      },\r\n    })\r\n\r\n    this.assertor.loadSnapshots()\r\n\r\n    if (this.caseManager.case.saveMock) {\r\n      const mockProxy = new MockProxy({\r\n        omitParams: this.options.proxy?.omitParams,\r\n      })\r\n      mockProxy.load(this.caseManager.pathResolve.mockFile)\r\n\r\n      this.browserManager.on('newPage', (page: Page, pageId: string) => {\r\n        mockProxy.proxyPage({ page, pageId, origin: this.caseManager?.case.origin, originCurrent: this.options.origin })\r\n      })\r\n\r\n      this.browserManager.on('newContext', context => {\r\n        this.options.proxy?.customProxy && mockProxy.addCustomProxy(context, this.options.proxy.customProxy)\r\n      })\r\n    }\r\n  }\r\n\r\n  async stopTracing(testInfoImpl: TestInfoImpl) {\r\n    return await this.browserManager.stopTracing(\r\n      join(this.options.traceDir, `${testInfoImpl.getTestInfo().testId}.zip`),\r\n    )\r\n  }\r\n\r\n  async runCase(caseDir: string, fileName: string) {\r\n    await this.init(caseDir, fileName)\r\n    const errorsDir = join(this.options.errorsDir, fileName)\r\n    this.options.beforeRunCase?.({ caseManager: this.caseManager })\r\n    this.caseName = this.caseManager.case.name\r\n    const runnerConfig = getRunnerConfig()\r\n\r\n    // 执行登录用例前需要把已有的state删掉，防止污染\r\n    if (this.caseManager.case.loginCase && existsSync(this.options.stateDir)) {\r\n      rmDir(this.options.stateDir)\r\n    }\r\n\r\n    const testInfoImpl = new TestInfoImpl({ name: fileName })\r\n    this.browserManager.initListener(testInfoImpl)\r\n    setTestInfoImplState(testInfoImpl)\r\n    for (let index = 0; index < this.caseManager.case.actions.length; index++) {\r\n      const action = this.caseManager.case.actions[index]\r\n      const startTime = Date.now()\r\n\r\n      try {\r\n        await this.runAction(action)\r\n      } catch (error) {\r\n        if (error instanceof Error) {\r\n          if ((action as ManualAction).page && this.browserManager) {\r\n            const pageUrl = this.browserManager\r\n              .getPage((action as ManualAction).context, (action as ManualAction).page)\r\n              .url()\r\n\r\n            if (!this.caseManager.case.loginCase && pageUrl === runnerConfig.loginUrl) {\r\n              error.message = '[user-state-error]'\r\n              await this.stopTracing(testInfoImpl)\r\n              await this.browserManager.closeContext()\r\n              throw error\r\n            }\r\n          }\r\n\r\n          writeJson(\r\n            {\r\n              action,\r\n              message: error.message,\r\n              cause: [...this.traceMap.keys()],\r\n            },\r\n            join(errorsDir, 'error.log'),\r\n          )\r\n\r\n          if (error.message.includes('waitForLoadState') && error.message.includes('Timeout')) {\r\n            ;[...this.traceMap.keys()].forEach(item => {\r\n              testInfoImpl.addStep({\r\n                stepId: 'pw:timeout@1',\r\n                title: '资源加载超时',\r\n                startTime,\r\n                endTime: Date.now(),\r\n                error: `[${dayjs(startTime).format('YYYY-MM-DD HH:mm:ss')}] 等待超时： ${item}`,\r\n                status: 'fail',\r\n              })\r\n            })\r\n          }\r\n\r\n          await this.stopTracing(testInfoImpl)\r\n          testInfoImpl.complete('fail')\r\n          this.emit('testEnd', testInfoImpl.getTestInfo())\r\n\r\n          if (this.caseManager.case.loginCase) {\r\n            error.message = '[login-error]'\r\n          } else {\r\n            await this.browserManager.closeContext()\r\n          }\r\n          throw error\r\n        }\r\n      }\r\n    }\r\n\r\n    testInfoImpl.complete('pass')\r\n    this.emit('testEnd', testInfoImpl.getTestInfo())\r\n\r\n    // 成功执行，删除error下的目录\r\n    rmDir(errorsDir)\r\n\r\n    this.options.afterRunCase?.({ caseManager: this.caseManager, result: [] })\r\n  }\r\n\r\n  private async runAction(action: Action) {\r\n    Log.runnerActionLog(action.action)\r\n    const runnerConfig = getRunnerConfig()\r\n    if (action.action === 'assertion') {\r\n      // await this.networkHelper.waitForNetworkSettled()\r\n      await this.assertor.runAssertion(action, this.browserManager.getPage(action.context, action.page))\r\n      return\r\n    }\r\n\r\n    if (action.action === 'newContext') {\r\n      const contextParams: BrowserContextOptions = {\r\n        viewport: this.caseManager.case.viewport,\r\n        ignoreHTTPSErrors: true,\r\n      }\r\n      if (existsSync(this.options.stateDir)) {\r\n        contextParams.storageState = this.options.stateDir\r\n      }\r\n      const context = await this.browserManager.newContext(action.params.id, contextParams)\r\n      await this.browserManager.startTracing(context, {\r\n        screenshots: this.options.reporter.tracingScreenshots,\r\n        snapshots: true,\r\n        title: this.caseName,\r\n      })\r\n      return\r\n    }\r\n\r\n    if (action.action === 'closeContext') {\r\n      const {\r\n        params: { id },\r\n      } = action\r\n\r\n      const ctx = this.browserManager.getContext(id)\r\n\r\n      const testInfoImpl = getTestInfoImplState()\r\n\r\n      // 当配置了总是输出跟踪栈，成功的时候也需要输出\r\n      if (this.options.reporter.alwaysShowTracing) {\r\n        await this.stopTracing(testInfoImpl)\r\n      }\r\n\r\n      await ctx.close()\r\n      return\r\n    }\r\n\r\n    if (action.action === 'newPage') {\r\n      const {\r\n        context: cxtId,\r\n        params: { id: pageId, url },\r\n      } = action\r\n      const context = this.browserManager.getContext(cxtId)\r\n      const page = await context.newPage()\r\n\r\n      page.on('request', interceptedRequest => {\r\n        const url = interceptedRequest.url()\r\n        this.traceMap.set(url, interceptedRequest)\r\n      })\r\n\r\n      page.on('requestfinished', interceptedRequest => {\r\n        const url = interceptedRequest.url()\r\n        this.traceMap.delete(url)\r\n      })\r\n\r\n      if (runnerConfig.abortUrl) {\r\n        await page.route(runnerConfig.abortUrl, route => {\r\n          route.abort()\r\n        })\r\n      }\r\n\r\n      // this.networkHelper = new NetworkHelper(page)\r\n      const newUrl =\r\n        this.caseManager?.case.origin && this.options.origin\r\n          ? url.replace(this.caseManager?.case.origin, this.options.origin)\r\n          : url\r\n      this.browserManager.setPage(page, cxtId, pageId)\r\n      await page.goto(newUrl, {\r\n        waitUntil: 'load',\r\n      })\r\n      await page.waitForLoadState('networkidle', {\r\n        timeout: this.options.timeout,\r\n      })\r\n      page.setDefaultTimeout(this.options.timeout)\r\n      return\r\n    }\r\n\r\n    if (action.action === 'saveStatus') {\r\n      const { context: cxtId } = action\r\n\r\n      const context = this.browserManager.getContext(cxtId)\r\n      context.addCookies(this.options.cookies)\r\n      await context.storageState({ path: this.options.stateDir })\r\n    }\r\n\r\n    if (action.action === 'closePage') {\r\n      const {\r\n        context: cxtId,\r\n        params: { id: pageId },\r\n      } = action\r\n      await this.browserManager.getPage(cxtId, pageId).close()\r\n      return\r\n    }\r\n\r\n    if (action.action === 'error') {\r\n      throw new Error(`Action: action '${action.action}' is invalid.`)\r\n    }\r\n\r\n    // await this.networkHelper.waitForNetworkSettled()\r\n    await this.runManualAction(action)\r\n  }\r\n\r\n  private async runManualAction(action: ManualAction) {\r\n    const { context: cxtId, page: pageId, signals = {} } = action\r\n    const page = this.browserManager.getPage(cxtId, pageId)\r\n\r\n    let actionPromise = () => Promise.resolve()\r\n\r\n    if (action.action === 'click') {\r\n      // 配置：https://playwright.dev/docs/api/class-page#page-click\r\n      const options = pick(action.params, [\r\n        'button',\r\n        'clickCount',\r\n        'delay',\r\n        'force',\r\n        'modifiers',\r\n        'noWaitAfter',\r\n        'position',\r\n        'strict',\r\n        'timeout',\r\n        'trial',\r\n      ])\r\n      const pageFn = (selector: string) => page.click(selector, options)\r\n      actionPromise = () => autoTrySelector(pageFn, action.params.selector, page)\r\n    }\r\n    if (action.action === 'hover') {\r\n      const pageFn = (selector: string) => page.hover(selector)\r\n      actionPromise = () => autoTrySelector(pageFn, action.params.selector, page)\r\n    }\r\n    if (action.action === 'waitForTimeout') {\r\n      await page.waitForTimeout(action.params.time)\r\n    }\r\n    if (action.action === 'input') {\r\n      const pageFn = (selector: string) => page.fill(selector, action.params.content)\r\n      actionPromise = () => autoTrySelector(pageFn, action.params.selector, page)\r\n    }\r\n    if (action.action === 'press') {\r\n      const modifier = action.params.modifiers?.join('+')\r\n      const key = modifier ? `${modifier}+${action.params.key}` : action.params.key\r\n      const pageFn = (selector: string) => page.press(selector, key)\r\n      actionPromise = () => autoTrySelector(pageFn, action.params.selector, page)\r\n    }\r\n    if (action.action === 'scroll') {\r\n      actionPromise = async () => {\r\n        await page.evaluate(`window.scrollTo(${action.params.x}, ${action.params.y})`)\r\n      }\r\n    }\r\n\r\n    if (signals.popup) {\r\n      const [popupPage] = await Promise.all([page.waitForEvent('popup'), actionPromise()])\r\n      this.browserManager.setPage(popupPage, cxtId, signals.popup.pageId)\r\n    } else {\r\n      // await this.networkHelper.waitForNetworkSettled()\r\n      await actionPromise()\r\n    }\r\n    await page.waitForTimeout(600)\r\n    await page.waitForLoadState('networkidle', {\r\n      timeout: this.options.timeout,\r\n    })\r\n  }\r\n\r\n  async finish() {\r\n    await this.browserManager?.close()\r\n  }\r\n}\r\n\r\nexport { Runner }\r\n"]}