Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: use the --expect parameter to specify HTTP response code #343

Merged
merged 3 commits into from Dec 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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