presidium 2.1.0 → 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.
Files changed (102) hide show
  1. package/Docker.js +3 -4
  2. package/GoogleChromeDevTools.js +902 -0
  3. package/S3Bucket.js +12 -8
  4. package/index.js +0 -1
  5. package/internal/Archive.js +113 -0
  6. package/internal/Archive.test.js +71 -0
  7. package/internal/GoogleChromeForTesting.js +218 -0
  8. package/internal/GoogleChromeForTesting.test.js +50 -0
  9. package/internal/parsePath.js +2 -2
  10. package/internal/tmp/chrome/BrowserMetrics/BrowserMetrics-69977DD3-9B6F.pma +0 -0
  11. package/internal/tmp/chrome/BrowserMetrics/BrowserMetrics-69977DD4-9B86.pma +0 -0
  12. package/internal/tmp/chrome/BrowserMetrics/BrowserMetrics-69978250-A191.pma +0 -0
  13. package/internal/tmp/chrome/BrowserMetrics/BrowserMetrics-69978251-A1AD.pma +0 -0
  14. package/internal/tmp/chrome/BrowserMetrics/BrowserMetrics-69978277-A1FA.pma +0 -0
  15. package/internal/tmp/chrome/BrowserMetrics/BrowserMetrics-69978278-A209.pma +0 -0
  16. package/internal/tmp/chrome/ChromeFeatureState +1 -0
  17. package/internal/tmp/chrome/Default/Affiliation Database +0 -0
  18. package/internal/tmp/chrome/Default/Affiliation Database-journal +0 -0
  19. package/internal/tmp/chrome/Default/ClientCertificates/LOCK +0 -0
  20. package/internal/tmp/chrome/Default/ClientCertificates/LOG +0 -0
  21. package/internal/tmp/chrome/Default/ClientCertificates/LOG.old +0 -0
  22. package/internal/tmp/chrome/Default/Extension Rules/000003.log +0 -0
  23. package/internal/tmp/chrome/Default/Extension Rules/CURRENT +1 -0
  24. package/internal/tmp/chrome/Default/Extension Rules/LOCK +0 -0
  25. package/internal/tmp/chrome/Default/Extension Rules/LOG +3 -0
  26. package/internal/tmp/chrome/Default/Extension Rules/LOG.old +3 -0
  27. package/internal/tmp/chrome/Default/Extension Rules/MANIFEST-000001 +0 -0
  28. package/internal/tmp/chrome/Default/Extension Scripts/000003.log +0 -0
  29. package/internal/tmp/chrome/Default/Extension Scripts/CURRENT +1 -0
  30. package/internal/tmp/chrome/Default/Extension Scripts/LOCK +0 -0
  31. package/internal/tmp/chrome/Default/Extension Scripts/LOG +3 -0
  32. package/internal/tmp/chrome/Default/Extension Scripts/LOG.old +3 -0
  33. package/internal/tmp/chrome/Default/Extension Scripts/MANIFEST-000001 +0 -0
  34. package/internal/tmp/chrome/Default/Favicons +0 -0
  35. package/internal/tmp/chrome/Default/Favicons-journal +0 -0
  36. package/internal/tmp/chrome/Default/History +0 -0
  37. package/internal/tmp/chrome/Default/History-journal +0 -0
  38. package/internal/tmp/chrome/Default/LOCK +0 -0
  39. package/internal/tmp/chrome/Default/LOG +0 -0
  40. package/internal/tmp/chrome/Default/LOG.old +0 -0
  41. package/internal/tmp/chrome/Default/Local Storage/leveldb/000003.log +0 -0
  42. package/internal/tmp/chrome/Default/Local Storage/leveldb/CURRENT +1 -0
  43. package/internal/tmp/chrome/Default/Local Storage/leveldb/LOCK +0 -0
  44. package/internal/tmp/chrome/Default/Local Storage/leveldb/LOG +2 -0
  45. package/internal/tmp/chrome/Default/Local Storage/leveldb/MANIFEST-000001 +0 -0
  46. package/internal/tmp/chrome/Default/PersistentOriginTrials/LOCK +0 -0
  47. package/internal/tmp/chrome/Default/PersistentOriginTrials/LOG +0 -0
  48. package/internal/tmp/chrome/Default/PersistentOriginTrials/LOG.old +0 -0
  49. package/internal/tmp/chrome/Default/README +1 -0
  50. package/internal/tmp/chrome/Default/Segmentation Platform/SegmentInfoDB/LOCK +0 -0
  51. package/internal/tmp/chrome/Default/Segmentation Platform/SegmentInfoDB/LOG +0 -0
  52. package/internal/tmp/chrome/Default/Segmentation Platform/SegmentInfoDB/LOG.old +0 -0
  53. package/internal/tmp/chrome/Default/Segmentation Platform/SignalDB/LOCK +0 -0
  54. package/internal/tmp/chrome/Default/Segmentation Platform/SignalDB/LOG +0 -0
  55. package/internal/tmp/chrome/Default/Segmentation Platform/SignalDB/LOG.old +0 -0
  56. package/internal/tmp/chrome/Default/Segmentation Platform/SignalStorageConfigDB/LOCK +0 -0
  57. package/internal/tmp/chrome/Default/Segmentation Platform/SignalStorageConfigDB/LOG +0 -0
  58. package/internal/tmp/chrome/Default/Segmentation Platform/SignalStorageConfigDB/LOG.old +0 -0
  59. package/internal/tmp/chrome/Default/ServerCertificate +0 -0
  60. package/internal/tmp/chrome/Default/ServerCertificate-journal +0 -0
  61. package/internal/tmp/chrome/Default/Site Characteristics Database/000003.log +0 -0
  62. package/internal/tmp/chrome/Default/Site Characteristics Database/CURRENT +1 -0
  63. package/internal/tmp/chrome/Default/Site Characteristics Database/LOCK +0 -0
  64. package/internal/tmp/chrome/Default/Site Characteristics Database/LOG +3 -0
  65. package/internal/tmp/chrome/Default/Site Characteristics Database/LOG.old +3 -0
  66. package/internal/tmp/chrome/Default/Site Characteristics Database/MANIFEST-000001 +0 -0
  67. package/internal/tmp/chrome/Default/Sync Data/LevelDB/000003.log +0 -0
  68. package/internal/tmp/chrome/Default/Sync Data/LevelDB/CURRENT +1 -0
  69. package/internal/tmp/chrome/Default/Sync Data/LevelDB/LOCK +0 -0
  70. package/internal/tmp/chrome/Default/Sync Data/LevelDB/LOG +3 -0
  71. package/internal/tmp/chrome/Default/Sync Data/LevelDB/LOG.old +3 -0
  72. package/internal/tmp/chrome/Default/Sync Data/LevelDB/MANIFEST-000001 +0 -0
  73. package/internal/tmp/chrome/Default/chrome_cart_db/LOCK +0 -0
  74. package/internal/tmp/chrome/Default/chrome_cart_db/LOG +0 -0
  75. package/internal/tmp/chrome/Default/chrome_cart_db/LOG.old +0 -0
  76. package/internal/tmp/chrome/Default/commerce_subscription_db/LOCK +0 -0
  77. package/internal/tmp/chrome/Default/commerce_subscription_db/LOG +0 -0
  78. package/internal/tmp/chrome/Default/commerce_subscription_db/LOG.old +0 -0
  79. package/internal/tmp/chrome/Default/discount_infos_db/LOCK +0 -0
  80. package/internal/tmp/chrome/Default/discount_infos_db/LOG +0 -0
  81. package/internal/tmp/chrome/Default/discount_infos_db/LOG.old +0 -0
  82. package/internal/tmp/chrome/Default/discounts_db/LOCK +0 -0
  83. package/internal/tmp/chrome/Default/discounts_db/LOG +0 -0
  84. package/internal/tmp/chrome/Default/discounts_db/LOG.old +0 -0
  85. package/internal/tmp/chrome/Default/parcel_tracking_db/LOCK +0 -0
  86. package/internal/tmp/chrome/Default/parcel_tracking_db/LOG +0 -0
  87. package/internal/tmp/chrome/Default/parcel_tracking_db/LOG.old +0 -0
  88. package/internal/tmp/chrome/Default/power_bookmarks/PowerBookmarks.db +0 -0
  89. package/internal/tmp/chrome/Default/power_bookmarks/PowerBookmarks.db-journal +0 -0
  90. package/internal/tmp/chrome/First Run +0 -0
  91. package/internal/tmp/chrome/Last Version +1 -0
  92. package/internal/tmp/chrome/Local State +1 -0
  93. package/internal/tmp/chrome/ShaderCache/data_0 +0 -0
  94. package/internal/tmp/chrome/ShaderCache/data_1 +0 -0
  95. package/internal/tmp/chrome/ShaderCache/data_2 +0 -0
  96. package/internal/tmp/chrome/ShaderCache/data_3 +0 -0
  97. package/internal/tmp/chrome/ShaderCache/index +0 -0
  98. package/internal/tmp/chrome/Variations +1 -0
  99. package/internal/tmp/chrome/segmentation_platform/ukm_db +0 -0
  100. package/internal/tmp/chrome/segmentation_platform/ukm_db-wal +0 -0
  101. package/package.json +3 -2
  102. package/Archive.js +0 -120
