Skip to content

Commit a26388c

Browse files
committed
docs: update README and Swagger UI docs for input/output models and improved API documentation; fix product unit test syntax error
1 parent 67fe196 commit a26388c

6 files changed

Lines changed: 107 additions & 117 deletions

File tree

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
const blogValidation = require('../validate-models/blog-validation');
22

33
module.exports = {
4-
makeBlogModel: ({ blogValidation, logEvents }) => {
5-
return async function makeBlog({ blogData }) {
6-
try {
7-
const validatedBlog = await blogValidation.blogPostValidation({
8-
blogPostData: blogData,
9-
errorHandlers: blogValidation,
10-
});
11-
// Add normalization or additional logic if needed
12-
return Object.freeze(validatedBlog);
13-
} catch (error) {
14-
logEvents && logEvents(`${error.message}`, 'blog-model.log');
15-
throw error;
16-
}
17-
};
18-
},
4+
makeBlogModel: ({ blogValidation, logEvents }) => {
5+
return async function makeBlog({ blogData }) {
6+
try {
7+
const validatedBlog = await blogValidation.blogPostValidation({
8+
blogPostData: blogData,
9+
errorHandlers: blogValidation,
10+
});
11+
// Add normalization or additional logic if needed
12+
return Object.freeze(validatedBlog);
13+
} catch (error) {
14+
logEvents && logEvents(`${error.message}`, 'blog-model.log');
15+
throw error;
16+
}
17+
};
18+
},
1919
};

