phantomas 2.0.0 → 2.4.0

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 (54) hide show
  1. package/Dockerfile +39 -25
  2. package/README.md +20 -8
  3. package/bin/phantomas.js +9 -164
  4. package/bin/program.js +198 -0
  5. package/bin/utils.js +16 -0
  6. package/core/modules/navigationTiming/scope.js +7 -1
  7. package/core/modules/requestsMonitor/requestsMonitor.js +30 -13
  8. package/core/scope.js +2 -1
  9. package/extensions/cookies/cookies.js +1 -2
  10. package/extensions/filmStrip/filmStrip.js +1 -1
  11. package/extensions/pageSource/pageSource.js +2 -0
  12. package/extensions/pageStorage/pageStorage.js +82 -0
  13. package/extensions/screenshot/screenshot.js +27 -9
  14. package/extensions/scroll/scroll.js +3 -1
  15. package/extensions/userAgent/userAgent.js +55 -0
  16. package/extensions/viewport/viewport.js +1 -1
  17. package/extensions/waitForSelector/waitForSelector.js +0 -1
  18. package/hooks/build +3 -0
  19. package/lib/browser.js +81 -33
  20. package/lib/index.js +18 -9
  21. package/lib/loader.js +3 -4
  22. package/lib/metadata/metadata.json +180 -29
  23. package/modules/ajaxRequests/scope.js +1 -1
  24. package/modules/analyzeCss/analyzeCss.js +79 -76
  25. package/modules/analyzeCss/scope.js +1 -1
  26. package/modules/blockDomains/blockDomains.js +21 -21
  27. package/modules/cacheHits/cacheHits.js +6 -3
  28. package/modules/cpuTasks/cpuTasks.js +22 -0
  29. package/modules/documentHeight/scope.js +1 -1
  30. package/modules/domComplexity/scope.js +1 -1
  31. package/modules/domHiddenContent/scope.js +1 -1
  32. package/modules/domMutations/scope.js +1 -1
  33. package/modules/domQueries/domQueries.js +16 -19
  34. package/modules/domQueries/scope.js +1 -1
  35. package/modules/domains/domains.js +1 -1
  36. package/modules/events/scope.js +2 -1
  37. package/modules/globalVariables/scope.js +1 -1
  38. package/modules/jQuery/scope.js +1 -1
  39. package/modules/javaScriptBottlenecks/scope.js +1 -1
  40. package/modules/lazyLoadableImages/scope.js +2 -2
  41. package/modules/localStorage/scope.js +1 -1
  42. package/modules/protocols/protocols.js +101 -0
  43. package/modules/requestsStats/requestsStats.js +1 -1
  44. package/modules/staticAssets/staticAssets.js +2 -1
  45. package/modules/windowPerformance/windowPerformance.js +1 -0
  46. package/package.json +31 -20
  47. package/lib/fast-stats.js +0 -634
  48. package/lib/metadata/generate.js +0 -283
  49. package/lib/metadata/make_docs.js +0 -185
  50. package/reporters/csv.js +0 -54
  51. package/reporters/plain.js +0 -173
  52. package/reporters/statsd.js +0 -82
  53. package/reporters/tap.js +0 -71
  54. package/reporters/teamcity.js +0 -73
