Skip to content

Commit 58b1a15

Browse files
committed
move validation to separate file
1 parent 429dc0d commit 58b1a15

File tree

7 files changed

+148
-18
lines changed

7 files changed

+148
-18
lines changed

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,10 @@
4646
},
4747
"devDependencies": {
4848
"ava": "^1.3.1",
49+
"chromium": "^2.1.0",
4950
"create-test-server": "^2.4.0",
5051
"prettier": "^1.16.4",
52+
"puppeteer-core": "^1.13.0",
5153
"xo": "^0.24.0"
5254
},
5355
"dependencies": {

src/index.js

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,34 @@
11
const puppeteer = require('puppeteer')
2+
const {validateBrowserOverride} = require('./validate')
23

34
function InvalidUrlError({url, statusCode, statusText}) {
45
this.name = 'InvalidUrlError'
56
this.message = `There was an error retrieving CSS from ${url}.\n\tHTTP status code: ${statusCode} (${statusText})`
67
}
78

8-
InvalidUrlError.prototype = Error.prototype
9-
109
module.exports = async (
1110
url,
12-
{debug = false, waitUntil = 'networkidle2'} = {}
11+
{debug = false, waitUntil = 'networkidle2', browserOverride = null} = {}
1312
) => {
13+
// Basic validation for browserOverride
14+
if (browserOverride !== null) {
15+
validateBrowserOverride(browserOverride)
16+
}
17+
18+
// Setup the minimal browser options that we need to launch
19+
const browserOptions = {
20+
headless: debug !== true,
21+
executablePath: browserOverride
22+
? browserOverride.executablePath
23+
: puppeteer.executablePath(),
24+
args: browserOverride ? browserOverride.args : []
25+
}
26+
1427
// Setup a browser instance
15-
const browser = await puppeteer.launch({
16-
headless: debug !== true
17-
})
28+
const browser = await (
29+
(browserOverride && browserOverride.puppeteer) ||
30+
puppeteer
31+
).launch(browserOptions)
1832

1933
// Create a new page and navigate to it
2034
const page = await browser.newPage()

src/validate.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
function InvalidBrowserOverrideError(message) {
2+
this.name = 'InvalidBrowserOverrideError'
3+
this.message = `BrowserOverride is not valid. ${message} https://github.com/bartveneman/extract-css-core#options`
4+
}
5+
6+
InvalidBrowserOverrideError.prototype = Error.prototype
7+
8+
exports.validateBrowserOverride = ({executablePath, args, puppeteer}) => {
9+
if (typeof executablePath !== 'string') {
10+
throw new InvalidBrowserOverrideError(
11+
`Check that executablePath is a valid string, got "${JSON.stringify(
12+
executablePath
13+
)}"`
14+
)
15+
}
16+
17+
if (!Array.isArray(args)) {
18+
throw new InvalidBrowserOverrideError('Check that args is an Array.')
19+
}
20+
21+
if (typeof puppeteer.launch !== 'function') {
22+
throw new InvalidBrowserOverrideError(
23+
'Check that puppeteer.launch is a function.'
24+
)
25+
}
26+
27+
return true
28+
}

test/index.js

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ const test = require('ava')
22
const createTestServer = require('create-test-server')
33
const {readFileSync} = require('fs')
44
const {resolve} = require('path')
5+
const chromium = require('chromium')
6+
const puppeteerCore = require('puppeteer-core')
7+
58
const extractCss = require('..')
69

710
let server
@@ -113,19 +116,22 @@ test('it rejects on an invalid url', async t => {
113116
await t.throwsAsync(extractCss('site.example'))
114117
})
115118

116-
// TODO: write coverage for dynamically inserted style tags
117-
test.skip('it finds CSS-in-JS (styled components)', async t => {
118-
const path = '/css-in-js'
119-
const cssInJsExampleHtml = readFileSync(
120-
resolve(__dirname, 'css-in-js.html'),
119+
test('it accepts a browser override for usage with other browsers', async t => {
120+
const path = '/browser-override'
121+
const kitchenSinkExample = readFileSync(
122+
resolve(__dirname, 'kitchen-sink.html'),
121123
'utf8'
122124
)
123125
server.get(path, (req, res) => {
124-
res.send(cssInJsExampleHtml)
126+
res.send(kitchenSinkExample)
127+
})
128+
const actual = await extractCss(server.url + path, {
129+
browserOverride: {
130+
executablePath: chromium.path,
131+
puppeteer: puppeteerCore,
132+
args: []
133+
}
125134
})
126135

127-
const actual = await extractCss(server.url + path)
128-
const expected = 'lots of JS generated classNames and styles'
129-
130-
t.is(actual, expected)
136+
t.snapshot(actual)
131137
})

test/snapshots/index.js.md

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ The actual snapshot is saved in `index.js.snap`.
44

55
Generated by [AVA](https://ava.li).
66

7-
## it accepts a custom Chrome and Puppeteer version for use on AWS
7+
## it combines server generated <link> and <style> tags with client side created <link> and <style> tags
88

99
> Snapshot 1
1010
@@ -18,7 +18,21 @@ Generated by [AVA](https://ava.li).
1818
counter-increment: 2;␊
1919
}.js-style { counter-increment: 3; }`
2020

21-
## it combines server generated <link> and <style> tags with client side created <link> and <style> tags
21+
## it finds CSS-in-JS (styled components)
22+
23+
> Snapshot 1
24+
25+
`body {␊
26+
color: teal;␊
27+
}␊
28+
body {␊
29+
color: teal;␊
30+
}␊
31+
.server-style {␊
32+
counter-increment: 2;␊
33+
}.js-style { counter-increment: 3; }`
34+
35+
## it accepts a browser override for usage with other browsers
2236

2337
> Snapshot 1
2438

test/snapshots/index.js.snap

49 Bytes
Binary file not shown.

test/validate.js

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
const test = require('ava')
2+
const extractCss = require('..')
3+
const {validateBrowserOverride} = require('../src/validate')
4+
5+
test('it does basic validation on browserOverride', async t => {
6+
const failures = [
7+
{},
8+
{executablePath: null},
9+
{executablePath: ''},
10+
{
11+
puppeteer: null
12+
},
13+
{puppeteer: {}},
14+
{puppeteer: {launch: null}}
15+
]
16+
const successes = [
17+
{
18+
executablePath: '/path/to/chromium',
19+
puppeteer: {launch: () => {}},
20+
args: []
21+
}
22+
]
23+
24+
failures.forEach(failure => {
25+
t.throws(() => validateBrowserOverride(failure))
26+
})
27+
successes.forEach(success =>
28+
t.notThrows(() => validateBrowserOverride(success))
29+
)
30+
})
31+
32+
test('it does basic validation on the browserOverride option', async t => {
33+
await t.throwsAsync(
34+
extractCss('http://google.com', {
35+
browserOverride: {
36+
executablePath: null
37+
}
38+
}),
39+
{
40+
message:
41+
'BrowserOverride is not valid. Check that executablePath is a valid string, got "null" https://github.com/bartveneman/extract-css-core#options'
42+
}
43+
)
44+
await t.throwsAsync(
45+
extractCss('http://google.com', {
46+
browserOverride: {
47+
puppeteer: null
48+
}
49+
}),
50+
{
51+
message:
52+
'BrowserOverride is not valid. Check that executablePath is a valid string, got "undefined" https://github.com/bartveneman/extract-css-core#options'
53+
}
54+
)
55+
await t.throwsAsync(
56+
extractCss('http://google.com', {
57+
browserOverride: {
58+
args: null
59+
}
60+
}),
61+
{
62+
message:
63+
'BrowserOverride is not valid. Check that executablePath is a valid string, got "undefined" https://github.com/bartveneman/extract-css-core#options'
64+
}
65+
)
66+
})

0 commit comments

Comments
 (0)