feat(tests): add Jest+Supertest infrastructure with jump route suite (14 tests)
- Extract Express app creation into src/createApp.js to enable testing without starting the server
- Add Jest, Supertest, test helpers (createTestApp, auth token generator)
- Write 14 integration tests for skydive/jumps: auth protection, CRUD, ownership checks
Bugs caught and fixed by the test suite:
- MongoDB models: author field typed as Schema.Types.UUID (Mongoose 6 rejects string UUIDs) → changed to String
- Jump.toJSONFor: called toProfileJSONFor on a UUID string → guarded with typeof check
- exceptions.handler: used err.statusCode but express-jwt throws err.status → returns 500 on 401 errors
- Jump.count(query): deprecated Mongoose method was ignoring the filter → replaced with countDocuments
- jumps.routes GET /: $or query included non-schema field "title" stripped by strictQuery, leaving {} (match-all) → replaced with slug/lieu search
- $regex: was passing a JS RegExp object which serializes to {} in MongoDB → now passes raw string
This commit is contained in:
@@ -3,31 +3,24 @@ if (appEnv == undefined) {
|
||||
appEnv = 'development';
|
||||
}
|
||||
require('dotenv').config({ path: `config/env/.env.${appEnv}` });
|
||||
|
||||
const { promisify } = require('util'),
|
||||
chalk = require('chalk');
|
||||
//bodyParser = require('body-parser')
|
||||
var express = require('express'),
|
||||
session = require('express-session'),
|
||||
cors = require('cors'),
|
||||
errorhandler = require('errorhandler'),
|
||||
chalk = require('chalk'),
|
||||
morgan = require('morgan');
|
||||
|
||||
const DateUtilities = require('./src/utils/dateUtilities'),
|
||||
exceptionHandler = require('./src/middlewares/exceptions.handler'),
|
||||
connectDb = require('./src/database/connectDb'),
|
||||
config = require('./src/config'),
|
||||
swaggerUi = require('swagger-ui-express'),
|
||||
swaggerSpec = require('./src/config/swagger');
|
||||
createApp = require('./src/createApp');
|
||||
|
||||
// Create global app object
|
||||
var app = express();
|
||||
app.use(cors());
|
||||
const app = createApp();
|
||||
|
||||
// Morgan status code color config
|
||||
morgan.token('statusColor', (req, res) => {
|
||||
let status = (typeof res.headersSent !== 'boolean' ? Boolean(res.header) : res.headersSent)
|
||||
const status = (typeof res.headersSent !== 'boolean' ? Boolean(res.header) : res.headersSent)
|
||||
? res.statusCode
|
||||
: undefined
|
||||
: undefined;
|
||||
return status >= 500 ? chalk.red(status)
|
||||
: status >= 429 ? chalk.magenta(status)
|
||||
: status >= 400 ? chalk.yellow(status)
|
||||
@@ -35,66 +28,32 @@ morgan.token('statusColor', (req, res) => {
|
||||
: status >= 200 ? chalk.green(status)
|
||||
: chalk.underline(status);
|
||||
});
|
||||
// Morgan log line config
|
||||
app.use(morgan('[:date[iso]] ":method :url HTTP/:http-version" :statusColor :res[content-length] ":referrer" ":user-agent" :remote-addr'));
|
||||
|
||||
//use express.json() to parse incoming requests with JSON payloads
|
||||
app.use(express.json());
|
||||
//parse incoming requests with urlencoded payloads
|
||||
app.use(express.urlencoded({ extended: true }));
|
||||
|
||||
//app.use(bodyParser.urlencoded({ extended: false }));
|
||||
//app.use(bodyParser.json());
|
||||
|
||||
app.use(require('method-override')());
|
||||
app.use(express.static(__dirname + '/public'));
|
||||
|
||||
app.use(session({ secret: config.secret, cookie: { maxAge: config.session_lifetime }, resave: false, saveUninitialized: false }));
|
||||
|
||||
if (appEnv !== 'production') {
|
||||
app.use(errorhandler());
|
||||
}
|
||||
|
||||
require('./src/database/models/mongo');
|
||||
config.initAuth();
|
||||
//config.initApiKey();
|
||||
|
||||
// Setup Swagger documentation
|
||||
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpec, {
|
||||
swaggerOptions: {
|
||||
persistAuthorization: true,
|
||||
},
|
||||
}));
|
||||
|
||||
// Register routes AFTER connections are established
|
||||
const setupRoutes = () => {
|
||||
const setupRoutes = (app) => {
|
||||
app.use(require('./src/routes'));
|
||||
|
||||
// Exception handlers MUST be AFTER routes
|
||||
app.use(exceptionHandler.notFoundErrorHandler);
|
||||
app.use(exceptionHandler.logErrorHandler);
|
||||
//app.use(exceptionHandler.clientErrorHandler);
|
||||
app.use(exceptionHandler.fianlErrorHandler);
|
||||
};
|
||||
|
||||
const startServer = async () => {
|
||||
try {
|
||||
// Initialize database connections and create relationships FIRST
|
||||
await connectDb.connectAllDb();
|
||||
console.log(`${DateUtilities.getDateTimeISOString()}`, chalk.green('All database connections established, relationships loaded'));
|
||||
|
||||
// NOW register the routes after connections are ready
|
||||
setupRoutes();
|
||||
setupRoutes(app);
|
||||
|
||||
// Start the HTTP server
|
||||
const port = process.env.SERVER_PORT || 3200;
|
||||
await promisify(app.listen).bind(app)(port);
|
||||
console.log(`${DateUtilities.getDateTimeISOString()}`, chalk.green(`${process.env.APP_ENV} API server listening on port ${port}`));
|
||||
console.log(`${DateUtilities.getDateTimeISOString()}`, chalk.green(`${appEnv} API server listening on port ${port}`));
|
||||
} catch (error) {
|
||||
console.error(`${DateUtilities.getDateTimeISOString()}`, chalk.red('Failed to start server:'), error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// finally, let's start our server...
|
||||
startServer();
|
||||
|
||||
Reference in New Issue
Block a user