package/Dockerfile CHANGED
@@ -1,23 +1,30 @@
1
- FROM node:14-alpine3.12
2
-
3
- # Installs latest Chromium package.
4
- # https://pkgs.alpinelinux.org/package/edge/community/x86_64/chromium
5
- RUN echo "http://dl-cdn.alpinelinux.org/alpine/edge/main" > /etc/apk/repositories \
6
- && echo "http://dl-cdn.alpinelinux.org/alpine/edge/community" >> /etc/apk/repositories \
7
- && echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories \
8
- && echo "http://dl-cdn.alpinelinux.org/alpine/v3.12/main" >> /etc/apk/repositories \
9
- && apk upgrade -U -a \
10
- && apk add \
11
- chromium \
12
- ca-certificates \
13
- freetype \
14
- freetype-dev \
15
- harfbuzz \
16
- nss \
17
- ttf-freefont
18
-
19
- RUN which chromium-browser
20
- RUN chromium-browser --no-sandbox --version
1
+ # https://hub.docker.com/_/node
2
+ FROM node:lts-bullseye-slim
3
+
4
+ # install dependencies of Chrome binary that will be fetched by npm ci
5
+ RUN apt-get update \
6
+ && apt-get install -y --no-install-recommends \
7
+ fonts-liberation \
8
+ libasound2 \
9
+ libatk-bridge2.0-0 \
10
+ libatk1.0-0 \
11
+ libatspi2.0-0 \
12
+ libc6 \
13
+ libcairo2 \
14
+ libcups2 \
15
+ libdbus-1-3 \
16
+ libfreetype6 \
17
+ libgbm1 \
18
+ libharfbuzz0b \
19
+ libnss3 \
20
+ libpango-1.0-0 \
21
+ libx11-6 \
22
+ libxext6 \
23
+ libxkbcommon0 \
24
+ x11-utils \
25
+ xdg-utils \
26
+ zlib1g \
27
+ && rm -rf /var/lib/apt/lists/*
21
28
 
22
29
  # Set up a working directory
23
30
  ENV HOME /opt/phantomas
@@ -27,11 +34,6 @@ RUN chown -R nobody:nogroup .
27
34
  # Run everything after as non-privileged user.
28
35
  USER nobody
29
36
 
30
- # Tell Puppeteer to skip installing Chrome. We'll be using the installed binary
31
- ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD true
32
-
33
- # Tell phantomas where Chromium binary is and that we're in docker
34
- ENV PHANTOMAS_CHROMIUM_EXECUTABLE /usr/bin/chromium-browser
35
37
  ENV DOCKERIZED yes
36
38
 
37
39
  # Install dependencies
@@ -39,5 +41,17 @@ COPY package.json .
39
41
  COPY package-lock.json .
40
42
  RUN npm ci
41
43
 
44
+ # TODO: find the chrome binary and symlink it to the PATH
45
+ RUN ldd $(find . -wholename '*chrome-linux/chrome') && \
46
+ $(find . -wholename '*chrome-linux/chrome') --version
47
+
48
+ ARG GITHUB_SHA="dev"
49
+ ENV COMMIT_SHA ${GITHUB_SHA}
50
+
51
+ # label the image with branch name and commit hash
52
+ LABEL maintainer="maciej.brencz@gmail.com"
53
+ LABEL org.opencontainers.image.source="https://github.com/macbre/phantomas"
54
+ LABEL org.opencontainers.image.revision="${COMMIT_SHA}"
55
+
42
56
  # Copy the content of the rest of the repository into a container
43
57
  COPY . .
package/README.md CHANGED
@@ -1,21 +1,25 @@
1
- phantomas [![npm](https://img.shields.io/npm/dt/phantomas.svg)]() [![Inline docs](http://inch-ci.org/github/macbre/phantomas.svg?branch=phantomas-v2)](http://inch-ci.org/github/macbre/phantomas) [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)
1
+ phantomas
2
+ [![npm](https://img.shields.io/npm/dt/phantomas.svg)]()
3
+ [![Inline docs](http://inch-ci.org/github/macbre/phantomas.svg?branch=phantomas-v2)](http://inch-ci.org/github/macbre/phantomas)
4
+ [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)
5
+ [![Coverage Status](https://coveralls.io/repos/github/macbre/phantomas/badge.svg?branch=devel&1)](https://coveralls.io/github/macbre/phantomas?branch=devel)
6
+ [![CodeFactor](https://www.codefactor.io/repository/github/macbre/phantomas/badge)](https://www.codefactor.io/repository/github/macbre/phantomas)
2
7
  =========
3
8
 
4
9
  [Headless Chromium](https://chromium.googlesource.com/chromium/src/+/lkgr/headless/README.md)-based modular web performance metrics collector. And why phantomas? Well, [because](http://en.wikipedia.org/wiki/Fantômas) :)
5
10
 
6
11
  ## Requirements
7
12
 
8
- * [NodeJS](http://nodejs.org) 12+
13
+ * [NodeJS](http://nodejs.org) 14+
9
14
 
10
15
  ## Installation
11
16
 
12
17
  #### Via npm
13
18
 
14
19
  <a href="https://www.npmjs.com/package/phantomas" title="latest"><img alt="latest" src="https://img.shields.io/npm/v/phantomas/latest.svg" /></a>
15
- <a href="https://www.npmjs.com/package/phantomas/v/next" title="next"><img alt="next" src="https://img.shields.io/npm/v/phantomas/next.svg" /></a>
16
20
 
17
21
  ```
18
- npm install phantomas@next
22
+ npm install phantomas
19
23
  ```
20
24
 
21
25
  > This will install [a recent version of Chromium](https://github.com/GoogleChrome/puppeteer#installation) supported by `puppeteer` module.
@@ -28,6 +32,12 @@ You can use [phantomas Docker image](https://hub.docker.com/r/macbre/phantomas):
28
32
  docker pull macbre/phantomas:latest
29
33
  ```
30
34
 
35
+ Or you can fetch from [GitHub's Containers registry](https://github.com/macbre/phantomas/pkgs/container/phantomas)
36
+
37
+ ```
38
+ docker pull ghcr.io/macbre/phantomas:latest
39
+ ```
40
+
31
41
  ## Support
32
42
 
33
43
  [![Foo](https://raw.githubusercontent.com/macbre/phantomas/devel/docs/phantomas-banner.png)](https://xscode.com/macbre/phantomas)
@@ -91,9 +101,7 @@ Please refer to **[/Troubleshooting.md](https://github.com/macbre/phantomas/blob
91
101
  * modular approach - each metric is generated by a separate "module"
92
102
  * phantomas "core" acts as an events emitter that each module can hook into
93
103
  * in-depth metrics such as: number of events bound via jQuery, calls to ``window.write``or [complex and duplicated CSS selectors (via analyze-css)](https://github.com/macbre/analyze-css)
94
- * JSON and CSV as available output formats for easy integration with automated reporting / monitoring tools
95
- * easy integration with Continuous Integration tools via TAP format and assertions handling
96
- * metrics can be sent via StatsD or stored in elasticsearch
104
+ * JSON as an output format
97
105
  * easy integration with other nodejs projects via CommonJS module ([see API docs](https://github.com/macbre/phantomas/wiki/npm-module))
98
106
  * metrics can be emitted from JavaScript code of the page phantomas is run against (thanks to [helper functions available in window.__phantomas](https://github.com/macbre/phantomas/wiki/Phantomas-scope))
99
107
  * device profiles allow phantomas to emulate mobile or tablet (by setting a proper user agent and viewport)
@@ -134,7 +142,6 @@ You can also use it as a **command line tool**. Run `phantomas -h` for more deta
134
142
 
135
143
  * [Best Practices for Speeding Up Your Web Site](http://developer.yahoo.com/performance/rules.html) (by Yahoo!)
136
144
  * [Web Performance Best Practices](https://developers.google.com/speed/docs/best-practices/rules_intro) (by Google)
137
- * [Writing Efficient CSS](http://developer.mozilla.org/en/Writing_Efficient_CSS) (by Mozilla)
138
145
  * [Planet Performance](http://www.perfplanet.com/) - news and views from the web performance blogosphere
139
146
  * [Performance of 3rd Party Content](http://stevesouders.com/p3pc/) (by Steve Souders)
140
147
  * [Profiling CSS for fun and profit. Optimization notes.](http://perfectionkills.com/profiling-css-for-fun-and-profit-optimization-notes/)
@@ -157,6 +164,7 @@ Introductions to phantomas and use cases:
157
164
  * [Grunt.js for the Enterprise - Vol.1: Frontend Performance with Phantomas](http://www.slideshare.net/DavidAm/grunt-js-for-the-enterprise) (by David Amend)
158
165
  * [Automated Frontend Testing at DrupalCon Austin 2014](https://austin2014.drupal.org/session/automated-frontend-testing) (+video)
159
166
  * [Phantomas: Fais-moi un strip !](https://wooster.checkmy.ws/2014/01/phantomas-performance-website/) (in French)
167
+ * [Untangle the JavaScript spaghetti code with YellowLabTools](https://gmetais.github.io/yellowlabtools/2014/11/18/untangle_the_js_spaghetti_code.html)
160
168
 
161
169
  ### Videos
162
170
 
@@ -169,3 +177,7 @@ Use [grunt](http://gruntjs.com/) to automate daily dev tasks, including your's a
169
177
  * [grunt-phantomas](https://github.com/stefanjudis/grunt-phantomas)
170
178
  * [juve](https://github.com/jared-stilwell/juve)
171
179
  * [grunt-devperf](https://github.com/gmetais/grunt-devperf)
180
+
181
+ ## Stargazers over time
182
+
183
+ [![Stargazers over time](https://starchart.cc/macbre/phantomas.svg)](https://starchart.cc/macbre/phantomas)
package/bin/phantomas.js CHANGED
@@ -9,183 +9,27 @@
9
9
  */