package/S3Bucket.js CHANGED
@@ -1309,11 +1309,12 @@ class S3Bucket {
1309
1309
  searchParams.set('versionId', options.VersionId)
1310
1310
  }
1311
1311
 
1312
+ const encodedKey = encodeURIComponentRFC3986(key).replace(/%2F/g, '/')
1312
1313
  const response = await this._awsRequest1(
1313
1314
  'GET',
1314
1315
  searchParams.size > 0
1315
- ? `/${key}?${searchParams.toString()}`
1316
- : `/${key}`,
1316
+ ? `/${encodedKey}?${searchParams.toString()}`
1317
+ : `/${encodedKey}`,
1317
1318
  headers,
1318
1319
  ''
1319
1320
  )
@@ -1500,11 +1501,12 @@ class S3Bucket {
1500
1501
  searchParams.set('versionId', options.VersionId)
1501
1502
  }
1502
1503
 
1504
+ const encodedKey = encodeURIComponentRFC3986(key).replace(/%2F/g, '/')
1503
1505
  const response = await this._awsRequest1(
1504
1506
  'GET',
1505
1507
  searchParams.size > 0
1506
- ? `/${key}?acl&${searchParams.toString()}`
1507
- : `/${key}?acl`,
1508
+ ? `/${encodedKey}?acl&${searchParams.toString()}`
1509
+ : `/${encodedKey}?acl`,
1508
1510
  headers,
1509
1511
  ''
1510
1512
  )
