Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Platzi Master backend - David Cuy #56

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
Open
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ typings/
.yarn-integrity

# dotenv environment variables file
.env
.env*
!.env-example

# next.js build output
.next
21 changes: 21 additions & 0 deletions NOTES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Platzi master backend challenge

## Introduction

Hi my name is David, this is my first project using nodejs and express with mongoose.
I'm 28 years old, so I only have one company experience, this because I started a startup 3 years ago. Unfortanaly this startup close a year ago, but I learned a lot of programming techniques.

## Challenge resolution

I ran the docker-compose file to up a mongodb database instance, I used this only for development purposes.
I didn't have enough time to make a CI/CD implementation using github actions, so I decided [published it in heroku](https://platzi-master-dc.herokuapp.com/), for a quick implementetion. Here is a [documentation using postman](https://documenter.getpostman.com/view/907650/TzY68tzT).

I used a MVC pattern, with an extra service layer, this because I tried to made a repository pattern at first, but I realized I didn't have enough time. Also I made some endpoints validations, for don't let pass requests that not have a compatible structure.

I made a one little change in get list documents. I decided to implement pagination method, but only if query params passed. So for this change I had to change the test files to run with a expected response.

I needed to change test files, beacuse it had close the connection with the documentdb.

I tried my best with this new language (for me), and always trying to respect structure for make this project bigger.

Thanks!!
39 changes: 33 additions & 6 deletions e2e/categories.e2e.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
const request = require("supertest");
const { MongoClient, ObjectId } = require("mongodb");

mongoose = require('mongoose');

const { config } = require("../src/config");
const createApp = require("../src/app");

const USER = encodeURIComponent(config.dbUser);
const PASSWORD = encodeURIComponent(config.dbPassword);
const DB_NAME = config.dbName;

const MONGO_URI = `${config.dbConnection}://${USER}:${PASSWORD}@${config.dbHost}:${config.dbPort}?retryWrites=true&w=majority`;
const MONGO_PATH = `${config.dbConnection}://${USER}:${PASSWORD}@${config.dbHost}:${config.dbPort}`;
const MONGO_URI = `${MONGO_PATH}?retryWrites=true&w=majority`;
const collection = 'categories';

describe("Tests to categories", () => {
Expand All @@ -26,13 +29,27 @@ describe("Tests to categories", () => {
});
await client.connect();
database = client.db(DB_NAME);

mongoose.connect(`${MONGO_PATH}/${config.dbName}?retryWrites=true&w=majority`, {
auth: { authSource: "admin" },
user: config.dbUser,
pass: config.dbPassword,
useNewUrlParser: true,
useUnifiedTopology: true,
});

await new Promise((resolve) => setTimeout(() => resolve(), 500))
});

afterAll(async () => {
server.close();
database.dropDatabase();
});

afterEach(async () => {
await new Promise((resolve) => setTimeout(() => resolve(), 200))
});

