Skip to content

Commit

Permalink
feat: use the --expect parameter to specify HTTP response code (#343)
Browse files Browse the repository at this point in the history
* feat: add --expect argument parsing

* feat: specify the --expected http status code

* chore: update the README
  • Loading branch information
bahmutov committed Dec 5, 2022
1 parent 6bedc4c commit 17a427c
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 22 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Expand Up @@ -54,6 +54,9 @@ jobs:
- name: Run demo multiple 📊
run: npm run demo-multiple

- name: Run demo expect 403 code 📊
run: npm run demo-expect-403

- name: Semantic Release 🚀
if: github.ref == 'refs/heads/master'
uses: cycjimmy/semantic-release-action@v3
Expand Down
10 changes: 10 additions & 0 deletions README.md
Expand Up @@ -167,6 +167,16 @@ If you want to start the server, wait for it to respond, and then run multiple t

The 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.

#### expected

The server might respond, but require authorization, returning an error HTTP code by default. You can still know that the server is responding by using `--expect` argument (or its alias `--expected`):

```
$ start-test --expect 403 start :9000 test:e2e
```

See `demo-expect-403` NPM script.

## `npx` and `yarn`

If 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:
Expand Down
4 changes: 2 additions & 2 deletions package.json
Expand Up @@ -48,7 +48,7 @@
"main": "src/",
"private": false,
"publishConfig": {
"registry": "http://registry.npmjs.org/"
"registry": "https://registry.npmjs.org/"
},
"repository": {
"type": "git",
Expand Down Expand Up @@ -93,7 +93,7 @@
"demo10": "node src/bin/start.js start-fail http://127.0.0.1:9000 test",
"demo11": "node src/bin/start.js http-get://127.0.0.1:9000",
"demo12": "node src/bin/start.js start-304 9000 test2",
"demo13": "node src/bin/start.js --expect 403 start-403 9000 'echo Waited'",
"demo-expect-403": "node src/bin/start.js --expect 403 start-403 9000 'echo Waited'",
"demo-interval": "WAIT_ON_INTERVAL=1000 node src/bin/start.js start http://127.0.0.1:9000 test2",
"demo-timeout": "WAIT_ON_TIMEOUT=10000 node src/bin/start.js start http://127.0.0.1:9000 test2",
"demo-cross-env": "node src/bin/start.js start-cross-env 9000",
Expand Down
9 changes: 6 additions & 3 deletions src/bin/start.js
Expand Up @@ -4,8 +4,11 @@ const debug = require('debug')('start-server-and-test')

const startAndTest = require('..').startAndTest
const utils = require('../utils')
const args = utils.crossArguments(process.argv.slice(2))

const namedArguments = utils.getNamedArguments(process.argv.slice(2))
debug('named arguments: %o', namedArguments)

const args = utils.crossArguments(process.argv.slice(2))
debug('parsing CLI arguments: %o', args)
const parsed = utils.getArguments(args)
debug('parsed args: %o', parsed)
Expand All @@ -15,9 +18,9 @@ if (!Array.isArray(services)) {
throw new Error(`Could not parse arguments %o, got %o`, args, parsed)
}

utils.printArguments({ services, test })
utils.printArguments({ services, test, namedArguments })

startAndTest({ services, test }).catch(e => {
startAndTest({ services, test, namedArguments }).catch(e => {
console.error(e)
process.exit(1)
})
16 changes: 11 additions & 5 deletions src/index.js
Expand Up @@ -28,14 +28,19 @@ const isDebug = () =>

const isInsecure = () => process.env.START_SERVER_AND_TEST_INSECURE

function waitAndRun ({ start, url, runFn }) {
function waitAndRun ({ start, url, runFn, namedArguments }) {
la(is.unemptyString(start), 'missing start script name', start)
la(is.fn(runFn), 'missing test script name', runFn)
la(
is.unemptyString(url) || is.unemptyArray(url),
'missing url to wait on',
url
)
const isSuccessfulHttpCode = status =>
(status >= 200 && status < 300) || status === 304
const validateStatus = namedArguments.expect
? status => status === namedArguments.expect
: isSuccessfulHttpCode

debug('starting server with command "%s", verbose mode?', start, isDebug())

Expand Down Expand Up @@ -89,8 +94,7 @@ function waitAndRun ({ start, url, runFn }) {
headers: {
Accept: 'text/html, application/json, text/plain, */*'
},
validateStatus: status =>
(status >= 200 && status < 300) || status === 304
validateStatus
}
debug('wait-on options %o', options)

Expand Down Expand Up @@ -121,7 +125,7 @@ const runTheTests = testCommand => () => {
* Starts a single service and runs tests or recursively
* runs a service, then goes to the next list, until it reaches 1 service and runs test.
*/
function startAndTest ({ services, test }) {
function startAndTest ({ services, test, namedArguments }) {
if (services.length === 0) {
throw new Error('Got zero services to start ...')
}
Expand All @@ -132,16 +136,18 @@ function startAndTest ({ services, test }) {
return waitAndRun({
start: services[0].start,
url: services[0].url,
namedArguments,
runFn: runTests
})
}

return waitAndRun({
start: services[0].start,
url: services[0].url,
namedArguments,
runFn: () => {
debug('previous service started, now going to the next one')
return startAndTest({ services: services.slice(1), test })
return startAndTest({ services: services.slice(1), test, namedArguments })
}
})
}
Expand Down
38 changes: 26 additions & 12 deletions src/utils.js
Expand Up @@ -5,21 +5,20 @@ const { existsSync } = require('fs')
const arg = require('arg')
const debug = require('debug')('start-server-and-test')

const namedArguments = {
'--expect': Number
}

/**
* Returns new array of command line arguments
* where leading and trailing " and ' are indicating
* the beginning and end of an argument.
*/
const crossArguments = cliArguments => {
const args = arg(
{
'--expect': Number
},
{
permissive: true,
argv: cliArguments
}
)
const args = arg(namedArguments, {
permissive: true,
argv: cliArguments
})
debug('initial parsed arguments %o', args)
// all other arguments
const cliArgs = args._
Expand Down Expand Up @@ -58,6 +57,19 @@ const crossArguments = cliArguments => {
return combinedArgs
}

const getNamedArguments = cliArgs => {
const args = arg(namedArguments, {
permissive: true,
argv: cliArgs
})
debug('initial parsed arguments %o', args)
return {
expect: args['--expect'],
// aliases
'--expected': '--expect'
}
}

/**
* Returns parsed command line arguments.
* If start command is NPM script name defined in the package.json
Expand Down Expand Up @@ -205,12 +217,13 @@ const normalizeUrl = input => {
})
}

function printArguments ({ services, test }) {
function printArguments ({ services, test, namedArguments }) {
services.forEach((service, k) => {
console.log('%d: starting server using command "%s"', k + 1, service.start)
console.log(
'and when url "%s" is responding with HTTP status code 200',
service.url
'and when url "%s" is responding with HTTP status code %d',
service.url,
namedArguments.expect
)
})

Expand All @@ -231,6 +244,7 @@ function printArguments ({ services, test }) {
const UTILS = {
crossArguments,
getArguments,
getNamedArguments,
isPackageScriptName,
isUrlOrPort,
normalizeUrl,
Expand Down

0 comments on commit 17a427c

Please sign in to comment.