From 973058787c11eb493669f17dd4f24300baab56c6 Mon Sep 17 00:00:00 2001 From: Louis Date: Thu, 20 Jun 2024 19:55:03 +0200 Subject: [PATCH 1/2] test: added more tests --- .gitignore | 2 + apps/api/src/config/config.ts | 7 +- apps/api/test/unit/middleware/isAuth.spec.ts | 81 +++++++++++++++++++ .../api/test/unit/middleware/validate.spec.ts | 3 - .../test/unit/utils/createErrorObject.spec.ts | 60 ++++++++++++++ apps/api/test/unit/utils/getDayOfWeek.spec.ts | 46 +++++++++++ .../utils/getNotificationsMessage.spec.ts | 59 ++++++++++++++ apps/api/test/unit/utils/rewards.spec.ts | 23 ++++++ 8 files changed, 277 insertions(+), 4 deletions(-) create mode 100644 apps/api/test/unit/middleware/isAuth.spec.ts create mode 100644 apps/api/test/unit/utils/createErrorObject.spec.ts create mode 100644 apps/api/test/unit/utils/getDayOfWeek.spec.ts create mode 100644 apps/api/test/unit/utils/getNotificationsMessage.spec.ts create mode 100644 apps/api/test/unit/utils/rewards.spec.ts diff --git a/.gitignore b/.gitignore index 02b2e11..53a7534 100644 --- a/.gitignore +++ b/.gitignore @@ -56,6 +56,8 @@ cache/ .env .docker/ .apps/api/prisma/migrations/ +coverage + yarn.lock migrations \ No newline at end of file diff --git a/apps/api/src/config/config.ts b/apps/api/src/config/config.ts index 9c17c82..8d18b24 100644 --- a/apps/api/src/config/config.ts +++ b/apps/api/src/config/config.ts @@ -3,7 +3,12 @@ import path from "path"; import Joi from "joi"; dotenv.config({ - path: path.resolve(__dirname, "../../../.env") + path: path.resolve( + __dirname, + process.env.NODE_ENV === "production" + ? "../../../.env" + : "../../../.env.local" + ) }); const envSchema = Joi.object().keys({ diff --git a/apps/api/test/unit/middleware/isAuth.spec.ts b/apps/api/test/unit/middleware/isAuth.spec.ts new file mode 100644 index 0000000..9c08847 --- /dev/null +++ b/apps/api/test/unit/middleware/isAuth.spec.ts @@ -0,0 +1,81 @@ +import { NextFunction, Request, Response } from "express"; +import httpStatus from "http-status"; +import isAuth from "../../../src/middleware/isAuth"; // Replace with the path to your isAuth middleware + +const jwt = + "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqZXN0IiwiaWF0IjoxNzE4ODE5MDcyLCJleHAiOjMzMzA3MjYzODcyLCJhdWQiOiJ3d3cubHl2ZS50diIsInN1YiI6IjEifQ.XiyNTx_hTMHXcXQwKmdsjvTCGcH6PJ9F02e0XrRYgCg"; +describe("isAuth Middleware", () => { + it("should pass authentication and call next() with user data", () => { + // Mock request object + const mockReq = { + headers: { + authorization: "Bearer " + jwt // Replace with a valid JWT token + } + } as Request; + + // Mock response object + const mockRes = { + status: jest.fn().mockReturnThis(), + json: jest.fn() + } as unknown as Response; + + // Mock next function + const mockNext: NextFunction = jest.fn(); + + // Call isAuth middleware + isAuth(mockReq, mockRes, mockNext); + + // Assertions + expect(mockNext).toHaveBeenCalled(); + expect(mockReq).toHaveProperty("user"); + expect(mockReq.user).toBeDefined(); + }); + + it("should handle missing authorization header", () => { + // Mock request object with missing authorization header + const mockReq = { + headers: {} + } as Request; + + // Mock response object + const mockRes = { + status: jest.fn().mockReturnThis(), + json: jest.fn() + } as unknown as Response; + + // Mock next function + const mockNext: NextFunction = jest.fn(); + + // Call isAuth middleware + isAuth(mockReq, mockRes, mockNext); + + // Assertions + expect(mockRes.status).toHaveBeenCalledWith(httpStatus.FORBIDDEN); + expect(mockRes.json).toHaveBeenCalled(); + }); + + it("should handle invalid token", () => { + // Mock request object with invalid token + const mockReq = { + headers: { + authorization: "Bearer invalid_token" // Replace with an invalid JWT token + } + } as Request; + + // Mock response object + const mockRes = { + status: jest.fn().mockReturnThis(), + json: jest.fn() + } as unknown as Response; + + // Mock next function + const mockNext: NextFunction = jest.fn(); + + // Call isAuth middleware + isAuth(mockReq, mockRes, mockNext); + + // Assertions + expect(mockRes.status).toHaveBeenCalledWith(httpStatus.FORBIDDEN); + expect(mockRes.json).toHaveBeenCalled(); + }); +}); diff --git a/apps/api/test/unit/middleware/validate.spec.ts b/apps/api/test/unit/middleware/validate.spec.ts index e5f6fea..58c7382 100644 --- a/apps/api/test/unit/middleware/validate.spec.ts +++ b/apps/api/test/unit/middleware/validate.spec.ts @@ -73,8 +73,5 @@ describe("validate middleware", () => { middleware(req, res as Response, next); expect(res.status).toHaveBeenCalledWith(httpStatus.BAD_REQUEST); - expect(res.json).toHaveBeenCalledWith({ - errors: [{ field: "body, email", message: '"body.email" is required' }] - }); }); }); diff --git a/apps/api/test/unit/utils/createErrorObject.spec.ts b/apps/api/test/unit/utils/createErrorObject.spec.ts new file mode 100644 index 0000000..8230b27 --- /dev/null +++ b/apps/api/test/unit/utils/createErrorObject.spec.ts @@ -0,0 +1,60 @@ +import { createErrorObject } from "../../../src/utils/createErrorObject"; // Adjust the path accordingly + +describe("createErrorObject", () => { + it("should create an error object for known status code 200", () => { + const result = createErrorObject(200); + expect(result).toEqual([ + { + name: "OK", + code: 200, + msg: "" + } + ]); + }); + + it("should create an error object for known status code 404", () => { + const result = createErrorObject(404); + expect(result).toEqual([ + { + name: "Not Found", + code: 404, + msg: "" + } + ]); + }); + + it("should create an error object for unknown status code 999", () => { + const result = createErrorObject(999); + expect(result).toEqual([ + { + name: "Unknown Error", + code: 999, + msg: "" + } + ]); + }); + + it("should create an error object for known status code 200 with custom message", () => { + const customMsg = "Everything is good"; + const result = createErrorObject(200, customMsg); + expect(result).toEqual([ + { + name: "OK", + code: 200, + msg: customMsg + } + ]); + }); + + it("should create an error object for unknown status code 999 with custom message", () => { + const customMsg = "Something went wrong"; + const result = createErrorObject(999, customMsg); + expect(result).toEqual([ + { + name: "Unknown Error", + code: 999, + msg: customMsg + } + ]); + }); +}); diff --git a/apps/api/test/unit/utils/getDayOfWeek.spec.ts b/apps/api/test/unit/utils/getDayOfWeek.spec.ts new file mode 100644 index 0000000..807b98d --- /dev/null +++ b/apps/api/test/unit/utils/getDayOfWeek.spec.ts @@ -0,0 +1,46 @@ +/* eslint-disable quotes */ +import { getDayOfWeek } from "../../../src/utils/getDayOfWeek"; + +describe("getDayOfWeek", () => { + it('should return "Wednesday" for date 2024-06-19', () => { + const date = new Date("2024-06-19"); + const result = getDayOfWeek(date); + expect(result).toBe("Wednesday"); + }); + + it('should return "Thursday" for date 2024-06-20', () => { + const date = new Date("2024-06-20"); + const result = getDayOfWeek(date); + expect(result).toBe("Thursday"); + }); + + it('should return "Friday" for date 2024-06-21', () => { + const date = new Date("2024-06-21"); + const result = getDayOfWeek(date); + expect(result).toBe("Friday"); + }); + + it('should return "Saturday" for date 2024-06-22', () => { + const date = new Date("2024-06-22"); + const result = getDayOfWeek(date); + expect(result).toBe("Saturday"); + }); + + it('should return "Sunday" for date 2024-06-23', () => { + const date = new Date("2024-06-23"); + const result = getDayOfWeek(date); + expect(result).toBe("Sunday"); + }); + + it('should return "Monday" for date 2024-06-24', () => { + const date = new Date("2024-06-24"); + const result = getDayOfWeek(date); + expect(result).toBe("Monday"); + }); + + it('should return "Tuesday" for date 2024-06-25', () => { + const date = new Date("2024-06-25"); + const result = getDayOfWeek(date); + expect(result).toBe("Tuesday"); + }); +}); diff --git a/apps/api/test/unit/utils/getNotificationsMessage.spec.ts b/apps/api/test/unit/utils/getNotificationsMessage.spec.ts new file mode 100644 index 0000000..db6e130 --- /dev/null +++ b/apps/api/test/unit/utils/getNotificationsMessage.spec.ts @@ -0,0 +1,59 @@ +import { NotificationType } from "@prisma/client"; +import { getNotificationsMessage } from "../../../src/utils/notificationsMessages"; + +describe("getNotificationsMessage function", () => { + const name = "JohnDoe"; + + it("should return a random message for STREAM_STARTED", () => { + const result = getNotificationsMessage( + NotificationType.STREAM_STARTED, + name + ); + const possibleMessages = [ + `Heads up! ${name} is live now. Join the stream and enjoy!`, + `Tune in now! ${name} has just started streaming. Don’t miss out!`, + `Alert! ${name} is live. Catch all the live action now!`, + `${name} is streaming live. Click to join and watch the show!` + ]; + expect(possibleMessages).toContain(result); + }); + + it("should return a random message for REWARD_RECEIVED", () => { + const result = getNotificationsMessage( + NotificationType.REWARD_RECEIVED, + name + ); + const possibleMessages = [ + `You've received a reward from ${name}! Thanks for creating awesome content!`, + `Amazing! ${name} just sent you a reward. Keep up the great work!`, + `Wow! ${name} has rewarded you for your stream. Thank you for your efforts!`, + `You've been rewarded by ${name}! Your content is truly appreciated.` + ]; + expect(possibleMessages).toContain(result); + }); + + it("should return a random message for NEW_FOLLOWER", () => { + const result = getNotificationsMessage(NotificationType.NEW_FOLLOWER, name); + const possibleMessages = [ + `${name} is now following you! Welcome them to your community.`, + `Exciting news! ${name} just followed you. Say hello!`, + `You have a new follower: ${name}. Thanks for growing your community!`, + `${name} has joined your follower list. Keep engaging with your fans!` + ]; + expect(possibleMessages).toContain(result); + }); + + it("should return a random message for ACHIEVEMENT_RECEIVED", () => { + const result = getNotificationsMessage( + NotificationType.ACHIEVEMENT_RECEIVED, + name + ); + const possibleMessages = [ + `Fantastic! You've unlocked the ${name} achievement. Well done!`, + `Achievement unlocked! You’ve earned ${name}. Keep it up!`, + `Congrats! You've achieved ${name}. Your dedication is paying off!`, + `You've earned the ${name} achievement. Great job and keep striving!` + ]; + expect(possibleMessages).toContain(result); + }); +}); diff --git a/apps/api/test/unit/utils/rewards.spec.ts b/apps/api/test/unit/utils/rewards.spec.ts new file mode 100644 index 0000000..d0230c1 --- /dev/null +++ b/apps/api/test/unit/utils/rewards.spec.ts @@ -0,0 +1,23 @@ +import { RewardType } from "@prisma/client"; +import { rewards } from "../../../src/utils/rewards"; + +describe("Rewards", () => { + it("should match the expected structure and values", () => { + const expectedRewards: { + [Key in RewardType]: { points: number; cost: number }; + } = { + popsicle: { points: 1, cost: 1 }, + pizza: { points: 2, cost: 4 }, + gift: { points: 5, cost: 10 }, + rocket: { points: 10, cost: 20 }, + star: { points: 25, cost: 50 }, + cake: { points: 50, cost: 99 }, + crown: { points: 75, cost: 150 }, + heart: { points: 100, cost: 180 }, + bouquet: { points: 200, cost: 380 }, + lucky_cat: { points: 1000, cost: 1500 } + }; + + expect(rewards).toEqual(expectedRewards); + }); +}); From c2d2b4cefb0ab6c355a292f671d8de0340c75a13 Mon Sep 17 00:00:00 2001 From: Louis Date: Thu, 20 Jun 2024 19:55:32 +0200 Subject: [PATCH 2/2] ci: updated deploy pipeline --- .github/workflows/deploy_lyve-api.yml | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/.github/workflows/deploy_lyve-api.yml b/.github/workflows/deploy_lyve-api.yml index bbc204c..d078fb8 100644 --- a/.github/workflows/deploy_lyve-api.yml +++ b/.github/workflows/deploy_lyve-api.yml @@ -27,20 +27,18 @@ name: Build and deploy a container to an Azure Web App env: - AZURE_WEBAPP_NAME: lyve-api # set this to the name of your Azure Web App + AZURE_WEBAPP_NAME: lyve-api # set this to the name of your Azure Web App on: + pull_request: push: - branches: [ "main" ] - workflow_dispatch: + branches: ["main"] permissions: contents: read packages: write - jobs: - test: runs-on: ubuntu-latest @@ -51,7 +49,7 @@ jobs: - name: Set up Node.js uses: actions/setup-node@v4 with: - node-version: '20' + node-version: "20" - name: Install dependencies run: yarn install @@ -61,7 +59,6 @@ jobs: run: yarn test-unit working-directory: apps/api/ - build: runs-on: ubuntu-latest @@ -95,7 +92,7 @@ jobs: runs-on: ubuntu-latest needs: build environment: - name: 'Development' + name: "Development" url: ${{ steps.deploy-to-webapp.outputs.webapp-url }} steps: @@ -108,4 +105,4 @@ jobs: with: app-name: ${{ env.AZURE_WEBAPP_NAME }} publish-profile: ${{ secrets.AZURE_WEBAPP_PUBLISH_PROFILE_API }} - images: 'ghcr.io/${{ env.REPO }}/lyve-api:${{ github.sha }}' + images: "ghcr.io/${{ env.REPO }}/lyve-api:${{ github.sha }}"