import path from 'path'
import { createRequire } from 'module'
import { spawn } from 'child_process'
import { chromium } from 'playwright'
import launchChromiumCore from './launchChromiumCore.mjs'
let require = createRequire(import.meta.url)
function runCli(args) {
//以此處解析之playwright(與上方import同一份)之CLI執行, 下載之瀏覽器即為該版Playwright所需版本
//以process.execPath(正在執行之node)執行, 不依賴npx與PATH; playwright/cli.js未列於exports, 故由package.json位置與bin組出路徑
let fpPkg = require.resolve('playwright/package.json')
let pkg = require(fpPkg)
let fpCli = path.join(path.dirname(fpPkg), pkg.bin.playwright)
//非同步執行, 下載期間不阻塞呼叫端之事件迴圈(例如同程序內其他子程序之輸出)
return new Promise((resolve, reject) => {
let cp = spawn(process.execPath, [fpCli, ...args], { stdio: 'inherit' })
cp.on('error', reject)
cp.on('close', (code) => {
if (code === 0) {
resolve()
}
else {
reject(new Error(`playwright ${args.join(' ')} failed with exit code ${code}`))
}
})
})
}
/**
* 啟動Playwright之Chromium,所需版本之瀏覽器不存在時先自動下載再啟動
*
* 不使用套件安裝腳本(npm 12起預設略過相依套件之install/postinstall),改於第一次啟動時以Playwright自身之CLI下載,
* 下載之瀏覽器為本套件所用Playwright版本指定之版本,與本機已安裝者相同,像素比對得以一致
*
* Linux缺少系統相依套件時先執行install-deps(非root時Playwright會自行使用sudo)再啟動;
* 指定系統瀏覽器(channel如'chrome')或自訂executablePath時不自動安裝
*
* 多個程序同時首次啟動時,Playwright安裝過程有目錄鎖,只會下載一次,其餘等待後直接使用
*
* @param {Object} [opt={}] 輸入chromium.launch之設定物件,原樣傳入,預設{}
* @returns {Promise} 回傳Promise,resolve回傳Browser,reject回傳錯誤
* @example
*
* import launchChromium from 'w-package-tools-e2e/src/launchChromium.mjs'
*
* let browser = await launchChromium({ headless: true, args: ['--disable-gpu'] })
* let page = await browser.newPage()
* await page.goto('http://127.0.0.1:8080')
* await browser.close()
*
*/
async function launchChromium(opt = {}) {
return launchChromiumCore(opt, {
launch: (o) => chromium.launch(o),
runCli,
platform: process.platform,
})
}
export default launchChromium