Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 30 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@ The **customer-service-app** is an application that allows users logs complaints

- Key Application features

1. Support Request
1. Functional requirements

- Creation of Support requests
- Fetching support requests
- Updating support requests
- Closing support requests logged
- Download CSV file of closed support requests for the last month

2. Comment
- Users can comment on a support request
Expand All @@ -36,55 +37,63 @@ The **customer-service-app** is an application that allows users logs complaints

- Clone the repo and cd into it:

```
``` bash
#!/bin/bash
git clone https://github.com/dbytecoderc/test-app.git
```

- Install dependencies using the command bellow:

```
``` bash
#!/bin/bash
yarn install
```

- Make a copy of the .env.sample file in the app folder and rename it to .env and update the variables accordingly, **it important that you copy the email and password details in that file just the way it is, you would need it to test admin functionalities and make sure the db urls are set to make sure the tests run**:

```
``` bash
#!/bin/bash
PORT=3000
MONGODB_URI="mongourl"
MONGO_URI_TEST="test mongourl"
MONGODB_URI="mongodb://127.0.0.1/fliqpay"
MONGO_URI_TEST="mongodb://127.0.0.1/fliqpay-test"
SECRET_KEY="secretKey"
ADMIN_PASSWORD="Admin0007"
NON_ADMIN_PASSWORD="User0007"
HASHED_ADMIN_PASSWORD='$2a$10$4IIoa9h4th7aPsMhWP7/Xu97SdwcUjImhyDHDsSK1wssiaIr0M.hm'
HASHED_NON_ADMIN_PASSWORD='$2a$10$WSwcXM1dIaygWLaSQMxAD.cNBDZmykPNJOWOkjwpiFiPr8CrT68ha'
```

* Run the application with the command
NOTE: It is important that the `MONGO_URI_TEST` is set because the integration tests depend on it to run

```
- Run the application with the command

yarn dev
``` bash
#!/bin/bash
yarn start:dev

```

- Data is seeded into the application as soon as you fire up the server, without needing to create a user you can login and create a json web token which is to be attached to the header in this format

```
``` bash
#!/bin/bash
Bearer 'sample token'
```

- Use these details to login an admin user

```
``` bash
#!/bin/bash
{
"email": "admin@admin.com",
"password": "Admin0007"
}
```

- Use these details to login an non-admin user
- Use these details to login a non-admin user