10
10
  "use strict";
11
11
 
12
- const { program } = require("commander"),
12
+ const { getProgram, parseArgv } = require("./program"),
13
13
  phantomas = require(".."),
14
14
  debug = require("debug")("phantomas:cli");
15
15
 
16
16
  var url = "";
17
17
 
18
- // parse options
19
- program
20
- .name("phantomas")
21
- .description(
22
- "Headless Chromium-based web performance metrics collector and monitoring tool"
23
- )
24
- .version(phantomas.version)
25
- .usage("--url <url> [options]")
26
-
27
- //
28
- // https://www.npmjs.com/package/commander#common-option-types-boolean-and-value
29
- //
30
-
31
- // mandatory
32
- .option("--url <url>", "Set URL to work with")
33
-
34
- .option("-v, --verbose", "print debug messages to the console")
35
- .option("-d, --debug", "run phantomas in debug mode")
36
- .option(
37
- "--modules <modules>",
38
- "run selected modules only [moduleOne],[moduleTwo],..."
39
- )
40
- .option(
41
- "--include-dirs <dirs>",
42
- "load modules from specified directories [dirOne],[dirTwo],..."
43
- )
44
- .option(
45
- "--skip-modules <modules>",
46
- "skip selected modules [moduleOne],[moduleTwo],..."
47
- )
48
-
49
- // .option(
50
- // "config",
51
- // "uses JSON or YAML-formatted config file to set parameters"
52
- // )
53
- // .string("config")
54
- // optional params
55
-
56
- // Client options
57
- .option("--phone", "force viewport and user agent of a mobile phone")
58
- .option("--tablet", "force viewport and user agent of a tablet")
59
- .option("--viewport <width x height>", "viewport dimensions", "800x600")
60
- .option("--user-agent <user agent>", "provide a custom user agent")
61
-
62
- // HTTP options
63
- .option(
64
- "--auth-user <user>",
65
- "sets the user name used for HTTP authentication"
66
- )
67
- .option(
68
- "--auth-pass <password>",
69
- "sets the password used for HTTP authentication"
70
- )
71
- .option(
72
- "--cookie <cookies>",
73
- 'document.cookie formatted string for setting a single cookie (e.g. "bar=foo;domain=url")'
74
- )
75
- .option(
76
- "--cookies-file <file>",
77
- "specifies the file name to store the persistent Cookies"
78
- )
79
- .option(
80
- "--ignore-ssl-errors",
81
- "ignores SSL errors, such as expired or self-signed certificate errors"
82
- )
83
- .option(
84
- "--proxy <host:port>",
85
- "specifies the proxy server to use (e.g. --proxy=192.168.1.42:8080)"
86
- )
87
- .option(
88
- "--proxy-auth <username:password>",
89
- "specifies the authentication information for the proxy"
90
- )
91
- .option(
92
- "--proxy-type <type>",
93
- "specifies the type of the proxy server [http|socks5|none]"
94
- )
95
- .option(
96
- "--ssl-protocol <protocol>",
97
- "sets the SSL protocol for secure connections [sslv3|sslv2|tlsv1|any]"
98
- )
99
-
100
- // Runtime options
101
- .option(
102
- "--allow-domain <domain>",
103
- "allow requests to given domain(s) - aka whitelist [domain],[domain],..."
104
- )
105
- .option(
106
- "--block-domain <domain>",
107
- "disallow requests to given domain(s) - aka blacklist [domain],[domain],..."
108
- )
109
- .option("--disable-js", "disable JavaScript on the page that will be loaded")
110
- .option("--no-externals", "block requests to 3rd party domains")
111
- .option("--post-load-delay <N>", "wait X seconds before generating a report")
112
- .option("--scroll", "scroll down the page when it's loaded")
113
- .option("--spy-eval", "report calls to eval()")
114
- .option("--stop-at-onload", "stop phantomas immediately after onload event")
115
- .option("--timeout <seconds>", "timeout for phantomas run", 15)
116
- .option(
117
- "--wait-for-event <event>",
118
- "wait for a given phantomas event before generating a report"
119
- )
120
- .option(
121
- "--wait-for-selector <selector>",
122
- "wait for an element matching given CSS selector before generating a report"
123
- )
124
- .option("--scroll", "scroll down the page when it's loaded")
125
-
126
- // Output and reporting
127
- .option("--analyze-css", "emit in-depth CSS metrics")
128
- .option("--colors", "forces ANSI colors even when output is piped")
129
- .option(
130
- "--film-strip",
131
- "register film strip when page is loading (a comma separated list of milliseconds can be passed)"
132
- )
133
- .option(
134
- "--film-strip-dir <dir>",
135
- "folder path to output film strip (default is ./filmstrip directory)"
136
- )
137
- .option("--har <file>", "save HAR to a given file")
138
- .option("--log <file>", "log to a given file")
139
- .option("--page-source", "save page source to file")
140
- .option(
141
- "--page-source-dir <dir>",
142
- "folder path to output page source (default is ./html directory)"
143
- )
144
- .option(
145
- "-R, --reporter, --format <reporter>",
146
- "output format / reporter",
147
- "plain"
148
- )
149
- .option("--pretty", "render formatted JSON")
150
- .option("--screenshot", "render fully loaded page to a given file")
151
- .option("-s, --silent", "don't write anything to the console");
152
-
153
- // handle --config (issue #209)
154
- //program.setConfigFile("config");
155
-
156
- // handle env variables (issue #685)
157
- //program.setReplacementVars(process.env);
158
-
159
- // parse it
160
- program.parse(process.argv);
161
- var options = program.opts();
162
-
163
- debug("argv: %j", process.argv);
164
- debug("opts: %j", options);
165
-
166
- // handle URL passed without --url option (#249)
167
- if (typeof options.url === "undefined" && process.argv.length >= 3) {
168
- if (!process.argv[2].startsWith("-")) {
169
- options.url = process.argv[2];
170
- }
171
- }
172
-
173
- // handle --no-foo options
174
- options["no-externals"] = options.externals === false;
175
- delete options.externals;
18
+ // parse command line arguments
19
+ let options = parseArgv(process.argv);
176
20
 
