feat: 新增包文件
This commit is contained in:
136
packages/electron-chrome-extensions/spec/spec-helpers.ts
Normal file
136
packages/electron-chrome-extensions/spec/spec-helpers.ts
Normal file
@@ -0,0 +1,136 @@
|
||||
// Copyright (c) 2013-2020 GitHub Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
import * as childProcess from 'node:child_process'
|
||||
import * as nodeCrypto from 'node:crypto'
|
||||
import * as path from 'node:path'
|
||||
import * as http from 'node:http'
|
||||
import * as v8 from 'v8'
|
||||
import { SuiteFunction, TestFunction } from 'mocha'
|
||||
|
||||
const addOnly = <T>(fn: Function): T => {
|
||||
const wrapped = (...args: any[]) => {
|
||||
return fn(...args)
|
||||
}
|
||||
;(wrapped as any).only = wrapped
|
||||
;(wrapped as any).skip = wrapped
|
||||
return wrapped as any
|
||||
}
|
||||
|
||||
export const ifit = (condition: boolean) => (condition ? it : addOnly<TestFunction>(it.skip))
|
||||
export const ifdescribe = (condition: boolean) =>
|
||||
condition ? describe : addOnly<SuiteFunction>(describe.skip)
|
||||
|
||||
export const delay = (time: number = 0) => new Promise((resolve) => setTimeout(resolve, time))
|
||||
|
||||
type CleanupFunction = (() => void) | (() => Promise<void>)
|
||||
const cleanupFunctions: CleanupFunction[] = []
|
||||
export async function runCleanupFunctions() {
|
||||
for (const cleanup of cleanupFunctions) {
|
||||
const r = cleanup()
|
||||
if (r instanceof Promise) {
|
||||
await r
|
||||
}
|
||||
}
|
||||
cleanupFunctions.length = 0
|
||||
}
|
||||
|
||||
export function defer(f: CleanupFunction) {
|
||||
cleanupFunctions.unshift(f)
|
||||
}
|
||||
|
||||
class RemoteControlApp {
|
||||
process: childProcess.ChildProcess
|
||||
port: number
|
||||
|
||||
constructor(proc: childProcess.ChildProcess, port: number) {
|
||||
this.process = proc
|
||||
this.port = port
|
||||
}
|
||||
|
||||
remoteEval = (js: string): Promise<any> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const req = http.request(
|
||||
{
|
||||
host: '127.0.0.1',
|
||||
port: this.port,
|
||||
method: 'POST',
|
||||
},
|
||||
(res) => {
|
||||
const chunks = [] as Buffer[]
|
||||
res.on('data', (chunk) => {
|
||||
chunks.push(chunk)
|
||||
})
|
||||
res.on('end', () => {
|
||||
const ret = v8.deserialize(Buffer.concat(chunks))
|
||||
if (Object.prototype.hasOwnProperty.call(ret, 'error')) {
|
||||
reject(new Error(`remote error: ${ret.error}\n\nTriggered at:`))
|
||||
} else {
|
||||
resolve(ret.result)
|
||||
}
|
||||
})
|
||||
},
|
||||
)
|
||||
req.write(js)
|
||||
req.end()
|
||||
})
|
||||
}
|
||||
|
||||
remotely = (script: Function, ...args: any[]): Promise<any> => {
|
||||
return this.remoteEval(`(${script})(...${JSON.stringify(args)})`)
|
||||
}
|
||||
}
|
||||
|
||||
export async function startRemoteControlApp() {
|
||||
const appPath = path.join(__dirname, 'fixtures', 'apps', 'remote-control')
|
||||
const appProcess = childProcess.spawn(process.execPath, [appPath])
|
||||
appProcess.stderr.on('data', (d) => {
|
||||
process.stderr.write(d)
|
||||
})
|
||||
const port = await new Promise<number>((resolve) => {
|
||||
appProcess.stdout.on('data', (d) => {
|
||||
const m = /Listening: (\d+)/.exec(d.toString())
|
||||
if (m && m[1] != null) {
|
||||
resolve(Number(m[1]))
|
||||
}
|
||||
})
|
||||
})
|
||||
defer(() => {
|
||||
appProcess.kill('SIGINT')
|
||||
})
|
||||
return new RemoteControlApp(appProcess, port)
|
||||
}
|
||||
|
||||
export async function getFiles(directoryPath: string, { filter = null }: any = {}) {
|
||||
const files: string[] = []
|
||||
const walker = require('walkdir').walk(directoryPath, {
|
||||
no_recurse: true,
|
||||
})
|
||||
walker.on('file', (file: string) => {
|
||||
if (!filter || filter(file)) {
|
||||
files.push(file)
|
||||
}
|
||||
})
|
||||
await new Promise((resolve) => walker.on('end', resolve))
|
||||
return files
|
||||
}
|
||||
|
||||
export const uuid = () => nodeCrypto.randomUUID()
|
||||
Reference in New Issue
Block a user