```
``` bash
#!/bin/bash
{
"email": "nonadmin@nonadmin.com",
"password": "User0007"
Expand All @@ -93,22 +102,20 @@ Bearer 'sample token'

## Running tests

Make sure the test database is set for this to work

```
Make sure the environment variable for the test database `MONGO_URI_TEST` is set for this to work

``` bash
#!/bin/bash
yarn test

```

NOTE: All the seed data are baked into the testing process, you won't need to run any script to seed data for tests, and as soon as the application relevant data is seeded into the application to ease manual testing

## API Endpoints

- Use the link below in the thumbnail to download a postman collection for the endpoints
[![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/9452a28c0f505b49eea3)

- Alternatively you can use this [link](https://documenter.getpostman.com/view/6057580/T1DjkziE?version=latest#a2542775-3976-45ca-a981-4453e29e2a6e) to view the api documentation in your browser.

## Notes
[![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/880c258c0500487ff4e6?action=collection%2Fimport#?env%5BFLIQPAY%5D=W3sia2V5IjoiYmFzZS11cmwiLCJ2YWx1ZSI6IlxuaHR0cDovL2xvY2FsaG9zdDozMDAwL2FwaS92MSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoidXNlci10b2tlbiIsInZhbHVlIjoiZXlKaGJHY2lPaUpJVXpJMU5pSXNJblI1Y0NJNklrcFhWQ0o5LmV5SnpkV0lpT2lKcWIyaHVaRzlsUUdkdFlXbHNMbU52YlNJc0ltRmtiV2x1SWpwbVlXeHpaU3dpYVdGMElqb3hOakU0TlRFek56azVMQ0psZUhBaU9qRTJNVGt4TVRnMU9UbDkuOWl2RFhMd05CZHhuTm5EeDhmWEI3TG56a1I0TEpOSE9IQmk3ZG5PZURsdyIsImVuYWJsZWQiOnRydWV9LHsia2V5Ijoic2Vjb25kLXVzZXItdG9rZW4iLCJ2YWx1ZSI6ImV5SmhiR2NpT2lKSVV6STFOaUlzSW5SNWNDSTZJa3BYVkNKOS5leUp6ZFdJaU9pSnFiMmh1Wkc5bE1rQm5iV0ZwYkM1amIyMGlMQ0poWkcxcGJpSTZabUZzYzJVc0ltbGhkQ0k2TVRZeE9EVXhPRGMxTkN3aVpYaHdJam94TmpFNU1USXpOVFUwZlEuaTRKd1J5R0NXUVp0OW1idTlfclBqdnVEekdEMDdKOUhPWHBlc2g5Tko1ZyIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiYWRtaW4tdXNlci10b2tlbiIsInZhbHVlIjoiZXlKaGJHY2lPaUpJVXpJMU5pSXNJblI1Y0NJNklrcFhWQ0o5LmV5SnpkV0lpT2lKaFpHMXBia0JuYldGcGJDNWpiMjBpTENKaFpHMXBiaUk2ZEhKMVpTd2lhV0YwSWpveE5qRTROVEUzT1RnMExDSmxlSEFpT2pFMk1Ua3hNakkzT0RSOS5yYnA3dDlVVE1HMnAxNTA5QXpnNGVialBXandfNDZJaVU3M1pKZl81d3NBIiwiZW5hYmxlZCI6dHJ1ZX1d)

- For feedback I thought the assessment specs could be better in terms of clarifying some of the instructions for ease of understanding.
- Due to time constraints I couldn't increase the test coverage, although I covered all the essential parts of the application.
- Alternatively you can use this [link](https://documenter.getpostman.com/view/6057580/TzJrBeaA) to view the api documentation in your browser.
- After visiting the link you can click on the dropdowns of each request to view preset examples of request edge-cases covered.
12 changes: 12 additions & 0 deletions src/@types/express/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,18 @@ interface CreateUserInput {
password: string;
}


interface SupportRequest extends Document {
description: string;
owner?: User;
comments?: Comment[]
}

interface Comment extends Document {
description: string;
owner?: User | string
}

interface User extends Document {
name: string;
email: string;
Expand Down
19 changes: 9 additions & 10 deletions src/app.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
import express, { Application } from 'express';
import express, { Application, Request, Response } from 'express';
import dotenv from 'dotenv';
dotenv.config();
import cors from 'cors';
import * as bodyparser from 'body-parser';
import dbconnect from './config/connection.db';
import morgan from 'morgan';

import modules from './modules';
// import seedData from './database/seeders/seeder';
import seedData from './database/seeders/seeder';

const app: Application = express();

const { PORT } = process.env;

app.use(cors());
app.use(bodyparser.json());

app.use(express.json());
app.use(express.urlencoded({ extended: true }));
if (process.env.NODE_ENV === 'development') {
app.use(morgan('dev'));
}
Expand All @@ -24,16 +23,16 @@ if (process.env.NODE_ENV === 'development') {
modules(app);

// catch all routers
app.use('*', (req, res) => {
res.status(404).json({
app.use('*', (request: Request, response: Response) => {
return response.status(404).json({
message: 'Not Found. Use /api/{app version} to access the Api',
});
});

dbconnect().then(async () => {
// if (process.env.NODE_ENV !== 'test') {
// await seedData();
// }
if (process.env.NODE_ENV !== 'test') {
await seedData();
}
if (!module.parent) {
app.listen(PORT, () => {
console.log(
Expand Down
14 changes: 7 additions & 7 deletions src/database/seeders/seeder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import dotenv from 'dotenv';

import User from '../models/User';
import SupportRequest from '../models/SupportRequest';
import Comment from '../models/Comment'

dotenv.config();

Expand All @@ -10,6 +11,7 @@ const { HASHED_ADMIN_PASSWORD, HASHED_NON_ADMIN_PASSWORD } = process.env;
const seedData = async () => {
await User.deleteMany({});
await SupportRequest.deleteMany({});
await Comment.deleteMany({});
const user1 = new User({
_id: '5e1863eeb0eb0406250967ba',
name: 'Admin user',
Expand All @@ -24,18 +26,16 @@ const seedData = async () => {
password: HASHED_NON_ADMIN_PASSWORD,
});

// t

await user1.save();
await user2.save();
await User.findOneAndUpdate({ email: 'admin@admin.com' }, { admin: true });
const user = await User.findOne({ email: 'nonadmin@nonadmin.com' });

const createdAt1 = new Date(2020, 4, 30);
const endedAt1 = new Date(2020, 5, 27);
const endedAt2 = new Date(2020, 5, 25);
const endedAt3 = new Date(2020, 5, 22);
const endedAt4 = new Date(2020, 5, 10);
const createdAt1 = new Date(2021, 4, 16);
const endedAt1 = new Date(2021, 4, 17);
const endedAt2 = new Date(2021, 5, 25);
const endedAt3 = new Date(2021, 5, 22);
const endedAt4 = new Date(2021, 5, 10);

const supportRequest1 = new SupportRequest({
_id: '5f14396f8cd92082e4bcb2f8',
Expand Down
2 changes: 0 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ import chalk from "chalk";
import { env } from "./config";
import app from "./app";
import logger from "./config/logger";
// import Utils from "./util/Utils";
// import Error from "./util/Error";

export const server: http.Server = http.createServer(app);

Expand Down
1 change: 1 addition & 0 deletions src/modules/comment/__test__/comment.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ describe('TEST SUITE FOR COMMENTS', () => {
afterAll(async (done) => {
await User.deleteMany({});
await SupportRequest.deleteMany({});
await Comment.deleteMany({});
await mongoose.connection.close();
server.close();
done();
Expand Down
7 changes: 3 additions & 4 deletions src/modules/comment/comment.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { Request, Response } from 'express';

import CommentRepository from './comment.repository';
import SupportRequestRepository from '../support-request/support-request.repository';
// import Utils from '../../utils/utils';
import Error from '../../utils/Error';

export default class SupportRequestController {
Expand Down Expand Up @@ -33,19 +32,19 @@ export default class SupportRequestController {
return Error.handleError('Support request not found', 400, response);
}

if (!admin && supportRequest.owner._id.toString() !== _id.toString()) {
if (!admin && supportRequest.owner!._id.toString() !== _id.toString()) {
return Error.handleError('Not allowed', 400, response);
}

if (supportRequest.comments.length === 0 && !request.user.admin) {
if (supportRequest.comments!.length === 0 && !request.user.admin) {
return Error.handleError(
'No support agent has responded to this request',
400,
response,
);
}

if (supportRequest.comments.length === 0 && request.user.admin) {
if (supportRequest.comments!.length === 0 && request.user.admin) {
await SupportRequestRepository.updateSupportRequest(
supportRequest._id,
{ status: 'INPROGRESS' },
Expand Down
13 changes: 11 additions & 2 deletions src/modules/comment/comment.repository.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
import CommentRequest from '../../database/models/Comment';
import { SupportRequest, Comment } from '../../@types/express';

export default class CommentRepository {
static async createComment(commentDetails: any, supportRequestDetails: any) {
/**
* @param {Comment} id - ID of data to be fetched
* @param {SupportRequest} support request detsils
* @returns {Promise<Comment>} returned datase object
*/
static async createComment(
commentDetails: Comment,
supportRequestDetails: SupportRequest,
): Promise<Comment> {
const comment = new CommentRequest(commentDetails);
await comment.save();
supportRequestDetails.comments.push(comment);
supportRequestDetails.comments!.push(comment);
await supportRequestDetails.save();
return comment;
}
Expand Down
Loading