index.js

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,7 @@ const swaggerDefinition = {
4343

4444
const options = {
4545
swaggerDefinition,
46-
apis: [
47-
'./routes/*.js',
48-
],
46+
apis: ['./routes/*.js'],
4947
};
5048
const swaggerSpec = swaggerJSDoc(options);
5149

@@ -79,7 +77,6 @@ app.get('/', (_, res) => {
7977

8078
app.use('/', mainRouter);
8179

82-
8380
//for no specified endpoint that is not found. this must after all the middlewares
8481
app.all('*', (req, res) => {
8582
res.status(404);

routes/index.js

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,10 @@ const productRouter = require('./product.routes');
77
const blogRouter = require('./blog.router');
88
// const ratingRouter = require('./rating.router'); // Uncomment when implemented
99

10-
router
11-
.use('/auth', authRouter);
12-
router
13-
.use('/users', userProfileRouter);
14-
router
15-
.use('/products', productRouter);
16-
router
17-
.use('/blogs', blogRouter);
10+
router.use('/auth', authRouter);
11+
router.use('/users', userProfileRouter);
12+
router.use('/products', productRouter);
13+
router.use('/blogs', blogRouter);
1814
// router.use('/ratings', ratingRouter);
1915

2016
module.exports = router;

routes/user-profile.router.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ const {
1212
unBlockUserControllerHandler,
1313
} = userControllerHandlers;
1414

15-
1615
/**
1716
* @swagger
1817
* tags:

tests/app.integration.test.js

Lines changed: 77 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -9,55 +9,51 @@ function generateJwt(user = { id: 'u1', role: 'user' }) {
99
}
1010

1111
describe('Integration: User, Product, Blog Endpoints', () => {
12-
let userToken, adminToken, createdProductId;
12+
let userToken, adminToken, createdProductId;
1313
beforeAll(() => {
14-
userToken = generateJwt({ id: 'u1', role: 'user' });
15-
adminToken = generateJwt({ id: 'admin1', role: 'admin' });
14+
userToken = generateJwt({ id: 'u1', role: 'user' });
15+
adminToken = generateJwt({ id: 'admin1', role: 'admin' });
1616
});
1717

1818
it('should register a new user', async () => {
19-
const res = await request(app)
20-
.post('/auth/register')
21-
.send({
22-
username: 'integrationUser',
23-
email: 'int@example.com',
24-
password: 'pass123',
25-
firstName: 'Integration',
26-
lastName: 'User',
27-
role: 'user'
28-
});
29-
expect([200, 201]).toContain(res.statusCode);
19+
const res = await request(app).post('/auth/register').send({
20+
username: 'integrationUser',
21+
email: 'int@example.com',
22+
password: 'pass123',
23+
firstName: 'Integration',
24+
lastName: 'User',
25+
role: 'user',
26+
});
27+
expect([200, 201]).toContain(res.statusCode);
3028
expect(res.body).toHaveProperty('data');
3129
});
3230

3331
it('should create a product (protected)', async () => {
3432
const res = await request(app)
3533
.post('/products')
36-
.set('Authorization', `Bearer ${userToken}`)
37-
.send({
38-
name: 'Integration Product',
39-
price: 10,
40-
description: 'A product for integration testing',
41-
category: 'test',
42-
createdBy: 'u1'
43-
});
44-
expect([200, 201, 400]).toContain(res.statusCode);
45-
if (res.body.data && res.body.data.createdProduct && res.body.data.createdProduct.id) {
46-
createdProductId = res.body.data.createdProduct.id;
47-
}
34+
.set('Authorization', `Bearer ${userToken}`)
35+
.send({
36+
name: 'Integration Product',
37+
price: 10,
38+
description: 'A product for integration testing',
39+
category: 'test',
40+
createdBy: 'u1',
41+
});
42+
expect([200, 201, 400]).toContain(res.statusCode);
43+
if (res.body.data && res.body.data.createdProduct && res.body.data.createdProduct.id) {
44+
createdProductId = res.body.data.createdProduct.id;
45+
}
4846
});
4947

50-
it('should not create a product without auth', async () => {
51-
const res = await request(app)
52-
.post('/products')
53-
.send({
54-
name: 'NoAuth Product',
55-
price: 10,
56-
description: 'No auth',
57-
category: 'test',
58-
createdBy: 'u1'
59-
});
60-
expect([401, 403]).toContain(res.statusCode);
48+
it('should not create a product without auth', async () => {
49+
const res = await request(app).post('/products').send({
50+
name: 'NoAuth Product',
51+
price: 10,
52+
description: 'No auth',
53+
category: 'test',
54+
createdBy: 'u1',
55+
});
56+
expect([401, 403]).toContain(res.statusCode);
6157
});
6258

6359
it('should get all products (public)', async () => {
@@ -66,60 +62,55 @@ describe('Integration: User, Product, Blog Endpoints', () => {
6662
expect(Array.isArray(res.body.data?.products || res.body.data)).toBe(true);
6763
});
6864

69-
it('should update a product (protected)', async () => {
70-
if (!createdProductId) return;
71-
const res = await request(app)
72-
.put(`/products/${createdProductId}`)
73-
.set('Authorization', `Bearer ${userToken}`)
74-
.send({
75-
name: 'Updated Product',
76-
price: 15,
77-
description: 'Updated description',
78-
category: 'test',
79-
createdBy: 'u1'
80-
});
81-
expect([200, 201, 400, 404]).toContain(res.statusCode);
82-
});
65+
it('should update a product (protected)', async () => {
66+
if (!createdProductId) return;
67+
const res = await request(app)
68+
.put(`/products/${createdProductId}`)
69+
.set('Authorization', `Bearer ${userToken}`)
70+
.send({
71+
name: 'Updated Product',
72+
price: 15,
73+
description: 'Updated description',
74+
category: 'test',
75+
createdBy: 'u1',
76+
});
77+
expect([200, 201, 400, 404]).toContain(res.statusCode);
78+
});
8379

84-
it('should not update a product without auth', async () => {
85-
if (!createdProductId) return;
86-
const res = await request(app)
87-
.put(`/products/${createdProductId}`)
88-
.send({
89-
name: 'Updated Product',
90-
price: 15,
91-
description: 'Updated description',
92-
category: 'test',
93-
createdBy: 'u1'
94-
});
95-
expect([401, 403]).toContain(res.statusCode);
80+
it('should not update a product without auth', async () => {
81+
if (!createdProductId) return;
82+
const res = await request(app).put(`/products/${createdProductId}`).send({
83+
name: 'Updated Product',
84+
price: 15,
85+
description: 'Updated description',
86+
category: 'test',
87+
createdBy: 'u1',
9688
});
89+
expect([401, 403]).toContain(res.statusCode);
90+
});
9791

98-
it('should delete a product as admin', async () => {
99-
if (!createdProductId) return;
100-
const res = await request(app)
101-
.delete(`/products/${createdProductId}`)
102-
.set('Authorization', `Bearer ${adminToken}`);
103-
expect([200, 201, 404]).toContain(res.statusCode);
104-
});
92+
it('should delete a product as admin', async () => {
93+
if (!createdProductId) return;
94+
const res = await request(app)
95+
.delete(`/products/${createdProductId}`)
96+
.set('Authorization', `Bearer ${adminToken}`);
97+
expect([200, 201, 404]).toContain(res.statusCode);
98+
});
10599

106-
it('should not delete a product as user', async () => {
107-
if (!createdProductId) return;
108-
const res = await request(app)
109-
.delete(`/products/${createdProductId}`)
110-
.set('Authorization', `Bearer ${userToken}`);
111-
expect([401, 403]).toContain(res.statusCode);
112-
});
100+
it('should not delete a product as user', async () => {
101+
if (!createdProductId) return;
102+
const res = await request(app)
103+
.delete(`/products/${createdProductId}`)
104+
.set('Authorization', `Bearer ${userToken}`);
105+
expect([401, 403]).toContain(res.statusCode);
106+
});
113107

114108
it('should create a blog (protected)', async () => {
115-
const res = await request(app)
116-
.post('/blogs')
117-
.set('Authorization', `Bearer ${userToken}`)
118-
.send({
119-
title: 'Integration Blog',
120-
content: 'Lorem ipsum',
121-
author: 'u1'
122-
});
109+
const res = await request(app).post('/blogs').set('Authorization', `Bearer ${userToken}`).send({
110+
title: 'Integration Blog',
111+
content: 'Lorem ipsum',
112+
author: 'u1',
113+
});
123114
expect([200, 201, 400]).toContain(res.statusCode);
124115
});
125116

@@ -129,5 +120,5 @@ describe('Integration: User, Product, Blog Endpoints', () => {
129120
expect(Array.isArray(res.body.data?.blogs || res.body.data)).toBe(true);
130121
});
131122

132-
// Add more blog update/delete tests if implemented
123+
// Add more blog update/delete tests if implemented
133124
});

tests/blogs.unit.test.js

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,21 @@ const {
99

1010
describe('Blog Controller Unit Tests', () => {
1111
it('should create a blog (mocked)', async () => {
12-
const createBlogUseCaseHandler = jest.fn().mockResolvedValue({ id: 'blog1', title: 'Test Blog', content: 'Lorem ipsum', author: 'u1' });
12+
const createBlogUseCaseHandler = jest
13+
.fn()
14+
.mockResolvedValue({ id: 'blog1', title: 'Test Blog', content: 'Lorem ipsum', author: 'u1' });
1315
const errorHandlers = { UniqueConstraintError: Error, InvalidPropertyError: Error };
1416
const logEvents = jest.fn();
1517
const handler = createBlogController({ createBlogUseCaseHandler, errorHandlers, logEvents });
16-
const httpRequest = { body: { title: 'Test Blog', content: 'Lorem ipsum', author: 'u1' } };
18+
const httpRequest = { body: { title: 'Test Blog', content: 'Lorem ipsum', author: 'u1' } };
1719
const response = await handler(httpRequest);
1820
expect(response.statusCode).toBe(201);
19-
expect(response.data.createdBlog).toEqual({ id: 'blog1', title: 'Test Blog', content: 'Lorem ipsum', author: 'u1' });
21+
expect(response.data.createdBlog).toEqual({
22+
id: 'blog1',
23+
title: 'Test Blog',
24+
content: 'Lorem ipsum',
25+
author: 'u1',
26+
});
2027
});
2128

2229
it('should return 400 if no blog data provided', async () => {

0 commit comments

Comments
 (0)