presidium 2.1.1 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Docker.js +3 -4
- package/GoogleChromeDevTools.js +902 -0
- package/index.js +0 -1
- package/internal/Archive.js +113 -0
- package/internal/Archive.test.js +71 -0
- package/internal/GoogleChromeForTesting.js +218 -0
- package/internal/GoogleChromeForTesting.test.js +50 -0
- package/internal/parsePath.js +2 -2
- package/internal/tmp/chrome/BrowserMetrics/BrowserMetrics-69977DD3-9B6F.pma +0 -0
- package/internal/tmp/chrome/BrowserMetrics/BrowserMetrics-69977DD4-9B86.pma +0 -0
- package/internal/tmp/chrome/BrowserMetrics/BrowserMetrics-69978250-A191.pma +0 -0
- package/internal/tmp/chrome/BrowserMetrics/BrowserMetrics-69978251-A1AD.pma +0 -0
- package/internal/tmp/chrome/BrowserMetrics/BrowserMetrics-69978277-A1FA.pma +0 -0
- package/internal/tmp/chrome/BrowserMetrics/BrowserMetrics-69978278-A209.pma +0 -0
- package/internal/tmp/chrome/ChromeFeatureState +1 -0
- package/internal/tmp/chrome/Default/Affiliation Database +0 -0
- package/internal/tmp/chrome/Default/Affiliation Database-journal +0 -0
- package/internal/tmp/chrome/Default/ClientCertificates/LOCK +0 -0
- package/internal/tmp/chrome/Default/ClientCertificates/LOG +0 -0
- package/internal/tmp/chrome/Default/ClientCertificates/LOG.old +0 -0
- package/internal/tmp/chrome/Default/Extension Rules/000003.log +0 -0
- package/internal/tmp/chrome/Default/Extension Rules/CURRENT +1 -0
- package/internal/tmp/chrome/Default/Extension Rules/LOCK +0 -0
- package/internal/tmp/chrome/Default/Extension Rules/LOG +3 -0
- package/internal/tmp/chrome/Default/Extension Rules/LOG.old +3 -0
- package/internal/tmp/chrome/Default/Extension Rules/MANIFEST-000001 +0 -0
- package/internal/tmp/chrome/Default/Extension Scripts/000003.log +0 -0
- package/internal/tmp/chrome/Default/Extension Scripts/CURRENT +1 -0
- package/internal/tmp/chrome/Default/Extension Scripts/LOCK +0 -0
- package/internal/tmp/chrome/Default/Extension Scripts/LOG +3 -0
- package/internal/tmp/chrome/Default/Extension Scripts/LOG.old +3 -0
- package/internal/tmp/chrome/Default/Extension Scripts/MANIFEST-000001 +0 -0
- package/internal/tmp/chrome/Default/Favicons +0 -0
- package/internal/tmp/chrome/Default/Favicons-journal +0 -0
- package/internal/tmp/chrome/Default/History +0 -0
- package/internal/tmp/chrome/Default/History-journal +0 -0
- package/internal/tmp/chrome/Default/LOCK +0 -0
- package/internal/tmp/chrome/Default/LOG +0 -0
- package/internal/tmp/chrome/Default/LOG.old +0 -0
- package/internal/tmp/chrome/Default/Local Storage/leveldb/000003.log +0 -0
- package/internal/tmp/chrome/Default/Local Storage/leveldb/CURRENT +1 -0
- package/internal/tmp/chrome/Default/Local Storage/leveldb/LOCK +0 -0
- package/internal/tmp/chrome/Default/Local Storage/leveldb/LOG +2 -0
- package/internal/tmp/chrome/Default/Local Storage/leveldb/MANIFEST-000001 +0 -0
- package/internal/tmp/chrome/Default/PersistentOriginTrials/LOCK +0 -0
- package/internal/tmp/chrome/Default/PersistentOriginTrials/LOG +0 -0
- package/internal/tmp/chrome/Default/PersistentOriginTrials/LOG.old +0 -0
- package/internal/tmp/chrome/Default/README +1 -0
- package/internal/tmp/chrome/Default/Segmentation Platform/SegmentInfoDB/LOCK +0 -0
- package/internal/tmp/chrome/Default/Segmentation Platform/SegmentInfoDB/LOG +0 -0
- package/internal/tmp/chrome/Default/Segmentation Platform/SegmentInfoDB/LOG.old +0 -0
- package/internal/tmp/chrome/Default/Segmentation Platform/SignalDB/LOCK +0 -0
- package/internal/tmp/chrome/Default/Segmentation Platform/SignalDB/LOG +0 -0
- package/internal/tmp/chrome/Default/Segmentation Platform/SignalDB/LOG.old +0 -0
- package/internal/tmp/chrome/Default/Segmentation Platform/SignalStorageConfigDB/LOCK +0 -0
- package/internal/tmp/chrome/Default/Segmentation Platform/SignalStorageConfigDB/LOG +0 -0
- package/internal/tmp/chrome/Default/Segmentation Platform/SignalStorageConfigDB/LOG.old +0 -0
- package/internal/tmp/chrome/Default/ServerCertificate +0 -0
- package/internal/tmp/chrome/Default/ServerCertificate-journal +0 -0
- package/internal/tmp/chrome/Default/Site Characteristics Database/000003.log +0 -0
- package/internal/tmp/chrome/Default/Site Characteristics Database/CURRENT +1 -0
- package/internal/tmp/chrome/Default/Site Characteristics Database/LOCK +0 -0
- package/internal/tmp/chrome/Default/Site Characteristics Database/LOG +3 -0
- package/internal/tmp/chrome/Default/Site Characteristics Database/LOG.old +3 -0
- package/internal/tmp/chrome/Default/Site Characteristics Database/MANIFEST-000001 +0 -0
- package/internal/tmp/chrome/Default/Sync Data/LevelDB/000003.log +0 -0
- package/internal/tmp/chrome/Default/Sync Data/LevelDB/CURRENT +1 -0
- package/internal/tmp/chrome/Default/Sync Data/LevelDB/LOCK +0 -0
- package/internal/tmp/chrome/Default/Sync Data/LevelDB/LOG +3 -0
- package/internal/tmp/chrome/Default/Sync Data/LevelDB/LOG.old +3 -0
- package/internal/tmp/chrome/Default/Sync Data/LevelDB/MANIFEST-000001 +0 -0
- package/internal/tmp/chrome/Default/chrome_cart_db/LOCK +0 -0
- package/internal/tmp/chrome/Default/chrome_cart_db/LOG +0 -0
- package/internal/tmp/chrome/Default/chrome_cart_db/LOG.old +0 -0
- package/internal/tmp/chrome/Default/commerce_subscription_db/LOCK +0 -0
- package/internal/tmp/chrome/Default/commerce_subscription_db/LOG +0 -0
- package/internal/tmp/chrome/Default/commerce_subscription_db/LOG.old +0 -0
- package/internal/tmp/chrome/Default/discount_infos_db/LOCK +0 -0
- package/internal/tmp/chrome/Default/discount_infos_db/LOG +0 -0
- package/internal/tmp/chrome/Default/discount_infos_db/LOG.old +0 -0
- package/internal/tmp/chrome/Default/discounts_db/LOCK +0 -0
- package/internal/tmp/chrome/Default/discounts_db/LOG +0 -0
- package/internal/tmp/chrome/Default/discounts_db/LOG.old +0 -0
- package/internal/tmp/chrome/Default/parcel_tracking_db/LOCK +0 -0
- package/internal/tmp/chrome/Default/parcel_tracking_db/LOG +0 -0
- package/internal/tmp/chrome/Default/parcel_tracking_db/LOG.old +0 -0
- package/internal/tmp/chrome/Default/power_bookmarks/PowerBookmarks.db +0 -0
- package/internal/tmp/chrome/Default/power_bookmarks/PowerBookmarks.db-journal +0 -0
- package/internal/tmp/chrome/First Run +0 -0
- package/internal/tmp/chrome/Last Version +1 -0
- package/internal/tmp/chrome/Local State +1 -0
- package/internal/tmp/chrome/ShaderCache/data_0 +0 -0
- package/internal/tmp/chrome/ShaderCache/data_1 +0 -0
- package/internal/tmp/chrome/ShaderCache/data_2 +0 -0
- package/internal/tmp/chrome/ShaderCache/data_3 +0 -0
- package/internal/tmp/chrome/ShaderCache/index +0 -0
- package/internal/tmp/chrome/Variations +1 -0
- package/internal/tmp/chrome/segmentation_platform/ukm_db +0 -0
- package/internal/tmp/chrome/segmentation_platform/ukm_db-wal +0 -0
- package/package.json +3 -2
- package/Archive.js +0 -120
package/index.js
CHANGED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
require('rubico/global')
|
|
2
|
+
const tarStream = require('tar-stream')
|
|
3
|
+
const fs = require('fs/promises')
|
|
4
|
+
const walk = require('./walk')
|
|
5
|
+
const pipe = require('rubico/pipe')
|
|
6
|
+
const tap = require('rubico/tap')
|
|
7
|
+
const get = require('rubico/get')
|
|
8
|
+
const reduce = require('rubico/reduce')
|
|
9
|
+
const thunkify = require('rubico/thunkify')
|
|
10
|
+
const pick = require('rubico/pick')
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @name Archive
|
|
14
|
+
*/
|
|
15
|
+
const Archive = {}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @name Archive.tar
|
|
19
|
+
*
|
|
20
|
+
* @docs
|
|
21
|
+
* ```coffeescript [specscript]
|
|
22
|
+
* module tar 'https://github.com/mafintosh/tar-stream'
|
|
23
|
+
*
|
|
24
|
+
* Archive.tar(path string, options {
|
|
25
|
+
* ignore: Array<string>,
|
|
26
|
+
* base: Object<string>,
|
|
27
|
+
* }) -> pack tar.Pack
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* Bundle multiple files and directories from a parent directory into a tarball.
|
|
31
|
+
*
|
|
32
|
+
* Arguments:
|
|
33
|
+
* * `path` - the path to the parent directory which contains the files and directories to bundle.
|
|
34
|
+
* * `options`
|
|
35
|
+
* * `ignore` - filepaths, filenames, or patterns to ignore.
|
|
36
|
+
*/
|
|
37
|
+
Archive.tar = function tar(path, options) {
|
|
38
|
+
const pathWithSlash = path.endsWith('/') ? path : `${path}/`
|
|
39
|
+
const ignore = get(options, 'ignore')
|
|
40
|
+
const pack = tarStream.pack()
|
|
41
|
+
|
|
42
|
+
pipe(path, [
|
|
43
|
+
walk,
|
|
44
|
+
filter(path => {
|
|
45
|
+
for (const part of ignore) {
|
|
46
|
+
if (path.includes(part)) {
|
|
47
|
+
return false
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return true
|
|
51
|
+
}),
|
|
52
|
+
|
|
53
|
+
reduce(async (pack, filepath) => {
|
|
54
|
+
pack.entry({
|
|
55
|
+
name: filepath.replace(pathWithSlash, ''),
|
|
56
|
+
...pipe([
|
|
57
|
+
fs.stat,
|
|
58
|
+
pick(['size', 'mode', 'mtime', 'uid', 'gid']),
|
|
59
|
+
])(filepath),
|
|
60
|
+
}, await fs.readFile(filepath))
|
|
61
|
+
return pack
|
|
62
|
+
}, pack),
|
|
63
|
+
|
|
64
|
+
tap(pack => {
|
|
65
|
+
const base = options.base ?? {}
|
|
66
|
+
for (const filename in base) {
|
|
67
|
+
pack.entry({ name: filename }, base[filename])
|
|
68
|
+
}
|
|
69
|
+
pack.finalize()
|
|
70
|
+
}),
|
|
71
|
+
])
|
|
72
|
+
|
|
73
|
+
return pack
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* @name untar
|
|
78
|
+
*
|
|
79
|
+
* @docs
|
|
80
|
+
* ```coffeescript [specscript]
|
|
81
|
+
* module tar 'https://github.com/mafintosh/tar-stream'
|
|
82
|
+
* module presidium 'https://presidium.services/docs'
|
|
83
|
+
*
|
|
84
|
+
* Archive.untar(pack tar.Pack) ->
|
|
85
|
+
* contentMap Promise<Map<(filepath string)=>(content presidium.Readable)> >
|
|
86
|
+
* ```
|
|
87
|
+
*
|
|
88
|
+
* Extract a tarball into a map of file paths to content streams.
|
|
89
|
+
*
|
|
90
|
+
* Arguments:
|
|
91
|
+
* * `pack` - a tarball represented by the `tar.Pack` type. Returned by the [tar](#tar) method.
|
|
92
|
+
*/
|
|
93
|
+
Archive.untar = function untar(pack) {
|
|
94
|
+
const extractStream = tarStream.extract()
|
|
95
|
+
const extracted = new Map()
|
|
96
|
+
return new Promise((resolve, reject) => {
|
|
97
|
+
extractStream.on('entry', (header, stream, next) => {
|
|
98
|
+
stream.header = header
|
|
99
|
+
extracted.set(header.name, stream)
|
|
100
|
+
next()
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
extractStream.on('finish', () => {
|
|
104
|
+
resolve(extracted)
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
extractStream.on('error', reject)
|
|
108
|
+
|
|
109
|
+
pack.pipe(extractStream)
|
|
110
|
+
})
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
module.exports = Archive
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
const assert = require('assert')
|
|
2
|
+
const stream = require('stream')
|
|
3
|
+
const fs = require('fs/promises')
|
|
4
|
+
const Test = require('thunk-test')
|
|
5
|
+
const Archive = require('./Archive')
|
|
6
|
+
const resolvePath = require('./resolvePath')
|
|
7
|
+
const map = require('rubico/map')
|
|
8
|
+
const reduce = require('rubico/reduce')
|
|
9
|
+
const Readable = require('../Readable')
|
|
10
|
+
|
|
11
|
+
const test = new Test('Archive', async function integration() {
|
|
12
|
+
|
|
13
|
+
{
|
|
14
|
+
const pack = await Archive.tar(__dirname, {
|
|
15
|
+
ignore: ['Dockerfile', 'node_modules', '.git', '.nyc_output'],
|
|
16
|
+
})
|
|
17
|
+
const extracted = await Archive.untar(pack)
|
|
18
|
+
assert(extracted.size > 0)
|
|
19
|
+
for (const [path, entry] of extracted) {
|
|
20
|
+
assert('header' in entry)
|
|
21
|
+
assert(!path.startsWith('/'))
|
|
22
|
+
assert.equal(typeof path, 'string')
|
|
23
|
+
assert.equal(typeof entry[Symbol.asyncIterator], 'function')
|
|
24
|
+
assert(entry.readable)
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
{
|
|
29
|
+
const base = {
|
|
30
|
+
Dockerfile: 'FROM node:15-alpine'
|
|
31
|
+
}
|
|
32
|
+
const ignore = ['fixtures']
|
|
33
|
+
const pack = await Archive.tar(__dirname, { ignore, base })
|
|
34
|
+
const extracted = await Archive.untar(pack)
|
|
35
|
+
const dir = await fs.readdir(__dirname)
|
|
36
|
+
.then(filter(n => !ignore.includes(n)))
|
|
37
|
+
const extractedKeys = [...extracted.keys()]
|
|
38
|
+
assert.equal(extracted.size, dir.length + 1) // extra Dockerfile
|
|
39
|
+
assert(extracted.has('Dockerfile'))
|
|
40
|
+
assert.equal(
|
|
41
|
+
await reduce(extracted.get('Dockerfile'), (a, b) => a + b, ''),
|
|
42
|
+
'FROM node:15-alpine'
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
{
|
|
47
|
+
const base = {
|
|
48
|
+
Dockerfile: 'FROM busybox:1.32',
|
|
49
|
+
'.aws/credentials': '[presidium]\naccessKeyId\nsecretAccessKey',
|
|
50
|
+
}
|
|
51
|
+
const pack = await Archive.tar(`${__dirname}/`, {
|
|
52
|
+
ignore: ['hashJSON.js'],
|
|
53
|
+
base,
|
|
54
|
+
})
|
|
55
|
+
const extracted = await Archive.untar(pack)
|
|
56
|
+
assert(extracted.size > 0)
|
|
57
|
+
assert(extracted.has('Dockerfile'))
|
|
58
|
+
assert(extracted.has('.aws/credentials'))
|
|
59
|
+
assert.equal(
|
|
60
|
+
await reduce(extracted.get('Dockerfile'), (a, b) => a + b, ''),
|
|
61
|
+
'FROM busybox:1.32'
|
|
62
|
+
)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
}).case()
|
|
66
|
+
|
|
67
|
+
if (process.argv[1] == __filename) {
|
|
68
|
+
test()
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
module.exports = test
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
const https = require('https')
|
|
2
|
+
const os = require('os')
|
|
3
|
+
const fs = require('fs')
|
|
4
|
+
const path = require('path')
|
|
5
|
+
const { spawn } = require('child_process')
|
|
6
|
+
const readline = require('readline')
|
|
7
|
+
const extract = require('extract-zip')
|
|
8
|
+
const HTTP = require('../HTTP')
|
|
9
|
+
const XML = require('../XML')
|
|
10
|
+
const Readable = require('../Readable')
|
|
11
|
+
const walk = require('./walk')
|
|
12
|
+
|
|
13
|
+
async function getChromeVersions() {
|
|
14
|
+
const http = new HTTP()
|
|
15
|
+
const response = await http.GET('https://googlechromelabs.github.io/chrome-for-testing/last-known-good-versions-with-downloads.json')
|
|
16
|
+
const data = await Readable.JSON(response)
|
|
17
|
+
return data
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function updateConsoleLog(message) {
|
|
21
|
+
readline.cursorTo(process.stdout, 0, undefined);
|
|
22
|
+
readline.clearLine(process.stdout, 0);
|
|
23
|
+
process.stdout.write(message);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async function getChromeUrl() {
|
|
27
|
+
let platform = os.platform()
|
|
28
|
+
if (platform == 'darwin') {
|
|
29
|
+
platform = 'mac'
|
|
30
|
+
}
|
|
31
|
+
const arch = os.arch()
|
|
32
|
+
|
|
33
|
+
if (platform == 'mac') {
|
|
34
|
+
platform = `${platform}-${arch}`
|
|
35
|
+
} else {
|
|
36
|
+
platform = `${platform}${arch.slice(1)}`
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
let url
|
|
40
|
+
if (['stable', 'beta', 'dev', 'canary'].includes(this.chromeVersion)) {
|
|
41
|
+
const chromeVersions = await getChromeVersions()
|
|
42
|
+
const channel = `${this.chromeVersion[0].toUpperCase()}${this.chromeVersion.slice(1)}`
|
|
43
|
+
const chromeVersionNumber = chromeVersions.channels[channel].version
|
|
44
|
+
url = `https://storage.googleapis.com/chrome-for-testing-public/${chromeVersionNumber}/${platform}/chrome-${platform}.zip`
|
|
45
|
+
} else {
|
|
46
|
+
const chromeVersionNumber = this.chromeVersion
|
|
47
|
+
url = `https://storage.googleapis.com/chrome-for-testing-public/${chromeVersionNumber}/${platform}/chrome-${platform}.zip`
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return url
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async function installChrome() {
|
|
54
|
+
const url = await getChromeUrl.call(this)
|
|
55
|
+
let filepath = `${this.chromeDir}/${url.replace('https://storage.googleapis.com/chrome-for-testing-public/', '')}`
|
|
56
|
+
if (!filepath.startsWith('/')) {
|
|
57
|
+
filepath = path.join(process.cwd(), filepath)
|
|
58
|
+
}
|
|
59
|
+
let parentDir = `${filepath.split('/').slice(0, -1).join('/')}`
|
|
60
|
+
if (!parentDir.startsWith('/')) {
|
|
61
|
+
parentDir = path.join(process.cwd(), parentDir)
|
|
62
|
+
}
|
|
63
|
+
await fs.promises.mkdir(parentDir, { recursive: true })
|
|
64
|
+
|
|
65
|
+
const http = new HTTP()
|
|
66
|
+
const response = await http.GET(url)
|
|
67
|
+
const contentLength = response.headers['content-length']
|
|
68
|
+
|
|
69
|
+
await fs.promises.mkdir(parentDir, { recursive: true })
|
|
70
|
+
const fileStream = fs.createWriteStream(filepath)
|
|
71
|
+
// response.pipe(fileStream)
|
|
72
|
+
|
|
73
|
+
let downloadedLength = 0
|
|
74
|
+
response.on('data', chunk => {
|
|
75
|
+
downloadedLength += chunk.length
|
|
76
|
+
if (downloadedLength == contentLength) {
|
|
77
|
+
updateConsoleLog(`Downloading ${url} (${downloadedLength} / ${contentLength} bytes)\n`)
|
|
78
|
+
} else {
|
|
79
|
+
updateConsoleLog(`Downloading ${url} (${downloadedLength} / ${contentLength} bytes)`)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
fileStream.write(chunk)
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
let resolve
|
|
86
|
+
const promise = new Promise(_resolve => {
|
|
87
|
+
resolve = _resolve
|
|
88
|
+
})
|
|
89
|
+
response.on('end', () => {
|
|
90
|
+
resolve()
|
|
91
|
+
})
|
|
92
|
+
await promise
|
|
93
|
+
|
|
94
|
+
await extract(filepath, { dir: parentDir })
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
async function getChromeFilepath() {
|
|
98
|
+
const url = await getChromeUrl.call(this)
|
|
99
|
+
const filepath = `${this.chromeDir}/${url.replace('https://storage.googleapis.com/chrome-for-testing-public/', '')}`
|
|
100
|
+
const parentDir = `${filepath.split('/').slice(0, -1).join('/')}`
|
|
101
|
+
|
|
102
|
+
const googleChromeForTestingFilepath = `${parentDir}`
|
|
103
|
+
try {
|
|
104
|
+
for await (const filepath of walk(parentDir)) {
|
|
105
|
+
console.log(filepath)
|
|
106
|
+
if (filepath.endsWith('Google Chrome for Testing')) {
|
|
107
|
+
return filepath
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
} catch (error) {
|
|
111
|
+
if (error.code == 'ENOENT') {
|
|
112
|
+
await installChrome.call(this)
|
|
113
|
+
const filepath = await getChromeFilepath.call(this)
|
|
114
|
+
return filepath
|
|
115
|
+
}
|
|
116
|
+
throw error
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
throw new Error('unable to find Google Chrome for Testing executable.')
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* @name GoogleChromeForTesting
|
|
124
|
+
*
|
|
125
|
+
* @docs
|
|
126
|
+
* ```coffeescript [specscript]
|
|
127
|
+
* new GoogleChromeForTesting(options {
|
|
128
|
+
* chromeVersion: 'stable'|'beta'|'dev'|'canary'|string,
|
|
129
|
+
* remoteDebuggingPort: number,
|
|
130
|
+
* headless: boolean,
|
|
131
|
+
* userDataDir: string,
|
|
132
|
+
* useMockKeychain: boolean,
|
|
133
|
+
* }) -> GoogleChromeForTesting
|
|
134
|
+
* ```
|
|
135
|
+
*
|
|
136
|
+
* References:
|
|
137
|
+
* * [Chrome for Testing availability](https://googlechromelabs.github.io/chrome-for-testing/)
|
|
138
|
+
*/
|
|
139
|
+
class GoogleChromeForTesting {
|
|
140
|
+
constructor(options = {}) {
|
|
141
|
+
this.chromeVersion = options.chromeVersion ?? 'stable'
|
|
142
|
+
this.chromeDir = options.chromeDir ?? 'google-chrome-for-testing'
|
|
143
|
+
this.remoteDebuggingPort = options.remoteDebuggingPort ?? 9222
|
|
144
|
+
this.headless = options.headless ?? false
|
|
145
|
+
this.userDataDir = options.userDataDir ?? './tmp/chrome'
|
|
146
|
+
this.useMockKeychain = options.useMockKeychain ?? false
|
|
147
|
+
this.devtoolsUrl = undefined
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* @name init
|
|
152
|
+
*
|
|
153
|
+
* @docs
|
|
154
|
+
* ```coffeescript [specscript]
|
|
155
|
+
* init() -> Promise<>
|
|
156
|
+
* ```
|
|
157
|
+
*/
|
|
158
|
+
async init() {
|
|
159
|
+
const chromeFilepath = await getChromeFilepath.call(this)
|
|
160
|
+
console.log('spawn', chromeFilepath)
|
|
161
|
+
|
|
162
|
+
const cmd = spawn(chromeFilepath, [
|
|
163
|
+
`--remote-debugging-port=${this.remoteDebuggingPort}`,
|
|
164
|
+
`--user-data-dir=${this.userDataDir}`,
|
|
165
|
+
...this.headless ? ['--headless'] : [],
|
|
166
|
+
...this.useMockKeychain ? ['--use-mock-keychain'] : [],
|
|
167
|
+
])
|
|
168
|
+
cmd.stdout.pipe(process.stdout)
|
|
169
|
+
cmd.stderr.pipe(process.stderr)
|
|
170
|
+
|
|
171
|
+
const devtoolsUrlPromiseWithResolvers = Promise.withResolvers()
|
|
172
|
+
cmd.stderr.on('data', chunk => {
|
|
173
|
+
const line = chunk.toString('utf8').trim()
|
|
174
|
+
if (line.includes('DevTools listening on')) {
|
|
175
|
+
const devtoolsUrl = line.replace('DevTools listening on ', '')
|
|
176
|
+
devtoolsUrlPromiseWithResolvers.resolve(devtoolsUrl)
|
|
177
|
+
}
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
const spawnPromiseWithResolvers = Promise.withResolvers()
|
|
181
|
+
cmd.on('spawn', () => {
|
|
182
|
+
spawnPromiseWithResolvers.resolve()
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
cmd.on('error', error => {
|
|
186
|
+
console.error(error)
|
|
187
|
+
process.exit(1)
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
process.on('SIGTERM', () => {
|
|
191
|
+
cmd.kill()
|
|
192
|
+
})
|
|
193
|
+
|
|
194
|
+
process.on('exit', () => {
|
|
195
|
+
cmd.kill()
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
this.cmd = cmd
|
|
199
|
+
|
|
200
|
+
await spawnPromiseWithResolvers.promise
|
|
201
|
+
this.devtoolsUrl = await devtoolsUrlPromiseWithResolvers.promise
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* @name close
|
|
206
|
+
*
|
|
207
|
+
* @docs
|
|
208
|
+
* ```coffeescript [specscript]
|
|
209
|
+
* close() -> undefined
|
|
210
|
+
* ```
|
|
211
|
+
*/
|
|
212
|
+
close() {
|
|
213
|
+
this.cmd.kill('SIGKILL')
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
module.exports = GoogleChromeForTesting
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
const Test = require('thunk-test')
|
|
2
|
+
const assert = require('assert')
|
|
3
|
+
const fs = require('fs')
|
|
4
|
+
const { exec } = require('child_process')
|
|
5
|
+
const Readable = require('../Readable')
|
|
6
|
+
const GoogleChromeForTesting = require('./GoogleChromeForTesting')
|
|
7
|
+
|
|
8
|
+
const test = new Test('GoogleChromeForTesting', async function integration() {
|
|
9
|
+
await fs.promises.rm('google-chrome-for-testing', { recursive: true, force: true })
|
|
10
|
+
|
|
11
|
+
const cmd = await exec('ps aux | grep "Google Chrome for Testing" | awk \'{print $2}\' | xargs kill', {
|
|
12
|
+
stdio: 'inherit',
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
{
|
|
16
|
+
const googleChromeForTesting = new GoogleChromeForTesting({
|
|
17
|
+
userDataDir: `${__dirname}/tmp/chrome`,
|
|
18
|
+
useMockKeychain: true,
|
|
19
|
+
})
|
|
20
|
+
await googleChromeForTesting.init()
|
|
21
|
+
|
|
22
|
+
assert.equal(typeof googleChromeForTesting.devtoolsUrl, 'string')
|
|
23
|
+
assert(googleChromeForTesting.devtoolsUrl.startsWith('ws://'))
|
|
24
|
+
|
|
25
|
+
googleChromeForTesting.close()
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
{
|
|
29
|
+
const googleChromeForTesting = new GoogleChromeForTesting({
|
|
30
|
+
userDataDir: `${__dirname}/tmp/chrome`,
|
|
31
|
+
useMockKeychain: true,
|
|
32
|
+
})
|
|
33
|
+
await googleChromeForTesting.init()
|
|
34
|
+
|
|
35
|
+
assert.equal(typeof googleChromeForTesting.devtoolsUrl, 'string')
|
|
36
|
+
assert(googleChromeForTesting.devtoolsUrl.startsWith('ws://'))
|
|
37
|
+
|
|
38
|
+
googleChromeForTesting.close()
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
await fs.promises.rm('google-chrome-for-testing', { recursive: true, force: true })
|
|
42
|
+
|
|
43
|
+
console.log('Success')
|
|
44
|
+
}).case()
|
|
45
|
+
|
|
46
|
+
if (process.argv[1] == __filename) {
|
|
47
|
+
test()
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
module.exports = test
|
package/internal/parsePath.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
1
|
+
const path = require('path')
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* @name parsePath
|
|
@@ -14,6 +14,6 @@ const nodePath = require('path')
|
|
|
14
14
|
* }
|
|
15
15
|
* ```
|
|
16
16
|
*/
|
|
17
|
-
const parsePath =
|
|
17
|
+
const parsePath = path.parse
|
|
18
18
|
|
|
19
19
|
module.exports = parsePath
|