From 53606c306d35003f1722e6ea59008b514fd9c175 Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Fri, 1 Mar 2024 14:21:41 +0100 Subject: [PATCH] feat: Implement get apps API endpoint --- .../src/controllers/api/v1/apps/get-apps.js | 16 +++++ .../controllers/api/v1/apps/get-apps.test.js | 63 +++++++++++++++++++ packages/backend/src/routes/api/v1/apps.js | 2 + .../test/mocks/rest/api/v1/apps/get-apps.js | 23 +++++++ 4 files changed, 104 insertions(+) create mode 100644 packages/backend/src/controllers/api/v1/apps/get-apps.js create mode 100644 packages/backend/src/controllers/api/v1/apps/get-apps.test.js create mode 100644 packages/backend/test/mocks/rest/api/v1/apps/get-apps.js diff --git a/packages/backend/src/controllers/api/v1/apps/get-apps.js b/packages/backend/src/controllers/api/v1/apps/get-apps.js new file mode 100644 index 00000000..be6e112e --- /dev/null +++ b/packages/backend/src/controllers/api/v1/apps/get-apps.js @@ -0,0 +1,16 @@ +import App from '../../../../models/app.js'; +import { renderObject } from '../../../../helpers/renderer.js'; + +export default async (request, response) => { + let apps = await App.findAll(request.query.name); + + if (request.query.onlyWithTriggers) { + apps = apps.filter((app) => app.triggers?.length); + } + + if (request.query.onlyWithActions) { + apps = apps.filter((app) => app.actions?.length); + } + + renderObject(response, apps, { serializer: 'App' }); +}; diff --git a/packages/backend/src/controllers/api/v1/apps/get-apps.test.js b/packages/backend/src/controllers/api/v1/apps/get-apps.test.js new file mode 100644 index 00000000..a7a39e7b --- /dev/null +++ b/packages/backend/src/controllers/api/v1/apps/get-apps.test.js @@ -0,0 +1,63 @@ +import { describe, it, expect, beforeEach } from 'vitest'; +import request from 'supertest'; +import App from '../../../../models/app'; +import app from '../../../../app.js'; +import createAuthTokenByUserId from '../../../../helpers/create-auth-token-by-user-id'; +import { createUser } from '../../../../../test/factories/user'; +import getAppsMock from '../../../../../test/mocks/rest/api/v1/apps/get-apps.js'; + +describe('GET /api/v1/apps', () => { + let currentUser, apps, token; + + beforeEach(async () => { + currentUser = await createUser(); + token = createAuthTokenByUserId(currentUser.id); + apps = await App.findAll(); + }); + + it('should return all apps', async () => { + const response = await request(app) + .get('/api/v1/apps') + .set('Authorization', token) + .expect(200); + + const expectedPayload = getAppsMock(apps); + expect(response.body).toEqual(expectedPayload); + }); + + it('should return all apps filtered by name', async () => { + const appsWithNameGit = apps.filter((app) => app.name.includes('Git')); + + const response = await request(app) + .get('/api/v1/apps?name=Git') + .set('Authorization', token) + .expect(200); + + const expectedPayload = getAppsMock(appsWithNameGit); + expect(response.body).toEqual(expectedPayload); + }); + + it('should return only the apps with triggers', async () => { + const appsWithTriggers = apps.filter((app) => app.triggers?.length > 0); + + const response = await request(app) + .get('/api/v1/apps?onlyWithTriggers=true') + .set('Authorization', token) + .expect(200); + + const expectedPayload = getAppsMock(appsWithTriggers); + expect(response.body).toEqual(expectedPayload); + }); + + it('should return only the apps with actions', async () => { + const appsWithActions = apps.filter((app) => app.actions?.length > 0); + + const response = await request(app) + .get('/api/v1/apps?onlyWithActions=true') + .set('Authorization', token) + .expect(200); + + const expectedPayload = getAppsMock(appsWithActions); + expect(response.body).toEqual(expectedPayload); + }); +}); diff --git a/packages/backend/src/routes/api/v1/apps.js b/packages/backend/src/routes/api/v1/apps.js index 2f696bb1..ef69b97e 100644 --- a/packages/backend/src/routes/api/v1/apps.js +++ b/packages/backend/src/routes/api/v1/apps.js @@ -2,10 +2,12 @@ import { Router } from 'express'; import asyncHandler from 'express-async-handler'; import { authenticateUser } from '../../../helpers/authentication.js'; import getAppAction from '../../../controllers/api/v1/apps/get-app.js'; +import getAppsAction from '../../../controllers/api/v1/apps/get-apps.js'; import getAuthAction from '../../../controllers/api/v1/apps/get-auth.js'; const router = Router(); +router.get('/', authenticateUser, asyncHandler(getAppsAction)); router.get('/:appKey', authenticateUser, asyncHandler(getAppAction)); router.get('/:appKey/auth', authenticateUser, asyncHandler(getAuthAction)); diff --git a/packages/backend/test/mocks/rest/api/v1/apps/get-apps.js b/packages/backend/test/mocks/rest/api/v1/apps/get-apps.js new file mode 100644 index 00000000..a097d1f2 --- /dev/null +++ b/packages/backend/test/mocks/rest/api/v1/apps/get-apps.js @@ -0,0 +1,23 @@ +const getAppsMock = (apps) => { + const appsData = apps.map((app) => ({ + authDocUrl: app.authDocUrl, + iconUrl: app.iconUrl, + key: app.key, + name: app.name, + primaryColor: app.primaryColor, + supportsConnections: app.supportsConnections, + })); + + return { + data: appsData, + meta: { + count: appsData.length, + currentPage: null, + isArray: true, + totalPages: null, + type: 'Object', + }, + }; +}; + +export default getAppsMock;