add openhack files
This commit is contained in:
1
apis/userprofile/.dockerignore
Normal file
1
apis/userprofile/.dockerignore
Normal file
@ -0,0 +1 @@
|
||||
node_modules
|
2
apis/userprofile/.eslintignore
Normal file
2
apis/userprofile/.eslintignore
Normal file
@ -0,0 +1,2 @@
|
||||
coverage
|
||||
templates
|
25
apis/userprofile/.eslintrc
Normal file
25
apis/userprofile/.eslintrc
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"rules": {
|
||||
"indent": [
|
||||
2,
|
||||
4
|
||||
],
|
||||
"quotes": [
|
||||
2,
|
||||
"single"
|
||||
],
|
||||
"linebreak-style": [
|
||||
2,
|
||||
"unix"
|
||||
],
|
||||
"semi": [
|
||||
2,
|
||||
"always"
|
||||
]
|
||||
},
|
||||
"env": {
|
||||
"es6": true,
|
||||
"node": true
|
||||
},
|
||||
"extends": "eslint:recommended"
|
||||
}
|
5
apis/userprofile/.gitignore
vendored
Normal file
5
apis/userprofile/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
*.xml
|
||||
coverage
|
||||
.nyc_output
|
||||
reports
|
||||
reports-tmp
|
51
apis/userprofile/.npmignore
Normal file
51
apis/userprofile/.npmignore
Normal file
@ -0,0 +1,51 @@
|
||||
# Automatically ignored per:
|
||||
# https://www.npmjs.org/doc/developers.html#Keeping-files-out-of-your-package
|
||||
#
|
||||
# .*.swp
|
||||
# ._*
|
||||
# .DS_Store
|
||||
# .git
|
||||
# .hg
|
||||
# .lock-wscript
|
||||
# .svn
|
||||
# .wafpickle-*
|
||||
# CVS
|
||||
# npm-debug.log
|
||||
# node_modules
|
||||
|
||||
*.seed
|
||||
*.log
|
||||
*.csv
|
||||
*.dat
|
||||
*.out
|
||||
*.pid
|
||||
*.gz
|
||||
*.orig
|
||||
|
||||
work
|
||||
build
|
||||
test
|
||||
pids
|
||||
logs
|
||||
results
|
||||
coverage
|
||||
lib-cov
|
||||
html-report
|
||||
xunit.xml
|
||||
|
||||
.project
|
||||
.idea
|
||||
.settings
|
||||
.iml
|
||||
*.sublime-workspace
|
||||
*.sublime-project
|
||||
|
||||
ehthumbs.db
|
||||
Icon?
|
||||
Thumbs.db
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
|
||||
test/temp
|
19
apis/userprofile/Dockerfile
Normal file
19
apis/userprofile/Dockerfile
Normal file
@ -0,0 +1,19 @@
|
||||
FROM node:12-alpine
|
||||
|
||||
COPY . /app
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
EXPOSE 8080
|
||||
|
||||
# docker build argument
|
||||
# This can be specified during the docker build step by adding " --build-arg build_version=<value>"
|
||||
# App version can be accessed via the uri path /api/version/user
|
||||
# https://vsupalov.com/docker-build-pass-environment-variables/
|
||||
ARG build_version="userprofile default"
|
||||
ENV APP_VERSION=$build_version
|
||||
|
||||
|
||||
RUN npm install
|
||||
|
||||
CMD npm start
|
35
apis/userprofile/README.md
Normal file
35
apis/userprofile/README.md
Normal file
@ -0,0 +1,35 @@
|
||||
# Overview
|
||||
|
||||
This server was generated by the [swagger-codegen](https://github.com/swagger-api/swagger-codegen) project. By using the [OpenAPI-Spec](https://github.com/OAI/OpenAPI-Specification) from a remote server, you can easily generate a server stub.
|
||||
|
||||
This api uses node 12.x and express as the server and c
|
||||
|
||||
## Install modules
|
||||
|
||||
To install modules, run:
|
||||
|
||||
```shell
|
||||
npm install
|
||||
```
|
||||
|
||||
## Running the server
|
||||
|
||||
To run the server, run:
|
||||
|
||||
```shell
|
||||
npm start
|
||||
```
|
||||
|
||||
### To view the Swagger UI interface
|
||||
|
||||
```shell
|
||||
open http://localhost:8080/api/docs/user
|
||||
```
|
||||
|
||||
### To execute the unit tests
|
||||
|
||||
```shell
|
||||
npm run test
|
||||
```
|
||||
|
||||
There will be a junit formatted report file called userprofile-report.xml under the current userprofile directory `/reports` subfolder.
|
7
apis/userprofile/buildtest.sh
Normal file
7
apis/userprofile/buildtest.sh
Normal file
@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
# install dependencies
|
||||
npm install
|
||||
|
||||
# run tests
|
||||
npm run test
|
15
apis/userprofile/config/sqlConfig.js
Normal file
15
apis/userprofile/config/sqlConfig.js
Normal file
@ -0,0 +1,15 @@
|
||||
const sqlConfig = {
|
||||
userName: process.env.SQL_USER || '',
|
||||
password: process.env.SQL_PASSWORD || '',
|
||||
server: process.env.SQL_SERVER || '', // You can use 'localhost\\instance' to connect to named instance
|
||||
options: {
|
||||
encrypt: true, // Use this if you're on Windows Azure
|
||||
database: process.env.SQL_DBNAME || 'mydrivingdb',
|
||||
MultipleActiveResultSets: false,
|
||||
TrustServerCertificate: false,
|
||||
rowCollectionOnDone: true
|
||||
// Persist Security Info=False;Connection Timeout=30
|
||||
}
|
||||
};
|
||||
|
||||
exports = module.exports = sqlConfig;
|
326
apis/userprofile/config/swagger.json
Normal file
326
apis/userprofile/config/swagger.json
Normal file
@ -0,0 +1,326 @@
|
||||
{
|
||||
"swagger": "2.0",
|
||||
"info": {
|
||||
"description": "API for the user profile in the My Driving example app. https://github.com/Azure-Samples/openhack-devops",
|
||||
"version": "0.1.0",
|
||||
"title": "My Driving User Profile API"
|
||||
},
|
||||
"basePath": "/api",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"paths": {
|
||||
"/healthcheck/user": {
|
||||
"x-swagger-router-controller": "healthcheck",
|
||||
"get": {
|
||||
"description": "Returns healthcheck for systems looking to ensure API is up and operational",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Service is healthy",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/Healthcheck"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "An error occurred",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/DefaultResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"tags": [ "User Profile" ]
|
||||
}
|
||||
},
|
||||
"/version/user": {
|
||||
"x-swagger-router-controller": "version",
|
||||
"get": {
|
||||
"description": "Returns APP_VERSION environment variable to ensure API is running with a specific version",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Build Version",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/Version"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "An error occurred",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/DefaultErrorResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/user": {
|
||||
"get": {
|
||||
"description": "List all user profiles",
|
||||
"operationId": "getAllUsers",
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "List of all users",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/Profile"
|
||||
}
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "An error occurred",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/DefaultResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"x-swagger-router-controller": "user",
|
||||
"tags": [ "User Profile" ]
|
||||
}
|
||||
},
|
||||
"/user/{userID}": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "userID",
|
||||
"in": "path",
|
||||
"description": "User's unique ID",
|
||||
"type": "string",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"get": {
|
||||
"description": "Get a User Profile by ID",
|
||||
"operationId": "userGET",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "List of profiles",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/Profile"
|
||||
}
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "An error occurred",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/DefaultResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"x-swagger-router-controller": "user",
|
||||
"tags": [ "User Profile" ]
|
||||
},
|
||||
"post": {
|
||||
"description": "Declares and creates a new profile",
|
||||
"operationId": "userPOST",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "body",
|
||||
"name": "_profile",
|
||||
"description": "Details of the profile",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/Profile"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "Creation successful",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/Profile"
|
||||
},
|
||||
"headers": {
|
||||
"location": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "An error occurred",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/DefaultResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"x-swagger-router-controller": "user",
|
||||
"tags": [ "User Profile" ]
|
||||
},
|
||||
"patch": {
|
||||
"description": "Update User",
|
||||
"operationId": "updateUser",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "User Updated",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/Profile"
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "User profile not found"
|
||||
},
|
||||
"default": {
|
||||
"description": "Unknown Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/DefaultResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"tags": [ "User Profile" ]
|
||||
},
|
||||
"delete": {
|
||||
"description": "Delete User By ID",
|
||||
"operationId": "userDELETE",
|
||||
"responses": {
|
||||
"204": {
|
||||
"description": "User Deleted"
|
||||
},
|
||||
"404": {
|
||||
"description": "User not found"
|
||||
},
|
||||
"default": {
|
||||
"description": "Unknown Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/DefaultResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"tags": [ "User Profile" ]
|
||||
}
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"Healthcheck": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": ""
|
||||
},
|
||||
"status": {
|
||||
"type": "string",
|
||||
"description": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
"Version": {
|
||||
"type": "string"
|
||||
},
|
||||
"Profile": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"Id": {
|
||||
"type": "string",
|
||||
"description": "User's unique identity"
|
||||
},
|
||||
"FirstName": {
|
||||
"type": "string",
|
||||
"minLength": 0,
|
||||
"maxLength": 50,
|
||||
"pattern": "^[A-Za-z \u0000-][a-zA-Z \u0000-]*$"
|
||||
},
|
||||
"LastName": {
|
||||
"type": "string",
|
||||
"minLength": 0,
|
||||
"maxLength": 80,
|
||||
"pattern": "^[A-Za-z \u0000-][a-zA-Z \u0000-]*$"
|
||||
},
|
||||
"UserId": {
|
||||
"type": "string",
|
||||
"description": "User's identity"
|
||||
},
|
||||
"ProfilePictureUri": {
|
||||
"type": "string",
|
||||
"format": "binary",
|
||||
"description": "User's Profile picture"
|
||||
},
|
||||
"Rating": {
|
||||
"type": "integer",
|
||||
"description": "User's rating"
|
||||
},
|
||||
"Ranking": {
|
||||
"type": "integer",
|
||||
"description": "User's ranking"
|
||||
},
|
||||
"TotalDistance": {
|
||||
"type": "number",
|
||||
"format": "float",
|
||||
"description": "User's total distance traveled"
|
||||
},
|
||||
"TotalTrips": {
|
||||
"type": "integer",
|
||||
"format": "long",
|
||||
"description": "User's total number of trips"
|
||||
},
|
||||
"TotalTime": {
|
||||
"type": "integer",
|
||||
"format": "long",
|
||||
"description": "User's total driving time"
|
||||
},
|
||||
"HardStops": {
|
||||
"type": "integer",
|
||||
"format": "long",
|
||||
"description": "User's total number of hard stops"
|
||||
},
|
||||
"HardAccelerations": {
|
||||
"type": "integer",
|
||||
"format": "long",
|
||||
"description": "User's total number of hard accelerations"
|
||||
},
|
||||
"FuelConsumption": {
|
||||
"type": "number",
|
||||
"format": "float",
|
||||
"description": "User's amount of fuel consumed"
|
||||
},
|
||||
"MaxSpeed": {
|
||||
"type": "number",
|
||||
"format": "float",
|
||||
"description": "User's maximum speed"
|
||||
},
|
||||
"CreatedAt": {
|
||||
"type": "string",
|
||||
"format": "date"
|
||||
},
|
||||
"UpdatedAt": {
|
||||
"type": "string",
|
||||
"format": "date"
|
||||
},
|
||||
"Deleted": {
|
||||
"type": "boolean",
|
||||
"description": "Whether the user has been deleted or not."
|
||||
}
|
||||
}
|
||||
},
|
||||
"DefaultErrorResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"status": {
|
||||
"description": "Error code (if available)",
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"message": {
|
||||
"description": "Error Message",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"DefaultResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"status": {
|
||||
"description": "Error code (if available)",
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"message": {
|
||||
"description": "Error Message",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
35
apis/userprofile/data/healthcheck/user.js
Normal file
35
apis/userprofile/data/healthcheck/user.js
Normal file
@ -0,0 +1,35 @@
|
||||
'use strict';
|
||||
var Mockgen = require('../mockgen.js');
|
||||
/**
|
||||
* Operations on /healthcheck/user
|
||||
*/
|
||||
module.exports = {
|
||||
/**
|
||||
* summary:
|
||||
* description: Returns healthcheck for systems looking to ensure API is up and operational
|
||||
* parameters:
|
||||
* produces:
|
||||
* responses: 200, default
|
||||
* operationId:
|
||||
*/
|
||||
get: {
|
||||
200: function (req, res, callback) {
|
||||
res.json({
|
||||
message: 'Userprofile Service Healthcheck',
|
||||
status: 'healthy'
|
||||
});
|
||||
callback;
|
||||
},
|
||||
default: function (req, res, callback) {
|
||||
/**
|
||||
* Using mock data generator module.
|
||||
* Replace this by actual data for the api.
|
||||
*/
|
||||
Mockgen().responses({
|
||||
path: '/healthcheck/user',
|
||||
operation: 'get',
|
||||
response: 'default'
|
||||
}, callback);
|
||||
}
|
||||
}
|
||||
};
|
13
apis/userprofile/data/mockgen.js
Normal file
13
apis/userprofile/data/mockgen.js
Normal file
@ -0,0 +1,13 @@
|
||||
'use strict';
|
||||
var Swagmock = require('swagmock');
|
||||
var Path = require('path');
|
||||
var apiPath = Path.resolve(__dirname, '../config/swagger.json');
|
||||
var mockgen;
|
||||
|
||||
module.exports = function () {
|
||||
/**
|
||||
* Cached mock generator
|
||||
*/
|
||||
mockgen = mockgen || Swagmock(apiPath);
|
||||
return mockgen;
|
||||
};
|
66
apis/userprofile/data/queries.js
Normal file
66
apis/userprofile/data/queries.js
Normal file
@ -0,0 +1,66 @@
|
||||
exports.INSERT_USER_PROFILE =
|
||||
`INSERT INTO userprofiles \
|
||||
(\
|
||||
Id,\
|
||||
FirstName,\
|
||||
LastName,\
|
||||
UserId,\
|
||||
ProfilePictureUri,\
|
||||
Rating,\
|
||||
Ranking,\
|
||||
TotalDistance,\
|
||||
TotalTrips,\
|
||||
TotalTime,\
|
||||
HardStops,\
|
||||
HardAccelerations,\
|
||||
FuelConsumption,\
|
||||
MaxSpeed,\
|
||||
CreatedAt,\
|
||||
UpdatedAt,\
|
||||
Deleted\
|
||||
) \
|
||||
SELECT \
|
||||
Id,\
|
||||
FirstName,\
|
||||
LastName,\
|
||||
UserId,\
|
||||
ProfilePictureUri,\
|
||||
Rating,\
|
||||
Ranking,\
|
||||
TotalDistance,\
|
||||
TotalTrips,\
|
||||
TotalTime,\
|
||||
HardStops,\
|
||||
HardAccelerations,\
|
||||
FuelConsumption,\
|
||||
MaxSpeed,\
|
||||
GETDATE(),\
|
||||
GETDATE(),\
|
||||
Deleted \
|
||||
FROM OPENJSON(@UserProfileJson) \
|
||||
WITH (
|
||||
Id nvarchar(128),\
|
||||
FirstName nvarchar(max),\
|
||||
LastName nvarchar(max),\
|
||||
UserId nvarchar(max),\
|
||||
ProfilePictureUri nvarchar(max),\
|
||||
Rating int,\
|
||||
Ranking int,\
|
||||
TotalDistance float(53),\
|
||||
TotalTrips bigint,\
|
||||
TotalTime bigint,\
|
||||
HardStops bigint,\
|
||||
HardAccelerations bigint,\
|
||||
FuelConsumption float(53),\
|
||||
MaxSpeed float(53),\
|
||||
Deleted bit\
|
||||
) AS JSON`;
|
||||
|
||||
exports.SELECT_USER_PROFILE_BY_ID=
|
||||
'select * from userprofiles where id = @user_profile_id FOR JSON PATH';
|
||||
|
||||
exports.SELECT_USER_PROFILES=
|
||||
'select * FROM userprofiles FOR JSON PATH';
|
||||
|
||||
exports.DELETE_USER_PROFILE=
|
||||
'UPDATE userprofiles SET Deleted = 1 WHERE id = @user_profile_id';
|
33
apis/userprofile/data/user.js
Normal file
33
apis/userprofile/data/user.js
Normal file
@ -0,0 +1,33 @@
|
||||
'use strict';
|
||||
var Mockgen = require('./mockgen.js');
|
||||
var queries = require('./queries');
|
||||
/**
|
||||
* Operations on /user
|
||||
*/
|
||||
module.exports = {
|
||||
/**
|
||||
* summary:
|
||||
* description: List all user profiles
|
||||
* parameters:
|
||||
* produces:
|
||||
* responses: 200, default
|
||||
* operationId: getAllUsers
|
||||
*/
|
||||
get: {
|
||||
200: function (req, res, callback) {
|
||||
|
||||
req.sql(queries.SELECT_USER_PROFILES)
|
||||
.into(res);
|
||||
callback;
|
||||
|
||||
},
|
||||
default: function (req, res, callback) {
|
||||
|
||||
Mockgen().responses({
|
||||
path: '/user',
|
||||
operation: 'get',
|
||||
response: 'default'
|
||||
}, callback);
|
||||
}
|
||||
}
|
||||
};
|
149
apis/userprofile/data/user/{userID}.js
Normal file
149
apis/userprofile/data/user/{userID}.js
Normal file
@ -0,0 +1,149 @@
|
||||
'use strict';
|
||||
var Mockgen = require('../mockgen.js');
|
||||
var TYPES = require('tedious').TYPES;
|
||||
var queries = require('../queries');
|
||||
/**
|
||||
* Operations on /user/{userID}
|
||||
*/
|
||||
module.exports = {
|
||||
/**
|
||||
* summary:
|
||||
* description: Get a User Profile by ID
|
||||
* parameters:
|
||||
* produces:
|
||||
* responses: 200, default
|
||||
* operationId: userGET
|
||||
*/
|
||||
get: {
|
||||
200: function (req, res, callback) {
|
||||
|
||||
req.sql(queries.SELECT_USER_PROFILE_BY_ID)
|
||||
.param('user_profile_id', req.params.userID, TYPES.NVarChar)
|
||||
.into(res, '{}');
|
||||
callback;
|
||||
|
||||
},
|
||||
default: function (req, res, callback) {
|
||||
/**
|
||||
* Using mock data generator module.
|
||||
* Replace this by factual data for the api.
|
||||
*/
|
||||
Mockgen().responses({
|
||||
path: '/user/{userID}',
|
||||
operation: 'get',
|
||||
response: 'default'
|
||||
}, callback);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* summary:
|
||||
* description: Declares and creates a new profile
|
||||
* parameters: _profile
|
||||
* produces:
|
||||
* responses: 201, default
|
||||
* operationId: userPOST
|
||||
*/
|
||||
post: {
|
||||
201: function (req, res, callback) {
|
||||
|
||||
req.sql(queries.INSERT_USER_PROFILE)
|
||||
.param('UserProfileJson', req.body, TYPES.NVarChar)
|
||||
.exec(res);
|
||||
callback;
|
||||
|
||||
},
|
||||
default: function (req, res, callback) {
|
||||
/**
|
||||
* Using mock data generator module.
|
||||
* Replace this by actual data for the api.
|
||||
*/
|
||||
Mockgen().responses({
|
||||
path: '/user/{userID}',
|
||||
operation: 'post',
|
||||
response: 'default'
|
||||
}, callback);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* summary:
|
||||
* description: Update User
|
||||
* parameters:
|
||||
* produces:
|
||||
* responses: 200, 404, default
|
||||
* operationId: updateUser
|
||||
*/
|
||||
patch: {
|
||||
200: function (req, res, callback) {
|
||||
|
||||
req.sql('EXEC UpdateProductFromJson @id, @json')
|
||||
.param('json', req.body, TYPES.NVarChar)
|
||||
.param('id', req.params.id, TYPES.Int)
|
||||
.exec(res);
|
||||
callback;
|
||||
|
||||
},
|
||||
404: function (req, res, callback) {
|
||||
/**
|
||||
* Using mock data generator module.
|
||||
* Replace this by actual data for the api.
|
||||
*/
|
||||
Mockgen().responses({
|
||||
path: '/user/{userID}',
|
||||
operation: 'patch',
|
||||
response: '404'
|
||||
}, callback);
|
||||
},
|
||||
default: function (req, res, callback) {
|
||||
/**
|
||||
* Using mock data generator module.
|
||||
* Replace this by actual data for the api.
|
||||
*/
|
||||
Mockgen().responses({
|
||||
path: '/user/{userID}',
|
||||
operation: 'patch',
|
||||
response: 'default'
|
||||
}, callback);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* summary:
|
||||
* description: Delete User By ID
|
||||
* parameters:
|
||||
* produces:
|
||||
* responses: 204, 404, default
|
||||
* operationId: userDELETE
|
||||
*/
|
||||
delete: {
|
||||
204: function (req, res, callback) {
|
||||
var tempmessage = '';
|
||||
var resmessage = tempmessage.concat('User profile ',req.params.userID,' deleted');
|
||||
req.sql(queries.DELETE_USER_PROFILE)
|
||||
.param('user_profile_id', req.params.userID, TYPES.NVarChar)
|
||||
.into(res, resmessage);
|
||||
callback;
|
||||
|
||||
},
|
||||
404: function (req, res, callback) {
|
||||
/**
|
||||
* Using mock data generator module.
|
||||
* Replace this by actual data for the api.
|
||||
*/
|
||||
Mockgen().responses({
|
||||
path: '/user/{userID}',
|
||||
operation: 'delete',
|
||||
response: '404'
|
||||
}, callback);
|
||||
},
|
||||
default: function (req, res, callback) {
|
||||
/**
|
||||
* Using mock data generator module.
|
||||
* Replace this by actual data for the api.
|
||||
*/
|
||||
Mockgen().responses({
|
||||
path: '/user/{userID}',
|
||||
operation: 'delete',
|
||||
response: 'default'
|
||||
}, callback);
|
||||
}
|
||||
}
|
||||
};
|
29
apis/userprofile/handlers/healthcheck/user.js
Normal file
29
apis/userprofile/handlers/healthcheck/user.js
Normal file
@ -0,0 +1,29 @@
|
||||
'use strict';
|
||||
var dataProvider = require('../../data/healthcheck/user.js');
|
||||
/**
|
||||
* Operations on /healthcheck/user
|
||||
*/
|
||||
module.exports = {
|
||||
/**
|
||||
* summary:
|
||||
* description: Returns healthcheck for systems looking to ensure API is up and operational
|
||||
* parameters:
|
||||
* produces:
|
||||
* responses: 200, default
|
||||
*/
|
||||
get: function (req, res, next) {
|
||||
/**
|
||||
* Get the data for response 200
|
||||
* For response `default` status 200 is used.
|
||||
*/
|
||||
var status = 200;
|
||||
var provider = dataProvider['get']['200'];
|
||||
provider(req, res, function (err, data) {
|
||||
if (err) {
|
||||
next(err);
|
||||
return;
|
||||
}
|
||||
res.status(status).send(data && data.responses);
|
||||
});
|
||||
}
|
||||
};
|
29
apis/userprofile/handlers/user.js
Normal file
29
apis/userprofile/handlers/user.js
Normal file
@ -0,0 +1,29 @@
|
||||
'use strict';
|
||||
var dataProvider = require('../data/user.js');
|
||||
/**
|
||||
* Operations on /user
|
||||
*/
|
||||
module.exports = {
|
||||
/**
|
||||
* summary:
|
||||
* description: List all user profiles
|
||||
* parameters:
|
||||
* produces:
|
||||
* responses: 200, default
|
||||
*/
|
||||
get: function getAllUsers(req, res, next) {
|
||||
/**
|
||||
* Get the data for response 200
|
||||
* For response `default` status 200 is used.
|
||||
*/
|
||||
var status = 200;
|
||||
var provider = dataProvider['get']['200'];
|
||||
provider(req, res, function (err, data) {
|
||||
if (err) {
|
||||
next(err);
|
||||
return;
|
||||
}
|
||||
res.status(status).send(data && data.responses);
|
||||
});
|
||||
}
|
||||
};
|
95
apis/userprofile/handlers/user/{userID}.js
Normal file
95
apis/userprofile/handlers/user/{userID}.js
Normal file
@ -0,0 +1,95 @@
|
||||
'use strict';
|
||||
var dataProvider = require('../../data/user/{userID}.js');
|
||||
/**
|
||||
* Operations on /user/{userID}
|
||||
*/
|
||||
module.exports = {
|
||||
/**
|
||||
* summary:
|
||||
* description: Get a User Profile by ID
|
||||
* parameters:
|
||||
* produces:
|
||||
* responses: 200, default
|
||||
*/
|
||||
get: function userGET(req, res, next) {
|
||||
/**
|
||||
* Get the data for response 200
|
||||
* For response `default` status 200 is used.
|
||||
*/
|
||||
var status = 200;
|
||||
var provider = dataProvider['get']['200'];
|
||||
provider(req, res, function (err, data) {
|
||||
if (err) {
|
||||
next(err);
|
||||
return;
|
||||
}
|
||||
res.status(status).send(data && data.responses);
|
||||
});
|
||||
},
|
||||
/**
|
||||
* summary:
|
||||
* description: Declares and creates a new profile
|
||||
* parameters: _profile
|
||||
* produces:
|
||||
* responses: 201, default
|
||||
*/
|
||||
post: function userPOST(req, res, next) {
|
||||
/**
|
||||
* Get the data for response 201
|
||||
* For response `default` status 200 is used.
|
||||
*/
|
||||
var status = 201;
|
||||
var provider = dataProvider['post']['201'];
|
||||
provider(req, res, function (err, data) {
|
||||
if (err) {
|
||||
next(err);
|
||||
return;
|
||||
}
|
||||
res.status(status).send(data && data.responses);
|
||||
});
|
||||
},
|
||||
/**
|
||||
* summary:
|
||||
* description: Update User
|
||||
* parameters:
|
||||
* produces:
|
||||
* responses: 200, 404, default
|
||||
*/
|
||||
patch: function updateUser(req, res, next) {
|
||||
/**
|
||||
* Get the data for response 200
|
||||
* For response `default` status 200 is used.
|
||||
*/
|
||||
var status = 200;
|
||||
var provider = dataProvider['patch']['200'];
|
||||
provider(req, res, function (err, data) {
|
||||
if (err) {
|
||||
next(err);
|
||||
return;
|
||||
}
|
||||
res.status(status).send(data && data.responses);
|
||||
});
|
||||
},
|
||||
/**
|
||||
* summary:
|
||||
* description: Delete User By ID
|
||||
* parameters:
|
||||
* produces:
|
||||
* responses: 204, 404, default
|
||||
*/
|
||||
delete: function userDELETE(req, res, next) {
|
||||
/**
|
||||
* Get the data for response 204
|
||||
* For response `default` status 200 is used.
|
||||
*/
|
||||
var status = 204;
|
||||
var provider = dataProvider['delete']['204'];
|
||||
provider(req, res, function (err, data) {
|
||||
if (err) {
|
||||
next(err);
|
||||
return;
|
||||
}
|
||||
res.status(status).send(data && data.responses);
|
||||
});
|
||||
}
|
||||
};
|
20
apis/userprofile/handlers/version/user.js
Normal file
20
apis/userprofile/handlers/version/user.js
Normal file
@ -0,0 +1,20 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Operations on /version/user
|
||||
*/
|
||||
module.exports = {
|
||||
/**
|
||||
* summary:
|
||||
* description: Returns healthcheck for systems looking to ensure API is up and operational
|
||||
* parameters:
|
||||
* produces:
|
||||
* responses: 200, default
|
||||
*/
|
||||
get: function (req, res, next) {
|
||||
let status = 200;
|
||||
let version = process.env.APP_VERSION;
|
||||
res.set('Content-Type', 'text/plain');
|
||||
res.status(status).send(version);
|
||||
}
|
||||
};
|
3752
apis/userprofile/package-lock.json
generated
Normal file
3752
apis/userprofile/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
60
apis/userprofile/package.json
Normal file
60
apis/userprofile/package.json
Normal file
@ -0,0 +1,60 @@
|
||||
{
|
||||
"name": "mydriving-user-api",
|
||||
"description": "This is the User API for the MyDriving service",
|
||||
"version": "1.0.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/Azure-Samples/openhack-devops-team.git"
|
||||
},
|
||||
"bugs": "http://github.com/Azure-Samples/openhack-devops-team/issues",
|
||||
"dependencies": {
|
||||
"body-parser": "^1.18.3",
|
||||
"dotenv": "^8.2.0",
|
||||
"express": "^4.16.3",
|
||||
"express4-tedious": "^0.3.0",
|
||||
"morgan": "^1.9.0",
|
||||
"swagger-ui-express": "^3.0.10",
|
||||
"swaggerize-express": "^4.0.5",
|
||||
"swagmock": "1.0.0",
|
||||
"tedious": "^2.6.4",
|
||||
"trim": "^1.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "6.8.0",
|
||||
"is-my-json-valid": "2.20.0",
|
||||
"js-yaml": "3.13.1",
|
||||
"nyc": "15.0.1",
|
||||
"supertest": "4.0.2",
|
||||
"swagger-parser": "9.0.1",
|
||||
"tap-junit": "^5.0.1",
|
||||
"tape": "5.0.0"
|
||||
},
|
||||
"nyc": {
|
||||
"check-coverage": true,
|
||||
"per-file": false,
|
||||
"lines": 25,
|
||||
"statements": 8,
|
||||
"functions": 9,
|
||||
"branches": 1,
|
||||
"reporter": [
|
||||
"cobertura",
|
||||
"html"
|
||||
],
|
||||
"require": [],
|
||||
"cache": true,
|
||||
"all": true,
|
||||
"temp-directory": "./reports-tmp",
|
||||
"report-dir": "./reports"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "tape 'tests/**/*.js' | tap-junit --output reports --name userprofile-report",
|
||||
"test-noreport": "tape 'tests/**/*.js'",
|
||||
"cover": "nyc tape -- 'tests/**/*.js' --cov",
|
||||
"lint": "eslint .",
|
||||
"regenerate": "yo swaggerize:test --framework express --apiPath './config/swagger.json'"
|
||||
},
|
||||
"generator-swaggerize": {
|
||||
"version": "4.1.0"
|
||||
},
|
||||
"main": "./server"
|
||||
}
|
46
apis/userprofile/server.js
Normal file
46
apis/userprofile/server.js
Normal file
@ -0,0 +1,46 @@
|
||||
'use strict';
|
||||
|
||||
require('dotenv').config()
|
||||
|
||||
var Http = require('http');
|
||||
var Express = require('express');
|
||||
var BodyParser = require('body-parser');
|
||||
var Swaggerize = require('swaggerize-express');
|
||||
var Path = require('path');
|
||||
var tediousExpress = require('express4-tedious');
|
||||
var sqlConfig = require('./config/sqlConfig');
|
||||
var morgan = require('morgan');
|
||||
const swaggerUi = require('swagger-ui-express');
|
||||
const swaggerDocument = require('./config/swagger.json');
|
||||
|
||||
var App = Express();
|
||||
|
||||
var Server = Http.createServer(App);
|
||||
|
||||
var logger = morgan(':remote-addr [:date[web]] :method :url HTTP/:http-version :status :res[content-length] :referrer :user-agent :response-time ms');
|
||||
|
||||
App.use(logger);
|
||||
|
||||
App.use(function (req, res, next) {
|
||||
req.sql = tediousExpress(sqlConfig);
|
||||
next();
|
||||
});
|
||||
|
||||
App.use(BodyParser.json());
|
||||
App.use(BodyParser.urlencoded({
|
||||
extended: true
|
||||
}));
|
||||
|
||||
App.use(Swaggerize({
|
||||
api: Path.resolve('./config/swagger.json'),
|
||||
handlers: Path.resolve('./handlers')
|
||||
}));
|
||||
|
||||
App.use('/api/docs/user', swaggerUi.serve, swaggerUi.setup(swaggerDocument));
|
||||
|
||||
Server.listen(8080, function () {
|
||||
App.swagger.api.host = this.address().address + ':' + this.address().port;
|
||||
/* eslint-disable no-console */
|
||||
console.log('App running on %s:%d', this.address().address, this.address().port);
|
||||
/* eslint-disable no-console */
|
||||
});
|
227
apis/userprofile/swagger/swagger.yaml
Normal file
227
apis/userprofile/swagger/swagger.yaml
Normal file
@ -0,0 +1,227 @@
|
||||
---
|
||||
swagger: "2.0"
|
||||
info:
|
||||
description: "API for the user profile in the My Driving example app. https://github.com/Azure-Samples/openhack-devops-team"
|
||||
version: "0.1.0"
|
||||
title: "My Driving User Profile API"
|
||||
basePath: "/api"
|
||||
schemes:
|
||||
- "http"
|
||||
consumes:
|
||||
- "application/json"
|
||||
produces:
|
||||
- "application/json"
|
||||
paths:
|
||||
/healthcheck/user:
|
||||
x-swagger-router-controller: healthcheck
|
||||
get:
|
||||
description: "Returns healthcheck for systems looking to ensure API is up and operational"
|
||||
responses:
|
||||
200:
|
||||
description: "Service is healthy"
|
||||
schema:
|
||||
$ref: "#/definitions/Healthcheck"
|
||||
default:
|
||||
description: "An error occurred"
|
||||
schema:
|
||||
$ref: "#/definitions/error_response_default"
|
||||
/version/user:
|
||||
x-swagger-router-controller: version
|
||||
get:
|
||||
description: "Returns APP_VERSION environment variable to ensure API is running with a specific versionl"
|
||||
responses:
|
||||
200:
|
||||
description: "BuildVersion"
|
||||
schema:
|
||||
$ref: "#/definitions/Version"
|
||||
default:
|
||||
description: "An error occurred"
|
||||
schema:
|
||||
$ref: "#/definitions/error_response_default"
|
||||
/user:
|
||||
get:
|
||||
description: "List all user profiles"
|
||||
operationId: "getAllUsers"
|
||||
parameters: []
|
||||
responses:
|
||||
200:
|
||||
description: "List of all users"
|
||||
schema:
|
||||
type: "array"
|
||||
items:
|
||||
$ref: "#/definitions/Profile"
|
||||
default:
|
||||
description: "An error occurred"
|
||||
schema:
|
||||
$ref: "#/definitions/inline_response_default"
|
||||
x-swagger-router-controller: "user"
|
||||
/user/{userID}:
|
||||
parameters:
|
||||
-
|
||||
name: "userID"
|
||||
in: "path"
|
||||
description: "User's unique ID"
|
||||
type: "string"
|
||||
required: true
|
||||
get:
|
||||
description: "Get a User Profile by ID"
|
||||
operationId: "userGET"
|
||||
responses:
|
||||
200:
|
||||
description: "List of profiles"
|
||||
schema:
|
||||
type: "array"
|
||||
items:
|
||||
$ref: "#/definitions/Profile"
|
||||
default:
|
||||
description: "An error occurred"
|
||||
schema:
|
||||
$ref: "#/definitions/inline_response_default"
|
||||
x-swagger-router-controller: "user"
|
||||
post:
|
||||
description: "Declares and creates a new profile"
|
||||
operationId: "userPOST"
|
||||
parameters:
|
||||
- in: "body"
|
||||
name: "_profile"
|
||||
description: "Details of the profile"
|
||||
required: true
|
||||
schema:
|
||||
$ref: "#/definitions/Profile"
|
||||
responses:
|
||||
201:
|
||||
description: "Creation successful"
|
||||
schema:
|
||||
$ref: "#/definitions/Profile"
|
||||
headers:
|
||||
location:
|
||||
type: "string"
|
||||
default:
|
||||
description: "An error occurred"
|
||||
schema:
|
||||
$ref: "#/definitions/inline_response_default"
|
||||
x-swagger-router-controller: "user"
|
||||
patch:
|
||||
description: "Update User"
|
||||
operationId: "updateUser"
|
||||
responses:
|
||||
200:
|
||||
description: "User Updated"
|
||||
schema:
|
||||
$ref: "#/definitions/Profile"
|
||||
404:
|
||||
description: "User profile not found"
|
||||
default:
|
||||
description: "Unknown Error"
|
||||
schema:
|
||||
$ref: "#/definitions/error_response_default"
|
||||
delete:
|
||||
description: "Delete User By ID"
|
||||
operationId: "userDELETE"
|
||||
responses:
|
||||
204:
|
||||
description: "User Deleted"
|
||||
404:
|
||||
description: "User not found"
|
||||
default:
|
||||
description: "Unknown Error"
|
||||
schema:
|
||||
$ref: "#/definitions/error_response_default"
|
||||
definitions:
|
||||
Healthcheck:
|
||||
type: "object"
|
||||
properties:
|
||||
message:
|
||||
type: "string"
|
||||
description: ""
|
||||
status:
|
||||
type: "string"
|
||||
description: ""
|
||||
Version:
|
||||
type: "string"
|
||||
Profile:
|
||||
type: "object"
|
||||
properties:
|
||||
Id:
|
||||
type: "string"
|
||||
description: "User's unique identity"
|
||||
FirstName:
|
||||
type: "string"
|
||||
minLength: 0
|
||||
maxLength: 50
|
||||
pattern: "^[A-Za-z \0-\x7f][a-zA-Z \0-\x7f]*$"
|
||||
LastName:
|
||||
type: "string"
|
||||
minLength: 0
|
||||
maxLength: 80
|
||||
pattern: "^[A-Za-z \0-\x7f][a-zA-Z \0-\x7f]*$"
|
||||
UserId:
|
||||
type: "string"
|
||||
description: "User's identity"
|
||||
ProfilePictureUri:
|
||||
type: "string"
|
||||
format: "binary"
|
||||
description: "User's Profile picture"
|
||||
Rating:
|
||||
type: "integer"
|
||||
description: "User's rating"
|
||||
Ranking:
|
||||
type: "integer"
|
||||
description: "User's ranking"
|
||||
TotalDistance:
|
||||
type: "number"
|
||||
format: "float"
|
||||
description: "User's total distance traveled"
|
||||
TotalTrips:
|
||||
type: "integer"
|
||||
format: "long"
|
||||
description: "User's total number of trips"
|
||||
TotalTime:
|
||||
type: "integer"
|
||||
format: "long"
|
||||
description: "User's total driving time"
|
||||
HardStops:
|
||||
type: "integer"
|
||||
format: "long"
|
||||
description: "User's total number of hard stops"
|
||||
HardAccelerations:
|
||||
type: "integer"
|
||||
format: "long"
|
||||
description: "User's total number of hard accelerations"
|
||||
FuelConsumption:
|
||||
type: "number"
|
||||
format: "float"
|
||||
description: "User's amount of fuel consumed"
|
||||
MaxSpeed:
|
||||
type: "number"
|
||||
format: "float"
|
||||
description: "User's maximum speed"
|
||||
CreatedAt:
|
||||
type: "string"
|
||||
format: "date"
|
||||
UpdatedAt:
|
||||
type: "string"
|
||||
format: "date"
|
||||
Deleted:
|
||||
type: "boolean"
|
||||
description: "Whether the user has been deleted or not."
|
||||
error_response_default:
|
||||
type: "object"
|
||||
properties:
|
||||
status:
|
||||
description: "Error code (if available)"
|
||||
type: "integer"
|
||||
format: "int32"
|
||||
message:
|
||||
description: "Error Message"
|
||||
type: "string"
|
||||
inline_response_default:
|
||||
required:
|
||||
- "message"
|
||||
- "status"
|
||||
properties:
|
||||
status:
|
||||
type: "integer"
|
||||
format: "int32"
|
||||
message:
|
||||
type: "string"
|
78
apis/userprofile/tests/healthcheck/user.js
Normal file
78
apis/userprofile/tests/healthcheck/user.js
Normal file
@ -0,0 +1,78 @@
|
||||
'use strict';
|
||||
var Test = require('tape');
|
||||
var Express = require('express');
|
||||
var BodyParser = require('body-parser');
|
||||
var Swaggerize = require('swaggerize-express');
|
||||
var Path = require('path');
|
||||
var Request = require('supertest');
|
||||
var Mockgen = require('../../data/mockgen.js');
|
||||
var Parser = require('swagger-parser');
|
||||
/**
|
||||
* Test for /healthcheck/user
|
||||
*/
|
||||
Test('/healthcheck/user', function (t) {
|
||||
var apiPath = Path.resolve(__dirname, '../../config/swagger.json');
|
||||
var App = Express();
|
||||
App.use(BodyParser.json());
|
||||
App.use(BodyParser.urlencoded({
|
||||
extended: true
|
||||
}));
|
||||
App.use(Swaggerize({
|
||||
api: apiPath,
|
||||
handlers: Path.resolve(__dirname, '../../handlers')
|
||||
}));
|
||||
Parser.validate(apiPath, function (err, api) {
|
||||
t.error(err, 'No parse error');
|
||||
t.ok(api, 'Valid swagger api');
|
||||
/**
|
||||
* summary:
|
||||
* description: Returns healthcheck for systems looking to ensure API is up and operational
|
||||
* parameters:
|
||||
* produces:
|
||||
* responses: 200, default
|
||||
*/
|
||||
t.test('test get operation', function (t) {
|
||||
Mockgen().requests({
|
||||
path: '/healthcheck/user',
|
||||
operation: 'get'
|
||||
}, function (err, mock) {
|
||||
var request;
|
||||
t.error(err);
|
||||
t.ok(mock);
|
||||
t.ok(mock.request);
|
||||
//Get the resolved path from mock request
|
||||
//Mock request Path templates({}) are resolved using path parameters
|
||||
request = Request(App)
|
||||
.get('/api' + mock.request.path);
|
||||
if (mock.request.body) {
|
||||
//Send the request body
|
||||
request = request.send(mock.request.body);
|
||||
} else if (mock.request.formData){
|
||||
//Send the request form data
|
||||
request = request.send(mock.request.formData);
|
||||
//Set the Content-Type as application/x-www-form-urlencoded
|
||||
request = request.set('Content-Type', 'application/x-www-form-urlencoded');
|
||||
}
|
||||
// If headers are present, set the headers.
|
||||
if (mock.request.headers && mock.request.headers.length > 0) {
|
||||
Object.keys(mock.request.headers).forEach(function (headerName) {
|
||||
request = request.set(headerName, mock.request.headers[headerName]);
|
||||
});
|
||||
}
|
||||
request.end(function (err, res) {
|
||||
t.error(err, 'No error');
|
||||
t.ok(res.statusCode === 200, 'Ok response status');
|
||||
var Validator = require('is-my-json-valid');
|
||||
var validate = Validator(api.paths['/healthcheck/user']['get']['responses']['200']['schema']);
|
||||
var response = res.body;
|
||||
if (Object.keys(response).length <= 0) {
|
||||
response = res.text;
|
||||
}
|
||||
t.ok(validate(response), 'Valid response');
|
||||
t.error(validate.errors, 'No validation errors');
|
||||
t.end();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
78
apis/userprofile/tests/user.js_
Normal file
78
apis/userprofile/tests/user.js_
Normal file
@ -0,0 +1,78 @@
|
||||
'use strict';
|
||||
var Test = require('tape');
|
||||
var Express = require('express');
|
||||
var BodyParser = require('body-parser');
|
||||
var Swaggerize = require('swaggerize-express');
|
||||
var Path = require('path');
|
||||
var Request = require('supertest');
|
||||
var Mockgen = require('../data/mockgen.js');
|
||||
var Parser = require('swagger-parser');
|
||||
/**
|
||||
* Test for /user
|
||||
*/
|
||||
Test('/user', function (t) {
|
||||
var apiPath = Path.resolve(__dirname, '../config/swagger.json');
|
||||
var App = Express();
|
||||
App.use(BodyParser.json());
|
||||
App.use(BodyParser.urlencoded({
|
||||
extended: true
|
||||
}));
|
||||
App.use(Swaggerize({
|
||||
api: apiPath,
|
||||
handlers: Path.resolve(__dirname, '../handlers')
|
||||
}));
|
||||
Parser.validate(apiPath, function (err, api) {
|
||||
t.error(err, 'No parse error');
|
||||
t.ok(api, 'Valid swagger api');
|
||||
/**
|
||||
* summary:
|
||||
* description: List all user profiles
|
||||
* parameters:
|
||||
* produces:
|
||||
* responses: 200, default
|
||||
*/
|
||||
t.test('test getAllUsers get operation', function (t) {
|
||||
Mockgen().requests({
|
||||
path: '/user',
|
||||
operation: 'get'
|
||||
}, function (err, mock) {
|
||||
var request;
|
||||
t.error(err);
|
||||
t.ok(mock);
|
||||
t.ok(mock.request);
|
||||
//Get the resolved path from mock request
|
||||
//Mock request Path templates({}) are resolved using path parameters
|
||||
request = Request(App)
|
||||
.get('/api' + mock.request.path);
|
||||
if (mock.request.body) {
|
||||
//Send the request body
|
||||
request = request.send(mock.request.body);
|
||||
} else if (mock.request.formData){
|
||||
//Send the request form data
|
||||
request = request.send(mock.request.formData);
|
||||
//Set the Content-Type as application/x-www-form-urlencoded
|
||||
request = request.set('Content-Type', 'application/x-www-form-urlencoded');
|
||||
}
|
||||
// If headers are present, set the headers.
|
||||
if (mock.request.headers && mock.request.headers.length > 0) {
|
||||
Object.keys(mock.request.headers).forEach(function (headerName) {
|
||||
request = request.set(headerName, mock.request.headers[headerName]);
|
||||
});
|
||||
}
|
||||
request.end(function (err, res) {
|
||||
t.error(err, 'No error');
|
||||
t.ok(res.statusCode === 200, 'Ok response status');
|
||||
var Validator = require('is-my-json-valid');
|
||||
var validate = Validator(api.paths['/user']['get']['responses']['200']['schema']);
|
||||
var response = res.body;
|
||||
if (Object.keys(response).length <= 0) {
|
||||
response = res.text;
|
||||
}
|
||||
t.ok(validate(response), 'Valid response');
|
||||
t.error(validate.errors, 'No validation errors');
|
||||
t.end();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
217
apis/userprofile/tests/user/{userID}.js_
Normal file
217
apis/userprofile/tests/user/{userID}.js_
Normal file
@ -0,0 +1,217 @@
|
||||
'use strict';
|
||||
var Test = require('tape');
|
||||
var Express = require('express');
|
||||
var BodyParser = require('body-parser');
|
||||
var Swaggerize = require('swaggerize-express');
|
||||
var Path = require('path');
|
||||
var Request = require('supertest');
|
||||
var Mockgen = require('../../data/mockgen.js');
|
||||
var Parser = require('swagger-parser');
|
||||
/**
|
||||
* Test for /user/{userID}
|
||||
*/
|
||||
Test('/user/{userID}', function (t) {
|
||||
var apiPath = Path.resolve(__dirname, '../../config/swagger.json');
|
||||
var App = Express();
|
||||
App.use(BodyParser.json());
|
||||
App.use(BodyParser.urlencoded({
|
||||
extended: true
|
||||
}));
|
||||
App.use(Swaggerize({
|
||||
api: apiPath,
|
||||
handlers: Path.resolve(__dirname, '../../handlers')
|
||||
}));
|
||||
Parser.validate(apiPath, function (err, api) {
|
||||
t.error(err, 'No parse error');
|
||||
t.ok(api, 'Valid swagger api');
|
||||
/**
|
||||
* summary:
|
||||
* description: Get a User Profile by ID
|
||||
* parameters:
|
||||
* produces:
|
||||
* responses: 200, default
|
||||
*/
|
||||
t.test('test userGET get operation', function (t) {
|
||||
Mockgen().requests({
|
||||
path: '/user/{userID}',
|
||||
operation: 'get'
|
||||
}, function (err, mock) {
|
||||
var request;
|
||||
t.error(err);
|
||||
t.ok(mock);
|
||||
t.ok(mock.request);
|
||||
//Get the resolved path from mock request
|
||||
//Mock request Path templates({}) are resolved using path parameters
|
||||
request = Request(App)
|
||||
.get('/api' + mock.request.path);
|
||||
if (mock.request.body) {
|
||||
//Send the request body
|
||||
request = request.send(mock.request.body);
|
||||
} else if (mock.request.formData){
|
||||
//Send the request form data
|
||||
request = request.send(mock.request.formData);
|
||||
//Set the Content-Type as application/x-www-form-urlencoded
|
||||
request = request.set('Content-Type', 'application/x-www-form-urlencoded');
|
||||
}
|
||||
// If headers are present, set the headers.
|
||||
if (mock.request.headers && mock.request.headers.length > 0) {
|
||||
Object.keys(mock.request.headers).forEach(function (headerName) {
|
||||
request = request.set(headerName, mock.request.headers[headerName]);
|
||||
});
|
||||
}
|
||||
request.end(function (err, res) {
|
||||
t.error(err, 'No error');
|
||||
t.ok(res.statusCode === 200, 'Ok response status');
|
||||
var Validator = require('is-my-json-valid');
|
||||
var validate = Validator(api.paths['/user/{userID}']['get']['responses']['200']['schema']);
|
||||
var response = res.body;
|
||||
if (Object.keys(response).length <= 0) {
|
||||
response = res.text;
|
||||
}
|
||||
t.ok(validate(response), 'Valid response');
|
||||
t.error(validate.errors, 'No validation errors');
|
||||
t.end();
|
||||
});
|
||||
});
|
||||
});/**
|
||||
* summary:
|
||||
* description: Declares and creates a new profile
|
||||
* parameters: _profile
|
||||
* produces:
|
||||
* responses: 201, default
|
||||
*/
|
||||
t.test('test userPOST post operation', function (t) {
|
||||
Mockgen().requests({
|
||||
path: '/user/{userID}',
|
||||
operation: 'post'
|
||||
}, function (err, mock) {
|
||||
var request;
|
||||
t.error(err);
|
||||
t.ok(mock);
|
||||
t.ok(mock.request);
|
||||
//Get the resolved path from mock request
|
||||
//Mock request Path templates({}) are resolved using path parameters
|
||||
request = Request(App)
|
||||
.post('/api' + mock.request.path);
|
||||
if (mock.request.body) {
|
||||
//Send the request body
|
||||
request = request.send(mock.request.body);
|
||||
} else if (mock.request.formData){
|
||||
//Send the request form data
|
||||
request = request.send(mock.request.formData);
|
||||
//Set the Content-Type as application/x-www-form-urlencoded
|
||||
request = request.set('Content-Type', 'application/x-www-form-urlencoded');
|
||||
}
|
||||
// If headers are present, set the headers.
|
||||
if (mock.request.headers && mock.request.headers.length > 0) {
|
||||
Object.keys(mock.request.headers).forEach(function (headerName) {
|
||||
request = request.set(headerName, mock.request.headers[headerName]);
|
||||
});
|
||||
}
|
||||
request.end(function (err, res) {
|
||||
t.error(err, 'No error');
|
||||
t.ok(res.statusCode === 201, 'Ok response status');
|
||||
var Validator = require('is-my-json-valid');
|
||||
var validate = Validator(api.paths['/user/{userID}']['post']['responses']['201']['schema']);
|
||||
var response = res.body;
|
||||
if (Object.keys(response).length <= 0) {
|
||||
response = res.text;
|
||||
}
|
||||
t.ok(validate(response), 'Valid response');
|
||||
t.error(validate.errors, 'No validation errors');
|
||||
t.end();
|
||||
});
|
||||
});
|
||||
});/**
|
||||
* summary:
|
||||
* description: Update User
|
||||
* parameters:
|
||||
* produces:
|
||||
* responses: 200, 404, default
|
||||
*/
|
||||
t.test('test updateUser patch operation', function (t) {
|
||||
Mockgen().requests({
|
||||
path: '/user/{userID}',
|
||||
operation: 'patch'
|
||||
}, function (err, mock) {
|
||||
var request;
|
||||
t.error(err);
|
||||
t.ok(mock);
|
||||
t.ok(mock.request);
|
||||
//Get the resolved path from mock request
|
||||
//Mock request Path templates({}) are resolved using path parameters
|
||||
request = Request(App)
|
||||
.patch('/api' + mock.request.path);
|
||||
if (mock.request.body) {
|
||||
//Send the request body
|
||||
request = request.send(mock.request.body);
|
||||
} else if (mock.request.formData){
|
||||
//Send the request form data
|
||||
request = request.send(mock.request.formData);
|
||||
//Set the Content-Type as application/x-www-form-urlencoded
|
||||
request = request.set('Content-Type', 'application/x-www-form-urlencoded');
|
||||
}
|
||||
// If headers are present, set the headers.
|
||||
if (mock.request.headers && mock.request.headers.length > 0) {
|
||||
Object.keys(mock.request.headers).forEach(function (headerName) {
|
||||
request = request.set(headerName, mock.request.headers[headerName]);
|
||||
});
|
||||
}
|
||||
request.end(function (err, res) {
|
||||
t.error(err, 'No error');
|
||||
t.ok(res.statusCode === 200, 'Ok response status');
|
||||
var Validator = require('is-my-json-valid');
|
||||
var validate = Validator(api.paths['/user/{userID}']['patch']['responses']['200']['schema']);
|
||||
var response = res.body;
|
||||
if (Object.keys(response).length <= 0) {
|
||||
response = res.text;
|
||||
}
|
||||
t.ok(validate(response), 'Valid response');
|
||||
t.error(validate.errors, 'No validation errors');
|
||||
t.end();
|
||||
});
|
||||
});
|
||||
});/**
|
||||
* summary:
|
||||
* description: Delete User By ID
|
||||
* parameters:
|
||||
* produces:
|
||||
* responses: 204, 404, default
|
||||
*/
|
||||
t.test('test userDELETE delete operation', function (t) {
|
||||
Mockgen().requests({
|
||||
path: '/user/{userID}',
|
||||
operation: 'delete'
|
||||
}, function (err, mock) {
|
||||
var request;
|
||||
t.error(err);
|
||||
t.ok(mock);
|
||||
t.ok(mock.request);
|
||||
//Get the resolved path from mock request
|
||||
//Mock request Path templates({}) are resolved using path parameters
|
||||
request = Request(App)
|
||||
.delete('/api' + mock.request.path);
|
||||
if (mock.request.body) {
|
||||
//Send the request body
|
||||
request = request.send(mock.request.body);
|
||||
} else if (mock.request.formData){
|
||||
//Send the request form data
|
||||
request = request.send(mock.request.formData);
|
||||
//Set the Content-Type as application/x-www-form-urlencoded
|
||||
request = request.set('Content-Type', 'application/x-www-form-urlencoded');
|
||||
}
|
||||
// If headers are present, set the headers.
|
||||
if (mock.request.headers && mock.request.headers.length > 0) {
|
||||
Object.keys(mock.request.headers).forEach(function (headerName) {
|
||||
request = request.set(headerName, mock.request.headers[headerName]);
|
||||
});
|
||||
}
|
||||
request.end(function (err, res) {
|
||||
t.error(err, 'No error');
|
||||
t.ok(res.statusCode === 204, 'Ok response status');
|
||||
t.end();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
Reference in New Issue
Block a user