diff --git a/controllers/trading.js b/controllers/trading.js index 617e2c538..0ba09f8f4 100644 --- a/controllers/trading.js +++ b/controllers/trading.js @@ -19,8 +19,7 @@ const trade = async (req, res) => { if (!canUserTrade) { return res.boom.forbidden(errorMessage); } - - return res.json({ userBalance }); + return res.json({ message: "Congrats, Stock Trade done successfully!! 🎉🎉🎉🎊🎊🎊", userBalance }); } catch (err) { logger.error(`Error during trading: ${err}`); return res.boom.badImplementation(INTERNAL_SERVER_ERROR); diff --git a/routes/trading.ts b/routes/trading.ts index 293a3fd36..7dc7a6ecb 100644 --- a/routes/trading.ts +++ b/routes/trading.ts @@ -3,7 +3,10 @@ const router = express.Router(); import authenticate from "../middlewares/authenticate"; import { newTrade } from "../middlewares/validators/trading"; import { trade } from "../controllers/trading"; +import { devFlagMiddleware } from "../middlewares/devFlag"; +import { userAuthorization } from "../middlewares/userAuthorization"; -router.post("/stock/new/self", authenticate, newTrade, trade); +router.post("/stock/new/self", authenticate, newTrade, trade); // this route is being deprecated, please use new available route `/stock/new/:userId` +router.post("/stock/new/:userId", devFlagMiddleware, authenticate, userAuthorization, newTrade, trade); module.exports = router; diff --git a/test/integration/trading.test.ts b/test/integration/trading.test.ts new file mode 100644 index 000000000..44ee36274 --- /dev/null +++ b/test/integration/trading.test.ts @@ -0,0 +1,120 @@ +import chai from "chai"; +import chaiHttp from "chai-http"; +import app from "../../server"; +import authService from "../../services/authService"; +import addUser from "../utils/addUser"; +import cleanDb from "../utils/cleanDb"; +import stocks from "../../models/stocks"; +import wallet from "../../models/wallets"; +import sinon from "sinon"; +import config from "config"; +import currencies from "../fixtures/currencies/currencies"; +import tradeService from "../../services/tradingService"; + +const cookieName: string = config.get("userToken.cookieName"); +chai.use(chaiHttp); +const { expect } = chai; + +describe("POST /trade/stock/new/:userId", function () { + let jwt: string; + let userId: string; + let userStock; + const newStockData = { name: "DINERO", quantity: 20000, price: 2 }; + let id; + let stockData; + + beforeEach(async function () { + userId = await addUser(); + jwt = authService.generateAuthToken({ userId }); + ({ id, stockData } = await stocks.addStock(newStockData)); + await wallet.createWallet(userId, currencies.default); + userStock = { + stockId: id, + stockName: stockData.name, + tradeType: "BUY", + quantity: 1, + listedPrice: stockData.price, + totalPrice: 1 * stockData.price, + }; + }); + + afterEach(async function () { + await cleanDb(); + sinon.restore(); + }); + + it("Should return success when trade is completed", function (done) { + chai + .request(app) + .post(`/trade/stock/new/${userId}?dev=true`) + .set("cookie", `${cookieName}=${jwt}`) + .send(userStock) + .end((err, res) => { + if (err) return done(err); + + expect(res).to.have.status(200); + expect(res.body).to.be.an("object"); + expect(res.body.message).to.equal("Congrats, Stock Trade done successfully!! 🎉🎉🎉🎊🎊🎊"); + expect(res.body.userBalance).to.be.a("number"); + return done(); + }); + }); + + it("Should return trade unsuccessful due to insufficient funds", function (done) { + userStock.tradeType = "BUY"; + userStock.quantity = 2000; + userStock.totalPrice = 2000 * stockData.price; + + chai + .request(app) + .post(`/trade/stock/new/${userId}?dev=true`) + .set("cookie", `${cookieName}=${jwt}`) + .send(userStock) + .end((err, res) => { + if (err) return done(err); + + expect(res).to.have.status(403); + expect(res.body).to.be.an("object"); + expect(res.body.message).to.equal("Trade was not successful due to insufficient funds"); + return done(); + }); + }); + + it("Should return trade unsuccessful due to insufficient stock quantity", function (done) { + userStock.tradeType = "SELL"; + userStock.quantity = 20001; + userStock.totalPrice = 20001 * stockData.price; + + chai + .request(app) + .post(`/trade/stock/new/${userId}?dev=true`) + .set("cookie", `${cookieName}=${jwt}`) + .send(userStock) + .end((err, res) => { + if (err) return done(err); + + expect(res).to.have.status(403); + expect(res.body).to.be.an("object"); + expect(res.body.message).to.equal("Trade was not successful because you do not have enough quantity"); + return done(); + }); + }); + + it("Should return 500 when an internal server error occurs", function (done) { + sinon.stub(tradeService, "trade").throws(new Error("Database error")); + + chai + .request(app) + .post(`/trade/stock/new/${userId}?dev=true`) + .set("cookie", `${cookieName}=${jwt}`) + .send(userStock) + .end((err, res) => { + if (err) return done(err); + + expect(res).to.have.status(500); + expect(res.body).to.be.an("object"); + expect(res.body.message).to.equal("An internal server error occurred"); + return done(); + }); + }); +});