UNPKG

9.56 kBMarkdownView Raw
1# n-test
2Runs smoke tests with Puppeteer (and optionally Browserstack). Define a set of URLs and expected behaviour in JSON, without the toil of writing full blown tests.
3
4[![CircleCI](https://circleci.com/gh/Financial-Times/n-test.svg?style=svg&circle-token=d042713e08cb5920c4c2b462e63867d4906a7a66)](https://circleci.com/gh/Financial-Times/n-test)
5[![Node.js version support][shield-node]](#)
6
7[shield-github]: (https://img.shields.io/github/tag/Financial-Times/n-test.svg
8[shield-node]: https://img.shields.io/badge/node.js%20support->=14.0.0-brightgreen.svg
9
10
11```
12n-test smoke
13n-test smoke --config path/to/config.js --host http://local.ft.com:3002 --header "X-Api-Key: 1234"
14n-test smoke basic
15n-test smoke -i
16
17n-test open
18n-test open headers --breakpoint M --config path/to/config.js --host https://local.ft.com:3002
19```
20
21Table of Contents
22-----------------
23 * [Requirements](#requirements)
24 * [Usage](#usage)
25 * [Expectations](#expectations)
26 * [Request types](#request-types)
27 * [FT User Sessions](#ft-user-sessions)
28 * [Using Programatically](#using-programatically)
29 * [Cross Browser Testing](#cross-browser-testing-experimental)
30 * [Contributing](#contributing)
31
32
33Requirements
34------------
35
36n-test requires the following to run:
37* [Node.js][node] Version defined by `engines.node` in `package.json`. Run command `nvm use` to switch your local Node version to the one specified in `.nvmrc`.
38* [npm][npm] (normally comes with Node.js)
39
40
41Usage
42-----
43
44n-test is easiest to use as a command line tool, installed by npm.
45
46`npm install @financial-times/n-test`
47
48You must create a _config file_ containing the set of URLs to test. This will be a javascript file, that exports an array of test suites. The default location is `test/smoke.js`. This can be overriden with a command line parameter.
49
50```
51module.exports = [
52 {
53 name: 'basic',
54 urls: {
55 '/': 200,
56 '/redirect': '/'
57 },
58 description: 'Test suite descriptions are optional',
59 }
60];
61```
62
63Then, you can run (assuming your application is running on port 8080 - the default is 3002):
64
65`n-test smoke -H http://localhost:8080`
66
67This will run a headless browser, open the URLs and check (in the above case) the response status is 200 for / and '/redirect' redirects to '/'. If both of those things are true, the command will exit with a success status.
68
69You can also run:
70
71`n-test open -H http://localhost:8080`
72
73This allows you to select a suite of URLs (in this case, "basic"), and open them in Chromium. This is useful for manually testing a set of URLs.
74
75If, when running locally, you are seeing errors about certificates not being valid, set NODE_ENV to be 'development' e.g. `NODE_ENV=development;n-test smoke -H http://localhost:8080`. This will use some launch options that ignore certificate errors.
76
77### Expectations
78
79Checking response statii is great for checking that your application responds with _something_, but not necessarily the right thing. n-test comes with a bunch of basic things that you check for.
80
81```
82...
83urls: {
84 '/article/1234': {
85 status: 200,
86 elements: {
87 '.this-should-exist-somewhere': true,
88 '.there-should-be-3-of-these': 3,
89 'div[exists=false]': false,
90 '#should-contain-text': 'text'
91 },
92 elementShifts: {
93 '.this-should-not-move': { maxCount: 0 },
94 '.this-can-move-up-to-3-times': { maxCount: 0 },
95 '.this-can-only-move-up-to-100-px': { maxPixels: 100 }
96 },
97 responseHeaders: {
98 'My-Header': 'expected-value'
99 },
100 pageErrors: 0,
101 networkRequests: {
102 '/some-third-party.js': 1,
103 'tracking.pixel': 4, //asserts 4 network requests were made to a URL containing 'tracking.pixel'
104 '/will-have-some-of-these.jpg': true,
105 'should-not-load-this.js': false
106 },
107 content: (content) => {
108 return content.includes('some-text');
109 },
110 visibleContent: {
111 contentSelector: '.headline, .image, .standfirst'
112 threshold: 30 // % of viewport that should be visible content
113 },
114 performance: true, //checks firstPaint/firstContentfulPaint against baseline. default = 2000, or can specify.
115 description: 'Each test may have an optional description. It will display when the test result is reported',
116 }
117}
118...
119```
120
121### Request types
122
123By default, URLs are assumed to be GET requests, but you can also specify request method/headers/bodies.
124
125```
126...
127urls: {
128 '/article/1234': {
129 headers: {
130 'My-Request-Header': 1
131 }
132 },
133 '/post': {
134 body: { "some": "data" },
135 method: 'POST',
136 status: 200,
137 https: true //Force this URL to be requested over HTTPS, even if the host is not
138 },
139 '/wait-for-load': {
140 waitUntil: 'load' //default = domcontentloaded
141 elements: {
142 '.loaded-by-js': true
143 }
144 }
145}
146...
147```
148
149These can all be set at a suite level, as well as a URL level, like so:
150
151
152```
153...
154{
155 name: 'authenticated-requests',
156 headers: {
157 'api-key': process.env.API_KEY
158 },
159 urls: {
160 '/article/1': 200,
161 '/article/2': 200,
162 '/article/404': 404
163 }
164}
165...
166```
167### Actions
168
169n-test allows some basic actions (e.g. clicking, interacting with forms). This has been ported from [pa11y](https://github.com/pa11y/pa11y) - see the [section on their README](https://github.com/pa11y/pa11y/blob/5.0.4/README.md#actions) for more.
170
171### FT User Sessions
172
173To run a test suite for a type of FT subscriber, add a `user` property to the suite and it will set the session tokens for that type of user before running the tests in that suite.
174
175For the test to get the user session tokens from [`next-test-sessions-lambda`](http://github.com/financial-times/next-test-sessions-lambda), it needs to rewrite the URL being tested to an ft.com host. The original URL is set in the `FT-Test-Host` header, which tells `next-router` to proxy the test URL rather than production.
176
177The test output will display the original URL.
178
179*Options:* `premium`, `standard`, `expired`.
180
181*Running locally:*
182
183Ngrok provides a secure public URL for the local test app and will need to be installed and running on the the app's port. Tests will then use the TEST_URL variable to specify the ngrok URL when starting the service. The local `next-router` needs to be running, as it will be used to proxy the test URL.
184
185Example steps to run next-article user tests locally:
186
187Run next-article and next-router locally:
188
189```sh
190$ cd ~/next-article
191$ make run
192$ cd ~/next-router
1934 make run
194```
195
196Run ngrok on next-article's local port:
197
198```
199$ ./ngrok http 3002
200```
201
202Run the test against the ngrok address provided (can be either http or https):
203
204```
205make smoke TEST_URL=https://05bd2344ebca.ngrok.io
206```
207
208*Remarks*
209
210Needs to set TEST_SESSIONS_URL (url to [`next-test-sessions-lambda`](http://github.com/financial-times/next-test-sessions-lambda)) and TEST_SESSIONS_API_KEY environment variables when running the tests.
211
212*Example*
213```
214[
215 {
216 user: 'premium',
217 urls: [
218 '/these-will': 200,
219 '/run-with-a': 200,
220 '/premium-user': 200
221 ]
222 },
223 {
224 'user': 'standard',
225 'urls': [
226 '/this-will-run-with-a-standard-user': 200
227 ]
228 },
229 {
230 'urls': [
231 '/these-will-run': 403,
232 '/without-session-token': 403
233 ]
234 }
235]
236```
237
238
239### Using Programatically
240
241`n-test` can also be used programatically. This allows you to extend the functionality by adding custom expectations. Below is an example.
242
243```
244const SmokeTest = require('@financial-times/n-test').SmokeTest;
245const smoke = new SmokeTests({ headers: { globalHeader: true }, host: 'local.ft.com:3002' });
246
247//Add custom checks like so:
248smoke.addCheck('custom', async (testPage) => {
249 const metrics = await testPage.page.metrics();
250
251 return {
252 expected: `no more than ${testPage.check.custom} DOM nodes`,
253 actual: `${metrics.Nodes} nodes`,
254 result: testPage.check.custom >= metrics.Nodes
255 }
256});
257
258smoke.run()
259 .then((results) => { //all passed })
260 .catch((results) => { //some failed });
261
262smoke.run(['basic']);
263```
264
265### Cross Browser Testing [Experimental]
266You can also run your test suite against Browserstack .
267
268Browserstack: you must have `BROWSERSTACK_USER` and `BROWSERSTACK_KEY` environment variables set, and enable cross browser tests on a suite/url basis.
269
270*Note* Browserstack supports running off a local host. If your host is local, it will spin up Browserstack Local and proxy through.
271*Caveat* sometimes browserstack local might not clean up properly after itself!
272
273```
274{
275 name: 'blah'
276 urls: {
277 '/only-puppeteer': {
278 status: 200
279 },
280 '/no-element-checks': {
281 status: 200,
282 browsers: true
283 },
284 '/runs-all-browsers': {
285 status: 200,
286 elements: {
287 '.js-success': true
288 },
289 browsers: true //runs against all enabled browsers, default ['chrome', 'firefox', 'safari', 'internet explorer', 'MicrosoftEdge', 'android'];
290 },
291 '/ios-only': {
292 status: 200,
293 elements: {
294 '.app-install-banner': true
295 },
296 browsers: ['ios']
297 },
298 }
299}
300```
301
302The set of enabled browsers to run against can be changed on the command line:
303
304`n-test smoke --browsers "chrome,internet explorer,android"`
305
306
307### Cross Browser Screenshotting [Experimental]
308
309There are two ways to get screenshots generated.
310
3111. As part of your smoke test run, you can generate PNG files with every run:
312
313Example:
314```
315{
316 name: 'blah'
317 urls: {
318 '/screenshot-me': {
319 status: 200,
320 screenshot: {
321 path: './tmp/screenshots'
322 }
323 }
324 }
325}
326```
327
3282. A command that takes screenshots on multiple browsers, and opens them in a headless chrome window.
329
330`n-test screenshot --browsers ie9,safari`
331
332#### HALPPPPP
333
334Call upon `n-test HALP` to get you through the tough times.
335
336If a test is failing because a subscription has expired, e.g. the premium subscription on nextpremium@ftqa.org has expired, email customer support to renew it.