177
21
  // --url is mandatory -> show help
178
22
  if (typeof options.url !== "string" && typeof options.config === "undefined") {
179
23
  debug("URL not provided - show help and leave");
180
- program.outputHelp();
181
- process.exit(1);
24
+ getProgram().outputHelp();
25
+ process.exitCode = 1;
26
+ return;
182
27
  }
183
28
 
184
29
  url = options.url;
185
30
  debug("url: %s", url);
186
31
 
187
32
  delete options.url;
188
- delete options.version;
189
33
 
190
34
  // add env variable to turn off ANSI colors when needed (#237)
191
35
  // suppress this behaviour by passing --colors option (issue #342)
@@ -199,12 +43,13 @@ phantomas(url, options)
199
43
  .catch((err) => {
200
44
  debug("Error: %s", err);
201
45
  console.error("" + err);
202
- process.exit(2);
46
+ process.exitCode = 2;
203
47
  })
204
48
  .then(async (results) => {
205
- debug("Calling a reporter...");
49
+ debug("Calling the JSON reporter...");
206
50
  debug("Metrics: %j", results.getMetrics());
207
51
 
52
+ // TODO: handle more reporters
208
53
  const reporter = require("../reporters/json")(results, options);
209
54
  const res = await reporter.render();
210
55
 
package/bin/program.js ADDED
@@ -0,0 +1,198 @@
1
+ const debug = require("debug")("phantomas:cli:program");
2
+ const phantomas = require("..");
3
+ const { decamelizeOptions } = require("./utils");
4
+
5
+ const { Command } = require("commander");
6
+
7
+ function getProgram() {
8
+ const program = new Command();
9
+
10
+ // define options
11
+ program
12
+ .name("phantomas")
13
+ .description(
14
+ "Headless Chromium-based web performance metrics collector and monitoring tool"
15
+ )
16
+ .version(phantomas.version)
17
+ .usage("--url <url> [options]")
18
+
19
+ //
20
+ // https://www.npmjs.com/package/commander#common-option-types-boolean-and-value
21
+ //
22
+
23
+ // mandatory
24
+ .option("--url <url>", "Set URL to work with")
25
+
26
+ .option("-v, --verbose", "print debug messages to the console")
27
+ .option("-d, --debug", "run phantomas in debug mode")
28
+ .option(
29
+ "--modules <modules>",
30
+ "run selected modules only [moduleOne],[moduleTwo],..."
31
+ )
32
+ .option(
33
+ "--include-dirs <dirs>",
34
+ "load modules from specified directories [dirOne],[dirTwo],..."
35
+ )
36
+ .option(
37
+ "--skip-modules <modules>",
38
+ "skip selected modules [moduleOne],[moduleTwo],..."
39
+ )
40
+
41
+ // .option(
42
+ // "config",
43
+ // "uses JSON or YAML-formatted config file to set parameters"
44
+ // )
45
+ // .string("config")
46
+ // optional params
47
+
48
+ // Client options
49
+ .option("--phone", "force viewport and user agent of a mobile phone")
50
+ .option("--tablet", "force viewport and user agent of a tablet")
51
+ .option("--viewport <width x height>", "viewport dimensions", "800x600")
52
+ .option("--user-agent <user agent>", "provide a custom user agent")
53
+
54
+ // HTTP options
55
+ .option(
56
+ "--auth-user <user>",
57
+ "sets the user name used for HTTP authentication"
58
+ )
59
+ .option(
60
+ "--auth-pass <password>",
61
+ "sets the password used for HTTP authentication"
62
+ )
63
+ .option(
64
+ "--cookie <cookies>",
65
+ 'document.cookie formatted string for setting a single cookie (e.g. "bar=foo;domain=url")'
66
+ )
67
+ .option(
68
+ "--cookies-file <file>",
69
+ "specifies the file name to store the persistent Cookies"
70
+ )
71
+ .option(
72
+ "--local-storage <values>",
73
+ 'ability to set a local storage, key-value pairs (e.g. "bar=foo;domain=url")'
74
+ )
75
+ .option(
76
+ "--session-storage <values>",
77
+ 'ability to set a session storage, key-value pairs (e.g. "bar=foo;domain=url")'
78
+ )
79
+ .option(
80
+ "--ignore-ssl-errors",
81
+ "ignores SSL errors, such as expired or self-signed certificate errors"
82
+ )
83
+ .option(
84
+ "--proxy <host:port>",
85
+ "specifies the proxy server to use (e.g. --proxy=192.168.1.42:8080)"
86
+ )
87
+ .option(
88
+ "--proxy-auth <username:password>",
89
+ "specifies the authentication information for the proxy"
90
+ )
91
+ .option(
92
+ "--proxy-type <type>",
93
+ "specifies the type of the proxy server [http|socks5|none]"
94
+ )
95
+ .option(
96
+ "--ssl-protocol <protocol>",
97
+ "sets the SSL protocol for secure connections [sslv3|sslv2|tlsv1|any]"
98
+ )
99
+
100
+ // Runtime options
101
+ .option(
102
+ "--allow-domain <domain>",
103
+ "allow requests to given domain(s) - aka whitelist [domain],[domain],..."
104
+ )
105
+ .option(
106
+ "--block-domain <domain>",
107
+ "disallow requests to given domain(s) - aka blacklist [domain],[domain],..."
108
+ )
109
+ .option(
110
+ "--disable-js",
111
+ "disable JavaScript on the page that will be loaded"
112
+ )
113
+ .option("--no-externals", "block requests to 3rd party domains")
114
+ .option(
115
+ "--post-load-delay <N>",
116
+ "wait X seconds before generating a report"
117
+ )
118
+ .option("--scroll", "scroll down the page when it's loaded")
119
+ .option("--spy-eval", "report calls to eval()")
120
+ .option("--stop-at-onload", "stop phantomas immediately after onload event")
121
+ .option("--timeout <seconds>", "timeout for phantomas run", 15)
122
+ .option(
123
+ "--wait-for-event <event>",
124
+ "wait for a given phantomas event before generating a report"
125
+ )
126
+ .option(
127
+ "--wait-for-selector <selector>",
128
+ "wait for an element matching given CSS selector before generating a report"
129
+ )
130
+ .option("--scroll", "scroll down the page when it's loaded")
131
+
132
+ // Output and reporting
133
+ .option("--analyze-css", "emit in-depth CSS metrics")
134
+ .option("--colors", "forces ANSI colors even when output is piped")
135
+ .option(
136
+ "--film-strip",
137
+ "register film strip when page is loading (a comma separated list of milliseconds can be passed)"
138
+ )
139
+ .option(
140
+ "--film-strip-dir <dir>",
141
+ "folder path to output film strip (default is ./filmstrip directory)"
142
+ )
143
+ .option("--har <file>", "save HAR to a given file")
144
+ .option("--log <file>", "log to a given file")
145
+ .option("--page-source", "save page source to file")
146
+ .option(
147
+ "--page-source-dir <dir>",
148
+ "folder path to output page source (default is ./html directory)"
149
+ )
150
+ .option("--pretty", "render formatted JSON")
151
+ .option(
152
+ "--screenshot <file>",
153
+ "render the viewport to a given file once fully loaded"
154
+ )
155
+ .option("--full-page-screenshot", "enlarge the screenshot to full page")
156
+ .option("-s, --silent", "don't write anything to the console");
157
+
158
+ // handle --config (issue #209)
159
+ //program.setConfigFile("config");
160
+
161
+ // handle env variables (issue #685)
162
+ //program.setReplacementVars(process.env);
163
+
164
+ return program;
165
+ }
166
+
167
+ function parseArgv(args) {
168
+ const program = getProgram();
169
+
170
+ // parse provided options
171
+ debug("argv: %j", args);
172
+ program.parse(args);
173
+
174
+ // make sure options are not "camelCased" but "have-dashes" instead (issue #863)
175
+ let options = decamelizeOptions(program.opts());
176
+ debug("decamelzed opts: %j", options);
177
+
178
+ // handle URL passed without --url option (#249)
179
+ if (typeof options.url === "undefined" && args.length >= 3) {
180
+ if (!args[2].startsWith("-")) {
181
+ options.url = args[2];
182
+ }
183
+ }
184
+
185
+ // handle --no-foo options
186
+ options["no-externals"] = options.externals === false;
187
+ delete options.externals;
188
+
189
+ delete options.version;
190
+
191
+ debug("opts: %j", options);
192
+ return options;
193
+ }
194
+
195
+ module.exports = {
196
+ getProgram,
197
+ parseArgv,
198
+ };
package/bin/utils.js ADDED
@@ -0,0 +1,16 @@
1
+ const decamelize = require("decamelize");
2
+
3
+ function decamelizeOptions(options) {
4
+ // decamelize option names as returned by commander (see issue #863)
5
+ let decamelized = {};
6
+
7
+ for (const [key, value] of Object.entries(options)) {
8
+ decamelized[decamelize(key, { separator: "-" })] = value;
9
+ }
10
+
11
+ return decamelized;
12
+ }
13
+
14
+ module.exports = {
15
+ decamelizeOptions,
16
+ };
@@ -1,4 +1,10 @@
1
- (function (phantomas) {
1
+ /* istanbul ignore next */
2
+ (function navigationTimingScope(phantomas) {
3
+ // Prevent events from being sent from an iframe. Only from the main document.
4
+ if (window.parent !== window || window.location.href === "about:blank") {
5
+ return;
6
+ }
7
+
2
8
  function emit(eventName) {
3
9
  phantomas.log("Navigation Timing milestone: %s", eventName);
4
10
  phantomas.emit("milestone", eventName); // @desc Page loading milestone has been reached: domInteractive, domReady and domComplete