@@ -1750,11 +1752,12 @@ class S3Bucket {
1750
1752
  searchParams.set('versionId', options.VersionId)
1751
1753
  }
1752
1754
 
1755
+ const encodedKey = encodeURIComponentRFC3986(key).replace(/%2F/g, '/')
1753
1756
  const response = await this._awsRequest1(
1754
1757
  'HEAD',
1755
1758
  searchParams.size > 0
1756
- ? `/${key}?${searchParams.toString()}`
1757
- : `/${key}`,
1759
+ ? `/${encodedKey}?${searchParams.toString()}`
1760
+ : `/${encodedKey}`,
1758
1761
  headers,
1759
1762
  ''
1760
1763
  )
@@ -1976,11 +1979,12 @@ class S3Bucket {
1976
1979
  searchParams.set('versionId', options.VersionId)
1977
1980
  }
1978
1981
 
1982
+ const encodedKey = encodeURIComponentRFC3986(key).replace(/%2F/g, '/')
1979
1983
  const response = await this._awsRequest1(
1980
1984
  'DELETE',
1981
1985
  searchParams.size > 0
1982
- ? `/${key}?${searchParams.toString()}`
1983
- : `/${key}`,
1986
+ ? `/${encodedKey}?${searchParams.toString()}`
1987
+ : `/${encodedKey}`,
1984
1988
  headers,
1985
1989
  ''
1986
1990
  )
package/index.js CHANGED
@@ -1,5 +1,4 @@
1
1
  module.exports = {
2
- Archive: require('./Archive.js'),
3
2
  AwsCredentials: require('./AwsCredentials.js'),
4
3
  Docker: require('./Docker.js'),
5
4
  DynamoDBGlobalSecondaryIndex: require('./DynamoDBGlobalSecondaryIndex.js'),
@@ -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
@@ -1,4 +1,4 @@
1
- const nodePath = require('path')
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 = nodePath.parse
17
+ const parsePath = path.parse
18
18
 
19
19
  module.exports = parsePath