1 |
|
2 | - [How to Contribute](#how-to-contribute)
|
3 | * [Contributor License Agreement](#contributor-license-agreement)
|
4 | * [Getting setup](#getting-setup)
|
5 | * [Code reviews](#code-reviews)
|
6 | * [Code Style](#code-style)
|
7 | * [API guidelines](#api-guidelines)
|
8 | * [Commit Messages](#commit-messages)
|
9 | * [Writing Documentation](#writing-documentation)
|
10 | * [Adding New Dependencies](#adding-new-dependencies)
|
11 | * [Writing Tests](#writing-tests)
|
12 | * [Public API Coverage](#public-api-coverage)
|
13 | * [Debugging Puppeteer](#debugging-puppeteer)
|
14 | - [For Project Maintainers](#for-project-maintainers)
|
15 | * [Releasing to NPM](#releasing-to-npm)
|
16 | * [Updating NPM dist tags](#updating-npm-dist-tags)
|
17 |
|
18 |
|
19 | # How to Contribute
|
20 |
|
21 | First of all, thank you for your interest in Puppeteer!
|
22 | We'd love to accept your patches and contributions!
|
23 |
|
24 | ## Contributor License Agreement
|
25 |
|
26 | Contributions to this project must be accompanied by a Contributor License
|
27 | Agreement. You (or your employer) retain the copyright to your contribution,
|
28 | this simply gives us permission to use and redistribute your contributions as
|
29 | part of the project. Head over to <https://cla.developers.google.com/> to see
|
30 | your current agreements on file or to sign a new one.
|
31 |
|
32 | You generally only need to submit a CLA once, so if you've already submitted one
|
33 | (even if it was for a different project), you probably don't need to do it
|
34 | again.
|
35 |
|
36 | ## Getting setup
|
37 |
|
38 | 1. Clone this repository
|
39 |
|
40 | ```bash
|
41 | git clone https://github.com/GoogleChrome/puppeteer
|
42 | cd puppeteer
|
43 | ```
|
44 |
|
45 | 2. Install dependencies
|
46 |
|
47 | ```bash
|
48 | npm install
|
49 | ```
|
50 |
|
51 | ## Code reviews
|
52 |
|
53 | All submissions, including submissions by project members, require review. We
|
54 | use GitHub pull requests for this purpose. Consult
|
55 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
|
56 | information on using pull requests.
|
57 |
|
58 | ## Code Style
|
59 |
|
60 | - Coding style is fully defined in [.eslintrc](https://github.com/GoogleChrome/puppeteer/blob/master/.eslintrc.js)
|
61 | - Code should be annotated with [closure annotations](https://github.com/google/closure-compiler/wiki/Annotating-JavaScript-for-the-Closure-Compiler).
|
62 | - Comments should be generally avoided. If the code would not be understood without comments, consider re-writing the code to make it self-explanatory.
|
63 |
|
64 | To run code linter, use:
|
65 |
|
66 | ```bash
|
67 | npm run lint
|
68 | ```
|
69 |
|
70 | ## API guidelines
|
71 |
|
72 | When authoring new API methods, consider the following:
|
73 | - Expose as little information as needed. When in doubt, don’t expose new information.
|
74 | - Methods are used in favor of getters/setters.
|
75 | - The only exception is namespaces, e.g. `page.keyboard` and `page.coverage`
|
76 | - All string literals must be small case. This includes event names and option values.
|
77 | - Avoid adding "sugar" API (API that is trivially implementable in user-space) unless they're **very** demanded.
|
78 |
|
79 | ## Commit Messages
|
80 |
|
81 | Commit messages should follow the Semantic Commit Messages format:
|
82 |
|
83 | ```
|
84 | label(namespace): title
|
85 |
|
86 | description
|
87 |
|
88 | footer
|
89 | ```
|
90 |
|
91 | 1. *label* is one of the following:
|
92 | - `fix` - puppeteer bug fixes.
|
93 | - `feat` - puppeteer features.
|
94 | - `docs` - changes to docs, e.g. `docs(api.md): ..` to change documentation.
|
95 | - `test` - changes to puppeteer tests infrastructure.
|
96 | - `style` - puppeteer code style: spaces/alignment/wrapping etc.
|
97 | - `chore` - build-related work, e.g. doclint changes / travis / appveyor.
|
98 | 2. *namespace* is put in parenthesis after label and is optional.
|
99 | 3. *title* is a brief summary of changes.
|
100 | 4. *description* is **optional**, new-line separated from title and is in present tense.
|
101 | 5. *footer* is **optional**, new-line separated from *description* and contains "fixes" / "references" attribution to github issues.
|
102 | 6. *footer* should also include "BREAKING CHANGE" if current API clients will break due to this change. It should explain what changed and how to get the old behavior.
|
103 |
|
104 | Example:
|
105 |
|
106 | ```
|
107 | fix(Page): fix page.pizza method
|
108 |
|
109 | This patch fixes page.pizza so that it works with iframes.
|
110 |
|
111 | Fixes #123, Fixes #234
|
112 |
|
113 | BREAKING CHANGE: page.pizza now delivers pizza at home by default.
|
114 | To deliver to a different location, use "deliver" option:
|
115 | `page.pizza({deliver: 'work'})`.
|
116 | ```
|
117 |
|
118 | ## Writing Documentation
|
119 |
|
120 | All public API should have a descriptive entry in the [docs/api.md](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md). There's a [documentation linter](https://github.com/GoogleChrome/puppeteer/tree/master/utils/doclint) which makes sure documentation is aligned with the codebase.
|
121 |
|
122 | To run documentation linter, use:
|
123 |
|
124 | ```bash
|
125 | npm run doc
|
126 | ```
|
127 |
|
128 | ## Adding New Dependencies
|
129 |
|
130 | For all dependencies (both installation and development):
|
131 | - **Do not add** a dependency if the desired functionality is easily implementable.
|
132 | - If adding a dependency, it should be well-maintained and trustworthy.
|
133 |
|
134 | A barrier for introducing new installation dependencies is especially high:
|
135 | - **Do not add** installation dependency unless it's critical to project success.
|
136 |
|
137 | ## Writing Tests
|
138 |
|
139 | - Every feature should be accompanied by a test.
|
140 | - Every public api event/method should be accompanied by a test.
|
141 | - Tests should be *hermetic*. Tests should not depend on external services.
|
142 | - Tests should work on all three platforms: Mac, Linux and Win. This is especially important for screenshot tests.
|
143 |
|
144 | Puppeteer tests are located in [test/test.js](https://github.com/GoogleChrome/puppeteer/blob/master/test/test.js)
|
145 | and are written with a [TestRunner](https://github.com/GoogleChrome/puppeteer/tree/master/utils/testrunner) framework.
|
146 | Despite being named 'unit', these are integration tests, making sure public API methods and events work as expected.
|
147 |
|
148 | - To run all tests:
|
149 |
|
150 | ```bash
|
151 | npm run unit
|
152 | ```
|
153 |
|
154 | - To run tests in parallel, use `-j` flag:
|
155 |
|
156 | ```bash
|
157 | npm run unit -- -j 4
|
158 | ```
|
159 |
|
160 | - To run a specific test, substitute the `it` with `fit` (mnemonic rule: '*focus it*'):
|
161 |
|
162 | ```js
|
163 | ...
|
164 | // Using "fit" to run specific test
|
165 | fit('should work', async function({server, page}) {
|
166 | const response = await page.goto(server.EMPTY_PAGE);
|
167 | expect(response.ok).toBe(true);
|
168 | })
|
169 | ```
|
170 |
|
171 | - To disable a specific test, substitute the `it` with `xit` (mnemonic rule: '*cross it*'):
|
172 |
|
173 | ```js
|
174 | ...
|
175 | // Using "xit" to skip specific test
|
176 | xit('should work', async function({server, page}) {
|
177 | const response = await page.goto(server.EMPTY_PAGE);
|
178 | expect(response.ok).toBe(true);
|
179 | })
|
180 | ```
|
181 |
|
182 | - To run tests in non-headless mode:
|
183 |
|
184 | ```bash
|
185 | HEADLESS=false npm run unit
|
186 | ```
|
187 |
|
188 | - To run tests with custom Chromium executable:
|
189 |
|
190 | ```bash
|
191 | CHROME=<path-to-executable> npm run unit
|
192 | ```
|
193 |
|
194 | - To run tests in slow-mode:
|
195 |
|
196 | ```bash
|
197 | HEADLESS=false SLOW_MO=500 npm run unit
|
198 | ```
|
199 |
|
200 | - To debug a test, "focus" a test first and then run:
|
201 |
|
202 | ```bash
|
203 | node --inspect-brk test/test.js
|
204 | ```
|
205 |
|
206 | ## Public API Coverage
|
207 |
|
208 | Every public API method or event should be called at least once in tests. To ensure this, there's a coverage command which tracks calls to public API and reports back if some methods/events were not called.
|
209 |
|
210 | Run coverage:
|
211 |
|
212 | ```bash
|
213 | npm run coverage
|
214 | ```
|
215 |
|
216 | ## Debugging Puppeteer
|
217 |
|
218 | See [Debugging Tips](README.md#debugging-tips) in the readme.
|
219 |
|
220 | # For Project Maintainers
|
221 |
|
222 | ## Releasing to NPM
|
223 |
|
224 | Releasing to NPM consists of 3 phases:
|
225 | 1. Source Code: mark a release.
|
226 | 1. Bump `package.json` version following the SEMVER rules and send a PR titled `'chore: mark version vXXX.YYY.ZZZ'` ([example](https://github.com/GoogleChrome/puppeteer/commit/808bf8e5582482a1d849ff22a51e52024810905c)).
|
227 | 2. Make sure the PR passes **all checks**.
|
228 | - **WHY**: there are linters in place that help to avoid unnecessary errors, e.g. [like this](https://github.com/GoogleChrome/puppeteer/pull/2446)
|
229 | 3. Merge the PR.
|
230 | 4. Once merged, publish release notes using the "create new tag" option.
|
231 | - **NOTE**: tag names are prefixed with `'v'`, e.g. for version `1.4.0` tag is `v1.4.0`.
|
232 | 2. Publish `puppeteer` to NPM.
|
233 | 1. On your local machine, pull from [upstream](https://github.com/GoogleChrome/puppeteer) and make sure the last commit is the one just merged.
|
234 | 2. Run `git status` and make sure there are no untracked files.
|
235 | - **WHY**: this is to avoid bundling unnecessary files to NPM package
|
236 | 3. Run [`pkgfiles`](https://www.npmjs.com/package/pkgfiles) to make sure you don't publish anything unnecessary.
|
237 | 4. Run `npm publish`. This will publish `puppeteer` package.
|
238 | 3. Publish `puppeteer-core` to NPM.
|
239 | 1. Run `./utils/prepare_puppeteer_core.js`. The script will change the name inside `package.json` to `puppeteer-core`.
|
240 | 2. Run `npm publish`. This will publish `puppeteer-core` package.
|
241 | 3. Run `git reset --hard` to reset the changes to `package.json`.
|
242 | 4. Source Code: mark post-release.
|
243 | 1. Bump `package.json` version to `-post` version and send a PR titled `'chore: bump version to vXXX.YYY.ZZZ-post'` ([example](https://github.com/GoogleChrome/puppeteer/commit/d02440d1eac98028e29f4e1cf55413062a259156))
|
244 | - **NOTE**: make sure to update the "released APIs" section in the top of `docs/api.md`.
|
245 | - **NOTE**: no other commits should be landed in-between release commit and bump commit.
|
246 |
|
247 | ## Updating NPM dist tags
|
248 |
|
249 | For both `puppeteer` and `puppeteer-firefox` we maintain the following NPM Tags:
|
250 | - `chrome-*` tags, e.g. `chrome-75` and so on. These tags match Puppeteer version that corresponds to the `chrome-*` release.
|
251 | - `chrome-stable` tag. This tag points to the Puppeteer version that works with current Chrome stable.
|
252 |
|
253 | These tags are updated on every Puppeteer release.
|
254 |
|
255 | > **NOTE**: due to Chrome's rolling release, we take [omahaproxy's linux stable version](https://omahaproxy.appspot.com/) as *stable*.
|
256 |
|
257 | Manging tags 101:
|
258 |
|
259 | ```bash
|
260 | # list tags
|
261 | $ npm dist-tag ls puppeteer
|
262 | # Removing a tag
|
263 | $ npm dist-tag rm puppeteer-core chrome-stable
|
264 | # Adding a tag
|
265 | $ npm dist-tag add puppeteer-core@1.13.0 chrome-stable
|
266 | ```
|