UNPKG

11 kBMarkdownView Raw
1# start-server-and-test
2
3> Starts server, waits for URL, then runs test command; when the tests end, shuts down server
4
5[![NPM][npm-icon] ][npm-url]
6
7[![Build status][ci-image] ][ci-url]
8[![semantic-release][semantic-image] ][semantic-url]
9[![js-standard-style][standard-image]][standard-url]
10[![renovate-app badge][renovate-badge]][renovate-app]
11
12## Install
13
14Requires [Node](https://nodejs.org/en/) version 8.9 or above.
15
16```sh
17npm install --save-dev start-server-and-test
18```
19
20## Use
21
22This command is meant to be used with NPM script commands. If you have a "start server", and "test" script names for example, you can start the server, wait for a url to respond, then run tests. When the test process exits, the server is shut down.
23
24```json
25{
26 "scripts": {
27 "start-server": "npm start",
28 "test": "mocha e2e-spec.js",
29 "ci": "start-server-and-test start-server http://localhost:8080 test"
30 }
31}
32```
33
34To execute all tests simply run `npm run ci`.
35
36### Commands
37
38In addition to using NPM script names, you can pass entire commands (surround them with quotes so it is still a single string) that will be executed "as is". For example, to start globally installed `http-server` before running and recording [Cypress.io](https://www.cypress.io) tests you can use
39
40```shell
41# run http-server, then when port 8000 responds run Cypress tests
42start-server-and-test 'http-server -c-1 --silent' 8000 './node_modules/.bin/cypress run --record'
43```
44
45Because `npm` scripts execute with `./node_modules/.bin` in the `$PATH`, you can mix global and locally installed tools when using commands inside `package.json` file. For example, if you want to run a single spec file:
46
47```json
48{
49 "scripts": {
50 "ci": "start-server-and-test 'http-server -c-1 --silent' 8080 'cypress run --spec cypress/integration/location.spec.js'"
51 }
52}
53```
54
55Or you can move `http-server` part into its own `start` script, which is used by default and have the equivalent JSON
56
57```json
58{
59 "scripts": {
60 "start": "http-server -c-1 --silent",
61 "ci": "start-server-and-test 8080 'cypress run --spec cypress/integration/location.spec.js'"
62 }
63}
64```
65
66Here is another example that uses Mocha
67
68```json
69{
70 "scripts": {
71 "ci": "start-server-and-test 'http-server -c-1 --silent' 8080 'mocha e2e-spec.js'"
72 }
73}
74```
75
76### Alias
77
78You can use either `start-server-and-test`, `server-test` or `start-test` commands in your scripts.
79
80You can use `:` in front of port number like `server-test :8080`, so all these are equivalent
81
82```
83start-server-and-test start http://localhost:8080 test
84server-test start http://localhost:8080 test
85server-test http://localhost:8080 test
86start-test :8080 test
87start-test 8080 test
88start-test 8080
89```
90
91### Options
92
93If you use convention and name your scripts "start" and "test" you can simply provide URL
94
95```json
96{
97 "scripts": {
98 "start": "npm start",
99 "test": "mocha e2e-spec.js",
100 "ci": "start-server-and-test http://localhost:8080"
101 }
102}
103```
104
105You can also shorten local url to just port, the code below is equivalent to checking `http://localhost:8080`.
106
107```json
108{
109 "scripts": {
110 "start": "npm start",
111 "test": "mocha e2e-spec.js",
112 "ci": "server-test 8080"
113 }
114}
115```
116
117You can provide first start command, port (or url) and implicit `test` command
118
119```json
120{
121 "scripts": {
122 "start-it": "npm start",
123 "test": "mocha e2e-spec.js",
124 "ci": "server-test start-it 8080"
125 }
126}
127```
128
129You can provide port number and custom test command, in that case `npm start` is assumed to start the server.
130
131```json
132{
133 "scripts": {
134 "start": "npm start",
135 "test-it": "mocha e2e-spec.js",
136 "ci": "server-test :9000 test-it"
137 }
138}
139```
140
141You can provide multiple resources to wait on, separated by a pipe `|`. _(be sure to wrap in quotes)_
142
143```json
144{
145 "scripts": {
146 "start": "npm start",
147 "test-it": "mocha e2e-spec.js",
148 "ci": "server-test \"8080|http://foo.com\""
149 }
150}
151```
152
153or for multiple ports simply: `server-test '8000|9000' test`.
154
155If you want to start the server, wait for it to respond, and then run multiple test commands (and stop the server after they finish), you should be able to use `&&` to separate the test commands:
156
157```json
158{
159 "scripts": {
160 "start": "npm start",
161 "test:unit": "mocha test.js",
162 "test:e2e": "mocha e2e.js",
163 "ci": "start-test 9000 'npm run test:unit && npm run test:e2e'"
164 }
165}
166```
167
168The above script `ci` after the `localhost:9000` responds executes the `npm run test:unit` command. Then when it finishes it runs `npm run test:e2e`. If the first or second command fails, the `ci` script fails. Of course, your mileage on Windows might vary.
169
170## `npx` and `yarn`
171
172If you have [npx](https://www.npmjs.com/package/npx) available, you can execute locally installed tools from the shell. For example, if the `package.json` has the following local tools:
173
174```json
175{
176 "devDependencies": {
177 "cypress": "3.2.0",
178 "http-server": "0.11.1",
179 "start-server-and-test": "1.9.0"
180 }
181}
182```
183
184Then you can execute tests simply:
185
186```text
187$ npx start-test 'http-server -c-1 .' 8080 'cypress run'
188starting server using command "http-server -c-1 ."
189and when url "http://localhost:8080" is responding
190running tests using command "cypress run"
191Starting up http-server, serving .
192...
193```
194
195Similarly, you can use [yarn](https://yarnpkg.com/en/) to call locally installed tools
196
197```text
198$ yarn start-test 'http-server -c-1 .' 8080 'cypress run'
199yarn run v1.13.0
200$ /private/tmp/test-t/node_modules/.bin/start-test 'http-server -c-1 .' 8080 'cypress run'
201starting server using command "http-server -c-1 ."
202and when url "http://localhost:8080" is responding
203running tests using command "cypress run"
204Starting up http-server, serving .
205...
206```
207
208## Note for yarn users
209
210By default, npm is used to run scripts, however you can specify that yarn is used as follows:
211
212```json
213"scripts": {
214 "start-server": "yarn start",
215 "test": "mocha e2e-spec.js",
216 "ci": "start-server-and-test 'yarn start-server' http://localhost:8080 'yarn test'"
217}
218```
219
220## Note for webpack-dev-server users
221
222If you are using [webpack-dev-server](https://www.npmjs.com/package/webpack-dev-server) (directly or via `angular/cli` or other boilerplates) then please use the following URL form to check
223
224```
225start-server-and-test http-get://localhost:8080
226```
227
228This is because under the hood this module uses [wait-on](https://github.com/jeffbski/wait-on) to ping the server. Wait-on uses `HEAD` by default, but `webpack-dev-server` does not respond to `HEAD` only to `GET` requests. Thus you need to use `http-get://` URL format to force `wait-on` to use `GET` probe.
229
230You can even wait on the bundle JavaScript url instead of the page url, see discussion in this [issue #4](https://github.com/bahmutov/start-server-and-test/issues/4)
231
232### Debugging
233
234To see diagnostic messages, run with environment variable `DEBUG=start-server-and-test`
235
236### Disable HTTPS certificate checks
237
238To disable HTTPS checks for `wait-on`, run with environment variable `START_SERVER_AND_TEST_INSECURE=1`.
239
240### Timeout
241
242This utility will wait for maximum of 5 minutes while checking for the server to respond (default). Setting an environment variable `WAIT_ON_TIMEOUT=600000` (milliseconds) sets the timeout for example to 10 minutes.
243
244### Starting two servers
245
246Sometimes you need to start one API server and one webserver in order to test the application. Use the syntax:
247
248```
249start-test <first command> <first resource> <second command> <second resource> <test command>
250```
251
252For example if API runs at port 3000 and server runs at port 8080:
253
254```json
255{
256 "scripts": {
257 "test": "node src/test",
258 "start:api": "node src/api",
259 "start:server": "node src/server",
260 "test:all": "start-test start:api 3000 start:server 8080 test"
261 }
262}
263```
264
265In the above example you would run `npm run test:all` to start the API first, then when it responds, start the server, and when the server is responding, it would run the tests. After the tests finish, it will shut down both servers. See the repo [start-two-servers-example](https://github.com/bahmutov/start-two-servers-example) for full example
266
267## Note for Apollo Server users
268
269When passing a simple GET request to Apollo Server it will respond with a 405 error. To get around this problem you need to pass a valid GraphQL query into the query parameter. Passing in a basic schema introspection query will work to determine the presence of an Apollo Server. You can configure your npm script like so:
270
271```json
272{
273 "scripts": {
274 "ci": "start-server-and-test start 'http-get://localhost:4000/graphql?query={ __schema { queryType { name } } }' test"
275 }
276}
277```
278
279### Small print
280
281Author: Gleb Bahmutov &lt;gleb.bahmutov@gmail.com&gt; &copy; 2017
282
283* [@bahmutov](https://twitter.com/bahmutov)
284* [glebbahmutov.com](https://glebbahmutov.com)
285* [blog](https://glebbahmutov.com/blog)
286
287License: MIT - do anything with the code, but don't blame me if it does not work.
288
289Support: if you find any problems with this module, email / tweet /
290[open issue](https://github.com/bahmutov/start-server-and-test/issues) on Github
291
292## MIT License
293
294Copyright (c) 2017 Gleb Bahmutov &lt;gleb.bahmutov@gmail.com&gt;
295
296Permission is hereby granted, free of charge, to any person
297obtaining a copy of this software and associated documentation
298files (the "Software"), to deal in the Software without
299restriction, including without limitation the rights to use,
300copy, modify, merge, publish, distribute, sublicense, and/or sell
301copies of the Software, and to permit persons to whom the
302Software is furnished to do so, subject to the following
303conditions:
304
305The above copyright notice and this permission notice shall be
306included in all copies or substantial portions of the Software.
307
308THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
309EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
310OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
311NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
312HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
313WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
314FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
315OTHER DEALINGS IN THE SOFTWARE.
316
317[npm-icon]: https://nodei.co/npm/start-server-and-test.svg?downloads=true
318[npm-url]: https://npmjs.org/package/start-server-and-test
319[ci-image]: https://github.com/bahmutov/start-server-and-test/workflows/ci/badge.svg?branch=master
320[ci-url]: https://github.com/bahmutov/start-server-and-test/actions
321[semantic-image]: https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg
322[semantic-url]: https://github.com/semantic-release/semantic-release
323[standard-image]: https://img.shields.io/badge/code%20style-standard-brightgreen.svg
324[standard-url]: http://standardjs.com/
325[renovate-badge]: https://img.shields.io/badge/renovate-app-blue.svg
326[renovate-app]: https://renovateapp.com/