From 58febdfa161848a0a63fd23a13c165e0dcd5a255 Mon Sep 17 00:00:00 2001 From: MayankJha014 Date: Tue, 25 Feb 2025 01:14:26 +0530 Subject: [PATCH 01/17] Plugin store data --- .../services/Plugin.helper/classes/default.md | 2 +- .../interfaces/InterfacePluginHelper.md | 16 ++++++++-------- schema.graphql | 2 +- src/GraphQl/Queries/PlugInQueries.ts | 2 +- .../AddOn/core/AddOnStore/AddOnStore.tsx | 18 ++++++++++++++---- .../AddOn/support/services/Plugin.helper.ts | 4 +++- src/types/AddOn/interface.ts | 2 +- 7 files changed, 29 insertions(+), 17 deletions(-) diff --git a/docs/docs/auto-docs/components/AddOn/support/services/Plugin.helper/classes/default.md b/docs/docs/auto-docs/components/AddOn/support/services/Plugin.helper/classes/default.md index 28fa9d3a9a..9859265f54 100644 --- a/docs/docs/auto-docs/components/AddOn/support/services/Plugin.helper/classes/default.md +++ b/docs/docs/auto-docs/components/AddOn/support/services/Plugin.helper/classes/default.md @@ -56,7 +56,7 @@ A promise that resolves to the store data in JSON format. > **generateLinks**(`plugins`): `object`[] -Defined in: [src/components/AddOn/support/services/Plugin.helper.ts:32](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/components/AddOn/support/services/Plugin.helper.ts#L32) +Defined in: [src/components/AddOn/support/services/Plugin.helper.ts:34](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/components/AddOn/support/services/Plugin.helper.ts#L34) Generates an array of links for the enabled plugins. diff --git a/docs/docs/auto-docs/types/AddOn/interface/interfaces/InterfacePluginHelper.md b/docs/docs/auto-docs/types/AddOn/interface/interfaces/InterfacePluginHelper.md index 16105f0776..49b30db4e4 100644 --- a/docs/docs/auto-docs/types/AddOn/interface/interfaces/InterfacePluginHelper.md +++ b/docs/docs/auto-docs/types/AddOn/interface/interfaces/InterfacePluginHelper.md @@ -8,14 +8,6 @@ Defined in: [src/types/AddOn/interface.ts:33](https://github.com/PalisadoesFound ## Properties -### \_id - -> **\_id**: `string` - -Defined in: [src/types/AddOn/interface.ts:34](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/types/AddOn/interface.ts#L34) - -*** - ### component > **component**: `string` @@ -32,6 +24,14 @@ Defined in: [src/types/AddOn/interface.ts:41](https://github.com/PalisadoesFound *** +### id + +> **id**: `string` + +Defined in: [src/types/AddOn/interface.ts:34](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/types/AddOn/interface.ts#L34) + +*** + ### installed > **installed**: `boolean` diff --git a/schema.graphql b/schema.graphql index 81f683c99d..5d920ccb06 100644 --- a/schema.graphql +++ b/schema.graphql @@ -1811,7 +1811,7 @@ enum PaginationDirection { scalar PhoneNumber type Plugin { - _id: ID! + id: ID! pluginCreatedBy: String! pluginDesc: String! pluginName: String! diff --git a/src/GraphQl/Queries/PlugInQueries.ts b/src/GraphQl/Queries/PlugInQueries.ts index 346fb712f3..f96cf0916c 100644 --- a/src/GraphQl/Queries/PlugInQueries.ts +++ b/src/GraphQl/Queries/PlugInQueries.ts @@ -9,7 +9,7 @@ import gql from 'graphql-tag'; export const PLUGIN_GET = gql` query getPluginList { getPlugins { - _id + id pluginName pluginCreatedBy pluginDesc diff --git a/src/components/AddOn/core/AddOnStore/AddOnStore.tsx b/src/components/AddOn/core/AddOnStore/AddOnStore.tsx index 24c9012461..9e1cb6550b 100644 --- a/src/components/AddOn/core/AddOnStore/AddOnStore.tsx +++ b/src/components/AddOn/core/AddOnStore/AddOnStore.tsx @@ -35,20 +35,27 @@ function addOnStore(): JSX.Element { PLUGIN_GET, ); + console.log(data); + const { orgId } = useParams<{ orgId: string }>(); /** * Fetches store plugins and updates the Redux store with the plugin data. */ const getStorePlugins = async (): Promise => { + console.log('Entered in getStorePlugins'); let plugins = await new PluginHelper().fetchStore(); + + console.log('get Store plugins is called : ', plugins); + const installIds = (await new PluginHelper().fetchInstalled()).map( - (plugin: InterfacePluginHelper) => plugin._id, + (plugin: InterfacePluginHelper) => plugin.id, ); plugins = plugins.map((plugin: InterfacePluginHelper) => { - plugin.installed = installIds.includes(plugin._id); + plugin.installed = installIds.includes(plugin.id); return plugin; }); + store.dispatch({ type: 'UPDATE_STORE', payload: plugins }); }; @@ -66,6 +73,7 @@ function addOnStore(): JSX.Element { */ const updateSelectedTab = (tab: string): void => { setIsStore(tab === 'available'); + console.log(tab); if (tab === 'available') { getStorePlugins(); } else { @@ -79,6 +87,7 @@ function addOnStore(): JSX.Element { * @param ev - The event object from the filter change. */ const filterChange = (ev: React.ChangeEvent): void => { + console.log(ev.target.value); setShowEnabled(ev.target.value === 'enabled'); }; @@ -86,6 +95,7 @@ function addOnStore(): JSX.Element { plugins: InterfacePluginHelper[], searchTerm: string, ): InterfacePluginHelper[] => { + console.log('Plugin is triggered: ', plugins); if (!searchTerm) { return plugins; } @@ -172,7 +182,7 @@ function addOnStore(): JSX.Element { {filteredPlugins.map((plug, i) => (
(
=> { - const result = await fetch(`http://localhost:3005/installed`); + const result = await fetch( + `http://localhost:${process.env.PORT}/installed`, + ); return await result.json(); }; diff --git a/src/types/AddOn/interface.ts b/src/types/AddOn/interface.ts index 1a727aa316..bd13cc2471 100644 --- a/src/types/AddOn/interface.ts +++ b/src/types/AddOn/interface.ts @@ -31,7 +31,7 @@ export interface InterfaceAddOnRegisterProps { } export interface InterfacePluginHelper { - _id: string; + id: string; pluginName?: string; pluginDesc?: string; pluginCreatedBy: string; From b6bf93b7fdeb568180d2a9c358e952f49ac2655f Mon Sep 17 00:00:00 2001 From: MayankJha014 Date: Wed, 26 Feb 2025 01:15:11 +0530 Subject: [PATCH 02/17] handling plugin store --- .../variables/UPDATE_ORG_STATUS_PLUGIN_MUTATION.md | 2 +- src/GraphQl/Mutations/mutations.ts | 14 +++++++------- .../AddOn/core/AddOnEntry/AddOnEntry.tsx | 2 +- .../AddOn/core/AddOnStore/AddOnStore.tsx | 2 ++ 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/docs/docs/auto-docs/GraphQl/Mutations/mutations/variables/UPDATE_ORG_STATUS_PLUGIN_MUTATION.md b/docs/docs/auto-docs/GraphQl/Mutations/mutations/variables/UPDATE_ORG_STATUS_PLUGIN_MUTATION.md index c322e4dc66..f2f4253469 100644 --- a/docs/docs/auto-docs/GraphQl/Mutations/mutations/variables/UPDATE_ORG_STATUS_PLUGIN_MUTATION.md +++ b/docs/docs/auto-docs/GraphQl/Mutations/mutations/variables/UPDATE_ORG_STATUS_PLUGIN_MUTATION.md @@ -10,4 +10,4 @@ Defined in: [src/GraphQl/Mutations/mutations.ts:463](https://github.com/Palisado ## Remarks -used `updatePluginStatus`to add or remove the current Organization the in the plugin list `uninstalledOrgs` +Used `updatePluginStatus` to add or remove the current organization in the plugin list `uninstalledOrgs`. diff --git a/src/GraphQl/Mutations/mutations.ts b/src/GraphQl/Mutations/mutations.ts index c076b74720..89bd142e20 100644 --- a/src/GraphQl/Mutations/mutations.ts +++ b/src/GraphQl/Mutations/mutations.ts @@ -444,9 +444,9 @@ export const FORGOT_PASSWORD_MUTATION = gql` * used to toggle `installStatus` (boolean value) of a Plugin */ export const UPDATE_INSTALL_STATUS_PLUGIN_MUTATION = gql` - mutation ($id: ID!, $orgId: ID!) { - updatePluginStatus(id: $id, orgId: $orgId) { - _id + mutation ($pluginId: String!, $orgId: String!) { + updatePluginStatus(pluginId: $pluginId, orgId: $orgId) { + id pluginName pluginCreatedBy pluginDesc @@ -458,12 +458,12 @@ export const UPDATE_INSTALL_STATUS_PLUGIN_MUTATION = gql` /** * {@label UPDATE_ORG_STATUS_PLUGIN_MUTATION} * @remarks - * used `updatePluginStatus`to add or remove the current Organization the in the plugin list `uninstalledOrgs` + * Used `updatePluginStatus` to add or remove the current organization in the plugin list `uninstalledOrgs`. */ export const UPDATE_ORG_STATUS_PLUGIN_MUTATION = gql` - mutation update_install_status_plugin_mutation($id: ID!, $orgId: ID!) { - updatePluginStatus(id: $id, orgId: $orgId) { - _id + mutation updateOrgStatusPluginMutation($pluginId: String!, $orgId: String!) { + updatePluginStatus(pluginId: $pluginId, orgId: $orgId) { + id pluginName pluginCreatedBy pluginDesc diff --git a/src/components/AddOn/core/AddOnEntry/AddOnEntry.tsx b/src/components/AddOn/core/AddOnEntry/AddOnEntry.tsx index 93a9dc2ed8..99a0b692ec 100644 --- a/src/components/AddOn/core/AddOnEntry/AddOnEntry.tsx +++ b/src/components/AddOn/core/AddOnEntry/AddOnEntry.tsx @@ -87,7 +87,7 @@ function addOnEntry({ setButtonLoading(true); await addOrgAsUninstalled({ variables: { - id: id.toString(), + pluginId: id.toString(), orgId: currentOrg.toString(), }, }); diff --git a/src/components/AddOn/core/AddOnStore/AddOnStore.tsx b/src/components/AddOn/core/AddOnStore/AddOnStore.tsx index 9e1cb6550b..6a1b843b13 100644 --- a/src/components/AddOn/core/AddOnStore/AddOnStore.tsx +++ b/src/components/AddOn/core/AddOnStore/AddOnStore.tsx @@ -51,6 +51,8 @@ function addOnStore(): JSX.Element { const installIds = (await new PluginHelper().fetchInstalled()).map( (plugin: InterfacePluginHelper) => plugin.id, ); + + console.log('get Installed plugins is called : ', installIds); plugins = plugins.map((plugin: InterfacePluginHelper) => { plugin.installed = installIds.includes(plugin.id); return plugin; From 545fb11b322f80cdbb2adf6ab8561b2569e04ee0 Mon Sep 17 00:00:00 2001 From: MayankJha014 Date: Wed, 26 Feb 2025 01:24:08 +0530 Subject: [PATCH 03/17] Removing console log --- src/components/AddOn/core/AddOnStore/AddOnStore.tsx | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/components/AddOn/core/AddOnStore/AddOnStore.tsx b/src/components/AddOn/core/AddOnStore/AddOnStore.tsx index 6a1b843b13..fb96f7f940 100644 --- a/src/components/AddOn/core/AddOnStore/AddOnStore.tsx +++ b/src/components/AddOn/core/AddOnStore/AddOnStore.tsx @@ -35,8 +35,6 @@ function addOnStore(): JSX.Element { PLUGIN_GET, ); - console.log(data); - const { orgId } = useParams<{ orgId: string }>(); /** @@ -46,13 +44,10 @@ function addOnStore(): JSX.Element { console.log('Entered in getStorePlugins'); let plugins = await new PluginHelper().fetchStore(); - console.log('get Store plugins is called : ', plugins); - const installIds = (await new PluginHelper().fetchInstalled()).map( (plugin: InterfacePluginHelper) => plugin.id, ); - console.log('get Installed plugins is called : ', installIds); plugins = plugins.map((plugin: InterfacePluginHelper) => { plugin.installed = installIds.includes(plugin.id); return plugin; @@ -75,7 +70,6 @@ function addOnStore(): JSX.Element { */ const updateSelectedTab = (tab: string): void => { setIsStore(tab === 'available'); - console.log(tab); if (tab === 'available') { getStorePlugins(); } else { @@ -89,7 +83,6 @@ function addOnStore(): JSX.Element { * @param ev - The event object from the filter change. */ const filterChange = (ev: React.ChangeEvent): void => { - console.log(ev.target.value); setShowEnabled(ev.target.value === 'enabled'); }; From e3a2f1f120191dc20a72776ff11ef089a213040a Mon Sep 17 00:00:00 2001 From: DangaRanga Date: Sun, 23 May 2021 12:22:05 -0500 Subject: [PATCH 04/17] Removed duplicate entry --- CONTRIBUTING.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1f68ebef12..bd17745a30 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -83,8 +83,6 @@ When multiple developers are working on issues there is bound to be a conflict o - Last but not the least, communication is important make sure to talk to other contributors, in these cases, in slack channel or in a issue/PR thread. - As a last resort the Admins would be responsible for deciding how to resolve this conflict. -### Contributing Code - Code contributions to Talawa come in the form of pull requests. These are done by forking the repo and making changes locally. Make sure you have read the [Documentation for Setting up the Project](https://github.com/PalisadoesFoundation/talawa-admin#project-setup) From 293da110713d07f70823039201d48f934cba2303 Mon Sep 17 00:00:00 2001 From: MayankJha014 Date: Wed, 26 Feb 2025 01:26:51 +0530 Subject: [PATCH 05/17] Removing console log --- CONTRIBUTING.md | 200 +++++++++++++++++++++++++----------------------- 1 file changed, 103 insertions(+), 97 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index bd17745a30..5bdbd6769a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -16,7 +16,6 @@ If you are new to contributing to open source, please read the Open Source Guide - [Pull Requests](#pull-requests) - [Branching Strategy](#branching-strategy) - [Conflict Resolution](#conflict-resolution) - - [Contributing Code](#contributing-code) - [General:](#general) - [Testing:](#testing) - [Jest Testing](#jest-testing) @@ -69,7 +68,7 @@ Make sure you are following [issue report guidelines](ISSUE_GUIDELINES.md) avail #### Branching Strategy -For Talawa Admin, we had employed the following branching strategy to simplify the development process and to ensure that only stable code is pushed to the `main` branch: +For Talawa Admin, we had employed the following branching strategy to simplify the development process and to ensure that only stable code is pushed to the `master` branch: - `develop`: For unstable code and bug fixing - `main`: Where the stable production ready code lies. This is our default branch. @@ -98,105 +97,112 @@ The process of proposing a change to Talawa Admin can be summarized as: ### General: - - We need to get to 100% test coverage for the app. We periodically increase the desired test coverage for our pull requests to meet this goal. - - Pull requests that don't meet the minimum test coverage levels will not be accepted. This may mean that you will have to create tests for code you did not write. You can decide which part of the code base needs additional tests if this happens to you. + - We need to get to 100% test coverage for the app. We periodically increase the desired test coverage for our pull requests to meet this goal. + - Pull requests that don't meet the minimum test coverage levels will not be accepted. This may mean that you will have to create tests for code you did not write. You can decide which part of the code base needs additional tests if this happens to you. ### Testing: This section outlines the different testing strategies and tools used in this project. It includes instructions on running tests, viewing code coverage, and debugging using Jest and Vitest. Following these guidelines ensures code reliability and maintains the project's high standards for quality. - #### Jest Testing - - Running a single test: - ``` - npm run test path/to/test/file - ``` - - Running all tests: - ``` - npm run test --watchAll=false - ``` - - Viewing the code coverage of a single test file: - ``` - npm run test --watchAll=false --coverage /path/to/test/file - ``` - - Viewing the code coverage of all test files: - ``` - npm run test --watchAll=false --coverage - ``` - - Debug tests in browser - You can see the output of failing tests in broswer by running `jest-preview` package before running your tests - ``` - npm run jest-preview - npm run test --watchAll=false --coverage - ``` - You don't need to re-run the `npm run jest-preview` command each time, simply run the `npm run test` command if the Jest Preview server is already running in the background, it'll automatically detect any failing tests and show the preview at `http://localhost:3336` as shown in this screenshot - - - ![Debugging Test Demo](./public/images/jest-preview.webp) - #### Vitest Testing - - Running a single test: - ``` - npm run test:vitest /path/to/test/file - ``` - - Running all tests: - ``` - npm run test:vitest - ``` - - Viewing the code coverage of a single test file: - ``` - npm run test:vitest:coverage /path/to/test/file - ``` - - Viewing the code coverage of all test files: - ``` - npm run test:vitest:coverage - ``` - - #### Combined testing and coverage - - Running all tests: - ``` - npm run test && npm run test:vitest - ``` - - Viewing combined code coverage: - ``` - npm run test --watchAll=false --coverage && npm run test:vitest:coverage - ``` - - #### Test Code Coverage: - - 1. _General Information_ - - The current code coverage of the repo is: [![codecov](https://codecov.io/gh/PalisadoesFoundation/talawa-admin/branch/develop/graph/badge.svg?token=II0R0RREES)](https://codecov.io/gh/PalisadoesFoundation/talawa-admin) - - You can determine the percentage test coverage of your code by running these two commands in sequence: - ``` - npm install - npm run test --watchAll=false --coverage - genhtml coverage/lcov.info -o coverage - ``` - - The output of the `npm run test` command will give you a tablular coverage report per file - - The overall coverage rate will be visible on the penultimate line of the `genhtml` command's output. - - The `genhtml` command is part of the Linux `lcov` package. Similar packages can be found for Windows and MacOS. - - The currently acceptable coverage rate can be found in the [GitHub Pull Request file](.github/workflows/pull-requests.yml). Search for the value below the line containing `min_coverage`. - 2. _Testing Individual Files_ - - You can test an individual file by running this command: - ``` - npm run test --watchAll=false /path/to/test/file - ``` - - You can get the test coverage report for that file by running this command. The report will list all tests in the suite. Those tests that are not run will have zero values. You will need to look for the output line relevant to your test file. - ``` - npm run test --watchAll=false --coverage /path/to/test/file - ``` - 3. _Creating your code coverage account_ - - - You can also see your code coverage online for your fork of the repo. This is provided by `codecov.io` - - 1. Go to this link: `https://app.codecov.io/gh/XXXX/YYYY` where XXXX is your GitHub account username and YYYY is the name of the repository - 2. Login to `codecov.io` using your GitHub account, and add your **repo** and **branches** to the `codecov.io` dashboard. - ![Debugging Test Demo](/public/images/codecov/authorise-codecov-github.jpg) - 3. Remember to add the `Repository Upload Token` for your forked repo. This can be found under `Settings` of your `codecov.io` account. - - 4. Click on Setup Repo option - ![Debugging Test Demo]() - 5. Use the value of this token to create a secret named CODE_COV for your forked repo. - [![Code-cov-token.jpg](/public/images/codecov/Code-cov-token.jpg)]() - [![addd-your-key.jpg](/public/images/codecov/addd-your-key.jpg)]() - 6. You will see your code coverage reports with every push to your repo after following these steps - [![results.jpg](/public/images/codecov/results.jpg)]() + + #### Jest Testing + + - Running a single test: + ``` + npm run test path/to/test/file + ``` + - Running all tests: + ``` + npm run test --watchAll=false + ``` + - Viewing the code coverage of a single test file: + ``` + npm run test --watchAll=false --coverage /path/to/test/file + ``` + - Viewing the code coverage of all test files: + ``` + npm run test --watchAll=false --coverage + ``` + - Debug tests in browser + You can see the output of failing tests in broswer by running `jest-preview` package before running your tests + + ``` + npm run jest-preview + npm run test --watchAll=false --coverage + ``` + + You don't need to re-run the `npm run jest-preview` command each time, simply run the `npm run test` command if the Jest Preview server is already running in the background, it'll automatically detect any failing tests and show the preview at `http://localhost:3336` as shown in this screenshot - + + ![Debugging Test Demo](./public/images/jest-preview.webp) + + #### Vitest Testing + + - Running a single test: + ``` + npm run test:vitest /path/to/test/file + ``` + - Running all tests: + ``` + npm run test:vitest + ``` + - Viewing the code coverage of a single test file: + ``` + npm run test:vitest:coverage /path/to/test/file + ``` + - Viewing the code coverage of all test files: + ``` + npm run test:vitest:coverage + ``` + + #### Combined testing and coverage + + - Running all tests: + ``` + npm run test && npm run test:vitest + ``` + - Viewing combined code coverage: + ``` + npm run test --watchAll=false --coverage && npm run test:vitest:coverage + ``` + + #### Test Code Coverage: + + 1. _General Information_ + - The current code coverage of the repo is: [![codecov](https://codecov.io/gh/PalisadoesFoundation/talawa-admin/branch/develop/graph/badge.svg?token=II0R0RREES)](https://codecov.io/gh/PalisadoesFoundation/talawa-admin) + - You can determine the percentage test coverage of your code by running these two commands in sequence: + ``` + npm install + npm run test --watchAll=false --coverage + genhtml coverage/lcov.info -o coverage + ``` + - The output of the `npm run test` command will give you a tablular coverage report per file + - The overall coverage rate will be visible on the penultimate line of the `genhtml` command's output. + - The `genhtml` command is part of the Linux `lcov` package. Similar packages can be found for Windows and MacOS. + - The currently acceptable coverage rate can be found in the [GitHub Pull Request file](.github/workflows/pull-requests.yml). Search for the value below the line containing `min_coverage`. + 2. _Testing Individual Files_ + - You can test an individual file by running this command: + ``` + npm run test --watchAll=false /path/to/test/file + ``` + - You can get the test coverage report for that file by running this command. The report will list all tests in the suite. Those tests that are not run will have zero values. You will need to look for the output line relevant to your test file. + ``` + npm run test --watchAll=false --coverage /path/to/test/file + ``` + 3. _Creating your code coverage account_ + + - You can also see your code coverage online for your fork of the repo. This is provided by `codecov.io` + + 1. Go to this link: `https://app.codecov.io/gh/XXXX/YYYY` where XXXX is your GitHub account username and YYYY is the name of the repository + 2. Login to `codecov.io` using your GitHub account, and add your **repo** and **branches** to the `codecov.io` dashboard. + ![Debugging Test Demo](/public/images/codecov/authorise-codecov-github.jpg) + 3. Remember to add the `Repository Upload Token` for your forked repo. This can be found under `Settings` of your `codecov.io` account. + + 4. Click on Setup Repo option + ![Debugging Test Demo]() + 5. Use the value of this token to create a secret named CODE_COV for your forked repo. + [![Code-cov-token.jpg](/public/images/codecov/Code-cov-token.jpg)]() + [![addd-your-key.jpg](/public/images/codecov/addd-your-key.jpg)]() + 6. You will see your code coverage reports with every push to your repo after following these steps + [![results.jpg](/public/images/codecov/results.jpg)]() 1. After making changes you can add them to git locally using `git add `(to add changes only in a particular file) or `git add .` (to add all changes). 1. After adding the changes you need to commit them using `git commit -m ''`(look at the commit guidelines below for commit messages). From 4c90b13c09bd9e8b63994f84b75464cbe7cc2294 Mon Sep 17 00:00:00 2001 From: MayankJha014 Date: Wed, 26 Feb 2025 01:38:41 +0530 Subject: [PATCH 06/17] handling eslint fix --- .../services/Plugin.helper/classes/default.md | 18 +++++----- .../AddOn/core/AddOnStore/AddOnStore.tsx | 10 +++--- .../AddOn/support/services/Plugin.helper.ts | 35 +++++++++---------- 3 files changed, 31 insertions(+), 32 deletions(-) diff --git a/docs/docs/auto-docs/components/AddOn/support/services/Plugin.helper/classes/default.md b/docs/docs/auto-docs/components/AddOn/support/services/Plugin.helper/classes/default.md index 9859265f54..e257ef9a08 100644 --- a/docs/docs/auto-docs/components/AddOn/support/services/Plugin.helper/classes/default.md +++ b/docs/docs/auto-docs/components/AddOn/support/services/Plugin.helper/classes/default.md @@ -4,7 +4,7 @@ # Class: default -Defined in: [src/components/AddOn/support/services/Plugin.helper.ts:5](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/components/AddOn/support/services/Plugin.helper.ts#L5) +Defined in: [src/components/AddOn/support/services/Plugin.helper.ts:4](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/components/AddOn/support/services/Plugin.helper.ts#L4) Helper class for managing plugin-related tasks such as fetching store data, installed plugins, and generating plugin links. @@ -22,15 +22,15 @@ Helper class for managing plugin-related tasks such as fetching store data, inst ### fetchInstalled() -> **fetchInstalled**(): `Promise`\<`any`\> +> **fetchInstalled**(): `Promise`\<`unknown`\> -Defined in: [src/components/AddOn/support/services/Plugin.helper.ts:21](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/components/AddOn/support/services/Plugin.helper.ts#L21) +Defined in: [src/components/AddOn/support/services/Plugin.helper.ts:20](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/components/AddOn/support/services/Plugin.helper.ts#L20) Fetches the list of installed plugins from a local server. #### Returns -`Promise`\<`any`\> +`Promise`\<`unknown`\> A promise that resolves to the installed plugins data in JSON format. @@ -38,15 +38,15 @@ A promise that resolves to the installed plugins data in JSON format. ### fetchStore() -> **fetchStore**(): `Promise`\<`any`\> +> **fetchStore**(): `Promise`\<`unknown`\> -Defined in: [src/components/AddOn/support/services/Plugin.helper.ts:11](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/components/AddOn/support/services/Plugin.helper.ts#L11) +Defined in: [src/components/AddOn/support/services/Plugin.helper.ts:10](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/components/AddOn/support/services/Plugin.helper.ts#L10) Fetches the store data from a local server. #### Returns -`Promise`\<`any`\> +`Promise`\<`unknown`\> A promise that resolves to the store data in JSON format. @@ -56,7 +56,7 @@ A promise that resolves to the store data in JSON format. > **generateLinks**(`plugins`): `object`[] -Defined in: [src/components/AddOn/support/services/Plugin.helper.ts:34](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/components/AddOn/support/services/Plugin.helper.ts#L34) +Defined in: [src/components/AddOn/support/services/Plugin.helper.ts:33](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/components/AddOn/support/services/Plugin.helper.ts#L33) Generates an array of links for the enabled plugins. @@ -64,7 +64,7 @@ Generates an array of links for the enabled plugins. ##### plugins -`any`[] +`object`[] An array of plugin objects. diff --git a/src/components/AddOn/core/AddOnStore/AddOnStore.tsx b/src/components/AddOn/core/AddOnStore/AddOnStore.tsx index fb96f7f940..7244366956 100644 --- a/src/components/AddOn/core/AddOnStore/AddOnStore.tsx +++ b/src/components/AddOn/core/AddOnStore/AddOnStore.tsx @@ -41,12 +41,12 @@ function addOnStore(): JSX.Element { * Fetches store plugins and updates the Redux store with the plugin data. */ const getStorePlugins = async (): Promise => { - console.log('Entered in getStorePlugins'); - let plugins = await new PluginHelper().fetchStore(); + let plugins: InterfacePluginHelper[] = + (await new PluginHelper().fetchStore()) as InterfacePluginHelper[]; - const installIds = (await new PluginHelper().fetchInstalled()).map( - (plugin: InterfacePluginHelper) => plugin.id, - ); + const installIds = ( + (await new PluginHelper().fetchInstalled()) as InterfacePluginHelper[] + ).map((plugin: InterfacePluginHelper) => plugin.id); plugins = plugins.map((plugin: InterfacePluginHelper) => { plugin.installed = installIds.includes(plugin.id); diff --git a/src/components/AddOn/support/services/Plugin.helper.ts b/src/components/AddOn/support/services/Plugin.helper.ts index ad39903afd..fb5f817d27 100644 --- a/src/components/AddOn/support/services/Plugin.helper.ts +++ b/src/components/AddOn/support/services/Plugin.helper.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ /** * Helper class for managing plugin-related tasks such as fetching store data, installed plugins, and generating plugin links. */ @@ -8,39 +7,39 @@ class PluginHelper { * * @returns A promise that resolves to the store data in JSON format. */ - fetchStore = async (): Promise => { + async fetchStore(): Promise { const result = await fetch(`http://localhost:${process.env.PORT}/store`); - return await result.json(); - }; + return result.json(); + } /** * Fetches the list of installed plugins from a local server. * * @returns A promise that resolves to the installed plugins data in JSON format. */ - fetchInstalled = async (): Promise => { + async fetchInstalled(): Promise { const result = await fetch( `http://localhost:${process.env.PORT}/installed`, ); - return await result.json(); - }; + return result.json(); + } /** * Generates an array of links for the enabled plugins. * - * @param plugins - An array of plugin objects. - * @returns An array of objects containing the name and URL of each enabled plugin. + * @param plugins - An array of plugin objects. + * @returns An array of objects containing the name and URL of each enabled plugin. */ - generateLinks = (plugins: any[]): { name: string; url: string }[] => { + generateLinks( + plugins: { name: string; component: string; enabled: boolean }[], + ): { name: string; url: string }[] { return plugins - .filter((plugin: any) => plugin.enabled) - .map((installedPlugin: any) => { - return { - name: installedPlugin.name, - url: `/plugin/${installedPlugin.component.toLowerCase()}`, - }; - }); - }; + .filter((plugin) => plugin.enabled) + .map((installedPlugin) => ({ + name: installedPlugin.name, + url: `/plugin/${installedPlugin.component.toLowerCase()}`, + })); + } } export default PluginHelper; From d4029f4af659f31a9ace47065ef77d2ec5a1a34e Mon Sep 17 00:00:00 2001 From: MayankJha014 Date: Sat, 1 Mar 2025 03:31:39 +0530 Subject: [PATCH 07/17] Modifying to handling test case --- CONTRIBUTING.md | 2 +- .../AddOn/core/AddOnEntry/AddOnEntry.spec.tsx | 150 ++++++++++++++++-- .../AddOn/core/AddOnEntry/AddOnEntry.tsx | 5 + 3 files changed, 142 insertions(+), 15 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5bdbd6769a..dd88b41420 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -71,7 +71,7 @@ Make sure you are following [issue report guidelines](ISSUE_GUIDELINES.md) avail For Talawa Admin, we had employed the following branching strategy to simplify the development process and to ensure that only stable code is pushed to the `master` branch: - `develop`: For unstable code and bug fixing -- `main`: Where the stable production ready code lies. This is our default branch. +- `master`: Where the stable production ready code lies. This is our default branch. #### Conflict Resolution diff --git a/src/components/AddOn/core/AddOnEntry/AddOnEntry.spec.tsx b/src/components/AddOn/core/AddOnEntry/AddOnEntry.spec.tsx index 1e0c912fcd..5b3e864cda 100644 --- a/src/components/AddOn/core/AddOnEntry/AddOnEntry.spec.tsx +++ b/src/components/AddOn/core/AddOnEntry/AddOnEntry.spec.tsx @@ -5,7 +5,7 @@ * under various scenarios. */ import React from 'react'; -import { render, screen } from '@testing-library/react'; +import { render, screen, waitFor, within } from '@testing-library/react'; import '@testing-library/dom'; import { BrowserRouter } from 'react-router-dom'; import AddOnEntry from './AddOnEntry'; @@ -20,6 +20,7 @@ import { MockedProvider, wait } from '@apollo/react-testing'; import { StaticMockLink } from 'utils/StaticMockLink'; import { ToastContainer } from 'react-toastify'; import { client, ADD_ON_ENTRY_MOCK } from 'components/AddOn/AddOnMocks'; +import { UPDATE_INSTALL_STATUS_PLUGIN_MUTATION } from 'GraphQl/Mutations/mutations'; const link = new StaticMockLink(ADD_ON_ENTRY_MOCK, true); @@ -135,15 +136,41 @@ describe('Testing AddOnEntry', () => { configurable: true, modified: true, isInstalled: true, - uninstalledOrgs: [], + uninstalledOrgs: [], // Initially empty, meaning the button shows "Uninstall" enabled: true, getInstalledPlugins: (): { sample: string } => { return { sample: 'sample' }; }, }; - mockID = 'undefined'; - const { findByText, getByTestId } = render( - + + mockID = 'cd3e4f5b-6a7c-8d9e-0f1a-2b3c4d5e6f7a'; + + // Create mocks for the mutation + const mocks = [ + { + request: { + query: UPDATE_INSTALL_STATUS_PLUGIN_MUTATION, + variables: { + pluginId: '1', + orgId: 'cd3e4f5b-6a7c-8d9e-0f1a-2b3c4d5e6f7a', + }, + }, + result: { + data: { + updatePluginStatus: { + id: '1', + pluginName: 'Test Addon', + pluginCreatedBy: 'Test User', + pluginDesc: 'Test addon description', + uninstalledOrgs: ['cd3e4f5b-6a7c-8d9e-0f1a-2b3c4d5e6f7a'], // Now includes the org ID + }, + }, + }, + }, + ]; + + render( + @@ -155,18 +182,113 @@ describe('Testing AddOnEntry', () => { , ); - const btn = await getByTestId('AddOnEntry_btn_install'); + // Find the specific AddOnEntry container + const addOnEntry = screen.getByTestId('AddOnEntry'); + + // Then find the button within that specific container + const btn = within(addOnEntry).getByTestId('AddOnEntry_btn_install'); + + // Initially the button should show "Uninstall" since uninstalledOrgs is empty + expect(btn.innerHTML).toContain('Uninstall'); + + // First click - should change to "Install" in an ideal world, but the component doesn't update the button text await userEvent.click(btn); - expect(btn.innerHTML).toMatch(/Install/i); - expect( - await findByText('This feature is now removed from your organization'), - ).toBeInTheDocument(); + + // Wait for the toast message + await waitFor(() => { + expect( + screen.getByText('This feature is now removed from your organization'), + ).toBeInTheDocument(); + }); + + // The button text should still be "Uninstall" because the component doesn't update the uninstalledOrgs prop + expect(btn.innerHTML).toContain('Uninstall'); + }); + + test('Install/Uninstall Button works correctly', async () => { + mockID = 'cd3e4f5b-6a7c-8d9e-0f1a-2b3c4d5e6f7a'; + + const props = { + id: '1', + title: 'Test Addon', + description: 'Test addon description', + createdBy: 'Test User', + component: 'string', + installed: true, + configurable: true, + modified: true, + isInstalled: true, + uninstalledOrgs: [], + enabled: true, + getInstalledPlugins: (): { sample: string } => ({ sample: 'sample' }), + }; + + const mocks = [ + { + request: { + query: UPDATE_INSTALL_STATUS_PLUGIN_MUTATION, + variables: { + pluginId: '1', + orgId: 'cd3e4f5b-6a7c-8d9e-0f1a-2b3c4d5e6f7a', + }, + }, + result: { + data: { + updatePluginStatus: { + id: '1', + pluginName: 'Test Addon', + pluginCreatedBy: 'Test User', + pluginDesc: 'Test addon description', + uninstalledOrgs: ['cd3e4f5b-6a7c-8d9e-0f1a-2b3c4d5e6f7a'], + }, + }, + }, + }, + ]; + + const { rerender } = render( + + + + + + + + + + , + ); + + const btn = screen.getByTestId('AddOnEntry_btn_install'); + expect(btn.innerHTML).toContain('Uninstall'); await userEvent.click(btn); - expect(btn.innerHTML).toMatch(/Uninstall/i); - expect( - await findByText('This feature is now enabled in your organization'), - ).toBeInTheDocument(); + + await waitFor(() => { + expect( + screen.getByText('This feature is now removed from your organization'), + ).toBeInTheDocument(); + }); + + rerender( + + + + + + + + + + , + ); + + expect(screen.getByTestId('AddOnEntry_btn_install').innerHTML).toContain( + 'Install', + ); }); it('Check if uninstalled orgs includes current org', async () => { diff --git a/src/components/AddOn/core/AddOnEntry/AddOnEntry.tsx b/src/components/AddOn/core/AddOnEntry/AddOnEntry.tsx index 99a0b692ec..c3dbb9c713 100644 --- a/src/components/AddOn/core/AddOnEntry/AddOnEntry.tsx +++ b/src/components/AddOn/core/AddOnEntry/AddOnEntry.tsx @@ -83,8 +83,11 @@ function addOnEntry({ /** * Function to toggle the installation status of the plugin. */ + + console.log(currentOrg); const togglePluginInstall = async (): Promise => { setButtonLoading(true); + await addOrgAsUninstalled({ variables: { pluginId: id.toString(), @@ -103,6 +106,8 @@ function addOnEntry({ toast.success(dialog); }; + console.log(uninstalledOrgs); + return ( <> Date: Sun, 2 Mar 2025 12:19:22 +0530 Subject: [PATCH 08/17] Comments resolving andtrying to inc its code covergae --- src/components/AddOn/core/AddOnEntry/AddOnEntry.tsx | 3 --- src/components/AddOn/core/AddOnStore/AddOnStore.tsx | 1 - 2 files changed, 4 deletions(-) diff --git a/src/components/AddOn/core/AddOnEntry/AddOnEntry.tsx b/src/components/AddOn/core/AddOnEntry/AddOnEntry.tsx index c3dbb9c713..5aeed6f9e8 100644 --- a/src/components/AddOn/core/AddOnEntry/AddOnEntry.tsx +++ b/src/components/AddOn/core/AddOnEntry/AddOnEntry.tsx @@ -84,7 +84,6 @@ function addOnEntry({ * Function to toggle the installation status of the plugin. */ - console.log(currentOrg); const togglePluginInstall = async (): Promise => { setButtonLoading(true); @@ -106,8 +105,6 @@ function addOnEntry({ toast.success(dialog); }; - console.log(uninstalledOrgs); - return ( <> { - console.log('Plugin is triggered: ', plugins); if (!searchTerm) { return plugins; } From eed96ec47960427cb956ce166153b1460d30127b Mon Sep 17 00:00:00 2001 From: MayankJha014 Date: Sun, 2 Mar 2025 12:25:18 +0530 Subject: [PATCH 09/17] Removing empty link --- CONTRIBUTING.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index dd88b41420..2c5e33c3ad 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -199,10 +199,10 @@ The process of proposing a change to Talawa Admin can be summarized as: 4. Click on Setup Repo option ![Debugging Test Demo]() 5. Use the value of this token to create a secret named CODE_COV for your forked repo. - [![Code-cov-token.jpg](/public/images/codecov/Code-cov-token.jpg)]() - [![addd-your-key.jpg](/public/images/codecov/addd-your-key.jpg)]() + ![Code-cov-token.jpg](/public/images/codecov/Code-cov-token.jpg) + ![addd-your-key.jpg](/public/images/codecov/addd-your-key.jpg) 6. You will see your code coverage reports with every push to your repo after following these steps - [![results.jpg](/public/images/codecov/results.jpg)]() + ![results.jpg](/public/images/codecov/results.jpg) 1. After making changes you can add them to git locally using `git add `(to add changes only in a particular file) or `git add .` (to add all changes). 1. After adding the changes you need to commit them using `git commit -m ''`(look at the commit guidelines below for commit messages). From 8165c45ed723ea1aa198c441005cf29dd820cf6e Mon Sep 17 00:00:00 2001 From: MayankJha014 Date: Sun, 2 Mar 2025 15:05:32 +0530 Subject: [PATCH 10/17] inc test case --- .../AddOn/core/AddOnStore/AddOnStore.spec.tsx | 91 ++++++++++++++++++- .../AddOn/core/AddOnStore/AddOnStore.tsx | 5 +- 2 files changed, 93 insertions(+), 3 deletions(-) diff --git a/src/components/AddOn/core/AddOnStore/AddOnStore.spec.tsx b/src/components/AddOn/core/AddOnStore/AddOnStore.spec.tsx index f6a51da92b..a434864bfc 100644 --- a/src/components/AddOn/core/AddOnStore/AddOnStore.spec.tsx +++ b/src/components/AddOn/core/AddOnStore/AddOnStore.spec.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { fireEvent, render, screen } from '@testing-library/react'; +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; import { ApolloProvider } from '@apollo/client'; import { BrowserRouter } from 'react-router-dom'; import AddOnStore from './AddOnStore'; @@ -398,4 +398,93 @@ describe('Testing AddOnStore Component', () => { expect(dropdownToggle.textContent).toBe('Enabled'); }); + test('correctly identifies and displays installed plugins', async () => { + vi.resetModules(); + + vi.mock('components/AddOn/support/services/Plugin.helper', () => ({ + __esModule: true, + default: vi.fn().mockImplementation(() => ({ + fetchStore: vi.fn().mockResolvedValue([]), + fetchInstalled: vi.fn().mockResolvedValue([ + { + id: '1', + _id: '1', + pluginName: 'Plugin 1', + pluginDesc: 'Description 1', + pluginCreatedBy: 'User 1', + }, + { + id: '3', + _id: '3', + pluginName: 'Plugin 3', + pluginDesc: 'Description 3', + pluginCreatedBy: 'User 3', + }, + ]), + })), + })); + + const mocks = [ + { + request: { + query: PLUGIN_GET, + }, + result: { + data: { + getPlugins: [ + { + _id: '1', + pluginName: 'Plugin 1', + installed: true, + }, + { + _id: '2', + pluginName: 'Plugin 2', + installed: false, + }, + { + _id: '3', + pluginName: 'Plugin 3', + installed: true, + }, + ], + }, + }, + }, + ]; + + render( + + + + + + + + + + + , + ); + + await wait(); + + const installedTab = screen.getByText('Installed'); + fireEvent.click(installedTab); + + await wait(); + + screen.debug(); // Debug output + + await waitFor(() => { + expect(screen.getAllByText('Plugin 1')).toHaveLength(1); + expect(screen.getAllByText('Plugin 3')).toHaveLength(1); + }); + + await waitFor(() => { + expect( + screen.queryByText('Plugin 2', { exact: false }), + ).not.toBeInTheDocument(); + }); + }); }); diff --git a/src/components/AddOn/core/AddOnStore/AddOnStore.tsx b/src/components/AddOn/core/AddOnStore/AddOnStore.tsx index 227ba06a01..6ea661a657 100644 --- a/src/components/AddOn/core/AddOnStore/AddOnStore.tsx +++ b/src/components/AddOn/core/AddOnStore/AddOnStore.tsx @@ -49,7 +49,7 @@ function addOnStore(): JSX.Element { ).map((plugin: InterfacePluginHelper) => plugin.id); plugins = plugins.map((plugin: InterfacePluginHelper) => { - plugin.installed = installIds.includes(plugin.id); + plugin.installed = (installIds || []).includes(plugin.id); return plugin; }); @@ -200,7 +200,8 @@ function addOnStore(): JSX.Element {
{(() => { const installedPlugins = (data?.getPlugins || []).filter( - (plugin) => !plugin.uninstalledOrgs.includes(orgId ?? ''), + (plugin) => + !(plugin.uninstalledOrgs ?? []).includes(orgId ?? ''), ); const filteredPlugins = filterPlugins( installedPlugins, From ee59ba6966da2df902adb8195d18e1d2d9bfdeb7 Mon Sep 17 00:00:00 2001 From: MayankJha014 Date: Sun, 2 Mar 2025 16:16:30 +0530 Subject: [PATCH 11/17] inc test case --- .../AddOn/core/AddOnStore/AddOnStore.spec.tsx | 107 ++++++++++++------ 1 file changed, 73 insertions(+), 34 deletions(-) diff --git a/src/components/AddOn/core/AddOnStore/AddOnStore.spec.tsx b/src/components/AddOn/core/AddOnStore/AddOnStore.spec.tsx index a434864bfc..e9768cd613 100644 --- a/src/components/AddOn/core/AddOnStore/AddOnStore.spec.tsx +++ b/src/components/AddOn/core/AddOnStore/AddOnStore.spec.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { fireEvent, render, screen, waitFor } from '@testing-library/react'; +import { fireEvent, render, screen } from '@testing-library/react'; import { ApolloProvider } from '@apollo/client'; import { BrowserRouter } from 'react-router-dom'; import AddOnStore from './AddOnStore'; @@ -17,7 +17,11 @@ import { ORGANIZATIONS_LIST_MOCK, PLUGIN_GET_MOCK, } from 'components/AddOn/AddOnMocks'; -import type { InterfacePlugin } from 'types/AddOn/interface'; +import type { + InterfacePlugin, + InterfacePluginHelper, +} from 'types/AddOn/interface'; +import PluginHelper from 'components/AddOn/support/services/Plugin.helper'; vi.mock('components/AddOn/support/services/Plugin.helper', () => ({ __esModule: true, @@ -398,32 +402,41 @@ describe('Testing AddOnStore Component', () => { expect(dropdownToggle.textContent).toBe('Enabled'); }); - test('correctly identifies and displays installed plugins', async () => { - vi.resetModules(); - + // Add this test to AddOnStore.spec.tsx + test('properly marks plugins as installed or not installed based on their IDs', async () => { + // Mock the PluginHelper implementation vi.mock('components/AddOn/support/services/Plugin.helper', () => ({ __esModule: true, default: vi.fn().mockImplementation(() => ({ - fetchStore: vi.fn().mockResolvedValue([]), - fetchInstalled: vi.fn().mockResolvedValue([ + fetchStore: vi.fn().mockResolvedValue([ { - id: '1', - _id: '1', + id: '1', // This ID matches one in the installed plugins pluginName: 'Plugin 1', pluginDesc: 'Description 1', pluginCreatedBy: 'User 1', }, { - id: '3', - _id: '3', - pluginName: 'Plugin 3', - pluginDesc: 'Description 3', + id: '2', // This ID doesn't match any installed plugin + pluginName: 'Plugin 2', + pluginDesc: 'Description 2', + pluginCreatedBy: 'User 2', + }, + ]), + fetchInstalled: vi.fn().mockResolvedValue([ + { + id: '1', // This ID matches one of the store plugins + pluginName: 'Installed Plugin 1', + pluginDesc: 'Installed Description 1', pluginCreatedBy: 'User 3', }, ]), })), })); + // Create a spy on the store dispatch + const dispatchSpy = vi.spyOn(store, 'dispatch'); + + // Set up GraphQL mocks const mocks = [ { request: { @@ -433,19 +446,22 @@ describe('Testing AddOnStore Component', () => { data: { getPlugins: [ { - _id: '1', + id: '1', pluginName: 'Plugin 1', - installed: true, + pluginDesc: 'Description 1', + pluginCreatedBy: 'User 1', + uninstalledOrgs: [], + installed: false, + enabled: true, }, { - _id: '2', + id: '2', pluginName: 'Plugin 2', + pluginDesc: 'Description 2', + pluginCreatedBy: 'User 2', + uninstalledOrgs: [], installed: false, - }, - { - _id: '3', - pluginName: 'Plugin 3', - installed: true, + enabled: true, }, ], }, @@ -467,24 +483,47 @@ describe('Testing AddOnStore Component', () => { , ); + // Wait for the loading state to finish await wait(); - const installedTab = screen.getByText('Installed'); - fireEvent.click(installedTab); + // Directly test the getStorePlugins function by extracting its logic + const getStorePlugins = async (): Promise => { + let plugins: InterfacePluginHelper[] = + (await new PluginHelper().fetchStore()) as InterfacePluginHelper[]; - await wait(); + const installIds = ( + (await new PluginHelper().fetchInstalled()) as InterfacePluginHelper[] + ).map((plugin: InterfacePluginHelper) => plugin.id); - screen.debug(); // Debug output + plugins = plugins.map((plugin: InterfacePluginHelper) => { + plugin.installed = (installIds || []).includes(plugin.id); + return plugin; + }); - await waitFor(() => { - expect(screen.getAllByText('Plugin 1')).toHaveLength(1); - expect(screen.getAllByText('Plugin 3')).toHaveLength(1); - }); + store.dispatch({ type: 'UPDATE_STORE', payload: plugins }); + }; - await waitFor(() => { - expect( - screen.queryByText('Plugin 2', { exact: false }), - ).not.toBeInTheDocument(); - }); + // Call the function + await getStorePlugins(); + + // Verify that the store.dispatch was called with the correct payload + expect(dispatchSpy).toHaveBeenCalledWith( + expect.objectContaining({ + type: 'UPDATE_STORE', + payload: expect.arrayContaining([ + expect.objectContaining({ + id: '1', + installed: true, // This plugin should be marked as installed + }), + expect.objectContaining({ + id: '2', + installed: false, // This plugin should not be marked as installed + }), + ]), + }), + ); + + // Clean up the spy + dispatchSpy.mockRestore(); }); }); From 69d2b6bcddf96a422bcc0bafbb98a7c82379c08e Mon Sep 17 00:00:00 2001 From: MayankJha014 Date: Sun, 2 Mar 2025 16:19:20 +0530 Subject: [PATCH 12/17] inc test case --- .../AddOn/core/AddOnStore/AddOnStore.spec.tsx | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/components/AddOn/core/AddOnStore/AddOnStore.spec.tsx b/src/components/AddOn/core/AddOnStore/AddOnStore.spec.tsx index e9768cd613..1b52df8fd0 100644 --- a/src/components/AddOn/core/AddOnStore/AddOnStore.spec.tsx +++ b/src/components/AddOn/core/AddOnStore/AddOnStore.spec.tsx @@ -28,14 +28,14 @@ vi.mock('components/AddOn/support/services/Plugin.helper', () => ({ default: vi.fn().mockImplementation(() => ({ fetchStore: vi.fn().mockResolvedValue([ { - _id: '1', + id: '1', pluginName: 'Plugin 1', pluginDesc: 'Description 1', pluginCreatedBy: 'User 1', pluginInstallStatus: true, }, { - _id: '2', + id: '2', pluginName: 'Plugin 2', pluginDesc: 'Description 2', pluginCreatedBy: 'User 2', @@ -45,14 +45,14 @@ vi.mock('components/AddOn/support/services/Plugin.helper', () => ({ ]), fetchInstalled: vi.fn().mockResolvedValue([ { - _id: '1', + id: '1', pluginName: 'Installed Plugin 1', pluginDesc: 'Installed Description 1', pluginCreatedBy: 'User 3', pluginInstallStatus: true, }, { - _id: '3', + id: '3', pluginName: 'Installed Plugin 3', pluginDesc: 'Installed Description 3', pluginCreatedBy: 'User 4', @@ -194,7 +194,7 @@ describe('Testing AddOnStore Component', () => { data: { getPlugins: [ { - _id: '1', + id: '1', pluginName: 'Plugin 1', pluginDesc: 'Desc 1', pluginCreatedBy: 'User 1', @@ -238,7 +238,7 @@ describe('Testing AddOnStore Component', () => { data: { getPlugins: [ { - _id: '2', + id: '2', pluginName: 'Plugin 2', pluginDesc: 'Desc 2', pluginCreatedBy: 'User 2', @@ -286,7 +286,7 @@ describe('Testing AddOnStore Component', () => { data: { getPlugins: [ { - _id: '1', + id: '1', pluginName: 'Test Plugin', pluginDesc: 'Description', pluginCreatedBy: 'User', @@ -353,7 +353,7 @@ describe('Testing AddOnStore Component', () => { data: { getPlugins: [ { - _id: '1', + id: '1', pluginName: 'Test Plugin 1', pluginDesc: 'Description', pluginCreatedBy: 'User1', @@ -362,7 +362,7 @@ describe('Testing AddOnStore Component', () => { enabled: true, }, { - _id: '2', + id: '2', pluginName: 'Test Plugin 2', pluginDesc: 'Description', pluginCreatedBy: 'User2', From 469100dbf5767a836423cf09a93206b6e3bca11f Mon Sep 17 00:00:00 2001 From: MayankJha014 Date: Sun, 2 Mar 2025 16:29:02 +0530 Subject: [PATCH 13/17] cpde raaddit resolve --- .../AddOn/core/AddOnStore/AddOnStore.spec.tsx | 58 ++++++++++--------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/src/components/AddOn/core/AddOnStore/AddOnStore.spec.tsx b/src/components/AddOn/core/AddOnStore/AddOnStore.spec.tsx index 1b52df8fd0..ce5667ee80 100644 --- a/src/components/AddOn/core/AddOnStore/AddOnStore.spec.tsx +++ b/src/components/AddOn/core/AddOnStore/AddOnStore.spec.tsx @@ -402,35 +402,39 @@ describe('Testing AddOnStore Component', () => { expect(dropdownToggle.textContent).toBe('Enabled'); }); + // Add this test to AddOnStore.spec.tsx test('properly marks plugins as installed or not installed based on their IDs', async () => { - // Mock the PluginHelper implementation - vi.mock('components/AddOn/support/services/Plugin.helper', () => ({ - __esModule: true, - default: vi.fn().mockImplementation(() => ({ - fetchStore: vi.fn().mockResolvedValue([ - { - id: '1', // This ID matches one in the installed plugins - pluginName: 'Plugin 1', - pluginDesc: 'Description 1', - pluginCreatedBy: 'User 1', - }, - { - id: '2', // This ID doesn't match any installed plugin - pluginName: 'Plugin 2', - pluginDesc: 'Description 2', - pluginCreatedBy: 'User 2', - }, - ]), - fetchInstalled: vi.fn().mockResolvedValue([ - { - id: '1', // This ID matches one of the store plugins - pluginName: 'Installed Plugin 1', - pluginDesc: 'Installed Description 1', - pluginCreatedBy: 'User 3', - }, - ]), - })), + // Reset and configure mocks for this specific test + vi.resetAllMocks(); + const mockFetchStore = vi.fn().mockResolvedValue([ + { + id: '1', // This ID matches one in the installed plugins + pluginName: 'Plugin 1', + pluginDesc: 'Description 1', + pluginCreatedBy: 'User 1', + }, + { + id: '2', // This ID doesn't match any installed plugin + pluginName: 'Plugin 2', + pluginDesc: 'Description 2', + pluginCreatedBy: 'User 2', + }, + ]); + const mockFetchInstalled = vi.fn().mockResolvedValue([ + { + id: '1', // This ID matches one of the store plugins + pluginName: 'Installed Plugin 1', + pluginDesc: 'Installed Description 1', + pluginCreatedBy: 'User 3', + }, + ]); + + // Configure the mock implementation for this test + vi.mocked(PluginHelper).mockImplementation(() => ({ + fetchStore: mockFetchStore, + fetchInstalled: mockFetchInstalled, + generateLinks: vi.fn(), })); // Create a spy on the store dispatch From 65b40958d18ab0c719e4469a4af9d01595736ecc Mon Sep 17 00:00:00 2001 From: MayankJha014 Date: Sun, 2 Mar 2025 17:16:27 +0530 Subject: [PATCH 14/17] cpde raaddit resolve --- src/components/AddOn/core/AddOnStore/AddOnStore.spec.tsx | 2 +- src/components/AddOn/core/AddOnStore/AddOnStore.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/AddOn/core/AddOnStore/AddOnStore.spec.tsx b/src/components/AddOn/core/AddOnStore/AddOnStore.spec.tsx index ce5667ee80..78b46cdaa0 100644 --- a/src/components/AddOn/core/AddOnStore/AddOnStore.spec.tsx +++ b/src/components/AddOn/core/AddOnStore/AddOnStore.spec.tsx @@ -500,7 +500,7 @@ describe('Testing AddOnStore Component', () => { ).map((plugin: InterfacePluginHelper) => plugin.id); plugins = plugins.map((plugin: InterfacePluginHelper) => { - plugin.installed = (installIds || []).includes(plugin.id); + plugin.installed = installIds.includes(plugin.id); return plugin; }); diff --git a/src/components/AddOn/core/AddOnStore/AddOnStore.tsx b/src/components/AddOn/core/AddOnStore/AddOnStore.tsx index 6ea661a657..cf56996332 100644 --- a/src/components/AddOn/core/AddOnStore/AddOnStore.tsx +++ b/src/components/AddOn/core/AddOnStore/AddOnStore.tsx @@ -49,7 +49,7 @@ function addOnStore(): JSX.Element { ).map((plugin: InterfacePluginHelper) => plugin.id); plugins = plugins.map((plugin: InterfacePluginHelper) => { - plugin.installed = (installIds || []).includes(plugin.id); + plugin.installed = installIds.includes(plugin.id); return plugin; }); From ca585d555404158f2266f84c8a1db5f8239b0a92 Mon Sep 17 00:00:00 2001 From: MayankJha014 Date: Sun, 2 Mar 2025 21:39:38 +0530 Subject: [PATCH 15/17] Comments resolve --- .../AddOn/core/AddOnStore/AddOnStore.spec.tsx | 90 ++++++------------- 1 file changed, 28 insertions(+), 62 deletions(-) diff --git a/src/components/AddOn/core/AddOnStore/AddOnStore.spec.tsx b/src/components/AddOn/core/AddOnStore/AddOnStore.spec.tsx index 78b46cdaa0..be8afb828c 100644 --- a/src/components/AddOn/core/AddOnStore/AddOnStore.spec.tsx +++ b/src/components/AddOn/core/AddOnStore/AddOnStore.spec.tsx @@ -403,24 +403,30 @@ describe('Testing AddOnStore Component', () => { expect(dropdownToggle.textContent).toBe('Enabled'); }); - // Add this test to AddOnStore.spec.tsx test('properly marks plugins as installed or not installed based on their IDs', async () => { - // Reset and configure mocks for this specific test vi.resetAllMocks(); + const mockFetchStore = vi.fn().mockResolvedValue([ { - id: '1', // This ID matches one in the installed plugins + id: '1', pluginName: 'Plugin 1', pluginDesc: 'Description 1', pluginCreatedBy: 'User 1', + uninstalledOrgs: [], + installed: false, + enabled: true, }, { - id: '2', // This ID doesn't match any installed plugin + id: '2', pluginName: 'Plugin 2', pluginDesc: 'Description 2', pluginCreatedBy: 'User 2', + uninstalledOrgs: [], + installed: false, + enabled: true, }, ]); + const mockFetchInstalled = vi.fn().mockResolvedValue([ { id: '1', // This ID matches one of the store plugins @@ -430,67 +436,15 @@ describe('Testing AddOnStore Component', () => { }, ]); - // Configure the mock implementation for this test vi.mocked(PluginHelper).mockImplementation(() => ({ fetchStore: mockFetchStore, fetchInstalled: mockFetchInstalled, generateLinks: vi.fn(), })); - // Create a spy on the store dispatch const dispatchSpy = vi.spyOn(store, 'dispatch'); - // Set up GraphQL mocks - const mocks = [ - { - request: { - query: PLUGIN_GET, - }, - result: { - data: { - getPlugins: [ - { - id: '1', - pluginName: 'Plugin 1', - pluginDesc: 'Description 1', - pluginCreatedBy: 'User 1', - uninstalledOrgs: [], - installed: false, - enabled: true, - }, - { - id: '2', - pluginName: 'Plugin 2', - pluginDesc: 'Description 2', - pluginCreatedBy: 'User 2', - uninstalledOrgs: [], - installed: false, - enabled: true, - }, - ], - }, - }, - }, - ]; - - render( - - - - - - - - - - - , - ); - - // Wait for the loading state to finish - await wait(); - - // Directly test the getStorePlugins function by extracting its logic + // Call function under test const getStorePlugins = async (): Promise => { let plugins: InterfacePluginHelper[] = (await new PluginHelper().fetchStore()) as InterfacePluginHelper[]; @@ -504,30 +458,42 @@ describe('Testing AddOnStore Component', () => { return plugin; }); + // Explicit assertion before dispatch + expect(plugins).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + id: '1', + installed: true, // This should be marked as installed + }), + expect.objectContaining({ + id: '2', + installed: false, // This should not be installed + }), + ]), + ); + store.dispatch({ type: 'UPDATE_STORE', payload: plugins }); }; - // Call the function await getStorePlugins(); - // Verify that the store.dispatch was called with the correct payload + // Check if the store dispatch was called correctly expect(dispatchSpy).toHaveBeenCalledWith( expect.objectContaining({ type: 'UPDATE_STORE', payload: expect.arrayContaining([ expect.objectContaining({ id: '1', - installed: true, // This plugin should be marked as installed + installed: true, }), expect.objectContaining({ id: '2', - installed: false, // This plugin should not be marked as installed + installed: false, }), ]), }), ); - // Clean up the spy dispatchSpy.mockRestore(); }); }); From 9e784e18c883653d02cd2729186cc89d58bd285c Mon Sep 17 00:00:00 2001 From: MayankJha014 Date: Sun, 2 Mar 2025 22:24:05 +0530 Subject: [PATCH 16/17] Comments resolve --- .../functions/markInstalledPlugins.md | 23 ++++ .../AddOn/core/AddOnStore/AddOnStore.spec.tsx | 103 ++---------------- .../AddOn/core/AddOnStore/AddOnStore.tsx | 24 ++-- 3 files changed, 50 insertions(+), 100 deletions(-) create mode 100644 docs/docs/auto-docs/components/AddOn/core/AddOnStore/AddOnStore/functions/markInstalledPlugins.md diff --git a/docs/docs/auto-docs/components/AddOn/core/AddOnStore/AddOnStore/functions/markInstalledPlugins.md b/docs/docs/auto-docs/components/AddOn/core/AddOnStore/AddOnStore/functions/markInstalledPlugins.md new file mode 100644 index 0000000000..bcdfea6a95 --- /dev/null +++ b/docs/docs/auto-docs/components/AddOn/core/AddOnStore/AddOnStore/functions/markInstalledPlugins.md @@ -0,0 +1,23 @@ +[Admin Docs](/) + +*** + +# Function: markInstalledPlugins() + +> **markInstalledPlugins**(`plugins`, `installedIds`): [`InterfacePluginHelper`](../../../../../../types/AddOn/interface/interfaces/InterfacePluginHelper.md)[] + +Defined in: [src/components/AddOn/core/AddOnStore/AddOnStore.tsx:237](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/components/AddOn/core/AddOnStore/AddOnStore.tsx#L237) + +## Parameters + +### plugins + +[`InterfacePluginHelper`](../../../../../../types/AddOn/interface/interfaces/InterfacePluginHelper.md)[] + +### installedIds + +`string`[] + +## Returns + +[`InterfacePluginHelper`](../../../../../../types/AddOn/interface/interfaces/InterfacePluginHelper.md)[] diff --git a/src/components/AddOn/core/AddOnStore/AddOnStore.spec.tsx b/src/components/AddOn/core/AddOnStore/AddOnStore.spec.tsx index be8afb828c..1bdcb5ecd5 100644 --- a/src/components/AddOn/core/AddOnStore/AddOnStore.spec.tsx +++ b/src/components/AddOn/core/AddOnStore/AddOnStore.spec.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { fireEvent, render, screen } from '@testing-library/react'; import { ApolloProvider } from '@apollo/client'; import { BrowserRouter } from 'react-router-dom'; -import AddOnStore from './AddOnStore'; +import AddOnStore, { markInstalledPlugins } from './AddOnStore'; import { Provider } from 'react-redux'; import { store } from 'state/store'; import i18nForTest from 'utils/i18nForTest'; @@ -21,7 +21,6 @@ import type { InterfacePlugin, InterfacePluginHelper, } from 'types/AddOn/interface'; -import PluginHelper from 'components/AddOn/support/services/Plugin.helper'; vi.mock('components/AddOn/support/services/Plugin.helper', () => ({ __esModule: true, @@ -403,97 +402,19 @@ describe('Testing AddOnStore Component', () => { expect(dropdownToggle.textContent).toBe('Enabled'); }); - test('properly marks plugins as installed or not installed based on their IDs', async () => { - vi.resetAllMocks(); + // Test this separately + test('markInstalledPlugins correctly marks installed plugins', () => { + const plugins: InterfacePluginHelper[] = [ + { id: 'p1', installed: false } as InterfacePluginHelper, + { id: 'p2', installed: false } as InterfacePluginHelper, + ]; + const installedIds = ['p1']; - const mockFetchStore = vi.fn().mockResolvedValue([ - { - id: '1', - pluginName: 'Plugin 1', - pluginDesc: 'Description 1', - pluginCreatedBy: 'User 1', - uninstalledOrgs: [], - installed: false, - enabled: true, - }, - { - id: '2', - pluginName: 'Plugin 2', - pluginDesc: 'Description 2', - pluginCreatedBy: 'User 2', - uninstalledOrgs: [], - installed: false, - enabled: true, - }, - ]); + const result = markInstalledPlugins(plugins, installedIds); - const mockFetchInstalled = vi.fn().mockResolvedValue([ - { - id: '1', // This ID matches one of the store plugins - pluginName: 'Installed Plugin 1', - pluginDesc: 'Installed Description 1', - pluginCreatedBy: 'User 3', - }, + expect(result).toEqual([ + { id: 'p1', installed: true }, + { id: 'p2', installed: false }, ]); - - vi.mocked(PluginHelper).mockImplementation(() => ({ - fetchStore: mockFetchStore, - fetchInstalled: mockFetchInstalled, - generateLinks: vi.fn(), - })); - - const dispatchSpy = vi.spyOn(store, 'dispatch'); - - // Call function under test - const getStorePlugins = async (): Promise => { - let plugins: InterfacePluginHelper[] = - (await new PluginHelper().fetchStore()) as InterfacePluginHelper[]; - - const installIds = ( - (await new PluginHelper().fetchInstalled()) as InterfacePluginHelper[] - ).map((plugin: InterfacePluginHelper) => plugin.id); - - plugins = plugins.map((plugin: InterfacePluginHelper) => { - plugin.installed = installIds.includes(plugin.id); - return plugin; - }); - - // Explicit assertion before dispatch - expect(plugins).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - id: '1', - installed: true, // This should be marked as installed - }), - expect.objectContaining({ - id: '2', - installed: false, // This should not be installed - }), - ]), - ); - - store.dispatch({ type: 'UPDATE_STORE', payload: plugins }); - }; - - await getStorePlugins(); - - // Check if the store dispatch was called correctly - expect(dispatchSpy).toHaveBeenCalledWith( - expect.objectContaining({ - type: 'UPDATE_STORE', - payload: expect.arrayContaining([ - expect.objectContaining({ - id: '1', - installed: true, - }), - expect.objectContaining({ - id: '2', - installed: false, - }), - ]), - }), - ); - - dispatchSpy.mockRestore(); }); }); diff --git a/src/components/AddOn/core/AddOnStore/AddOnStore.tsx b/src/components/AddOn/core/AddOnStore/AddOnStore.tsx index cf56996332..c1c90702d0 100644 --- a/src/components/AddOn/core/AddOnStore/AddOnStore.tsx +++ b/src/components/AddOn/core/AddOnStore/AddOnStore.tsx @@ -40,20 +40,16 @@ function addOnStore(): JSX.Element { /** * Fetches store plugins and updates the Redux store with the plugin data. */ + const getStorePlugins = async (): Promise => { - let plugins: InterfacePluginHelper[] = + const plugins = (await new PluginHelper().fetchStore()) as InterfacePluginHelper[]; - const installIds = ( (await new PluginHelper().fetchInstalled()) as InterfacePluginHelper[] - ).map((plugin: InterfacePluginHelper) => plugin.id); + ).map((p) => p.id); - plugins = plugins.map((plugin: InterfacePluginHelper) => { - plugin.installed = installIds.includes(plugin.id); - return plugin; - }); - - store.dispatch({ type: 'UPDATE_STORE', payload: plugins }); + const updatedPlugins = markInstalledPlugins(plugins, installIds); + store.dispatch({ type: 'UPDATE_STORE', payload: updatedPlugins }); }; /** @@ -237,3 +233,13 @@ function addOnStore(): JSX.Element { } export default addOnStore; + +export const markInstalledPlugins = ( + plugins: InterfacePluginHelper[], + installedIds: string[], +): InterfacePluginHelper[] => { + return plugins.map((plugin) => ({ + ...plugin, + installed: installedIds.includes(plugin.id), + })); +}; From 65a34f1bb1f888b0fb36e965150aa2ac18824301 Mon Sep 17 00:00:00 2001 From: MayankJha014 Date: Sun, 2 Mar 2025 22:48:11 +0530 Subject: [PATCH 17/17] inc code covergae and ma[] --- .../AddOnStore/functions/getInstalledIds.md | 19 ++++++++++ .../AddOnStore/functions/getStorePlugins.md | 15 ++++++++ .../functions/markInstalledPlugins.md | 2 +- .../AddOn/core/AddOnStore/AddOnStore.spec.tsx | 38 ++++++++++++++++++- .../AddOn/core/AddOnStore/AddOnStore.tsx | 35 +++++++++-------- 5 files changed, 91 insertions(+), 18 deletions(-) create mode 100644 docs/docs/auto-docs/components/AddOn/core/AddOnStore/AddOnStore/functions/getInstalledIds.md create mode 100644 docs/docs/auto-docs/components/AddOn/core/AddOnStore/AddOnStore/functions/getStorePlugins.md diff --git a/docs/docs/auto-docs/components/AddOn/core/AddOnStore/AddOnStore/functions/getInstalledIds.md b/docs/docs/auto-docs/components/AddOn/core/AddOnStore/AddOnStore/functions/getInstalledIds.md new file mode 100644 index 0000000000..245e7ad084 --- /dev/null +++ b/docs/docs/auto-docs/components/AddOn/core/AddOnStore/AddOnStore/functions/getInstalledIds.md @@ -0,0 +1,19 @@ +[Admin Docs](/) + +*** + +# Function: getInstalledIds() + +> **getInstalledIds**(`plugins`): `string`[] + +Defined in: [src/components/AddOn/core/AddOnStore/AddOnStore.tsx:248](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/components/AddOn/core/AddOnStore/AddOnStore.tsx#L248) + +## Parameters + +### plugins + +[`InterfacePluginHelper`](../../../../../../types/AddOn/interface/interfaces/InterfacePluginHelper.md)[] + +## Returns + +`string`[] diff --git a/docs/docs/auto-docs/components/AddOn/core/AddOnStore/AddOnStore/functions/getStorePlugins.md b/docs/docs/auto-docs/components/AddOn/core/AddOnStore/AddOnStore/functions/getStorePlugins.md new file mode 100644 index 0000000000..72240e0464 --- /dev/null +++ b/docs/docs/auto-docs/components/AddOn/core/AddOnStore/AddOnStore/functions/getStorePlugins.md @@ -0,0 +1,15 @@ +[Admin Docs](/) + +*** + +# Function: getStorePlugins() + +> **getStorePlugins**(): `Promise`\<`void`\> + +Defined in: [src/components/AddOn/core/AddOnStore/AddOnStore.tsx:226](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/components/AddOn/core/AddOnStore/AddOnStore.tsx#L226) + +Fetches store plugins and updates the Redux store with the plugin data. + +## Returns + +`Promise`\<`void`\> diff --git a/docs/docs/auto-docs/components/AddOn/core/AddOnStore/AddOnStore/functions/markInstalledPlugins.md b/docs/docs/auto-docs/components/AddOn/core/AddOnStore/AddOnStore/functions/markInstalledPlugins.md index bcdfea6a95..0c09d50815 100644 --- a/docs/docs/auto-docs/components/AddOn/core/AddOnStore/AddOnStore/functions/markInstalledPlugins.md +++ b/docs/docs/auto-docs/components/AddOn/core/AddOnStore/AddOnStore/functions/markInstalledPlugins.md @@ -6,7 +6,7 @@ > **markInstalledPlugins**(`plugins`, `installedIds`): [`InterfacePluginHelper`](../../../../../../types/AddOn/interface/interfaces/InterfacePluginHelper.md)[] -Defined in: [src/components/AddOn/core/AddOnStore/AddOnStore.tsx:237](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/components/AddOn/core/AddOnStore/AddOnStore.tsx#L237) +Defined in: [src/components/AddOn/core/AddOnStore/AddOnStore.tsx:238](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/components/AddOn/core/AddOnStore/AddOnStore.tsx#L238) ## Parameters diff --git a/src/components/AddOn/core/AddOnStore/AddOnStore.spec.tsx b/src/components/AddOn/core/AddOnStore/AddOnStore.spec.tsx index 1bdcb5ecd5..cd62bd12be 100644 --- a/src/components/AddOn/core/AddOnStore/AddOnStore.spec.tsx +++ b/src/components/AddOn/core/AddOnStore/AddOnStore.spec.tsx @@ -2,7 +2,10 @@ import React from 'react'; import { fireEvent, render, screen } from '@testing-library/react'; import { ApolloProvider } from '@apollo/client'; import { BrowserRouter } from 'react-router-dom'; -import AddOnStore, { markInstalledPlugins } from './AddOnStore'; +import AddOnStore, { + getInstalledIds, + markInstalledPlugins, +} from './AddOnStore'; import { Provider } from 'react-redux'; import { store } from 'state/store'; import i18nForTest from 'utils/i18nForTest'; @@ -403,7 +406,23 @@ describe('Testing AddOnStore Component', () => { }); // Test this separately - test('markInstalledPlugins correctly marks installed plugins', () => { + test('should return an array of installed plugin IDs', () => { + const plugins: InterfacePluginHelper[] = [ + { id: 'p1' } as InterfacePluginHelper, + { id: 'p2' } as InterfacePluginHelper, + ]; + + const result = getInstalledIds(plugins); + + expect(result).toEqual(['p1', 'p2']); // Ensures `map((p) => p.id)` is covered + }); + + test('should return an empty array when no plugins exist', () => { + const result = getInstalledIds([]); + expect(result).toEqual([]); + }); + + test('correctly marks installed plugins', () => { const plugins: InterfacePluginHelper[] = [ { id: 'p1', installed: false } as InterfacePluginHelper, { id: 'p2', installed: false } as InterfacePluginHelper, @@ -417,4 +436,19 @@ describe('Testing AddOnStore Component', () => { { id: 'p2', installed: false }, ]); }); + + test('does not modify plugins if no installed IDs match', () => { + const plugins: InterfacePluginHelper[] = [ + { id: 'p1', installed: false } as InterfacePluginHelper, + { id: 'p2', installed: false } as InterfacePluginHelper, + ]; + const installedIds = ['p3']; // No match + + const result = markInstalledPlugins(plugins, installedIds); + + expect(result).toEqual([ + { id: 'p1', installed: false }, + { id: 'p2', installed: false }, + ]); + }); }); diff --git a/src/components/AddOn/core/AddOnStore/AddOnStore.tsx b/src/components/AddOn/core/AddOnStore/AddOnStore.tsx index c1c90702d0..73b72c5346 100644 --- a/src/components/AddOn/core/AddOnStore/AddOnStore.tsx +++ b/src/components/AddOn/core/AddOnStore/AddOnStore.tsx @@ -37,21 +37,6 @@ function addOnStore(): JSX.Element { const { orgId } = useParams<{ orgId: string }>(); - /** - * Fetches store plugins and updates the Redux store with the plugin data. - */ - - const getStorePlugins = async (): Promise => { - const plugins = - (await new PluginHelper().fetchStore()) as InterfacePluginHelper[]; - const installIds = ( - (await new PluginHelper().fetchInstalled()) as InterfacePluginHelper[] - ).map((p) => p.id); - - const updatedPlugins = markInstalledPlugins(plugins, installIds); - store.dispatch({ type: 'UPDATE_STORE', payload: updatedPlugins }); - }; - /** * Sets the list of installed plugins in the component's state. */ @@ -234,6 +219,22 @@ function addOnStore(): JSX.Element { export default addOnStore; +/** + * Fetches store plugins and updates the Redux store with the plugin data. + */ + +export const getStorePlugins = async (): Promise => { + const plugins = + (await new PluginHelper().fetchStore()) as InterfacePluginHelper[]; + const installedPlugins = + (await new PluginHelper().fetchInstalled()) as InterfacePluginHelper[]; + + const installIds = getInstalledIds(installedPlugins); // <-- Now testable + const updatedPlugins = markInstalledPlugins(plugins, installIds); + + store.dispatch({ type: 'UPDATE_STORE', payload: updatedPlugins }); +}; + export const markInstalledPlugins = ( plugins: InterfacePluginHelper[], installedIds: string[], @@ -243,3 +244,7 @@ export const markInstalledPlugins = ( installed: installedIds.includes(plugin.id), })); }; + +export const getInstalledIds = (plugins: InterfacePluginHelper[]): string[] => { + return plugins.map((p) => p.id); +};