Now that we have the pipeline in place, let's add a more meaningful process, such as integration testing. Since almost everything is in place, we just have to include two more pieces of information in our .travis.yml file—the MongoDB service and the test command:
language: node_js
node_js:
- '10'
sudo: required
services:
- docker
- mongodb
script:
- npm run test
Since we are going to handle more than one environment, that is, dev, test, and prod with different information, we should start working with a tool to help us handle environment variables. To do that, we will install the dotenv library:
$ npm install --save dotenv
Also, there are some adjustments to be made to the package.json file, because we are going to use the order-api application in production mode and there are some libraries that are only dev dependencies that should also be prod dependencies. The new package.json file is as follows:
{
"name": "order-api",
"version": "1.0.0",
"description": "This is the example from the Book Hands on RESTful APIs with TypeScript 3",
"main": "./dist/server.js",
"scripts": {
"build": "npm run clean && tsc",
"clean": "rimraf dist && rimraf reports",
"lint": "tslint ./src/**/*.ts ./test/**/*.spec.ts",
"lint:fix": "tslint --fix ./src/**/*.ts ./test/**/*.spec.ts -t verbose",
"pretest": "cross-env NODE_ENV=test npm run build && npm run lint",
"test": "cross-env NODE_ENV=test mocha --reporter spec --compilers ts:ts-node/register test/**/*.spec.ts --exit",
"test:mutation": "stryker run",
"stryker:init": "stryker init",
"dev": "cross-env PORT=3000 NODE_ENV=dev ts-node ./src/server.ts",
"prod": "PORT=3000 NODE_ENV=prod npm run build && npm run start",
"start": "NODE_ENV=prod node dist/server.js",
"tsc": "tsc"
},
"engines": {
"node": ">=8.0.0"
},
"keywords": [
"order POC",
"Hands on RESTful APIs with TypeScript 3",
"TypeScript 3",
"Packt Books"
],
"author": "Biharck Muniz Araújo",
"license": "MIT",
"devDependencies": {
"@types/bcrypt": "^3.0.0",
"@types/body-parser": "^1.17.0",
"@types/chai": "^4.1.7",
"@types/chai-http": "^3.0.5",
"@types/express": "^4.16.0",
"@types/express-winston": "^3.0.0",
"@types/jsonwebtoken": "^8.3.0",
"@types/mocha": "^5.2.5",
"@types/mongodb": "^3.1.17",
"@types/mongoose": "^5.3.5",
"@types/passport": "^0.4.7",
"@types/passport-jwt": "^3.0.1",
"@types/passport-local": "^1.0.33",
"@types/mongoose-unique-validator": "^1.0.1"
},
"dependencies": {
"@types/node": "^10.12.12",
"bcrypt": "^3.0.2",
"body-parser": "^1.18.3",
"chai": "^4.2.0",
"chai-http": "^4.2.0",
"cross-env": "^5.2.0",
"dotenv": "^6.2.0",
"express": "^4.16.4",
"express-winston": "^3.0.1",
"halson": "^3.0.0",
"js2xmlparser": "^3.0.0",
"lodash": "^4.17.11",
"mocha": "^5.2.0",
"mongoose": "^5.4.0",
"mongoose-unique-validator": "^2.0.2",
"passport": "^0.4.0",
"passport-jwt": "^4.0.0",
"passport-local": "^1.0.0",
"rimraf": "^2.6.2",
"stryker": "^0.33.1",
"stryker-api": "^0.22.0",
"stryker-html-reporter": "^0.16.9",
"stryker-mocha-framework": "^0.13.2",
"stryker-mocha-runner": "^0.15.2",
"stryker-typescript": "^0.16.1",
"ts-node": "^7.0.1",
"tslint": "^5.11.0",
"tslint-config-prettier": "^1.17.0",
"typescript": "^3.2.1",
"winston": "^3.1.0"
}
}
Also, go to the app.js file, remove the ../src/ folder reference from the routes, and change the way we now get MongoDB credentials using environment variables such as the following:
import * as bodyParser from 'body-parser'
import * as dotenv from 'dotenv'
import * as express from 'express'
import * as expressWinston from 'express-winston'
import * as mongoose from 'mongoose'
import * as winston from 'winston'
import { APIRoute } from './routes/api'
import { OrderRoute } from './routes/order'
import { UserRoute } from './routes/user'
import * as errorHandler from './utility/errorHandler'
class App {
public app: express.Application
public userRoutes: UserRoute = new UserRoute()
public apiRoutes: APIRoute = new APIRoute()
public orderRoutes: OrderRoute = new OrderRoute()
public mongoUrl: string
public mongoUser: string
public mongoPass: string
constructor() {
const path = `${__dirname}/../.env.${process.env.NODE_ENV}`
dotenv.config({ path: path })
this.mongoUrl = `mongodb://${process.env.MONGODB_URL_PORT}/${
process.env.MONGODB_DATABASE
}`
this.mongoUser = `${process.env.MONGODB_USER}`
this.mongoPass = `${process.env.MONGODB_PASS}`
this.app = express()
this.app.use(bodyParser.json())
this.userRoutes.routes(this.app)
this.apiRoutes.routes(this.app)
this.orderRoutes.routes(this.app)
this.mongoSetup()
this.app.use(
expressWinston.errorLogger({
transports: [new winston.transports.Console()],
})
)
this.app.use(errorHandler.logging)
this.app.use(errorHandler.clientErrorHandler)
this.app.use(errorHandler.errorHandler)
}
private mongoSetup(): void {
let options
if (process.env.NODE_ENV !== 'prod') {
options = {
useNewUrlParser: true,
}
} else {
options = {
user: this.mongoUser,
pass: this.mongoPass,
useNewUrlParser: true,
}
}
mongoose.connect(
this.mongoUrl,
options
)
}
}
export default new App().app
As you can see, we now have to have environment variable files to help us with configurations. Up to now, we just needed the dev and test ones. Create two files—one called .env.dev in the root folder, with the following content:
MONGODB_URL_PORT=localhost:27017
MONGODB_DATABASE=order-api
Then, create another one called .env.test with the following content:
MONGODB_URL_PORT=localhost:27017
MONGODB_DATABASE=order-api-test
Now, just add the files, and commit and push the changes. Go to Travis CI and follow the pipeline. You will see that the tests will run on Travis CI. This means that every change that is pushed to the master branch will trigger the Travis CI pipeline, which will run the integration tests: