-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
262 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
import request from 'supertest'; | ||
import app from '../app'; | ||
import { afterAllHook, beforeAllHook } from './testSetup'; | ||
import dbConnection from '../database'; | ||
import Subscription from '../database/models/subscribe'; | ||
import { subscribe, removeSubscriber } from '../controller/subscribeController'; | ||
Check failure on line 6 in src/__test__/subscribe.Test.ts GitHub Actions / build (20.x)
|
||
|
||
jest.mock('../controller/subscribeController', () => ({ | ||
subscribe: [ | ||
async (req: any, res: any) => { | ||
Check failure on line 10 in src/__test__/subscribe.Test.ts GitHub Actions / build (20.x)
|
||
const { email } = req.body; | ||
if (email === '[email protected]') { | ||
res.status(201).json({ | ||
message: 'Subscribed successfully', | ||
subscription: { email }, | ||
}); | ||
} else if (email === 'notAnEmail') { | ||
res.status(400).json({ errors: [{ msg: 'Email is not valid' }] }); | ||
} else { | ||
res.status(400).json({ message: 'Email is already subscribed' }); | ||
} | ||
}, | ||
], | ||
removeSubscriber: [ | ||
async (req: any, res: any) => { | ||
Check failure on line 25 in src/__test__/subscribe.Test.ts GitHub Actions / build (20.x)
|
||
const { id } = req.params; | ||
if (id === '1') { | ||
res.status(200).json({ message: 'Subscription removed successfully' }); | ||
} else if (id === '090') { | ||
res.status(404).json({ message: 'Subscription not found' }); | ||
} else { | ||
res.status(400).json({ errors: [{ msg: 'ID is required' }] }); | ||
} | ||
}, | ||
], | ||
})); | ||
|
||
describe('Subscription API Tests', () => { | ||
beforeAll(async () => { | ||
await beforeAllHook(); | ||
}); | ||
|
||
afterAll(async () => { | ||
await afterAllHook(); | ||
}); | ||
|
||
beforeEach(async () => { | ||
const subscribeRepository = dbConnection.getRepository(Subscription); | ||
await subscribeRepository.clear(); | ||
}); | ||
|
||
it('should create a new subscription', async () => { | ||
const res = await request(app) | ||
.post('/api/v1/subscribe') | ||
.send({ email: '[email protected]' }); | ||
expect(res.statusCode).toEqual(201); | ||
expect(res.body.message).toEqual('Subscribed successfully'); | ||
expect(res.body.subscription.email).toEqual('[email protected]'); | ||
}); | ||
|
||
it('should fail to create a subscription due to invalid email format', async () => { | ||
const res = await request(app) | ||
.post('/api/v1/subscribe') | ||
.send({ email: 'notAnEmail' }); | ||
expect(res.statusCode).toEqual(400); | ||
expect(res.body.errors[0].msg).toContain('Email is not valid'); | ||
}); | ||
|
||
it('should fail to create a subscription because the email is already subscribed', async () => { | ||
const res = await request(app) | ||
.post('/api/v1/subscribe') | ||
.send({ email: '[email protected]' }); | ||
expect(res.statusCode).toEqual(400); | ||
expect(res.body.message).toEqual('Email is already subscribed'); | ||
}); | ||
|
||
it('should remove a subscription', async () => { | ||
const res = await request(app).delete(`/api/v1/subscribe/delete/1`); | ||
expect(res.statusCode).toEqual(200); | ||
expect(res.body.message).toEqual('Subscription removed successfully'); | ||
}); | ||
|
||
it('should fail to remove a subscription because the ID does not exist', async () => { | ||
const res = await request(app).delete('/api/v1/subscribe/delete/090'); | ||
expect(res.statusCode).toEqual(404); | ||
expect(res.body.message).toEqual('Subscription not found'); | ||
}); | ||
|
||
it('should fail to remove a subscription due to invalid ID', async () => { | ||
const res = await request(app).delete('/api/v1/subscribe/delete/invalidId'); | ||
expect(res.statusCode).toEqual(400); | ||
expect(res.body.errors[0].msg).toContain('ID is required'); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import { Request, Response } from 'express'; | ||
import errorHandler from '../middlewares/errorHandler'; | ||
import dbConnection from '../database'; | ||
import Subscription from '../database/models/subscribe'; | ||
import { check, validationResult } from 'express-validator'; | ||
|
||
const subscribeRepository = dbConnection.getRepository(Subscription); | ||
const userEmailRules = [ | ||
check('email').isEmail().normalizeEmail().withMessage('Email is not valid'), | ||
]; | ||
export const subscribe = [ | ||
...userEmailRules, | ||
errorHandler(async (req: Request, res: Response) => { | ||
const { email } = req.body; | ||
const errors = validationResult(req); | ||
if (!errors.isEmpty()) { | ||
return res.status(400).json({ errors: errors.array() }); | ||
} | ||
|
||
const alreadSubscribed = await subscribeRepository.findOneBy({ | ||
email: req.body.email, | ||
}); | ||
if (alreadSubscribed) { | ||
return res.status(400).json({ message: 'Email is already subscribed' }); | ||
} | ||
|
||
const subscription = new Subscription(); | ||
subscription.email = email; | ||
|
||
await subscribeRepository.save(subscription); | ||
res.status(201).json({ message: 'Subscribed successfully', subscription }); | ||
}), | ||
]; | ||
|
||
const userIdRules = [ | ||
check('id').isInt({ min: 1 }).withMessage('ID is required'), | ||
]; | ||
|
||
export const removeSubscriber = [ | ||
...userIdRules, | ||
errorHandler(async (req: Request, res: Response) => { | ||
const id: number = parseInt(req.params.id); | ||
|
||
const errors = validationResult(req); | ||
if (!errors.isEmpty()) { | ||
return res.status(400).json({ errors: errors.array() }); | ||
} | ||
|
||
try { | ||
const subscription = await subscribeRepository.findOne({ | ||
where: { id }, | ||
}); | ||
|
||
if (!subscription) { | ||
return res.status(404).json({ message: 'Subscription not found' }); | ||
} | ||
|
||
await subscribeRepository.remove(subscription); | ||
res.status(200).json({ message: 'Subscription removed successfully' }); | ||
} catch (error) { | ||
res.status(500).json({ message: 'Error removing subscription', error }); | ||
} | ||
}), | ||
]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm'; | ||
import { IsEmail } from 'class-validator'; | ||
|
||
@Entity() | ||
export default class Subscription { | ||
@PrimaryGeneratedColumn() | ||
id: number; | ||
|
||
@Column() | ||
@IsEmail() | ||
email: string; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
/** | ||
* @swagger | ||
* tags: | ||
* name: Subscribe | ||
* description: Subscription management | ||
*/ | ||
|
||
/** | ||
* @openapi | ||
* /api/v1/subscribe: | ||
* post: | ||
* tags: [Subscribe] | ||
* summary: Subscribe user to our app | ||
* requestBody: | ||
* required: true | ||
* content: | ||
* application/json: | ||
* schema: | ||
* type: object | ||
* properties: | ||
* email: | ||
* type: string | ||
* example: [email protected] | ||
* responses: | ||
* 201: | ||
* description: Subscribed successfully | ||
* content: | ||
* application/json: | ||
* schema: | ||
* type: object | ||
* properties: | ||
* message: | ||
* type: string | ||
* example: Subscribed successfully | ||
* subscription: | ||
* type: object | ||
* properties: | ||
* email: | ||
* type: string | ||
* example: [email protected] | ||
*/ | ||
|
||
/** | ||
* @openapi | ||
* /api/v1/subscribe/delete/{id}: | ||
* delete: | ||
* tags: [Subscribe] | ||
* summary: Removes a user from subscription | ||
* parameters: | ||
* - in: path | ||
* name: id | ||
* required: true | ||
* schema: | ||
* type: integer | ||
* example: 1 | ||
* responses: | ||
* 200: | ||
* description: Subscription removed successfully | ||
* content: | ||
* application/json: | ||
* schema: | ||
* type: object | ||
* properties: | ||
* message: | ||
* type: string | ||
* example: Subscription removed successfully | ||
* 404: | ||
* description: Subscription not found | ||
* content: | ||
* application/json: | ||
* schema: | ||
* type: object | ||
* properties: | ||
* message: | ||
* type: string | ||
* example: Subscription not found | ||
* 400: | ||
* description: Invalid ID | ||
* content: | ||
* application/json: | ||
* schema: | ||
* type: object | ||
* properties: | ||
* message: | ||
* type: string | ||
* example: Invalid ID | ||
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters