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

feat(automator): support safari,firefox

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