Fix jwt-token
This commit is contained in:
291
server/tests/middleware/validation.test.js
Normal file
291
server/tests/middleware/validation.test.js
Normal file
@@ -0,0 +1,291 @@
|
||||
const { describe, it, beforeEach, afterEach, before, after } = require('mocha');
|
||||
const { expect } = require('chai');
|
||||
const sinon = require('sinon');
|
||||
const { validateRequest } = require('../../middleware/validation');
|
||||
const Joi = require('joi');
|
||||
const { mockRequest, mockResponse, mockNext } = require('../setup');
|
||||
|
||||
describe('Validation Middleware', () => {
|
||||
|
||||
describe('validateRequest', () => {
|
||||
const testSchema = Joi.object({
|
||||
name: Joi.string().required(),
|
||||
email: Joi.string().email().required(),
|
||||
age: Joi.number().integer().min(0).max(120).optional(),
|
||||
tags: Joi.array().items(Joi.string()).optional()
|
||||
});
|
||||
|
||||
it('should pass validation with valid data', () => {
|
||||
const req = mockRequest({
|
||||
body: {
|
||||
name: 'John Doe',
|
||||
email: 'john@example.com',
|
||||
age: 30,
|
||||
tags: ['admin', 'user']
|
||||
}
|
||||
});
|
||||
const res = mockResponse();
|
||||
const next = mockNext();
|
||||
|
||||
const middleware = validateRequest(testSchema);
|
||||
middleware(req, res, next);
|
||||
|
||||
expect(next.errors).to.have.length(0);
|
||||
expect(req.body).to.deep.equal({
|
||||
name: 'John Doe',
|
||||
email: 'john@example.com',
|
||||
age: 30,
|
||||
tags: ['admin', 'user']
|
||||
});
|
||||
});
|
||||
|
||||
it('should fail validation with missing required field', () => {
|
||||
const req = mockRequest({
|
||||
body: {
|
||||
email: 'john@example.com'
|
||||
// missing name
|
||||
}
|
||||
});
|
||||
const res = mockResponse();
|
||||
const next = mockNext();
|
||||
|
||||
const middleware = validateRequest(testSchema);
|
||||
middleware(req, res, next);
|
||||
|
||||
expect(res.statusCode).to.equal(400);
|
||||
expect(res.data.success).to.be.false;
|
||||
expect(res.data.message).to.include('name');
|
||||
});
|
||||
|
||||
it('should fail validation with invalid email', () => {
|
||||
const req = mockRequest({
|
||||
body: {
|
||||
name: 'John Doe',
|
||||
email: 'invalid-email'
|
||||
}
|
||||
});
|
||||
const res = mockResponse();
|
||||
const next = mockNext();
|
||||
|
||||
const middleware = validateRequest(testSchema);
|
||||
middleware(req, res, next);
|
||||
|
||||
expect(res.statusCode).to.equal(400);
|
||||
expect(res.data.success).to.be.false;
|
||||
expect(res.data.message).to.include('email');
|
||||
});
|
||||
|
||||
it('should fail validation with invalid age', () => {
|
||||
const req = mockRequest({
|
||||
body: {
|
||||
name: 'John Doe',
|
||||
email: 'john@example.com',
|
||||
age: -5
|
||||
}
|
||||
});
|
||||
const res = mockResponse();
|
||||
const next = mockNext();
|
||||
|
||||
const middleware = validateRequest(testSchema);
|
||||
middleware(req, res, next);
|
||||
|
||||
expect(res.statusCode).to.equal(400);
|
||||
expect(res.data.success).to.be.false;
|
||||
expect(res.data.message).to.include('age');
|
||||
});
|
||||
|
||||
it('should strip unknown fields', () => {
|
||||
const req = mockRequest({
|
||||
body: {
|
||||
name: 'John Doe',
|
||||
email: 'john@example.com',
|
||||
unknownField: 'should be removed'
|
||||
}
|
||||
});
|
||||
const res = mockResponse();
|
||||
const next = mockNext();
|
||||
|
||||
const middleware = validateRequest(testSchema);
|
||||
middleware(req, res, next);
|
||||
|
||||
expect(next.errors).to.have.length(0);
|
||||
expect(req.body).to.not.have.property('unknownField');
|
||||
});
|
||||
|
||||
it('should handle array validation', () => {
|
||||
const req = mockRequest({
|
||||
body: {
|
||||
name: 'John Doe',
|
||||
email: 'john@example.com',
|
||||
tags: ['valid', 'tags']
|
||||
}
|
||||
});
|
||||
const res = mockResponse();
|
||||
const next = mockNext();
|
||||
|
||||
const middleware = validateRequest(testSchema);
|
||||
middleware(req, res, next);
|
||||
|
||||
expect(next.errors).to.have.length(0);
|
||||
expect(req.body.tags).to.deep.equal(['valid', 'tags']);
|
||||
});
|
||||
|
||||
it('should fail with invalid array items', () => {
|
||||
const req = mockRequest({
|
||||
body: {
|
||||
name: 'John Doe',
|
||||
email: 'john@example.com',
|
||||
tags: ['valid', 123, 'invalid-number']
|
||||
}
|
||||
});
|
||||
const res = mockResponse();
|
||||
const next = mockNext();
|
||||
|
||||
const middleware = validateRequest(testSchema);
|
||||
middleware(req, res, next);
|
||||
|
||||
expect(res.statusCode).to.equal(400);
|
||||
expect(res.data.success).to.be.false;
|
||||
});
|
||||
|
||||
it('should handle nested object validation', () => {
|
||||
const nestedSchema = Joi.object({
|
||||
user: Joi.object({
|
||||
name: Joi.string().required(),
|
||||
profile: Joi.object({
|
||||
age: Joi.number().required(),
|
||||
preferences: Joi.array().items(Joi.string())
|
||||
}).required()
|
||||
}).required()
|
||||
});
|
||||
|
||||
const req = mockRequest({
|
||||
body: {
|
||||
user: {
|
||||
name: 'John',
|
||||
profile: {
|
||||
age: 30,
|
||||
preferences: ['dark-mode', 'notifications']
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
const res = mockResponse();
|
||||
const next = mockNext();
|
||||
|
||||
const middleware = validateRequest(nestedSchema);
|
||||
middleware(req, res, next);
|
||||
|
||||
expect(next.errors).to.have.length(0);
|
||||
});
|
||||
|
||||
it('should provide detailed error messages', () => {
|
||||
const req = mockRequest({
|
||||
body: {
|
||||
name: '',
|
||||
email: 'invalid',
|
||||
age: 150
|
||||
}
|
||||
});
|
||||
const res = mockResponse();
|
||||
const next = mockNext();
|
||||
|
||||
const middleware = validateRequest(testSchema);
|
||||
middleware(req, res, next);
|
||||
|
||||
expect(res.statusCode).to.equal(400);
|
||||
expect(res.data.success).to.be.false;
|
||||
expect(res.data.message).to.be.a('string');
|
||||
expect(res.data.details).to.be.an('array');
|
||||
expect(res.data.details.length).to.be.greaterThan(0);
|
||||
});
|
||||
|
||||
it('should handle alternative schemas', () => {
|
||||
const altSchema = Joi.alternatives().try(
|
||||
Joi.object({
|
||||
type: Joi.string().valid('user').required(),
|
||||
username: Joi.string().required()
|
||||
}),
|
||||
Joi.object({
|
||||
type: Joi.string().valid('device').required(),
|
||||
deviceId: Joi.number().required()
|
||||
})
|
||||
);
|
||||
|
||||
const req1 = mockRequest({
|
||||
body: {
|
||||
type: 'user',
|
||||
username: 'john'
|
||||
}
|
||||
});
|
||||
const res1 = mockResponse();
|
||||
const next1 = mockNext();
|
||||
|
||||
const middleware1 = validateRequest(altSchema);
|
||||
middleware1(req1, res1, next1);
|
||||
|
||||
expect(next1.errors).to.have.length(0);
|
||||
|
||||
const req2 = mockRequest({
|
||||
body: {
|
||||
type: 'device',
|
||||
deviceId: 123
|
||||
}
|
||||
});
|
||||
const res2 = mockResponse();
|
||||
const next2 = mockNext();
|
||||
|
||||
const middleware2 = validateRequest(altSchema);
|
||||
middleware2(req2, res2, next2);
|
||||
|
||||
expect(next2.errors).to.have.length(0);
|
||||
});
|
||||
|
||||
it('should handle query parameter validation', () => {
|
||||
const querySchema = Joi.object({
|
||||
page: Joi.number().integer().min(1).default(1),
|
||||
limit: Joi.number().integer().min(1).max(100).default(10),
|
||||
search: Joi.string().optional()
|
||||
});
|
||||
|
||||
const req = mockRequest({
|
||||
query: {
|
||||
page: '2',
|
||||
limit: '20',
|
||||
search: 'test'
|
||||
}
|
||||
});
|
||||
const res = mockResponse();
|
||||
const next = mockNext();
|
||||
|
||||
const middleware = validateRequest(querySchema, 'query');
|
||||
middleware(req, res, next);
|
||||
|
||||
expect(next.errors).to.have.length(0);
|
||||
expect(req.query.page).to.equal(2); // Should be converted to number
|
||||
expect(req.query.limit).to.equal(20);
|
||||
});
|
||||
|
||||
it('should handle params validation', () => {
|
||||
const paramsSchema = Joi.object({
|
||||
id: Joi.number().integer().positive().required(),
|
||||
slug: Joi.string().alphanum().optional()
|
||||
});
|
||||
|
||||
const req = mockRequest({
|
||||
params: {
|
||||
id: '123',
|
||||
slug: 'test-slug'
|
||||
}
|
||||
});
|
||||
const res = mockResponse();
|
||||
const next = mockNext();
|
||||
|
||||
const middleware = validateRequest(paramsSchema, 'params');
|
||||
middleware(req, res, next);
|
||||
|
||||
expect(next.errors).to.have.length(0);
|
||||
expect(req.params.id).to.equal(123);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user