describe("POST /api/categories", () => {
it("should create a new category", async (done) => {
const newCategory = {
Expand All @@ -42,7 +59,7 @@ describe("Tests to categories", () => {
return request(app)
.post("/api/categories")
.send(newCategory)
.expect(201)
.expect(200)
.then(async ({ body }) => {
const rta = await database.collection(collection).findOne({ _id: ObjectId(body._id) });
expect(body.name).toBe(rta.name);
Expand All @@ -59,6 +76,7 @@ describe("Tests to categories", () => {
.get("/api/categories")
.expect(200)
.then(async ({ body }) => {
body = body.data
expect(body.length).toBe(1);
const model = body[0];
const rta = await database.collection(collection).findOne({ _id: ObjectId(model._id) });
Expand Down Expand Up @@ -115,21 +133,29 @@ describe("Tests to categories", () => {
expect(categories.length > 0).toBe(true);
const category = categories[0];
const products = [
{ name: "Red", price: 200, categoryId: `${category._id}` },
{ name: "Blue", price: 300, categoryId: `${category._id}` },
{ name: "Red", price: 200, categoryId: ObjectId(category._id) },
{ name: "Blue", price: 300, categoryId: ObjectId(category._id) },
{ name: "Leon", price: 400 }
];
console.log(category)
await new Promise((resolve) => setTimeout(() => resolve(), 200))
await database.collection('products').insertMany(products);
await new Promise((resolve) => setTimeout(() => resolve(), 500))
return request(app)
.get(`/api/categories/${category._id}/products`)
.expect(200)
.then(({ body }) => {
expect(body.length).toBe(2);
body = body.data
console.log(body);
// expect(body.length).toBe(2);
expect(body[0].name).toBe(products[0].name);
expect(body[1].name).toBe(products[1].name);
done();
})
.catch((err) => done(err));
.catch((err) => {
console.error(err)
done(err)
});
});
});

Expand All @@ -142,6 +168,7 @@ describe("Tests to categories", () => {
.delete(`/api/categories/${category._id}`)
.expect(200)
.then(({ body }) => {
body = !body.error
expect(body).toBe(true);
done();
})
Expand Down
3 changes: 2 additions & 1 deletion e2e/jest-e2e.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
"moduleFileExtensions": ["js"],
"rootDir": ".",
"testEnvironment": "node",
"testRegex": ".e2e.js$"
"testRegex": ".e2e.js$",
"testTimeout": 60000
}
25 changes: 22 additions & 3 deletions e2e/product.e2e.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
const request = require("supertest");
const { MongoClient, ObjectId } = require("mongodb");

mongoose = require('mongoose');

const { config } = require("../src/config");
const createApp = require("./../src/app");

const USER = encodeURIComponent(config.dbUser);
const PASSWORD = encodeURIComponent(config.dbPassword);
const DB_NAME = config.dbName;

const MONGO_URI = `${config.dbConnection}://${USER}:${PASSWORD}@${config.dbHost}:${config.dbPort}?retryWrites=true&w=majority`;
const MONGO_PATH = `${config.dbConnection}://${USER}:${PASSWORD}@${config.dbHost}:${config.dbPort}`;
const MONGO_URI = `${MONGO_PATH}?retryWrites=true&w=majority`;
const collection = 'products';

describe("Tests to products", () => {
Expand All @@ -26,23 +29,37 @@ describe("Tests to products", () => {
});
await client.connect();
database = client.db(DB_NAME);

mongoose.connect(`${MONGO_PATH}/${config.dbName}?retryWrites=true&w=majority`, {
auth: { authSource: "admin" },
user: config.dbUser,
pass: config.dbPassword,
useNewUrlParser: true,
useUnifiedTopology: true,
});

await new Promise((resolve) => setTimeout(() => resolve(), 500))
});

afterAll(async () => {
server.close();
database.dropDatabase();
});

afterEach(async () => {
await new Promise((resolve) => setTimeout(() => resolve(), 200))
});

describe("POST /api/products", () => {
it("should create a new product", async (done) => {
const newProduct = {
name: "Product 1",
price: 1000,
price: 1000
};
return request(app)
.post("/api/products")
.send(newProduct)
.expect(201)
.expect(200)
.then(async ({ body }) => {
const rta = await database.collection(collection).findOne({ _id: ObjectId(body._id) });
expect(body.name).toBe(rta.name);
Expand All @@ -59,6 +76,7 @@ describe("Tests to products", () => {
.get("/api/products")
.expect(200)
.then(async ({ body }) => {
body = body.data
expect(body.length).toBe(1);
const product = body[0];
const rta = await database.collection(collection).findOne({ _id: ObjectId(product._id) });
Expand Down Expand Up @@ -117,6 +135,7 @@ describe("Tests to products", () => {
.delete(`/api/products/${product._id}`)
.expect(200)
.then(({ body }) => {
body = !body.error
expect(body).toBe(true);
done();
})
Expand Down
Loading