Adding books microservice for GE 8.6
This commit is contained in:
parent
1deac4dc9b
commit
f3b01722a2
17 changed files with 4273 additions and 0 deletions
34
books/.eslintrc
Normal file
34
books/.eslintrc
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
{
|
||||||
|
"extends": "airbnb-base",
|
||||||
|
"parserOptions": {
|
||||||
|
"sourceType": "script",
|
||||||
|
},
|
||||||
|
"rules": {
|
||||||
|
"strict": 0,
|
||||||
|
"no-param-reassign": [
|
||||||
|
"error",
|
||||||
|
{ "props": false }
|
||||||
|
],
|
||||||
|
"func-names": 0,
|
||||||
|
"comma-dangle": 0,
|
||||||
|
"prefer-template": 0,
|
||||||
|
"camelcase": 0,
|
||||||
|
"no-underscore-dangle": 0,
|
||||||
|
"consistent-return": 0,
|
||||||
|
"no-bitwise": ["error", { "allow": ["~"] }]
|
||||||
|
},
|
||||||
|
"globals": {
|
||||||
|
"describe": true,
|
||||||
|
"it": true,
|
||||||
|
"after": true,
|
||||||
|
"afterEach": true,
|
||||||
|
"before": true,
|
||||||
|
"beforeEach": true,
|
||||||
|
"should": true,
|
||||||
|
"reqServer": true
|
||||||
|
},
|
||||||
|
"env": {
|
||||||
|
"node": true,
|
||||||
|
"mocha": true
|
||||||
|
}
|
||||||
|
}
|
||||||
115
books/.gitignore
vendored
Normal file
115
books/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,115 @@
|
||||||
|
# General
|
||||||
|
.DS_Store
|
||||||
|
.AppleDouble
|
||||||
|
.LSOverride
|
||||||
|
|
||||||
|
# Icon must end with two \r
|
||||||
|
Icon
|
||||||
|
|
||||||
|
# Thumbnails
|
||||||
|
._*
|
||||||
|
|
||||||
|
# Files that might appear in the root of a volume
|
||||||
|
.DocumentRevisions-V100
|
||||||
|
.fseventsd
|
||||||
|
.Spotlight-V100
|
||||||
|
.TemporaryItems
|
||||||
|
.Trashes
|
||||||
|
.VolumeIcon.icns
|
||||||
|
.com.apple.timemachine.donotpresent
|
||||||
|
|
||||||
|
# Directories potentially created on remote AFP share
|
||||||
|
.AppleDB
|
||||||
|
.AppleDesktop
|
||||||
|
Network Trash Folder
|
||||||
|
Temporary Items
|
||||||
|
.apdisk
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||||
|
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||||
|
|
||||||
|
# Runtime data
|
||||||
|
pids
|
||||||
|
*.pid
|
||||||
|
*.seed
|
||||||
|
*.pid.lock
|
||||||
|
|
||||||
|
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||||
|
lib-cov
|
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul
|
||||||
|
coverage
|
||||||
|
*.lcov
|
||||||
|
|
||||||
|
# nyc test coverage
|
||||||
|
.nyc_output
|
||||||
|
|
||||||
|
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||||
|
.grunt
|
||||||
|
|
||||||
|
# Bower dependency directory (https://bower.io/)
|
||||||
|
bower_components
|
||||||
|
|
||||||
|
# node-waf configuration
|
||||||
|
.lock-wscript
|
||||||
|
|
||||||
|
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||||
|
build/Release
|
||||||
|
|
||||||
|
# Dependency directories
|
||||||
|
node_modules/
|
||||||
|
jspm_packages/
|
||||||
|
|
||||||
|
# TypeScript v1 declaration files
|
||||||
|
typings/
|
||||||
|
|
||||||
|
# TypeScript cache
|
||||||
|
*.tsbuildinfo
|
||||||
|
|
||||||
|
# Optional npm cache directory
|
||||||
|
.npm
|
||||||
|
|
||||||
|
# Optional eslint cache
|
||||||
|
.eslintcache
|
||||||
|
|
||||||
|
# Optional REPL history
|
||||||
|
.node_repl_history
|
||||||
|
|
||||||
|
# Output of 'npm pack'
|
||||||
|
*.tgz
|
||||||
|
|
||||||
|
# Yarn Integrity file
|
||||||
|
.yarn-integrity
|
||||||
|
|
||||||
|
# dotenv environment variables file
|
||||||
|
.env
|
||||||
|
.env.test
|
||||||
|
|
||||||
|
# parcel-bundler cache (https://parceljs.org/)
|
||||||
|
.cache
|
||||||
|
|
||||||
|
# next.js build output
|
||||||
|
.next
|
||||||
|
|
||||||
|
# nuxt.js build output
|
||||||
|
.nuxt
|
||||||
|
|
||||||
|
# vuepress build output
|
||||||
|
.vuepress/dist
|
||||||
|
|
||||||
|
# Serverless directories
|
||||||
|
.serverless/
|
||||||
|
|
||||||
|
# FuseBox cache
|
||||||
|
.fusebox/
|
||||||
|
|
||||||
|
# DynamoDB Local files
|
||||||
|
.dynamodb/
|
||||||
29
books/data/authors.js
Normal file
29
books/data/authors.js
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
const authors = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: 'James Joyce',
|
||||||
|
dob: 1882
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: 'F Scott Fitzgerald',
|
||||||
|
dob: 1896
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
name: 'Aldous Huxley',
|
||||||
|
dob: 1894
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
name: 'Vladimir Nabokov',
|
||||||
|
dob: 1899
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 5,
|
||||||
|
name: 'William Faulkner',
|
||||||
|
dob: 1897
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
module.exports.books = authors;
|
||||||
39
books/data/books.js
Normal file
39
books/data/books.js
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
const books = [
|
||||||
|
{
|
||||||
|
ranking: 1,
|
||||||
|
name: 'ULYSSES',
|
||||||
|
Author: 'James Joyce',
|
||||||
|
country: 'Ireland',
|
||||||
|
yearPublished: '1922'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ranking: 2,
|
||||||
|
name: 'THE GREAT GATSBY',
|
||||||
|
Author: 'F. Scott Fitzgerald',
|
||||||
|
country: 'USA',
|
||||||
|
yearPublished: '1925'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ranking: 3,
|
||||||
|
name: 'A PORTRAIT OF THE ARTIST AS A YOUNG MAN',
|
||||||
|
Author: 'James Joyce',
|
||||||
|
country: 'Ireland',
|
||||||
|
yearPublished: '1916'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ranking: 4,
|
||||||
|
name: 'BRAVE NEW WORLD',
|
||||||
|
Author: 'Aldous Huxley',
|
||||||
|
country: 'UK',
|
||||||
|
yearPublished: '1932'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ranking: 5,
|
||||||
|
name: 'THE SOUND AND THE FURY',
|
||||||
|
Author: 'William Faulkner',
|
||||||
|
country: 'USA',
|
||||||
|
yearPublished: '1929'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
module.exports.books = books;
|
||||||
90
books/exec/www
Executable file
90
books/exec/www
Executable file
|
|
@ -0,0 +1,90 @@
|
||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module dependencies.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var app = require('../server');
|
||||||
|
var debug = require('debug')('movies:server');
|
||||||
|
var http = require('http');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get port from environment and store in Express.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var port = normalizePort(process.env.PORT || '8080');
|
||||||
|
app.set('port', port);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create HTTP server.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var server = http.createServer(app);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listen on provided port, on all network interfaces.
|
||||||
|
*/
|
||||||
|
|
||||||
|
server.listen(port);
|
||||||
|
server.on('error', onError);
|
||||||
|
server.on('listening', onListening);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalize a port into a number, string, or false.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function normalizePort(val) {
|
||||||
|
var port = parseInt(val, 10);
|
||||||
|
|
||||||
|
if (isNaN(port)) {
|
||||||
|
// named pipe
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (port >= 0) {
|
||||||
|
// port number
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event listener for HTTP server "error" event.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function onError(error) {
|
||||||
|
if (error.syscall !== 'listen') {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
var bind = typeof port === 'string'
|
||||||
|
? 'Pipe ' + port
|
||||||
|
: 'Port ' + port;
|
||||||
|
|
||||||
|
// handle specific listen errors with friendly messages
|
||||||
|
switch (error.code) {
|
||||||
|
case 'EACCES':
|
||||||
|
console.error(bind + ' requires elevated privileges');
|
||||||
|
process.exit(1);
|
||||||
|
break;
|
||||||
|
case 'EADDRINUSE':
|
||||||
|
console.error(bind + ' is already in use');
|
||||||
|
process.exit(1);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event listener for HTTP server "listening" event.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function onListening() {
|
||||||
|
var addr = server.address();
|
||||||
|
var bind = typeof addr === 'string'
|
||||||
|
? 'pipe ' + addr
|
||||||
|
: 'port ' + addr.port;
|
||||||
|
debug('Listening on ' + bind);
|
||||||
|
}
|
||||||
152
books/jenkins/Jenkinsfile
vendored
Normal file
152
books/jenkins/Jenkinsfile
vendored
Normal file
|
|
@ -0,0 +1,152 @@
|
||||||
|
pipeline {
|
||||||
|
options {
|
||||||
|
// set a timeout of 30 minutes for this pipeline
|
||||||
|
timeout(time: 30, unit: 'MINUTES')
|
||||||
|
}
|
||||||
|
agent {
|
||||||
|
node {
|
||||||
|
label 'nodejs'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
environment {
|
||||||
|
DEV_PROJECT = "youruser-books-dev"
|
||||||
|
STAGE_PROJECT = "youruser-books-stage"
|
||||||
|
APP_GIT_URL = "https://github.com/youruser/DO288-apps"
|
||||||
|
NEXUS_SERVER = "http://nexus-common.apps.cluster.domain.example.com/repository/nodejs"
|
||||||
|
|
||||||
|
// DO NOT CHANGE THE GLOBAL VARS BELOW THIS LINE
|
||||||
|
APP_NAME = "books"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
stages {
|
||||||
|
|
||||||
|
stage('NPM Install') {
|
||||||
|
steps {
|
||||||
|
echo '### Installing NPM dependencies ###'
|
||||||
|
sh '''
|
||||||
|
npm config set registry ${NEXUS_SERVER}
|
||||||
|
cd books
|
||||||
|
npm install
|
||||||
|
'''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stage('Run Unit Tests') {
|
||||||
|
steps {
|
||||||
|
echo '### Running unit tests ###'
|
||||||
|
sh 'cd books; npm test'
|
||||||
|
junit 'books/reports/server/mocha/test-results.xml'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stage('Run Linting Tools') {
|
||||||
|
steps {
|
||||||
|
echo '### Running eslint on code ###'
|
||||||
|
sh 'cd books; npm run lint'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stage('Launch new app in DEV env') {
|
||||||
|
steps {
|
||||||
|
echo '### Cleaning existing resources in DEV env ###'
|
||||||
|
sh '''
|
||||||
|
oc project ${DEV_PROJECT}
|
||||||
|
oc delete all -l app=${APP_NAME}
|
||||||
|
sleep 5
|
||||||
|
'''
|
||||||
|
|
||||||
|
echo '### Creating a new app in DEV env ###'
|
||||||
|
sh '''
|
||||||
|
oc project ${DEV_PROJECT}
|
||||||
|
oc new-app --name books nodejs:8~${APP_GIT_URL} --build-env npm_config_registry=${NEXUS_SERVER} --context-dir ${APP_NAME}
|
||||||
|
oc expose svc/${APP_NAME}
|
||||||
|
'''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stage('Wait for S2I build to complete') {
|
||||||
|
steps {
|
||||||
|
script {
|
||||||
|
openshift.withCluster() {
|
||||||
|
openshift.withProject( "${DEV_PROJECT}" ) {
|
||||||
|
def bc = openshift.selector("bc", "${APP_NAME}")
|
||||||
|
bc.logs('-f')
|
||||||
|
def builds = bc.related('builds')
|
||||||
|
builds.untilEach(1) {
|
||||||
|
return (it.object().status.phase == "Complete")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stage('Wait for deployment in DEV env') {
|
||||||
|
steps {
|
||||||
|
script {
|
||||||
|
openshift.withCluster() {
|
||||||
|
openshift.withProject( "${DEV_PROJECT}" ) {
|
||||||
|
def deployment = openshift.selector("dc", "${APP_NAME}").rollout()
|
||||||
|
openshift.selector("dc", "${APP_NAME}").related('pods').untilEach(1) {
|
||||||
|
return (it.object().status.phase == "Running")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stage('Promote to Staging Env') {
|
||||||
|
steps {
|
||||||
|
timeout(time: 60, unit: 'MINUTES') {
|
||||||
|
input message: "Promote to Staging?"
|
||||||
|
}
|
||||||
|
script {
|
||||||
|
openshift.withCluster() {
|
||||||
|
openshift.tag("${DEV_PROJECT}/books:latest", "${STAGE_PROJECT}/books:stage")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stage('Deploy to Staging Env') {
|
||||||
|
steps {
|
||||||
|
echo '### Cleaning existing resources in Staging ###'
|
||||||
|
sh '''
|
||||||
|
oc project ${STAGE_PROJECT}
|
||||||
|
oc delete all -l app=${APP_NAME}
|
||||||
|
sleep 5
|
||||||
|
'''
|
||||||
|
|
||||||
|
echo '### Creating a new app in Staging ###'
|
||||||
|
sh '''
|
||||||
|
oc project ${STAGE_PROJECT}
|
||||||
|
oc new-app --name books -i books:stage
|
||||||
|
oc expose svc/${APP_NAME}
|
||||||
|
'''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stage('Wait for deployment in Staging') {
|
||||||
|
steps {
|
||||||
|
sh "oc get route ${APP_NAME} -n ${STAGE_PROJECT} -o jsonpath='{ .spec.host }' --loglevel=4 > routehost"
|
||||||
|
|
||||||
|
script {
|
||||||
|
routeHost = readFile('routehost').trim()
|
||||||
|
|
||||||
|
openshift.withCluster() {
|
||||||
|
openshift.withProject( "${STAGE_PROJECT}" ) {
|
||||||
|
def deployment = openshift.selector("dc", "${APP_NAME}").rollout()
|
||||||
|
openshift.selector("dc", "${APP_NAME}").related('pods').untilEach(1) {
|
||||||
|
return (it.object().status.phase == "Running")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
echo "Deployment to Staging env is complete. Access the app at the URL http://${routeHost}."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
3637
books/package-lock.json
generated
Normal file
3637
books/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
30
books/package.json
Normal file
30
books/package.json
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
{
|
||||||
|
"name": "books",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"start": "node ./exec/www",
|
||||||
|
"test": "export MOCHA_FILE='reports/server/mocha/test-results.xml' && IP=0.0.0.0 PORT=3030 node_modules/.bin/nyc --reporter=text node_modules/.bin/mocha tests/*_test.js -R mocha-junit-reporter",
|
||||||
|
"lint": "node_modules/.bin/eslint . --ext .js"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"cookie-parser": "~1.4.4",
|
||||||
|
"debug": "~2.6.9",
|
||||||
|
"express": "~4.16.1",
|
||||||
|
"express-prettify": "^0.1.1",
|
||||||
|
"hbs": "~4.0.4",
|
||||||
|
"http-errors": "~1.6.3",
|
||||||
|
"morgan": "~1.9.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"chai": "^4.2.0",
|
||||||
|
"chai-http": "^4.3.0",
|
||||||
|
"eslint": "^5.16.0",
|
||||||
|
"eslint-config-airbnb-base": "^13.1.0",
|
||||||
|
"eslint-plugin-import": "^2.18.0",
|
||||||
|
"mocha": "^6.1.4",
|
||||||
|
"mocha-junit-reporter": "^1.23.0",
|
||||||
|
"nyc": "^14.1.1",
|
||||||
|
"request": "^2.88.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
8
books/public/stylesheets/style.css
Normal file
8
books/public/stylesheets/style.css
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
body {
|
||||||
|
padding: 50px;
|
||||||
|
font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #00B7FF;
|
||||||
|
}
|
||||||
13
books/routes/authors.js
Normal file
13
books/routes/authors.js
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
const express = require('express');
|
||||||
|
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
const authors = require('../data/authors');
|
||||||
|
|
||||||
|
|
||||||
|
/* GET users listing. */
|
||||||
|
router.get('/', (req, res) => {
|
||||||
|
res.json(authors);
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
12
books/routes/books.js
Normal file
12
books/routes/books.js
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
const express = require('express');
|
||||||
|
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
const books = require('../data/books');
|
||||||
|
|
||||||
|
/* GET users listing. */
|
||||||
|
router.get('/', (req, res) => {
|
||||||
|
res.json(books);
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
10
books/routes/index.js
Normal file
10
books/routes/index.js
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
const express = require('express');
|
||||||
|
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
/* GET home page. */
|
||||||
|
router.get('/', (req, res) => {
|
||||||
|
res.render('index', { title: 'The Book List' });
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
45
books/server.js
Normal file
45
books/server.js
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
const createError = require('http-errors');
|
||||||
|
const express = require('express');
|
||||||
|
const pretty = require('express-prettify');
|
||||||
|
const path = require('path');
|
||||||
|
const cookieParser = require('cookie-parser');
|
||||||
|
const logger = require('morgan');
|
||||||
|
|
||||||
|
const indexRouter = require('./routes/index');
|
||||||
|
const booksRouter = require('./routes/books');
|
||||||
|
const authorsRouter = require('./routes/authors');
|
||||||
|
|
||||||
|
const app = express();
|
||||||
|
|
||||||
|
// view engine setup
|
||||||
|
app.set('views', path.join(__dirname, 'views'));
|
||||||
|
app.set('view engine', 'hbs');
|
||||||
|
|
||||||
|
app.use(logger('dev'));
|
||||||
|
app.use(express.json());
|
||||||
|
app.use(express.urlencoded({ extended: false }));
|
||||||
|
app.use(cookieParser());
|
||||||
|
app.use(express.static(path.join(__dirname, 'public')));
|
||||||
|
app.use(pretty({ query: 'pretty' }));
|
||||||
|
|
||||||
|
app.use('/', indexRouter);
|
||||||
|
app.use('/books', booksRouter);
|
||||||
|
app.use('/authors', authorsRouter);
|
||||||
|
|
||||||
|
// catch 404 and forward to error handler
|
||||||
|
app.use((req, res, next) => {
|
||||||
|
next(createError(404));
|
||||||
|
});
|
||||||
|
|
||||||
|
// error handler
|
||||||
|
app.use((err, req, res) => {
|
||||||
|
// set locals, only providing error in development
|
||||||
|
res.locals.message = err.message;
|
||||||
|
res.locals.error = req.app.get('env') === 'development' ? err : {};
|
||||||
|
|
||||||
|
// render the error page
|
||||||
|
res.status(err.status || 500);
|
||||||
|
res.render('error');
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = app;
|
||||||
41
books/tests/app_test.js
Normal file
41
books/tests/app_test.js
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
const chai = require('chai');
|
||||||
|
const chaiHTTP = require('chai-http');
|
||||||
|
const server = require('../server');
|
||||||
|
|
||||||
|
const { expect } = chai;
|
||||||
|
|
||||||
|
chai.use(chaiHTTP);
|
||||||
|
|
||||||
|
reqServer = process.env.HTTP_TEST_SERVER || server;
|
||||||
|
|
||||||
|
describe('Books App routes test', () => {
|
||||||
|
it('GET to / should return 200', (done) => {
|
||||||
|
chai.request(reqServer)
|
||||||
|
.get('/')
|
||||||
|
.end((err, res) => {
|
||||||
|
expect(res).to.have.status(200);
|
||||||
|
expect(res.text).to.include('Welcome');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('GET to /books should return 200', (done) => {
|
||||||
|
chai.request(reqServer)
|
||||||
|
.get('/books')
|
||||||
|
.end((err, res) => {
|
||||||
|
expect(res).to.have.status(200);
|
||||||
|
expect(res.text).to.include('ULYSSES');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('GET to /authors should return 200', (done) => {
|
||||||
|
chai.request(reqServer)
|
||||||
|
.get('/authors')
|
||||||
|
.end((err, res) => {
|
||||||
|
expect(res).to.have.status(200);
|
||||||
|
expect(res.text).to.include('James Joyce');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
3
books/views/error.hbs
Normal file
3
books/views/error.hbs
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<h1>{{message}}</h1>
|
||||||
|
<h2>{{error.status}}</h2>
|
||||||
|
<pre>{{error.stack}}</pre>
|
||||||
5
books/views/index.hbs
Normal file
5
books/views/index.hbs
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
<h1>{{title}}</h1>
|
||||||
|
<p>Welcome to {{title}}</p>
|
||||||
|
|
||||||
|
<p>The List of books is <a href="/books">here</a>.</p>
|
||||||
|
<p>The List of authors is <a href="/authors">here</a>.</p>
|
||||||
10
books/views/layout.hbs
Normal file
10
books/views/layout.hbs
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>{{title}}</title>
|
||||||
|
<link rel='stylesheet' href='/stylesheets/style.css' />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
{{{body}}}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Loading…
Add table
Reference in a new issue