提交 feaf1646 编写于 作者: fxy060608's avatar fxy060608

feat(automator): support safari,firefox

上级 9bd8db1d
......@@ -5,5 +5,12 @@ packages/uni-automator/lib
packages/uni-cli-nvue/lib
packages/uni-cli-shared/lib
packages/uni-components/lib
packages/uni-cloud/lib
packages/uni-mp-alipay/lib
packages/uni-mp-baidu/lib
packages/uni-mp-kuaishou/lib
packages/uni-mp-qq/lib
packages/uni-mp-toutiao/lib
packages/uni-mp-vue/lib
packages/uni-cloud/lib
\ No newline at end of file
packages/uni-mp-weixin/lib
packages/uni-mp-quickapp-webview/lib
\ No newline at end of file
'use strict'
function _interopDefault(ex) {
return ex && typeof ex === 'object' && 'default' in ex ? ex['default'] : ex
function t(t) {
return t && 'object' == typeof t && 'default' in t ? t.default : t
}
var fs = _interopDefault(require('fs'))
var debug = _interopDefault(require('debug'))
var parser = _interopDefault(require('postcss-selector-parser'))
var fs$1 = _interopDefault(require('fs-extra'))
var dateFormat = _interopDefault(require('licia/dateFormat'))
var path = require('path')
var util = require('util')
require('address')
require('default-gateway')
require('licia/isStr')
require('licia/getPort')
function transform(selectors) {
selectors.walk((selector) => {
if (selector.type === 'tag') {
const value = selector.value
if (value === 'page') {
//@ts-ignore
{
selector.value = 'body'
}
} else {
selector.value = 'uni-' + value
}
var e = t(require('fs')),
s = t(require('debug')),
i = t(require('postcss-selector-parser')),
r = t(require('fs-extra')),
a = t(require('licia/dateFormat')),
n = require('path'),
o = require('util')
require('address'),
require('default-gateway'),
require('licia/isStr'),
require('licia/getPort')
s('automator:devtool')
function l(t) {
t.walk((t) => {
if ('tag' === t.type) {
const e = t.value
t.value = 'page' === e ? 'body' : 'uni-' + e
}
})
}
function transSelector(method) {
return {
reflect: async (send, params) => send(method, params, false),
params(params) {
if (params.selector) {
params.selector = parser(transform).processSync(params.selector)
}
return params
},
}
}
const methods = [
const c = [
'Page.getElement',
'Page.getElements',
'Element.getElement',
'Element.getElements',
]
function initAdapter(adapter) {
methods.forEach((method) => {
adapter[method] = transSelector(method)
})
}
const qrCodeTerminal = require('qrcode-terminal')
const QrCodeReader = require('qrcode-reader')
const isWin = /^win/.test(process.platform)
const normalizePath = (path) => (isWin ? path.replace(/\\/g, '/') : path)
const debugLauncher = debug('automator:launcher')
const APPID = 'HBuilder'
const PACKAGE = 'io.dcloud.HBuilder'
const readdir = util.promisify(fs.readdir)
const stat = util.promisify(fs.stat)
async function getFiles(dir) {
const subdirs = await readdir(dir)
const files = await Promise.all(
subdirs.map(async (subdir) => {
const res = path.resolve(dir, subdir)
return (await stat(res)).isDirectory() ? getFiles(res) : res
})
)
return files.reduce((a, f) => a.concat(f), [])
}
class Launcher {
constructor(options) {
this.id = options.id
this.app = options.executablePath
this.appid = options.appid || APPID
this.package = options.package || PACKAGE
require('qrcode-terminal'), require('qrcode-reader')
const h = /^win/.test(process.platform),
u = s('automator:launcher'),
d = o.promisify(e.readdir),
p = o.promisify(e.stat)
class m {
constructor(t) {
;(this.id = t.id),
(this.app = t.executablePath),
(this.appid = t.appid || 'HBuilder'),
(this.package = t.package || 'io.dcloud.HBuilder')
}
shouldPush() {
return this.exists(this.FILE_APP_SERVICE)
.then(() => {
debugLauncher(
`${dateFormat('yyyy-mm-dd HH:MM:ss:l')} ${
this.FILE_APP_SERVICE
} exists`
.then(
() => (
u(`${a('yyyy-mm-dd HH:MM:ss:l')} ${this.FILE_APP_SERVICE} exists`), !1
)
return false
})
.catch(() => {
debugLauncher(
`${dateFormat('yyyy-mm-dd HH:MM:ss:l')} ${
this.FILE_APP_SERVICE
} not exists`
)
.catch(
() => (
u(
`${a('yyyy-mm-dd HH:MM:ss:l')} ${this.FILE_APP_SERVICE} not exists`
),
!0
)
return true
})
)
}
push(from) {
return getFiles(from)
.then((files) => {
const pushs = files.map((file) => {
const to = normalizePath(
path.join(this.DIR_WWW, path.relative(from, file))
push(t) {
return (async function t(e) {
const s = await d(e)
return (
await Promise.all(
s.map(async (s) => {
const i = n.resolve(e, s)
return (await p(i)).isDirectory() ? t(i) : i
})
)
).reduce((t, e) => t.concat(e), [])
})(t)
.then((e) => {
const s = e.map((e) => {
const s = ((t) => (h ? t.replace(/\\/g, '/') : t))(
n.join(this.DIR_WWW, n.relative(t, e))
)
debugLauncher(
`${dateFormat('yyyy-mm-dd HH:MM:ss:l')} push ${file} ${to}`
return (
u(`${a('yyyy-mm-dd HH:MM:ss:l')} push ${e} ${s}`),
this.pushFile(e, s)
)
return this.pushFile(file, to)
})
return Promise.all(pushs)
return Promise.all(s)
})
.then((res) => true)
.then((t) => !0)
}
get FILE_APP_SERVICE() {
return `${this.DIR_WWW}/app-service.js`
return this.DIR_WWW + '/app-service.js'
}
}
const debugClient = debug('automator:simctl')
function padZero(str) {
const num = parseInt(str)
return num > 9 ? String(num) : '0' + num
const y = s('automator:simctl')
function f(t) {
const e = parseInt(t)
return e > 9 ? String(e) : '0' + e
}
class IOS extends Launcher {
class g extends m {
constructor() {
super(...arguments)
this.bundleVersion = ''
super(...arguments), (this.bundleVersion = '')
}
async init() {
const Simctl = require('node-simctl').Simctl
this.tool = new Simctl({ udid: this.id })
const t = require('node-simctl').Simctl
this.tool = new t({ udid: this.id })
try {
await this.tool.bootDevice()
} catch (e) {}
await this.initSDCard()
debugClient(`${dateFormat('yyyy-mm-dd HH:MM:ss:l')} init ${this.id}`)
} catch (t) {}
await this.initSDCard(), y(`${a('yyyy-mm-dd HH:MM:ss:l')} init ${this.id}`)
}
async initSDCard() {
const appInfo = await this.tool.appInfo(this.package)
debugClient(`${dateFormat('yyyy-mm-dd HH:MM:ss:l')} appInfo ${appInfo}`)
const matches = appInfo.match(/DataContainer\s+=\s+"(.*)"/)
if (!matches) {
return Promise.resolve('')
}
const versionMatches = appInfo.match(/CFBundleVersion\s+=\s+(.*);/)
if (!versionMatches) {
return Promise.resolve('')
}
this.sdcard = matches[1].replace('file:', '')
this.bundleVersion = versionMatches[1]
debugClient(`${dateFormat('yyyy-mm-dd HH:MM:ss:l')} install ${this.sdcard}`)
const t = await this.tool.appInfo(this.package)
y(`${a('yyyy-mm-dd HH:MM:ss:l')} appInfo ${t}`)
const e = t.match(/DataContainer\s+=\s+"(.*)"/)
if (!e) return Promise.resolve('')
const s = t.match(/CFBundleVersion\s+=\s+(.*);/)
if (!s) return Promise.resolve('')
;(this.sdcard = e[1].replace('file:', '')),
(this.bundleVersion = s[1]),
y(`${a('yyyy-mm-dd HH:MM:ss:l')} install ${this.sdcard}`)
}
async version() {
return Promise.resolve(this.bundleVersion)
}
formatVersion(version) {
const versions = version.split('.')
if (versions.length !== 3) {
return version
}
return versions[0] + padZero(versions[1]) + padZero(versions[2])
formatVersion(t) {
const e = t.split('.')
return 3 !== e.length ? t : e[0] + f(e[1]) + f(e[2])
}
async install() {
debugClient(`${dateFormat('yyyy-mm-dd HH:MM:ss:l')} install ${this.app}`)
await this.tool.installApp(this.app)
await this.tool.grantPermission(this.package, 'all')
await this.initSDCard()
return Promise.resolve(true)
return (
y(`${a('yyyy-mm-dd HH:MM:ss:l')} install ${this.app}`),
await this.tool.installApp(this.app),
await this.tool.grantPermission(this.package, 'all'),
await this.initSDCard(),
Promise.resolve(!0)
)
}
async start() {
try {
await this.tool.terminateApp(this.package)
await this.tool.launchApp(this.package)
} catch (e) {}
return Promise.resolve(true)
await this.tool.terminateApp(this.package),
await this.tool.launchApp(this.package)
} catch (t) {}
return Promise.resolve(!0)
}
async exit() {
await this.tool.terminateApp(this.package)
await this.tool.shutdownDevice()
return Promise.resolve(true)
return (
await this.tool.terminateApp(this.package),
await this.tool.shutdownDevice(),
Promise.resolve(!0)
)
}
async captureScreenshot() {
return Promise.resolve(await this.tool.getScreenshot())
}
exists(file) {
return fs$1.existsSync(file)
? Promise.resolve(true)
: Promise.reject(Error(`${file} not exists`))
exists(t) {
return r.existsSync(t)
? Promise.resolve(!0)
: Promise.reject(Error(t + ' not exists'))
}
pushFile(from, to) {
return Promise.resolve(fs$1.copySync(from, to))
pushFile(t, e) {
return Promise.resolve(r.copySync(t, e))
}
get DIR_WWW() {
return `${this.sdcard}/Documents/Pandora/apps/${this.appid}/www/`
}
}
const adb = require('adbkit')
const debugClient$1 = debug('automator:adb')
const $EXTERNAL_STORAGE = '$EXTERNAL_STORAGE'
class Android extends Launcher {
const w = require('adbkit'),
M = s('automator:adb')
class P extends m {
async init() {
// adbkit 异常时,可能不会关闭 socket
this.tool = adb.createClient()
if (!this.id) {
const devices = await this.tool.listDevices()
if (!devices.length) {
throw Error(`Device not found`)
}
this.id = devices[0].id
if (((this.tool = w.createClient()), !this.id)) {
const t = await this.tool.listDevices()
if (!t.length) throw Error('Device not found')
this.id = t[0].id
}
this.sdcard = (await this.shell(this.COMMAND_EXTERNAL)).trim()
debugClient$1(
`${dateFormat('yyyy-mm-dd HH:MM:ss:l')} init ${this.id} ${this.sdcard}`
)
;(this.sdcard = (await this.shell(this.COMMAND_EXTERNAL)).trim()),
M(`${a('yyyy-mm-dd HH:MM:ss:l')} init ${this.id} ${this.sdcard}`)
}
version() {
return this.shell(this.COMMAND_VERSION).then((output) => {
const matches = output.match(/versionName=(.*)/)
if (matches && matches.length > 1) {
return matches[1]
}
return ''
return this.shell(this.COMMAND_VERSION).then((t) => {
const e = t.match(/versionName=(.*)/)
return e && e.length > 1 ? e[1] : ''
})
}
formatVersion(version) {
return version
formatVersion(t) {
return t
}
async install() {
let grant = true
let t = !0
try {
const props = await this.tool.getProperties(this.id)
const version = props['ro.build.version.release'].split('.')[0]
if (parseInt(version) < 6) {
grant = false
}
} catch (e) {}
debugClient$1(
`${dateFormat('yyyy-mm-dd HH:MM:ss:l')} install ${
this.app
} permission=${grant}`
)
if (grant) {
const Command = require('adbkit/lib/adb/command.js')
const oldSend = Command.prototype._send
Command.prototype._send = function send(data) {
if (data.indexOf('shell:pm install -r ') === 0) {
data = data.replace('shell:pm install -r ', 'shell:pm install -r -g ')
debugClient$1(`${dateFormat('yyyy-mm-dd HH:MM:ss:l')} ${data} `)
}
return oldSend.call(this, data)
const e = (await this.tool.getProperties(this.id))[
'ro.build.version.release'
].split('.')[0]
parseInt(e) < 6 && (t = !1)
} catch (t) {}
if (
(M(`${a('yyyy-mm-dd HH:MM:ss:l')} install ${this.app} permission=${t}`),
t)
) {
const t = require('adbkit/lib/adb/command.js'),
e = t.prototype._send
t.prototype._send = function (t) {
return (
0 === t.indexOf('shell:pm install -r ') &&
((t = t.replace('shell:pm install -r ', 'shell:pm install -r -g ')),
M(`${a('yyyy-mm-dd HH:MM:ss:l')} ${t} `)),
e.call(this, t)
)
}
}
return this.tool.install(this.id, this.app).then(() => this.init())
......@@ -265,151 +212,126 @@ class Android extends Launcher {
return this.shell(this.COMMAND_STOP)
}
captureScreenshot() {
return this.tool.screencap(this.id).then((stream) => {
return new Promise((resolve) => {
const chunks = []
stream.on('data', function (chunk) {
chunks.push(chunk)
})
stream.on('end', function () {
resolve(Buffer.concat(chunks).toString('base64'))
return this.tool.screencap(this.id).then(
(t) =>
new Promise((e) => {
const s = []
t.on('data', function (t) {
s.push(t)
}),
t.on('end', function () {
e(Buffer.concat(s).toString('base64'))
})
})
})
})
}
exists(file) {
return this.tool.stat(this.id, file)
}
pushFile(from, to) {
return this.tool.push(this.id, from, to)
)
}
shell(command) {
debugClient$1(`${dateFormat('yyyy-mm-dd HH:MM:ss:l')} SEND ► ${command}`)
return this.tool
.shell(this.id, command)
.then(adb.util.readAll)
.then((output) => {
const res = output.toString()
debugClient$1(`${dateFormat('yyyy-mm-dd HH:MM:ss:l')} ◀ RECV ${res}`)
return res
})
exists(t) {
return this.tool.stat(this.id, t)
}
pushFile(t, e) {
return this.tool.push(this.id, t, e)
}
shell(t) {
return (
M(`${a('yyyy-mm-dd HH:MM:ss:l')} SEND ► ${t}`),
this.tool
.shell(this.id, t)
.then(w.util.readAll)
.then((t) => {
const e = t.toString()
return M(`${a('yyyy-mm-dd HH:MM:ss:l')} ◀ RECV ${e}`), e
})
)
}
get DIR_WWW() {
return `${this.sdcard}/Android/data/${this.package}/apps/${this.appid}/www`
}
get COMMAND_EXTERNAL() {
return `echo ${$EXTERNAL_STORAGE}`
return 'echo $EXTERNAL_STORAGE'
}
get COMMAND_VERSION() {
return `dumpsys package ${this.package}`
return 'dumpsys package ' + this.package
}
get COMMAND_STOP() {
return `am force-stop ${this.package}`
return 'am force-stop ' + this.package
}
get COMMAND_START() {
return `am start -n ${this.package}/io.dcloud.PandoraEntry --es ${this.appid} --ez needUpdateApp false --ez reload true`
}
}
const debugDevtools = debug('automator:devtool')
let launcher
let install = false
function createLauncher(platform, options) {
if (platform === 'ios') {
return new IOS(options)
}
return new Android(options)
}
const VERSIONS_RE = {
android: /android_version=(.*)/,
ios: /iphone_version=(.*)/,
}
function getVersion(version, platform) {
if (version.endsWith('.txt')) {
try {
const versionStr = fs.readFileSync(version).toString()
const matches = versionStr.match(VERSIONS_RE[platform])
if (matches) {
return matches[1]
}
} catch (e) {
console.error(e)
}
}
return version
}
async function validateDevtools(options, puppet) {
options.platform = (
options.platform || process.env.UNI_OS_NAME
).toLocaleLowerCase()
Object.assign(options, options[options.platform])
launcher = createLauncher(options.platform, options)
await launcher.init() // check device
const version = await launcher.version()
if (!version) {
install = true
} else if (options.version) {
const newVersion = launcher.formatVersion(
getVersion(options.version, options.platform)
)
debugDevtools(`version: ${version}`)
debugDevtools(`newVersion: ${newVersion}`)
if (newVersion !== version) {
install = true
}
}
if (install) {
if (!options.executablePath) {
throw Error(
`app-plus->${options.platform}->executablePath is not provided`
)
}
if (!fs.existsSync(options.executablePath)) {
throw Error(`${options.executablePath} not exists`)
}
}
return options
}
async function createDevtools(projectPath, options, puppet) {
if (install) {
//install
await launcher.install()
}
if (install || puppet.compiled || (await launcher.shouldPush())) {
await launcher.push(projectPath)
}
await launcher.start()
}
const adapter = {
'Tool.close': {
reflect: async () => {},
},
'App.exit': {
reflect: async () => launcher.exit(),
},
'App.enableLog': {
reflect: () => Promise.resolve(),
},
const v = s('automator:devtool')
let E,
$ = !1
const S = { android: /android_version=(.*)/, ios: /iphone_version=(.*)/ }
const A = {
'Tool.close': { reflect: async () => {} },
'App.exit': { reflect: async () => E.exit() },
'App.enableLog': { reflect: () => Promise.resolve() },
'App.captureScreenshot': {
reflect: async (send, params) => {
const data = await launcher.captureScreenshot(params)
debugDevtools(`App.captureScreenshot ${data.length}`)
return {
data,
}
reflect: async (t, e) => {
const s = await E.captureScreenshot(e)
return v('App.captureScreenshot ' + s.length), { data: s }
},
},
}
initAdapter(adapter)
const puppet = {
!(function (t) {
c.forEach((e) => {
t[e] = (function (t) {
return {
reflect: async (e, s) => e(t, s, !1),
params: (t) => (
t.selector && (t.selector = i(l).processSync(t.selector)), t
),
}
})(e)
})
})(A)
const _ = {
devtools: {
name: 'App',
paths: [],
required: ['manifest.json', 'app-service.js'],
validate: validateDevtools,
create: createDevtools,
validate: async function (t, s) {
;(t.platform = (
t.platform || process.env.UNI_OS_NAME
).toLocaleLowerCase()),
Object.assign(t, t[t.platform]),
(E = (function (t, e) {
return 'ios' === t ? new g(e) : new P(e)
})(t.platform, t)),
await E.init()
const i = await E.version()
if (i) {
if (t.version) {
const s = E.formatVersion(
(function (t, s) {
if (t.endsWith('.txt'))
try {
const i = e.readFileSync(t).toString().match(S[s])
if (i) return i[1]
} catch (t) {
console.error(t)
}
return t
})(t.version, t.platform)
)
v('version: ' + i), v('newVersion: ' + s), s !== i && ($ = !0)
}
} else $ = !0
if ($) {
if (!t.executablePath)
throw Error(`app-plus->${t.platform}->executablePath is not provided`)
if (!e.existsSync(t.executablePath))
throw Error(t.executablePath + ' not exists')
}
return t
},
create: async function (t, e, s) {
$ && (await E.install()),
($ || s.compiled || (await E.shouldPush())) && (await E.push(t)),
await E.start()
},
},
adapter,
adapter: A,
}
module.exports = puppet
module.exports = _
'use strict';
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var NodeEnvironment = _interopDefault(require('jest-environment-node'));
var Automator = _interopDefault(require('./index.js'));
const automator = new Automator();
class UniAutomatorEnvironment extends NodeEnvironment {
constructor(config, context) {
super(config);
if (process.env.UNI_AUTOMATOR_CONFIG) {
this.launchOptions = require(process.env.UNI_AUTOMATOR_CONFIG);
}
else {
this.launchOptions = config.testEnvironmentOptions;
}
}
async setup() {
await super.setup();
const globalThis = global;
if (!globalThis.__init__) {
globalThis.__init__ = true;
// 必须启用runInBand,否则会launch多次
this.launchOptions.platform =
this.launchOptions.platform || process.env.UNI_PLATFORM;
globalThis.program = await automator.launch(this.launchOptions);
if (this.launchOptions.devtools && this.launchOptions.devtools.remote) {
await globalThis.program.remote(true);
}
}
else {
if (!globalThis.program) {
throw Error(`Program init failed`);
}
}
this.global.program = globalThis.program;
}
async teardown() {
await super.teardown();
}
}
module.exports = UniAutomatorEnvironment;
"use strict";function t(t){return t&&"object"==typeof t&&"default"in t?t.default:t}var e=t(require("jest-environment-node"));const s=new(t(require("./index.js")));module.exports=class extends e{constructor(t,e){super(t),process.env.UNI_AUTOMATOR_CONFIG?this.launchOptions=require(process.env.UNI_AUTOMATOR_CONFIG):this.launchOptions=t.testEnvironmentOptions}async setup(){await super.setup();const t=global;if(t.__init__){if(!t.program)throw Error("Program init failed")}else t.__init__=!0,this.launchOptions.platform=this.launchOptions.platform||process.env.UNI_PLATFORM,t.program=await s.launch(this.launchOptions),this.launchOptions.devtools&&this.launchOptions.devtools.remote&&await t.program.remote(!0);this.global.program=t.program}async teardown(){await super.teardown()}};
'use strict';
async function teardown() {
const program = global.program;
program && program.teardown();
await new Promise((resolve) => {
setTimeout(() => {
resolve();
}, 3000);
});
}
module.exports = teardown;
"use strict";module.exports=async function(){const o=global.program;o&&o.teardown(),await new Promise(o=>{setTimeout(()=>{o(void 0)},3e3)})};
此差异已折叠。
'use strict'
function _interopDefault(ex) {
return ex && typeof ex === 'object' && 'default' in ex ? ex['default'] : ex
function e(e) {
return e && 'object' == typeof e && 'default' in e ? e.default : e
}
var debug = _interopDefault(require('debug'))
var puppeteer = _interopDefault(require('puppeteer'))
var parser = _interopDefault(require('postcss-selector-parser'))
function transform(selectors) {
selectors.walk((selector) => {
if (selector.type === 'tag') {
const value = selector.value
if (value === 'page') {
//@ts-ignore
{
selector.value = 'uni-page-body'
}
} else {
selector.value = 'uni-' + value
}
var t = e(require('debug')),
o = e(require('postcss-selector-parser'))
const n = t('automator:devtool')
function r(e) {
e.walk((e) => {
if ('tag' === e.type) {
const t = e.value
e.value = 'page' === t ? 'uni-page-body' : 'uni-' + t
}
})
}
function transSelector(method) {
return {
reflect: async (send, params) => send(method, params, false),
params(params) {
if (params.selector) {
params.selector = parser(transform).processSync(params.selector)
}
return params
},
}
}
const methods = [
const s = [
'Page.getElement',
'Page.getElements',
'Element.getElement',
'Element.getElements',
]
function initAdapter(adapter) {
methods.forEach((method) => {
adapter[method] = transSelector(method)
})
}
const debugDevtools = debug('automator:devtool')
async function validateDevtools(options) {
options.options = options.options || {}
if (options.executablePath && !options.options.executablePath) {
options.options.executablePath = options.executablePath
}
options.options.defaultViewport = Object.assign(
{
width: 375,
height: 667,
deviceScaleFactor: 2,
hasTouch: true,
isMobile: true,
},
options.options.defaultViewport || {}
const i = ['chromium', 'firefox', 'webkit']
let a = !1
try {
a = !!require('playwright')
} catch (e) {}
const c = new Map()
function p(e = 'chromium') {
const t = e && i.includes(e) ? e : i[0]
let o = c.get(t)
return (
o ||
((o = (function (e) {
if ('webkit' === e) return l('webkit')
if ('firefox' === e) return l('firefox')
return a
? l('chromium')
: (function () {
const e = require('puppeteer')
let t, o
return {
type: 'chromium',
provider: 'puppeteer',
async open(r, s, i) {
t = await e.launch(s.options)
const a = t.process()
a ? n('%s %o', a.spawnfile, s.options) : n('%o', s.options),
(o = await t.newPage()),
o.on('console', (e) => {
i.emit('App.logAdded', {
type: e.type(),
args: [e.text()],
})
}),
o.on('pageerror', (e) => {
i.emit('App.exceptionThrown', e)
}),
await o.goto(s.url || r),
await o.waitFor(1e3)
},
close: () => t.close(),
screenshot: (e = !1) =>
o.screenshot({ encoding: 'base64', fullPage: e }),
}
})()
})(t)),
c.set(t, o)),
o
)
if (!options.teardown) {
options.teardown =
options.options.headless === false ? 'disconnect' : 'close'
}
return options
}
let browser
let page
async function createDevtools(url, options, puppet) {
browser = await puppeteer.launch(options.options)
const process = browser.process()
if (process) {
debugDevtools('%s %o', process.spawnfile, options.options)
} else {
debugDevtools('%o', options.options)
function l(e) {
const t = require('playwright')
let o, r
return {
type: e,
provider: 'playwright',
async open(s, i, a) {
;(o = await t[e].launch(i.options)),
'firefox' === e && (i.contextOptions.isMobile = !1),
n('browser.newContext ' + JSON.stringify(i.contextOptions))
const c = await o.newContext(i.contextOptions)
;(r = await c.newPage()),
r.on('console', (e) => {
a.emit('App.logAdded', { type: e.type(), args: [e.text()] })
}),
r.on('pageerror', (e) => {
a.emit('App.exceptionThrown', e)
}),
await r.goto(i.url || s),
await r.waitForTimeout(1e3)
},
close: () => o.close(),
screenshot: (e = !1) =>
r.screenshot({ fullPage: e }).then((e) => e.toString('base64')),
}
page = await browser.newPage()
page.on('console', (msg) => {
puppet.emit('App.logAdded', { type: msg.type(), args: [msg.text()] })
})
page.on('pageerror', (err) => {
puppet.emit('App.exceptionThrown', err)
})
await page.goto(options.url || url)
await page.waitFor(1000)
}
const adapter = {
let u
const f = {
'Tool.close': {
reflect: async () => {
await browser.close()
await u.close()
},
},
'App.exit': {
reflect: async () => {},
},
'App.enableLog': {
reflect: () => Promise.resolve(),
},
'App.exit': { reflect: async () => {} },
'App.enableLog': { reflect: () => Promise.resolve() },
'App.captureScreenshot': {
reflect: async (send, params) => {
const data = await page.screenshot({
encoding: 'base64',
fullPage: !!params.fullPage,
})
debugDevtools(`App.captureScreenshot ${data.length}`)
return {
data,
}
reflect: async (e, t) => {
const o = await u.screenshot(!!t.fullPage)
return n('App.captureScreenshot ' + o.length), { data: o }
},
},
}
initAdapter(adapter)
const puppet = {
!(function (e) {
s.forEach((t) => {
e[t] = (function (e) {
return {
reflect: async (t, o) => t(e, o, !1),
params: (e) => (
e.selector && (e.selector = o(r).processSync(e.selector)), e
),
}
})(t)
})
})(f)
const h = {
devtools: {
name: 'google chrome',
name: 'browser',
paths: [],
validate: validateDevtools,
create: createDevtools,
},
shouldCompile(options, devtoolsOptions) {
if (devtoolsOptions.url) {
return false
}
return true
validate: async function (e) {
return (
(e.options = e.options || {}),
e.executablePath &&
!e.options.executablePath &&
(e.options.executablePath = e.executablePath),
(e.contextOptions = {
viewport: Object.assign(
{ width: 375, height: 667 },
e.options.defaultViewport || {}
),
hasTouch: !0,
isMobile: !0,
deviceScaleFactor: 2,
}),
(e.options.defaultViewport = Object.assign(
{
width: 375,
height: 667,
deviceScaleFactor: 2,
hasTouch: !0,
isMobile: !0,
},
e.options.defaultViewport || {}
)),
e.teardown ||
(e.teardown = !1 === e.options.headless ? 'disconnect' : 'close'),
e
)
},
create: async function (e, t, o) {
;(u = p(process.env.BROWSER)),
n(
'createDevtools ' +
(u.provider + ' ' + u.type + ' ' + JSON.stringify(t))
),
await u.open(e, t, o)
},
},
adapter,
shouldCompile: (e, t) => !t.url,
adapter: f,
}
module.exports = puppet
module.exports = h
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册