From edc4c6345eda8e42eac3502afc8d387b04711148 Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Tue, 2 Apr 2024 01:56:11 +0530 Subject: [PATCH 01/39] init --- .../common-util/List/ListTable/helpers.jsx | 6 ------ 1 file changed, 6 deletions(-) diff --git a/apps/autonolas-registry/common-util/List/ListTable/helpers.jsx b/apps/autonolas-registry/common-util/List/ListTable/helpers.jsx index 5782fcc4..0ac0b249 100644 --- a/apps/autonolas-registry/common-util/List/ListTable/helpers.jsx +++ b/apps/autonolas-registry/common-util/List/ListTable/helpers.jsx @@ -46,12 +46,6 @@ export const getTableColumns = ( width: 180, render: (text) => , }, - { - title: 'No. of component dependencies', - dataIndex: 'dependency', - width: isMobile ? 70 : 300, - key: 'dependency', - }, { width: isMobile ? 40 : 120, title: 'Action', From 748a72decd96f4fb5527823dd514d2c8b1e86730 Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Wed, 3 Apr 2024 01:58:37 +0530 Subject: [PATCH 02/39] remove goerli --- apps/autonolas-registry/common-util/Login/config.jsx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/apps/autonolas-registry/common-util/Login/config.jsx b/apps/autonolas-registry/common-util/Login/config.jsx index 172d46d4..c3a6b4b2 100644 --- a/apps/autonolas-registry/common-util/Login/config.jsx +++ b/apps/autonolas-registry/common-util/Login/config.jsx @@ -8,7 +8,6 @@ import { mainnet, gnosis, polygon, - goerli, polygonMumbai, gnosisChiado, arbitrum, @@ -31,7 +30,6 @@ export const projectId = process.env.NEXT_PUBLIC_WALLET_PROJECT_ID; export const SUPPORTED_CHAINS = [ mainnet, - goerli, gnosis, gnosisChiado, polygon, @@ -87,7 +85,6 @@ export const ethereumClient = new EthereumClient(wagmiConfig, chains); * @example * [ * { name: 'Mainnet', id: 1, network: 'ethereum' }, - * { name: 'Goerli', id: 5, network: 'goerli' }, * // ... * ] */ @@ -176,7 +173,6 @@ export const ALL_SUPPORTED_CHAINS = [ 'base', 'optimism', 'celo', - 'goerli', 'gnosis-chiado', 'polygon-mumbai', 'solana-devnet', From 23a540b825c05869f9da2ec90df7285e38e28345 Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Wed, 3 Apr 2024 01:58:54 +0530 Subject: [PATCH 03/39] add grapql package --- package.json | 1 + yarn.lock | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/package.json b/package.json index 3da38fa8..329583b9 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "cors": "^2.8.5", "ethers": "^5.7.2", "express": "^4.18.2", + "graphql-request": "^6.1.0", "ipfs": "^0.63.5", "ipfs-http-client": "^57.0.3", "ipfs-only-hash": "^4.0.0", diff --git a/yarn.lock b/yarn.lock index 9ab0c6d4..99d7d0e9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2336,6 +2336,11 @@ resolved "https://registry.yarnpkg.com/@gnosis.pm/safe-contracts/-/safe-contracts-1.3.0.tgz#316741a7690d8751a1f701538cfc9ec80866eedc" integrity sha512-1p+1HwGvxGUVzVkFjNzglwHrLNA67U/axP0Ct85FzzH8yhGJb4t9jDjPYocVMzLorDoWAfKicGy1akPY9jXRVw== +"@graphql-typed-document-node/core@^3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@graphql-typed-document-node/core/-/core-3.2.0.tgz#5f3d96ec6b2354ad6d8a28bf216a1d97b5426861" + integrity sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ== + "@grpc/grpc-js@^1.1.8": version "1.10.2" resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.10.2.tgz#19e6da577d88210a01ecc7987b2394b841ed34dd" @@ -14539,6 +14544,14 @@ graphql-request@^3.5.0: extract-files "^9.0.0" form-data "^3.0.0" +graphql-request@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/graphql-request/-/graphql-request-6.1.0.tgz#f4eb2107967af3c7a5907eb3131c671eac89be4f" + integrity sha512-p+XPfS4q7aIpKVcgmnZKhMNqhltk20hfXtkaIkTfjjmiKMJ5xrt5c743cL03y/K7y1rg3WrIC49xGiEQ4mxdNw== + dependencies: + "@graphql-typed-document-node/core" "^3.2.0" + cross-fetch "^3.1.5" + graphql@^15.6.1: version "15.8.0" resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.8.0.tgz#33410e96b012fa3bdb1091cc99a94769db212b38" From 8bdb0e7756419e0dbc71e112e086fd07d29c9da2 Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Wed, 3 Apr 2024 01:59:15 +0530 Subject: [PATCH 04/39] add useSubgraph --- .../common-util/hooks/useSubgraph.jsx | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 apps/autonolas-registry/common-util/hooks/useSubgraph.jsx diff --git a/apps/autonolas-registry/common-util/hooks/useSubgraph.jsx b/apps/autonolas-registry/common-util/hooks/useSubgraph.jsx new file mode 100644 index 00000000..c295409f --- /dev/null +++ b/apps/autonolas-registry/common-util/hooks/useSubgraph.jsx @@ -0,0 +1,16 @@ +import { GraphQLClient } from 'graphql-request'; + +export const useSubgraph = () => { + const graphQLClient = new GraphQLClient( + process.env.NEXT_PUBLIC_AUTONOLAS_SUB_GRAPH_URL, + { + method: 'POST', + jsonSerializer: { + parse: JSON.parse, + stringify: JSON.stringify, + }, + }, + ); + + return graphQLClient; +}; From edad7fb1902a4485626d2d97a689be171a40e6a6 Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Wed, 3 Apr 2024 02:17:37 +0530 Subject: [PATCH 05/39] useListAllUnits --- .../common-util/hooks/useList.jsx | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 apps/autonolas-registry/common-util/hooks/useList.jsx diff --git a/apps/autonolas-registry/common-util/hooks/useList.jsx b/apps/autonolas-registry/common-util/hooks/useList.jsx new file mode 100644 index 00000000..eee142ff --- /dev/null +++ b/apps/autonolas-registry/common-util/hooks/useList.jsx @@ -0,0 +1,89 @@ +/** + * Helper hook to manage list of items (e.g. components, agents & services) + */ + +import { useCallback } from 'react'; +import { gql } from 'graphql-request'; + +import { useSubgraph } from './useSubgraph'; +import dummyData from './mock.json'; +import { TOTAL_VIEW_COUNT } from '../../util/constants'; + +export const useListAllUnits = () => { + const graphQLClient = useSubgraph(); + + const getUnits = useCallback( + async (type, currentPage) => { + try { + // TODO: check query + const query = gql` + { + units( + first: ${TOTAL_VIEW_COUNT}, + skip: ${TOTAL_VIEW_COUNT * (currentPage - 1)}, + where: { packageType: "${type}" }, orderBy: tokenId + ) { + id + packageType + tokenId + packageHash + metadataHash + } + } + `; + + const response = await graphQLClient.request(query); + const units = response?.units || dummyData.data.units; // TODO: remove dummyData + return units; + } catch (error) { + console.error(error); + } + }, + [graphQLClient], + ); + + const getFilteredUnits = useCallback( + async (type, searchValue, currentPage) => { + try { + // TODO: check query & search name, description, public id, token id, package hash + const query = gql` + { + units( + first: ${TOTAL_VIEW_COUNT}, + skip: ${TOTAL_VIEW_COUNT * (currentPage - 1)}, + OR: [ + { + packageType: "${type}", + name_contains: "${searchValue}" + }, + { + packageType: "${type}", + packageHash_contains: "${searchValue}" + } + ], + orderBy: tokenId + ) { + id + packageType + tokenId + packageHash + metadataHash + } + } + `; + + const response = await graphQLClient.request(query); + const units = response?.units || dummyData.data.units; // TODO: remove dummyData + return units; + } catch (error) { + console.error(error); + } + }, + [graphQLClient], + ); + + return { + getUnits, + getFilteredUnits, + }; +}; From bd906d68e6bf4c9b95a6f40e4c65fa0cc4e4da83 Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Wed, 3 Apr 2024 03:31:19 +0530 Subject: [PATCH 06/39] update query --- .../common-util/hooks/useList.jsx | 198 ++++++++++++------ 1 file changed, 137 insertions(+), 61 deletions(-) diff --git a/apps/autonolas-registry/common-util/hooks/useList.jsx b/apps/autonolas-registry/common-util/hooks/useList.jsx index eee142ff..6758f4ab 100644 --- a/apps/autonolas-registry/common-util/hooks/useList.jsx +++ b/apps/autonolas-registry/common-util/hooks/useList.jsx @@ -1,4 +1,7 @@ +// TODO: check all query + /** + * * Helper hook to manage list of items (e.g. components, agents & services) */ @@ -9,81 +12,154 @@ import { useSubgraph } from './useSubgraph'; import dummyData from './mock.json'; import { TOTAL_VIEW_COUNT } from '../../util/constants'; -export const useListAllUnits = () => { +/** + * Hook to get ALL units + * @returns {function} function to get all units + * + */ +export const useAllUnits = () => { const graphQLClient = useSubgraph(); - const getUnits = useCallback( + return useCallback( async (type, currentPage) => { - try { - // TODO: check query - const query = gql` - { - units( - first: ${TOTAL_VIEW_COUNT}, - skip: ${TOTAL_VIEW_COUNT * (currentPage - 1)}, - where: { packageType: "${type}" }, orderBy: tokenId - ) { - id - packageType - tokenId - packageHash - metadataHash - } + const query = gql` + { + units( + first: ${TOTAL_VIEW_COUNT}, + skip: ${TOTAL_VIEW_COUNT * (currentPage - 1)}, + where: { packageType: "${type}" }, + orderBy: tokenId + ) { + id + packageType + tokenId + packageHash + metadataHash } - `; + } + `; - const response = await graphQLClient.request(query); - const units = response?.units || dummyData.data.units; // TODO: remove dummyData - return units; - } catch (error) { - console.error(error); - } + const response = await graphQLClient.request(query); + return response?.units || dummyData.data.units; // TODO: remove dummyData }, [graphQLClient], ); +}; + +/** + * Hook to get ALL units by search + * @returns {function} function to get all units by search + */ +export const useAllUnitsBySearch = () => { + const graphQLClient = useSubgraph(); - const getFilteredUnits = useCallback( + return useCallback( async (type, searchValue, currentPage) => { - try { - // TODO: check query & search name, description, public id, token id, package hash - const query = gql` - { - units( - first: ${TOTAL_VIEW_COUNT}, - skip: ${TOTAL_VIEW_COUNT * (currentPage - 1)}, - OR: [ - { - packageType: "${type}", - name_contains: "${searchValue}" - }, - { - packageType: "${type}", - packageHash_contains: "${searchValue}" - } - ], - orderBy: tokenId - ) { - id - packageType - tokenId - packageHash - metadataHash - } + const query = gql` + { + units( + first: ${TOTAL_VIEW_COUNT}, + skip: ${TOTAL_VIEW_COUNT * (currentPage - 1)}, + OR: [ + { + packageType: "${type}", + name_contains: "${searchValue}" + }, + { + packageType: "${type}", + packageHash_contains: "${searchValue}" + } + ], + orderBy: tokenId + ) { + id + packageType + tokenId + packageHash + metadataHash } - `; + } + `; - const response = await graphQLClient.request(query); - const units = response?.units || dummyData.data.units; // TODO: remove dummyData - return units; - } catch (error) { - console.error(error); - } + const response = await graphQLClient.request(query); + return response?.units || dummyData.data.units; // TODO: remove dummyData }, [graphQLClient], ); +}; - return { - getUnits, - getFilteredUnits, - }; +/** + * Hook to get MY units + * @returns {function} function to get my units + */ +export const useMyUnits = () => { + const graphQLClient = useSubgraph(); + + return useCallback( + async (type, ownerAddress, currentPage) => { + const query = gql` + { + units( + first: ${TOTAL_VIEW_COUNT}, + skip: ${TOTAL_VIEW_COUNT * (currentPage - 1)}, + where: { + owner: "${ownerAddress}", + packageType: "${type}" + }, + orderBy: tokenId, + ) { + id + packageType + tokenId + packageHash + metadataHash + } + } + `; + + const response = await graphQLClient.request(query); + const units = response?.units || dummyData.data.units; // TODO: remove dummyData + return units; + }, + [graphQLClient], + ); +}; + +export const useMyUnitsBySearch = () => { + const graphQLClient = useSubgraph(); + + return useCallback( + async (type, ownerAddress, searchValue, currentPage) => { + const query = gql` + { + units( + first: ${TOTAL_VIEW_COUNT}, + skip: ${TOTAL_VIEW_COUNT * (currentPage - 1)}, + where: { owner: "${ownerAddress}" } + OR: [ + { + packageType: "${type}", + name_contains: "${searchValue}" + }, + { + packageType: "${type}", + packageHash_contains: "${searchValue}" + } + ], + orderBy: tokenId, + ) { + id + packageType + tokenId + packageHash + metadataHash + } + } + `; + + const response = await graphQLClient.request(query); + return response?.units || dummyData.data.units; // TODO: remove dummyData + }, + [graphQLClient], + ); }; From f258525ffe6f993ef490511dfd6b6e7f0d8922b8 Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Wed, 3 Apr 2024 04:18:25 +0530 Subject: [PATCH 07/39] update ListComponents --- .../components/ListComponents/index.jsx | 45 +++++++++++++------ 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/apps/autonolas-registry/components/ListComponents/index.jsx b/apps/autonolas-registry/components/ListComponents/index.jsx index b926b1e9..4fe99783 100644 --- a/apps/autonolas-registry/components/ListComponents/index.jsx +++ b/apps/autonolas-registry/components/ListComponents/index.jsx @@ -2,15 +2,17 @@ import { useState, useEffect } from 'react'; import { Tabs } from 'antd'; import { useRouter } from 'next/router'; import { notifyError } from '@autonolas/frontend-library'; -import { NAV_TYPES } from 'util/constants'; -import ListTable from 'common-util/List/ListTable'; + +import { NAV_TYPES } from '../../util/constants'; +import ListTable from '../../common-util/List/ListTable'; import { useExtraTabContent, getHash, isMyTab, -} from 'common-util/List/ListTable/helpers'; -import { getMyListOnPagination } from 'common-util/ContractUtils/myList'; -import { useHelpers } from 'common-util/hooks'; +} from '../../common-util/List/ListTable/helpers'; +import { getMyListOnPagination } from '../../common-util/ContractUtils/myList'; +import { useHelpers } from '../../common-util/hooks'; +import { useAllUnits, useSearchUnits } from '../../common-util/hooks/useList'; import { getComponents, getFilteredComponents, @@ -28,9 +30,10 @@ const ListComponents = () => { isMyTab(hash) ? MY_COMPONENTS : ALL_COMPONENTS, ); - const { - account, chainId, links, isL1OnlyNetwork, isSvm, - } = useHelpers(); + const { account, chainId, links, isL1OnlyNetwork, isSvm } = useHelpers(); + + const getAllUnits = useAllUnits(); + const getUnitsBySearch = useSearchUnits(); /** * extra tab content & view click @@ -94,7 +97,10 @@ const ListComponents = () => { // All components if (currentTab === ALL_COMPONENTS) { setList([]); - const everyComps = await getComponents(total, currentPage); + const everyComps = + chainId === 1 + ? await getAllUnits(NAV_TYPES.AGENT, currentPage) + : await getComponents(total, currentPage); setList(everyComps); } @@ -104,6 +110,7 @@ const ListComponents = () => { * - API will be called only once & store the complete list */ if (currentTab === MY_COMPONENTS && list.length === 0 && account) { + // TODO: use getMyUnits const e = await getFilteredComponents(account); setList(e); } @@ -129,11 +136,21 @@ const ListComponents = () => { setList([]); try { - const filteredList = await getFilteredComponents( - searchValue, - currentTab === MY_COMPONENTS ? account : null, - ); - setList(filteredList); + if (chainId === 1) { + const filteredList = await getUnitsBySearch( + NAV_TYPES.COMPONENT, + searchValue, + currentPage, + currentTab === MY_COMPONENTS ? account : null, + ); + setList(filteredList); + } else { + const filteredList = await getFilteredComponents( + searchValue, + currentTab === MY_COMPONENTS ? account : null, + ); + setList(filteredList); + } setTotal(0); // total won't be used if search is used setCurrentPage(1); } catch (e) { From 54f270f36b6b90d7b42de834f8b40ef60b3ab263 Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Wed, 3 Apr 2024 04:20:30 +0530 Subject: [PATCH 08/39] update hooks for search, middleware update, table column fix --- .../common-util/List/ListTable/helpers.jsx | 14 ++++++-- .../common-util/hooks/useList.jsx | 34 ++++++++++++++++++- .../components/ListComponents/index.jsx | 15 +++++--- apps/autonolas-registry/middleware.js | 1 + 4 files changed, 57 insertions(+), 7 deletions(-) diff --git a/apps/autonolas-registry/common-util/List/ListTable/helpers.jsx b/apps/autonolas-registry/common-util/List/ListTable/helpers.jsx index 0ac0b249..25b5d641 100644 --- a/apps/autonolas-registry/common-util/List/ListTable/helpers.jsx +++ b/apps/autonolas-registry/common-util/List/ListTable/helpers.jsx @@ -8,6 +8,7 @@ import { } from '@autonolas/frontend-library'; import { + HASH_PREFIX, NAV_TYPES, SERVICE_STATE, TOTAL_VIEW_COUNT, @@ -37,14 +38,23 @@ export const getTableColumns = ( dataIndex: 'owner', key: 'owner', width: 160, - render: (text) => , + render: (text) => { + if (!text || text === NA) return NA; + return ; + }, }, { title: 'Hash', dataIndex: 'hash', key: 'hash', width: 180, - render: (text) => , + render: (text) => { + if (!text || text === NA) return NA; + const updatedText = text.replace(HASH_PREFIX, '0x'); + return ( + + ); + }, }, { width: isMobile ? 40 : 120, diff --git a/apps/autonolas-registry/common-util/hooks/useList.jsx b/apps/autonolas-registry/common-util/hooks/useList.jsx index 6758f4ab..f5e4ce7e 100644 --- a/apps/autonolas-registry/common-util/hooks/useList.jsx +++ b/apps/autonolas-registry/common-util/hooks/useList.jsx @@ -12,6 +12,14 @@ import { useSubgraph } from './useSubgraph'; import dummyData from './mock.json'; import { TOTAL_VIEW_COUNT } from '../../util/constants'; +const transformToTableData = (data) => { + return data.map((item) => ({ + id: item.tokenId, + owner: item.owner, + unitHash: item.metadataHash, + })); +}; + /** * Hook to get ALL units * @returns {function} function to get all units @@ -40,7 +48,7 @@ export const useAllUnits = () => { `; const response = await graphQLClient.request(query); - return response?.units || dummyData.data.units; // TODO: remove dummyData + return transformToTableData(response?.units?.das || dummyData.data.units); // TODO: remove dummyData }, [graphQLClient], ); @@ -125,6 +133,10 @@ export const useMyUnits = () => { ); }; +/** + * Hook to get MY units by search + * @returns {function} function to search units + */ export const useMyUnitsBySearch = () => { const graphQLClient = useSubgraph(); @@ -163,3 +175,23 @@ export const useMyUnitsBySearch = () => { [graphQLClient], ); }; + +export const useSearchUnits = () => { + const getAllUnitsBySearch = useAllUnitsBySearch(); + const getMyUnitsBySearch = useMyUnitsBySearch(); + + return useCallback( + async (type, searchValue, currentPage, ownerAddress) => { + if (ownerAddress) { + return await getMyUnitsBySearch( + type, + ownerAddress, + searchValue, + currentPage, + ); + } + return await getAllUnitsBySearch(type, searchValue, currentPage); + }, + [getAllUnitsBySearch, getMyUnitsBySearch], + ); +}; diff --git a/apps/autonolas-registry/components/ListComponents/index.jsx b/apps/autonolas-registry/components/ListComponents/index.jsx index 4fe99783..5af56b59 100644 --- a/apps/autonolas-registry/components/ListComponents/index.jsx +++ b/apps/autonolas-registry/components/ListComponents/index.jsx @@ -12,7 +12,11 @@ import { } from '../../common-util/List/ListTable/helpers'; import { getMyListOnPagination } from '../../common-util/ContractUtils/myList'; import { useHelpers } from '../../common-util/hooks'; -import { useAllUnits, useSearchUnits } from '../../common-util/hooks/useList'; +import { + useAllUnits, + useMyUnits, + useSearchUnits, +} from '../../common-util/hooks/useList'; import { getComponents, getFilteredComponents, @@ -33,6 +37,7 @@ const ListComponents = () => { const { account, chainId, links, isL1OnlyNetwork, isSvm } = useHelpers(); const getAllUnits = useAllUnits(); + const getMyUnits = useMyUnits(); const getUnitsBySearch = useSearchUnits(); /** @@ -99,7 +104,7 @@ const ListComponents = () => { setList([]); const everyComps = chainId === 1 - ? await getAllUnits(NAV_TYPES.AGENT, currentPage) + ? await getAllUnits(NAV_TYPES.COMPONENT, currentPage) : await getComponents(total, currentPage); setList(everyComps); } @@ -110,8 +115,10 @@ const ListComponents = () => { * - API will be called only once & store the complete list */ if (currentTab === MY_COMPONENTS && list.length === 0 && account) { - // TODO: use getMyUnits - const e = await getFilteredComponents(account); + const e = + chainId === 1 + ? await getMyUnits(NAV_TYPES.COMPONENT, account) + : await getFilteredComponents(account); setList(e); } } catch (e) { diff --git a/apps/autonolas-registry/middleware.js b/apps/autonolas-registry/middleware.js index fed87cc0..4713deb7 100644 --- a/apps/autonolas-registry/middleware.js +++ b/apps/autonolas-registry/middleware.js @@ -47,6 +47,7 @@ const getCspHeader = (browserName) => { 'https://sepolia.optimism.io/', 'https://forno.celo.org', 'https://alfajores-forno.celo-testnet.org', + process.env.NEXT_PUBLIC_AUTONOLAS_SUB_GRAPH_URL ]; if (isDev) { From ba619376c4911566ddaf68c2fcbd8d0b69998d3b Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Wed, 3 Apr 2024 04:51:52 +0530 Subject: [PATCH 09/39] listAgents --- .../common-util/hooks/useSubgraph.jsx | 20 +++-- .../components/ListAgents/index.jsx | 83 ++++++++++++++----- .../components/ListComponents/index.jsx | 28 ++++++- 3 files changed, 101 insertions(+), 30 deletions(-) diff --git a/apps/autonolas-registry/common-util/hooks/useSubgraph.jsx b/apps/autonolas-registry/common-util/hooks/useSubgraph.jsx index c295409f..21e7d41e 100644 --- a/apps/autonolas-registry/common-util/hooks/useSubgraph.jsx +++ b/apps/autonolas-registry/common-util/hooks/useSubgraph.jsx @@ -1,15 +1,19 @@ +import { useMemo } from 'react'; import { GraphQLClient } from 'graphql-request'; export const useSubgraph = () => { - const graphQLClient = new GraphQLClient( - process.env.NEXT_PUBLIC_AUTONOLAS_SUB_GRAPH_URL, - { - method: 'POST', - jsonSerializer: { - parse: JSON.parse, - stringify: JSON.stringify, + const graphQLClient = useMemo( + () => new GraphQLClient( + process.env.NEXT_PUBLIC_AUTONOLAS_SUB_GRAPH_URL, + { + method: 'POST', + jsonSerializer: { + parse: JSON.parse, + stringify: JSON.stringify, + }, }, - }, + ), + [] ); return graphQLClient; diff --git a/apps/autonolas-registry/components/ListAgents/index.jsx b/apps/autonolas-registry/components/ListAgents/index.jsx index 008b375d..9d126927 100644 --- a/apps/autonolas-registry/components/ListAgents/index.jsx +++ b/apps/autonolas-registry/components/ListAgents/index.jsx @@ -3,15 +3,20 @@ import { Tabs } from 'antd'; import { useRouter } from 'next/router'; import { notifyError } from '@autonolas/frontend-library'; -import { NAV_TYPES } from 'util/constants'; -import ListTable from 'common-util/List/ListTable'; +import { NAV_TYPES } from '../../util/constants'; +import ListTable from '../../common-util/List/ListTable'; import { useExtraTabContent, getHash, isMyTab, -} from 'common-util/List/ListTable/helpers'; -import { getMyListOnPagination } from 'common-util/ContractUtils/myList'; -import { useHelpers } from 'common-util/hooks'; +} from '../../common-util/List/ListTable/helpers'; +import { getMyListOnPagination } from '../../common-util/ContractUtils/myList'; +import { useHelpers } from '../../common-util/hooks'; +import { + useAllUnits, + useMyUnits, + useSearchUnits, +} from '../../common-util/hooks/useList'; import { getAgents, getFilteredAgents, @@ -29,9 +34,11 @@ const ListAgents = () => { isMyTab(hash) ? MY_AGENTS : ALL_AGENTS, ); - const { - account, chainId, links, isL1OnlyNetwork, isSvm, - } = useHelpers(); + const { account, chainId, links, isL1OnlyNetwork, isSvm } = useHelpers(); + + const getAllUnits = useAllUnits(); + const getMyUnits = useMyUnits(); + const getUnitsBySearch = useSearchUnits(); /** * extra tab content & view click @@ -54,7 +61,7 @@ const ListAgents = () => { useEffect(() => { setCurrentTab(isMyTab(hash) ? MY_AGENTS : ALL_AGENTS); setList([]); - }, [router.asPath]); + }, [router.asPath, hash]); // fetch total useEffect(() => { @@ -85,6 +92,8 @@ const ListAgents = () => { })(); }, [account, chainId, isL1OnlyNetwork, currentTab, searchValue, isSvm]); + const isListEmpty = list.length === 0; + // fetch the list (without search) useEffect(() => { (async () => { @@ -95,7 +104,10 @@ const ListAgents = () => { // All agents if (currentTab === ALL_AGENTS) { setList([]); - const everyAgents = await getAgents(total, currentPage); + const everyAgents = + chainId === 1 + ? await getAllUnits(NAV_TYPES.AGENT, currentPage) + : await getAgents(total, currentPage); setList(everyAgents); } @@ -104,8 +116,11 @@ const ListAgents = () => { * - search by `account` as searchValue * - API will be called only once & store the complete list */ - if (currentTab === MY_AGENTS && list.length === 0 && account) { - const e = await getFilteredAgents(account); + if (currentTab === MY_AGENTS && isListEmpty && account) { + const e = + chainId === 1 + ? await getMyUnits(NAV_TYPES.AGENT, account) + : await getFilteredAgents(account); setList(e); } } catch (e) { @@ -116,7 +131,20 @@ const ListAgents = () => { } } })(); - }, [account, chainId, isL1OnlyNetwork, total, currentPage, isSvm]); + }, [ + account, + chainId, + isL1OnlyNetwork, + total, + currentPage, + isSvm, + getMyUnits, + getUnitsBySearch, + getAllUnits, + currentTab, + isListEmpty, + searchValue, + ]); /** * Search (All agents, My agents) @@ -130,11 +158,21 @@ const ListAgents = () => { setList([]); try { - const filteredList = await getFilteredAgents( - searchValue, - currentTab === MY_AGENTS ? account : null, - ); - setList(filteredList); + if (chainId === 1) { + const filteredList = await getUnitsBySearch( + NAV_TYPES.AGENT, + searchValue, + currentPage, + currentTab === MY_AGENTS ? account : null, + ); + setList(filteredList); + } else { + const filteredList = await getFilteredAgents( + searchValue, + currentTab === MY_AGENTS ? account : null, + ); + setList(filteredList); + } setTotal(0); // total won't be used if search is used setCurrentPage(1); } catch (e) { @@ -145,7 +183,14 @@ const ListAgents = () => { } } })(); - }, [account, chainId, searchValue, currentTab]); + }, [ + account, + chainId, + searchValue, + currentTab, + currentPage, + getUnitsBySearch, + ]); const tableCommonProps = { type: NAV_TYPES.AGENT, diff --git a/apps/autonolas-registry/components/ListComponents/index.jsx b/apps/autonolas-registry/components/ListComponents/index.jsx index 5af56b59..4a6eff0e 100644 --- a/apps/autonolas-registry/components/ListComponents/index.jsx +++ b/apps/autonolas-registry/components/ListComponents/index.jsx @@ -92,6 +92,8 @@ const ListComponents = () => { })(); }, [account, chainId, isL1OnlyNetwork, currentTab, searchValue, isSvm]); + const isListEmpty = list.length === 0; + // fetch the list (without search) useEffect(() => { (async () => { @@ -114,7 +116,7 @@ const ListComponents = () => { * - search by `account` as searchValue * - API will be called only once & store the complete list */ - if (currentTab === MY_COMPONENTS && list.length === 0 && account) { + if (currentTab === MY_COMPONENTS && isListEmpty && account) { const e = chainId === 1 ? await getMyUnits(NAV_TYPES.COMPONENT, account) @@ -129,7 +131,20 @@ const ListComponents = () => { } } })(); - }, [account, chainId, isL1OnlyNetwork, total, currentPage, isSvm]); + }, [ + account, + chainId, + isL1OnlyNetwork, + total, + currentPage, + isSvm, + getMyUnits, + getUnitsBySearch, + getAllUnits, + currentTab, + isListEmpty, + searchValue, + ]); /** * Search (All components, My Components) @@ -168,7 +183,14 @@ const ListComponents = () => { } } })(); - }, [account, chainId, searchValue, currentTab]); + }, [ + account, + chainId, + searchValue, + currentTab, + currentPage, + getUnitsBySearch, + ]); const tableCommonProps = { type: NAV_TYPES.COMPONENT, From e406c38b69d34f9ab1468a5614787ab275cbf975 Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Wed, 3 Apr 2024 13:33:35 +0530 Subject: [PATCH 10/39] update for service --- .../components/ListAgents/index.jsx | 18 ++--- .../components/ListServices/index.jsx | 76 ++++++++++++------- 2 files changed, 54 insertions(+), 40 deletions(-) diff --git a/apps/autonolas-registry/components/ListAgents/index.jsx b/apps/autonolas-registry/components/ListAgents/index.jsx index 9d126927..487d5412 100644 --- a/apps/autonolas-registry/components/ListAgents/index.jsx +++ b/apps/autonolas-registry/components/ListAgents/index.jsx @@ -103,20 +103,17 @@ const ListAgents = () => { try { // All agents if (currentTab === ALL_AGENTS) { - setList([]); const everyAgents = chainId === 1 ? await getAllUnits(NAV_TYPES.AGENT, currentPage) : await getAgents(total, currentPage); setList(everyAgents); - } - - /** - * My agents - * - search by `account` as searchValue - * - API will be called only once & store the complete list - */ - if (currentTab === MY_AGENTS && isListEmpty && account) { + } else if (currentTab === MY_AGENTS && isListEmpty && account) { + /** + * My agents + * - search by `account` as searchValue + * - API will be called only once & store the complete list + */ const e = chainId === 1 ? await getMyUnits(NAV_TYPES.AGENT, account) @@ -155,8 +152,6 @@ const ListAgents = () => { (async () => { if (searchValue) { setIsLoading(true); - setList([]); - try { if (chainId === 1) { const filteredList = await getUnitsBySearch( @@ -215,7 +210,6 @@ const ListAgents = () => { onChange={(e) => { setCurrentTab(e); - setList([]); setTotal(0); setCurrentPage(1); setIsLoading(true); diff --git a/apps/autonolas-registry/components/ListServices/index.jsx b/apps/autonolas-registry/components/ListServices/index.jsx index eac87cff..7974a0ce 100644 --- a/apps/autonolas-registry/components/ListServices/index.jsx +++ b/apps/autonolas-registry/components/ListServices/index.jsx @@ -3,15 +3,20 @@ import { Tabs } from 'antd'; import { useRouter } from 'next/router'; import { notifyError } from '@autonolas/frontend-library'; -import { NAV_TYPES } from 'util/constants'; -import ListTable from 'common-util/List/ListTable'; +import { NAV_TYPES } from '../../util/constants'; +import ListTable from '../../common-util/List/ListTable'; import { useExtraTabContent, getHash, isMyTab, -} from 'common-util/List/ListTable/helpers'; -import { getMyListOnPagination } from 'common-util/ContractUtils/myList'; -import { useHelpers } from 'common-util/hooks'; +} from '../../common-util/List/ListTable/helpers'; +import { getMyListOnPagination } from '../../common-util/ContractUtils/myList'; +import { useHelpers } from '../../common-util/hooks'; +import { + useAllUnits, + useMyUnits, + useSearchUnits, +} from '../../common-util/hooks/useList'; import { getServices, getFilteredServices, @@ -30,7 +35,11 @@ const ListServices = () => { isMyTab(hash) ? MY_SERVICES : ALL_SERVICES, ); - const { account, chainName, links, isSvm } = useHelpers(); + const { account, chainName, links, isSvm, chainId } = useHelpers(); + + const getAllUnits = useAllUnits(); + const getMyUnits = useMyUnits(); + const getUnitsBySearch = useSearchUnits(); /** * extra tab content & view click @@ -111,29 +120,34 @@ const ListServices = () => { try { // All services if (currentTab === ALL_SERVICES) { - setList([]); - const everyComps = isSvm - ? await getSvmServices(total, currentPage) - : await getServices(total, currentPage); - setList(everyComps); - } + if (chainId === 1) { + const e = await getAllUnits(NAV_TYPES.SERVICE, currentPage); + setList(e); + } else { + const e = isSvm + ? await getSvmServices(total, currentPage) + : await getServices(total, currentPage); + setList(e); + } + } else if (currentTab === MY_SERVICES && list.length === 0 && account) { + /** + * My services + * - search by `account` as searchValue + * - API will be called only once & store the complete list + */ + if (chainId === 1) { + const e = await getMyUnits(NAV_TYPES.SERVICE, account); + setList(e); + } else { + const e = isSvm + ? await getMySvmServices(account, total) + : await getFilteredServices(account); + setList(e); - /** - * My services - * - search by `account` as searchValue - * - API will be called only once & store the complete list - */ - if (currentTab === MY_SERVICES && list.length === 0 && account) { - setList([]); - - const e = isSvm - ? await getMySvmServices(account, total) - : await getFilteredServices(account); - setList(e); - - // TODO: remove this once `getTotalForMySvmServices` is fixed - if (isSvm) { - setTotal(e.length); + // TODO: remove this once `getTotalForMySvmServices` is fixed + if (isSvm) { + setTotal(e.length); + } } } } catch (e) { @@ -149,12 +163,18 @@ const ListServices = () => { } }, [ account, + chainId, chainName, total, currentPage, currentTab, searchValue, isSvm, + getMyUnits, + getUnitsBySearch, + getAllUnits, + getSvmServices, + getMySvmServices, // list?.length, ]); From e85fdceb9a632a2b0c333ecbcbcabf2d1022a557 Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Wed, 3 Apr 2024 13:38:54 +0530 Subject: [PATCH 11/39] update service list --- .../components/ListServices/index.jsx | 40 ++++++++++++++----- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/apps/autonolas-registry/components/ListServices/index.jsx b/apps/autonolas-registry/components/ListServices/index.jsx index 7974a0ce..8bc5a8c8 100644 --- a/apps/autonolas-registry/components/ListServices/index.jsx +++ b/apps/autonolas-registry/components/ListServices/index.jsx @@ -112,6 +112,8 @@ const ListServices = () => { getSvmServices, ]); + const isListEmpty = list.length === 0; + // fetch the list (All services, My Services) - WITHOUT search useEffect(() => { const getList = async () => { @@ -129,7 +131,7 @@ const ListServices = () => { : await getServices(total, currentPage); setList(e); } - } else if (currentTab === MY_SERVICES && list.length === 0 && account) { + } else if (currentTab === MY_SERVICES && isListEmpty && account) { /** * My services * - search by `account` as searchValue @@ -171,11 +173,10 @@ const ListServices = () => { searchValue, isSvm, getMyUnits, - getUnitsBySearch, getAllUnits, getSvmServices, getMySvmServices, - // list?.length, + isListEmpty, ]); /** @@ -187,14 +188,24 @@ const ListServices = () => { (async () => { if (searchValue) { setIsLoading(true); - setList([]); try { - const filteredList = await getFilteredServices( - searchValue, - currentTab === MY_SERVICES ? account : null, - ); - setList(filteredList); + if (chainId === 1) { + const filteredList = await getUnitsBySearch( + NAV_TYPES.SERVICE, + searchValue, + currentPage, + currentTab === MY_SERVICES ? account : null, + ); + setList(filteredList); + } else { + const filteredList = await getFilteredServices( + searchValue, + currentTab === MY_SERVICES ? account : null, + ); + setList(filteredList); + } + setTotal(0); // total won't be used if search is used setCurrentPage(1); } catch (e) { @@ -205,7 +216,15 @@ const ListServices = () => { } } })(); - }, [account, chainName, searchValue, currentTab]); + }, [ + account, + chainName, + searchValue, + currentTab, + chainId, + currentPage, + getUnitsBySearch, + ]); const tableCommonProps = { type: NAV_TYPES.SERVICE, @@ -232,7 +251,6 @@ const ListServices = () => { onChange={(e) => { setCurrentTab(e); - setList([]); setTotal(0); setCurrentPage(1); setIsLoading(true); From 6428372490df8efd3322fafbdbc20c574adfc481 Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Wed, 3 Apr 2024 16:13:37 +0530 Subject: [PATCH 12/39] add extra column and update Search button --- .../common-util/List/ListTable/helpers.jsx | 41 +++++++++++++++++-- .../common-util/hooks/useList.jsx | 24 +++++------ .../common-util/hooks/useSubgraph.jsx | 4 +- 3 files changed, 51 insertions(+), 18 deletions(-) diff --git a/apps/autonolas-registry/common-util/List/ListTable/helpers.jsx b/apps/autonolas-registry/common-util/List/ListTable/helpers.jsx index 25b5d641..5dc8c5c4 100644 --- a/apps/autonolas-registry/common-util/List/ListTable/helpers.jsx +++ b/apps/autonolas-registry/common-util/List/ListTable/helpers.jsx @@ -1,11 +1,12 @@ import { useState } from 'react'; -import { Input, Space, Button, Typography } from 'antd'; -import { SearchOutlined } from '@ant-design/icons'; +import { Input, Space, Button, Typography, Tooltip } from 'antd'; +import { SearchOutlined, InfoCircleOutlined } from '@ant-design/icons'; import { AddressLink, areAddressesEqual, NA, } from '@autonolas/frontend-library'; +import styled from 'styled-components'; import { HASH_PREFIX, @@ -50,12 +51,19 @@ export const getTableColumns = ( width: 180, render: (text) => { if (!text || text === NA) return NA; - const updatedText = text.replace(HASH_PREFIX, '0x'); + const updatedText = text.replace(HASH_PREFIX, '0x'); // .toUpperCase(); return ( ); }, }, + { + title: 'Package Name', + dataIndex: 'packageId', + key: 'packageId', + width: 180, + render: (text) => text || NA, + }, { width: isMobile ? 40 : 120, title: 'Action', @@ -191,6 +199,13 @@ export const fetchDataSource = (type, rawData, { current }) => { return data; }; +const SearchTooltip = styled.div` + ul { + margin: 0; + padding: 0 0 0 16px; + } +`; + /** * tab content */ @@ -215,9 +230,27 @@ export const useExtraTabContent = ({ <> } - placeholder="Owner or Hash" + placeholder="Search..." value={value} onChange={(e) => setValue(e.target.value)} + suffix={ + +
Search by:
+
    +
  • Name
  • +
  • Description
  • +
  • Public ID
  • +
  • Token ID
  • +
  • Package Hash
  • +
+ + } + > + +
+ } /> - - ), - }, ]; + + const actionColumn = { + width: isMobile ? 40 : 120, + title: 'Action', + key: 'action', + fixed: 'right', + render: (_text, record) => ( + + + + ), + }; + + return chainId === 1 + ? [tokenIdColumn, ownerColumn, ...otherEthColumns, actionColumn] + : [tokenIdColumn, ownerColumn, dependencyColumn, actionColumn]; } if (type === NAV_TYPES.SERVICE) { @@ -162,7 +176,7 @@ export const getTableColumns = ( return []; }; -export const fetchDataSource = (type, rawData, { current }) => { +export const fetchDataSource = (type, rawData, { current, chainId }) => { /** * @example * TOTAL_VIEW_COUNT = 10, current = 1 @@ -175,20 +189,46 @@ export const fetchDataSource = (type, rawData, { current }) => { * = 41 */ const startIndex = (current - 1) * TOTAL_VIEW_COUNT + 1; - let data = []; - if (type === NAV_TYPES.COMPONENT || type === NAV_TYPES.AGENT) { - data = rawData.map((item) => ({ - id: item.tokenId, - tokenId: item.tokenId, - owner: item.owner, - hash: item.metadataHash, - packageName: item.publicId, - packageHash: item.packageHash, + + // for mainnet + if (chainId === 1) { + if (type === NAV_TYPES.COMPONENT || type === NAV_TYPES.AGENT) { + return rawData.map((item) => ({ + id: item.tokenId, + tokenId: item.tokenId, + owner: item.owner, + hash: item.metadataHash, + packageName: item.publicId, + packageHash: item.packageHash, + })); + } + } + + // non-mainnet chain + if (type === NAV_TYPES.COMPONENT) { + return rawData.map((item, index) => ({ + id: item.id || `${startIndex + index}`, + description: item.description || NA, + developer: item.developer || NA, + owner: item.owner || NA, + hash: item.unitHash || NA, + dependency: (item.dependencies || []).length, + })); + } + + if (type === NAV_TYPES.AGENT) { + return rawData.map((item, index) => ({ + id: item.id || `${startIndex + index}`, + description: item.description || NA, + developer: item.developer || NA, + owner: item.owner || NA, + hash: item.unitHash || NA, + dependency: (item.dependencies || []).length, })); } if (type === NAV_TYPES.SERVICE) { - data = rawData.map((item, index) => ({ + return rawData.map((item, index) => ({ id: item.id || `${startIndex + index}`, developer: item.developer || NA, owner: item.owner || NA, @@ -197,7 +237,7 @@ export const fetchDataSource = (type, rawData, { current }) => { })); } - return data; + return []; }; const SearchTooltip = styled.div` diff --git a/apps/autonolas-registry/common-util/List/ListTable/index.jsx b/apps/autonolas-registry/common-util/List/ListTable/index.jsx index de01208c..39dd7a21 100644 --- a/apps/autonolas-registry/common-util/List/ListTable/index.jsx +++ b/apps/autonolas-registry/common-util/List/ListTable/index.jsx @@ -52,7 +52,10 @@ const ListTable = ({ chainId, account, }); - const dataSource = fetchDataSource(type, list, { current: currentPage }); + const dataSource = fetchDataSource(type, list, { + current: currentPage, + chainId, + }); const pagination = { total, current: currentPage, diff --git a/apps/autonolas-registry/tests/components/ListServices/details.test.jsx b/apps/autonolas-registry/tests/components/ListServices/details.test.jsx index 77aa268f..16351bfc 100644 --- a/apps/autonolas-registry/tests/components/ListServices/details.test.jsx +++ b/apps/autonolas-registry/tests/components/ListServices/details.test.jsx @@ -99,7 +99,7 @@ jest.mock('../../../components/ListServices/ServiceState/utils', () => ({ ), })); -jest.mock('../../../components/ListServices/useSvmService', () => ({ +jest.mock('../../../components/ListServices/hooks/useSvmService', () => ({ useAgentInstanceAndOperator: jest.fn(() => ({ getSvmAgentInstanceAndOperator: jest.fn(), })), @@ -128,7 +128,7 @@ jest.mock( }), ); -jest.mock('../../../components/ListServices/useService', () => ({ +jest.mock('../../../components/ListServices/hooks/useService', () => ({ useGetServiceDetails: jest.fn(), useGetServiceOwner: jest.fn(), useGetServiceTokenUri: jest.fn(), From 577625a3f106647199e54cf9284f849593e70b92 Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Fri, 5 Apr 2024 06:08:16 +0530 Subject: [PATCH 21/39] test updates --- .../common-util/List/ListTable/index.jsx | 1 + .../components/ListAgents/index.test.tsx | 207 ++++++++++++++---- .../components/ListComponents/index.test.jsx | 152 ++++++++++--- .../components/ListServices/index.test.jsx | 4 +- .../tests/tests-helpers/index.jsx | 16 ++ 5 files changed, 306 insertions(+), 74 deletions(-) diff --git a/apps/autonolas-registry/common-util/List/ListTable/index.jsx b/apps/autonolas-registry/common-util/List/ListTable/index.jsx index 39dd7a21..083076b5 100644 --- a/apps/autonolas-registry/common-util/List/ListTable/index.jsx +++ b/apps/autonolas-registry/common-util/List/ListTable/index.jsx @@ -78,6 +78,7 @@ const ListTable = ({ pagination={canShowPagination ? pagination : false} scroll={{ x: scrollX || 1200 }} rowKey={(record) => `${type}-row-${record.id}`} + data-testid={`${type}-table`} /> )} diff --git a/apps/autonolas-registry/tests/components/ListAgents/index.test.tsx b/apps/autonolas-registry/tests/components/ListAgents/index.test.tsx index 6c70954a..3cee8e1a 100644 --- a/apps/autonolas-registry/tests/components/ListAgents/index.test.tsx +++ b/apps/autonolas-registry/tests/components/ListAgents/index.test.tsx @@ -1,4 +1,4 @@ -import { render, waitFor } from '@testing-library/react'; +import { render, waitFor, within } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import '@testing-library/jest-dom'; @@ -15,10 +15,37 @@ import { getTableTd, useHelpersEvmMock, svmConnectivityEmptyMock, + mockCodeUri, + dummyAddress, + dummyHash1, + dummyAddress1, } from '../../tests-helpers'; -const allAgentsResponse = { id: '1', dependencies: ['4'] }; -const myAgentsResponse = { id: '2', dependencies: ['5'] }; +const allAgentsResponse = [ + { + id: '1', + tokenId: '1', + owner: dummyAddress, + publicId: 'good_package_name_all_agents', + packageHash: dummyHash1, + metadataHash: mockCodeUri, + }, +]; +const myAgentsResponse = [ + { + ...allAgentsResponse[0], + tokenId: '2', + owner: dummyAddress1, + publicId: 'good_package_name_my_agents', + }, +]; +const allAgentsSearchResponse = [ + { + ...allAgentsResponse[0], + tokenId: '3', + publicId: 'good_package_name_agents_search', + }, +]; jest.mock('../../../components/ListAgents/utils', () => ({ getAgents: jest.fn(), @@ -27,6 +54,12 @@ jest.mock('../../../components/ListAgents/utils', () => ({ getTotalForMyAgents: jest.fn(), })); +jest.mock('../../../components/ListAgents/useAgents', () => ({ + useAllAgents: () => () => Promise.resolve(allAgentsResponse), + useMyAgents: () => () => Promise.resolve(myAgentsResponse), + useSearchAgents: () => () => Promise.resolve(allAgentsSearchResponse), +})); + jest.mock('../../../common-util/hooks/useHelpers', () => ({ useHelpers: () => useHelpersEvmMock, })); @@ -38,62 +71,158 @@ jest.mock('../../../common-util/hooks/useSvmConnectivity', () => ({ describe('listAgents/index.jsx', () => { beforeEach(() => { jest.clearAllMocks(); - (getAgents as jest.Mock).mockResolvedValue([allAgentsResponse]); - (getFilteredAgents as jest.Mock).mockResolvedValue([myAgentsResponse]); + (getAgents as jest.Mock).mockResolvedValue(allAgentsResponse); + (getFilteredAgents as jest.Mock).mockResolvedValue(myAgentsResponse); (getTotalForAllAgents as jest.Mock).mockResolvedValue(1); (getTotalForMyAgents as jest.Mock).mockResolvedValue(1); }); - it('should render tabs with `All Tab` as active tab & Mint button', async () => { - const { container, getByRole } = render(wrapProvider()); + it('should display the column names', async () => { + const { container, getByTestId } = render(wrapProvider()); if (!container) { throw new Error('`All tab` is null'); } - // check if the selected tab is `All` & has the correct content - await waitFor(async () => - expect(container.querySelector(ACTIVE_TAB)?.textContent).toBe('All'), - ); - await waitFor(async () => { - // ckecking Id, description column - expect(container.querySelector(getTableTd(1))?.textContent).toBe('1'); - expect(container.querySelector(getTableTd(4))?.textContent).toBe( - allAgentsResponse.dependencies.length.toString(), - ); - expect(getByRole('button', { name: 'View' })).toBeInTheDocument(); + expect( + within(getByTestId('agent-table')).getByText('ID'), + ).toBeInTheDocument(); + expect( + within(getByTestId('agent-table')).getByText('Owner'), + ).toBeInTheDocument(); + expect( + within(getByTestId('agent-table')).getByText('Hash'), + ).toBeInTheDocument(); + expect( + within(getByTestId('agent-table')).getByText('Package Name'), + ).toBeInTheDocument(); + expect( + within(getByTestId('agent-table')).getByText('Action'), + ).toBeInTheDocument(); + }); + }); - // it should be called once - // expect(useRouter).toHaveBeenCalledTimes(1); + describe('All Agents', () => { + it('should display mint button', async () => { + const { getByRole } = render(wrapProvider()); - // Mint button expect(getByRole('button', { name: 'Mint' })).toBeInTheDocument(); }); + + it('should display all agents', async () => { + const { container, getByTestId } = render(wrapProvider()); + + if (!container) { + throw new Error('`All tab` is null'); + } + + // check if the selected tab is `All` & has the correct content + await waitFor(async () => + expect(container.querySelector(ACTIVE_TAB)?.textContent).toBe('All'), + ); + + const firstAgent = allAgentsResponse[0]; + + await waitFor(async () => { + expect( + within(getByTestId('agent-table')).getByText(firstAgent.tokenId), + ).toBeInTheDocument(); + expect( + within(getByTestId('agent-table')).getByText(/0x8626...9C1199/), + ).toBeInTheDocument(); + expect( + within(getByTestId('agent-table')).getByText(/0x9cf4...315ab0/), + ).toBeInTheDocument(); + expect( + within(getByTestId('agent-table')).getByText(firstAgent.publicId), + ).toBeInTheDocument(); + expect( + within(getByTestId('agent-table')).getByText('View'), + ).toBeInTheDocument(); + }); + }); + + it.skip('should display all agents search', async () => { + const { container, getByTestId, getByRole, getByPlaceholderText } = + render(wrapProvider()); + + if (!container) { + throw new Error('`All tab` is null'); + } + + const searchInput = getByPlaceholderText('Search...'); + await userEvent.type(searchInput, 'good_package_name_agents_search'); + + const searchButton = getByRole('button', { name: 'Search' }); + await userEvent.click(searchButton); + + const firstAgent = allAgentsSearchResponse[0]; + + await waitFor(async () => { + expect( + within(getByTestId('agent-table')).getByText(firstAgent.tokenId), + ).toBeInTheDocument(); + expect( + within(getByTestId('agent-table')).getByText(/0x8626...9C1199/), + ).toBeInTheDocument(); + expect( + within(getByTestId('agent-table')).getByText(/0x9cf4...315ab0/), + ).toBeInTheDocument(); + expect( + within(getByTestId('agent-table')).getByText(firstAgent.publicId), + ).toBeInTheDocument(); + expect( + within(getByTestId('agent-table')).getByText('View'), + ).toBeInTheDocument(); + }); + }); }); - it('should render tabs with `My Agents` as active tab & Mint button', async () => { - const { container, getByRole } = render(wrapProvider()); - if (!container) { - throw new Error('`My agents` is null'); - } + describe('My Agents', () => { + it('should display mint button', async () => { + const { getByRole } = render(wrapProvider()); - const myAgentsTab = container.querySelector('.ant-tabs-tab:nth-child(2)'); - if (!myAgentsTab) { - throw new Error('`My agents` tab is null'); - } + expect(getByRole('button', { name: 'Mint' })).toBeInTheDocument(); + }); - // click the `My agents` tab - userEvent.click(myAgentsTab); + it('should display my agents', async () => { + const { container } = render(wrapProvider()); - // check if the selected tab is `My agents` & has the correct content - await waitFor(async () => { - expect(container.querySelector(ACTIVE_TAB)?.textContent).toBe( - 'My Agents', + const myAgentsTab = container.querySelector('.ant-tabs-tab:nth-child(2)'); + if (!myAgentsTab) { + throw new Error('`My agents` tab is null'); + } + + // click the `My agents` tab + userEvent.click(myAgentsTab); + + // check if the selected tab is `My` & has the correct content + await waitFor(async () => + expect(container.querySelector(ACTIVE_TAB)?.textContent).toBe( + 'My Agents', + ), ); - }); - // Mint button - expect(getByRole('button', { name: 'Mint' })).toBeInTheDocument(); + const firstAgent = myAgentsResponse[0]; + + await waitFor(async () => { + expect(container.querySelector(getTableTd(1))?.textContent).toBe( + firstAgent.tokenId, + ); + expect(container.querySelector(getTableTd(2))?.textContent).toBe( + '0x8626...9C1000', + ); + expect(container.querySelector(getTableTd(3))?.textContent).toBe( + '0x9cf4...315ab0', + ); + expect(container.querySelector(getTableTd(4))?.textContent).toBe( + firstAgent.publicId, + ); + expect(container.querySelector(getTableTd(5))?.textContent).toBe( + 'View', + ); + }); + }); }); }); diff --git a/apps/autonolas-registry/tests/components/ListComponents/index.test.jsx b/apps/autonolas-registry/tests/components/ListComponents/index.test.jsx index 006bd7be..c947730f 100644 --- a/apps/autonolas-registry/tests/components/ListComponents/index.test.jsx +++ b/apps/autonolas-registry/tests/components/ListComponents/index.test.jsx @@ -1,5 +1,6 @@ -import { render, waitFor } from '@testing-library/react'; +import { within, render, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; + import ListComponents from '../../../components/ListComponents'; import { getComponents, @@ -10,13 +11,45 @@ import { import { wrapProvider, ACTIVE_TAB, - getTableTd, svmConnectivityEmptyMock, useHelpersEvmMock, + mockCodeUri, + dummyAddress, + dummyHash1, + dummyAddress1, } from '../../tests-helpers'; -const allComponentResponse = { id: '1', dependencies: ['1'] }; -const myComponentResponse = { id: '2', dependencies: ['2'] }; +const allComponentsResponse = [ + { + id: '1', + tokenId: '1', + owner: dummyAddress, + publicId: 'good_package_name_all_components', + packageHash: dummyHash1, + metadataHash: mockCodeUri, + }, +]; +const myComponentsResponse = [ + { + ...allComponentsResponse[0], + tokenId: '2', + owner: dummyAddress1, + publicId: 'good_package_name_my_components', + }, +]; +const allComponentsSearchResponse = [ + { + ...allComponentsResponse[0], + tokenId: '3', + publicId: 'good_package_name_components_search', + }, +]; + +jest.mock('../../../components/ListComponents/useComponents', () => ({ + useAllComponents: () => () => Promise.resolve(allComponentsResponse), + useMyComponents: () => () => Promise.resolve(myComponentsResponse), + useSearchComponents: () => () => Promise.resolve(allComponentsSearchResponse), +})); jest.mock('../../../common-util/hooks/useHelpers', () => ({ useHelpers: () => useHelpersEvmMock, @@ -33,51 +66,104 @@ jest.mock('../../../components/ListComponents/utils', () => ({ getTotalForMyComponents: jest.fn(), })); -describe('listComponents/index.jsx', () => { +describe.skip('listComponents/index.jsx', () => { beforeEach(() => { jest.clearAllMocks(); - getComponents.mockResolvedValue([allComponentResponse]); - getFilteredComponents.mockResolvedValue([myComponentResponse]); + getComponents.mockResolvedValue(allComponentsResponse); + getFilteredComponents.mockResolvedValue(myComponentsResponse); getTotalForAllComponents.mockResolvedValue(1); getTotalForMyComponents.mockResolvedValue(1); }); - it('should render tabs with `All Tab` as active tab & Mint button', async () => { - const { container, getByRole } = render(wrapProvider()); + it('should display the column names', async () => { + const { container, getByText } = render(wrapProvider()); - // check if the selected tab is `All` & has the correct content - await waitFor(async () => - expect(container.querySelector(ACTIVE_TAB).textContent).toBe('All'), - ); + if (!container) { + throw new Error('`All tab` is null'); + } await waitFor(async () => { - // ckecking Id, description column - expect(container.querySelector(getTableTd(1)).textContent).toBe('1'); - expect(container.querySelector(getTableTd(4)).textContent).toBe( - allComponentResponse.dependencies.length.toString(), - ); + expect(getByText('ID')).toBeInTheDocument(); + expect(getByText('Owner')).toBeInTheDocument(); + expect(getByText('Hash')).toBeInTheDocument(); + expect(getByText('Package Name')).toBeInTheDocument(); + expect(getByText('Action')).toBeInTheDocument(); + }); + }); - // it should be called once - // expect(useRouter).toHaveBeenCalledTimes(1); + describe('All Components', () => { + it('should display mint button', async () => { + const { getByRole } = render(wrapProvider()); expect(getByRole('button', { name: 'Mint' })).toBeInTheDocument(); }); - }); - it('should render tabs with `My Components` as active tab & Mint button', async () => { - const { container, getByRole } = render(wrapProvider()); + it('should display all components', async () => { + const { container, getByTestId } = render(wrapProvider()); - // click the `My components` tab - userEvent.click(container.querySelector('.ant-tabs-tab:nth-child(2)')); + if (!container) { + throw new Error('`All tab` is null'); + } + + // check if the selected tab is `All` & has the correct content + await waitFor(async () => + expect(container.querySelector(ACTIVE_TAB)?.textContent).toBe('All'), + ); - // check if the selected tab is `My components` & has the correct content - await waitFor(async () => - expect(container.querySelector(ACTIVE_TAB).textContent).toBe( - 'My Components', - ), - ); + const firstAgent = allComponentsResponse[0]; - // Mint button - expect(getByRole('button', { name: 'Mint' })).toBeInTheDocument(); + await waitFor(async () => { + expect( + within(getByTestId('agent-table')).getByText(firstAgent.tokenId), + ).toBeInTheDocument(); + expect( + within(getByTestId('agent-table')).getByText(/0x8626...9C1199/), + ).toBeInTheDocument(); + expect( + within(getByTestId('agent-table')).getByText(/0x9cf4...315ab0/), + ).toBeInTheDocument(); + expect( + within(getByTestId('agent-table')).getByText(firstAgent.publicId), + ).toBeInTheDocument(); + expect( + within(getByTestId('agent-table')).getByText('View'), + ).toBeInTheDocument(); + }); + }); + + it('should display all components search', async () => { + const { container, getByTestId, getByRole, getByPlaceholderText } = + render(wrapProvider()); + + if (!container) { + throw new Error('`All tab` is null'); + } + + const searchInput = getByPlaceholderText('Search...'); + await userEvent.type(searchInput, 'good_package_name_components_search'); + + const searchButton = getByRole('button', { name: 'Search' }); + await userEvent.click(searchButton); + + const firstAgent = allComponentsSearchResponse[0]; + + await waitFor(async () => { + expect( + within(getByTestId('agent-table')).getByText(firstAgent.tokenId), + ).toBeInTheDocument(); + expect( + within(getByTestId('agent-table')).getByText(/0x8626...9C1199/), + ).toBeInTheDocument(); + expect( + within(getByTestId('agent-table')).getByText(/0x9cf4...315ab0/), + ).toBeInTheDocument(); + expect( + within(getByTestId('agent-table')).getByText(firstAgent.publicId), + ).toBeInTheDocument(); + expect( + within(getByTestId('agent-table')).getByText('View'), + ).toBeInTheDocument(); + }); + }); }); }); diff --git a/apps/autonolas-registry/tests/components/ListServices/index.test.jsx b/apps/autonolas-registry/tests/components/ListServices/index.test.jsx index ef415c74..145da47e 100644 --- a/apps/autonolas-registry/tests/components/ListServices/index.test.jsx +++ b/apps/autonolas-registry/tests/components/ListServices/index.test.jsx @@ -34,11 +34,11 @@ jest.mock('../../../common-util/hooks/useSvmConnectivity', () => ({ useSvmConnectivity: jest.fn(() => svmConnectivityEmptyMock), })); -jest.mock('../../../components/ListServices/useSvmService', () => ({ +jest.mock('../../../components/ListServices/hooks/useSvmService', () => ({ useServiceInfo: jest.fn(), })); -describe('listServices/index.jsx', () => { +describe.skip('listServices/index.jsx', () => { describe('EVM', () => { beforeEach(() => { jest.clearAllMocks(); diff --git a/apps/autonolas-registry/tests/tests-helpers/index.jsx b/apps/autonolas-registry/tests/tests-helpers/index.jsx index 28a074b0..c7b6f402 100644 --- a/apps/autonolas-registry/tests/tests-helpers/index.jsx +++ b/apps/autonolas-registry/tests/tests-helpers/index.jsx @@ -7,7 +7,9 @@ export const HEADER = '.ant-typography'; const mockStore = configureMockStore(); export const dummyAddress = '0x8626f6940E2eb28930eFb4CeF49B2d1F2C9C1199'; +export const dummyAddress1 = '0x8626f6940E2eb28930eFb4CeF49B2d1F2C9C1000'; export const dummyHash = 'QmYuLhvusXYh2Pw5BqntNi9ZGg4Chcf1dhiuzxZesJCnK1'; +export const dummyHash1 = 'bafybeidetrrkvdgveu4ph5g6v53lbh7ardfspbkpstmjxctx647bzyosyy'; export const emptyStore = mockStore({}); export const initStore = mockStore({ @@ -68,6 +70,20 @@ export const useHelpersEvmMock = { isSvm: false, }; +export const useHelpersBaseMock = { + account: dummyAddress, + vmType: 'EVM', + chainId: 8453, + chainDisplayName: 'Base', + chainName: 'base', + isL1OnlyNetwork: false, + isL1Network: false, + doesNetworkHaveValidServiceManagerToken: true, + links: { AGENTS: '/base/agents' }, + isConnectedToWrongNetwork: false, + isSvm: false, +}; + export const mockSvmAddress = 'DrGvsAxY8ehyXjE6qSZXcT5A9pTsUkVm3en5ZQD3Wm5x'; export const useHelpersSvmMock = { From ba86580661d9e87af2c3a6fb75ba7e05a7cbc84a Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Fri, 5 Apr 2024 16:30:15 +0530 Subject: [PATCH 22/39] test-case fixes --- .../common-util/List/ListTable/helpers.jsx | 3 +- .../common-util/List/ListTable/index.jsx | 15 +- .../components/ListAgents/index.jsx | 17 +- .../components/ListComponents/index.jsx | 15 +- .../components/ListAgents/index.test.tsx | 182 ++++++++++-------- .../components/ListComponents/index.test.jsx | 128 ++++++------ 6 files changed, 211 insertions(+), 149 deletions(-) diff --git a/apps/autonolas-registry/common-util/List/ListTable/helpers.jsx b/apps/autonolas-registry/common-util/List/ListTable/helpers.jsx index d78d545f..efd60e01 100644 --- a/apps/autonolas-registry/common-util/List/ListTable/helpers.jsx +++ b/apps/autonolas-registry/common-util/List/ListTable/helpers.jsx @@ -42,7 +42,7 @@ export const getTableColumns = ( width: 160, render: (text) => { if (!text || text === NA) return NA; - return ; + return ; }, }; @@ -282,6 +282,7 @@ export const useExtraTabContent = ({
  • Name
  • Description
  • +
  • Owner
  • Public ID
  • Package Hash
diff --git a/apps/autonolas-registry/common-util/List/ListTable/index.jsx b/apps/autonolas-registry/common-util/List/ListTable/index.jsx index 083076b5..7104bc50 100644 --- a/apps/autonolas-registry/common-util/List/ListTable/index.jsx +++ b/apps/autonolas-registry/common-util/List/ListTable/index.jsx @@ -20,6 +20,7 @@ const ListTable = ({ onViewClick, onUpdateClick, extra, + tableDataTestId, }) => { const { chainName, account, isSvm, chainId } = useHelpers(); /** @@ -76,9 +77,9 @@ const ListTable = ({ columns={columns} dataSource={dataSource} pagination={canShowPagination ? pagination : false} - scroll={{ x: scrollX || 1200 }} + scroll={{ x: scrollX }} rowKey={(record) => `${type}-row-${record.id}`} - data-testid={`${type}-table`} + data-testid={tableDataTestId || `${type}-table`} /> )} @@ -97,7 +98,10 @@ ListTable.propTypes = { isAccountRequired: PropTypes.bool, onViewClick: PropTypes.func, onUpdateClick: PropTypes.func, - extra: PropTypes.shape({ scrollX: PropTypes.number }), + tableDataTestId: PropTypes.string, + extra: PropTypes.shape({ + scrollX: PropTypes.number, + }), }; ListTable.defaultProps = { @@ -110,7 +114,10 @@ ListTable.defaultProps = { isAccountRequired: false, onViewClick: () => {}, onUpdateClick: null, - extra: {}, + tableDataTestId: null, + extra: { + scrollX: 1200, + }, }; export default ListTable; diff --git a/apps/autonolas-registry/components/ListAgents/index.jsx b/apps/autonolas-registry/components/ListAgents/index.jsx index f8a044b2..2fc00a18 100644 --- a/apps/autonolas-registry/components/ListAgents/index.jsx +++ b/apps/autonolas-registry/components/ListAgents/index.jsx @@ -60,7 +60,7 @@ const ListAgents = () => { // fetch total useEffect(() => { (async () => { - if(isSvm) return; + if (isSvm) return; if (!isL1OnlyNetwork) return; if (searchValue !== '') return; @@ -211,13 +211,24 @@ const ListAgents = () => { { key: ALL_AGENTS, label: 'All', - children: , + children: ( + + ), }, { key: MY_AGENTS, label: 'My Agents', children: ( - + ), }, ]} diff --git a/apps/autonolas-registry/components/ListComponents/index.jsx b/apps/autonolas-registry/components/ListComponents/index.jsx index 3e788900..be6e6ce5 100644 --- a/apps/autonolas-registry/components/ListComponents/index.jsx +++ b/apps/autonolas-registry/components/ListComponents/index.jsx @@ -219,13 +219,24 @@ const ListComponents = () => { { key: ALL_COMPONENTS, label: 'All', - children: , + children: ( + + ), }, { label: 'My Components', key: MY_COMPONENTS, children: ( - + ), }, ]} diff --git a/apps/autonolas-registry/tests/components/ListAgents/index.test.tsx b/apps/autonolas-registry/tests/components/ListAgents/index.test.tsx index 3cee8e1a..51e89443 100644 --- a/apps/autonolas-registry/tests/components/ListAgents/index.test.tsx +++ b/apps/autonolas-registry/tests/components/ListAgents/index.test.tsx @@ -12,9 +12,8 @@ import { import { wrapProvider, ACTIVE_TAB, - getTableTd, - useHelpersEvmMock, svmConnectivityEmptyMock, + useHelpersEvmMock, mockCodeUri, dummyAddress, dummyHash1, @@ -78,40 +77,34 @@ describe('listAgents/index.jsx', () => { }); it('should display the column names', async () => { - const { container, getByTestId } = render(wrapProvider()); + const { container, findByTestId } = render(wrapProvider()); if (!container) { throw new Error('`All tab` is null'); } + const allAgentsTable = await findByTestId('all-agents-table'); + await waitFor(async () => { + expect(within(allAgentsTable).getByText('ID')).toBeInTheDocument(); + expect(within(allAgentsTable).getByText('Owner')).toBeInTheDocument(); + expect(within(allAgentsTable).getByText('Hash')).toBeInTheDocument(); expect( - within(getByTestId('agent-table')).getByText('ID'), - ).toBeInTheDocument(); - expect( - within(getByTestId('agent-table')).getByText('Owner'), - ).toBeInTheDocument(); - expect( - within(getByTestId('agent-table')).getByText('Hash'), - ).toBeInTheDocument(); - expect( - within(getByTestId('agent-table')).getByText('Package Name'), - ).toBeInTheDocument(); - expect( - within(getByTestId('agent-table')).getByText('Action'), + within(allAgentsTable).getByText('Package Name'), ).toBeInTheDocument(); + expect(within(allAgentsTable).getByText('Action')).toBeInTheDocument(); }); }); - describe('All Agents', () => { - it('should display mint button', async () => { - const { getByRole } = render(wrapProvider()); + it('should display mint button', async () => { + const { findByRole } = render(wrapProvider()); - expect(getByRole('button', { name: 'Mint' })).toBeInTheDocument(); - }); + expect(await findByRole('button', { name: 'Mint' })).toBeInTheDocument(); + }); + describe('All Agents', () => { it('should display all agents', async () => { - const { container, getByTestId } = render(wrapProvider()); + const { container, findByTestId } = render(wrapProvider()); if (!container) { throw new Error('`All tab` is null'); @@ -123,28 +116,25 @@ describe('listAgents/index.jsx', () => { ); const firstAgent = allAgentsResponse[0]; + const allAgentsTable = await findByTestId('all-agents-table'); - await waitFor(async () => { - expect( - within(getByTestId('agent-table')).getByText(firstAgent.tokenId), - ).toBeInTheDocument(); - expect( - within(getByTestId('agent-table')).getByText(/0x8626...9C1199/), - ).toBeInTheDocument(); - expect( - within(getByTestId('agent-table')).getByText(/0x9cf4...315ab0/), - ).toBeInTheDocument(); - expect( - within(getByTestId('agent-table')).getByText(firstAgent.publicId), - ).toBeInTheDocument(); - expect( - within(getByTestId('agent-table')).getByText('View'), - ).toBeInTheDocument(); - }); + expect( + within(allAgentsTable).getByText(firstAgent.tokenId), + ).toBeInTheDocument(); + expect( + within(allAgentsTable).getByText(/0x8626...9C1199/), + ).toBeInTheDocument(); + expect( + within(allAgentsTable).getByText(/0x9cf4...315ab0/), + ).toBeInTheDocument(); + expect( + within(allAgentsTable).getByText(firstAgent.publicId), + ).toBeInTheDocument(); + expect(within(allAgentsTable).getByText('View')).toBeInTheDocument(); }); - it.skip('should display all agents search', async () => { - const { container, getByTestId, getByRole, getByPlaceholderText } = + it('should display all agents search', async () => { + const { container, getByRole, findByTestId, getByPlaceholderText } = render(wrapProvider()); if (!container) { @@ -152,42 +142,33 @@ describe('listAgents/index.jsx', () => { } const searchInput = getByPlaceholderText('Search...'); - await userEvent.type(searchInput, 'good_package_name_agents_search'); + await userEvent.type(searchInput, '!'); const searchButton = getByRole('button', { name: 'Search' }); await userEvent.click(searchButton); const firstAgent = allAgentsSearchResponse[0]; + const allAgentsTable = await findByTestId('all-agents-table'); - await waitFor(async () => { - expect( - within(getByTestId('agent-table')).getByText(firstAgent.tokenId), - ).toBeInTheDocument(); - expect( - within(getByTestId('agent-table')).getByText(/0x8626...9C1199/), - ).toBeInTheDocument(); - expect( - within(getByTestId('agent-table')).getByText(/0x9cf4...315ab0/), - ).toBeInTheDocument(); - expect( - within(getByTestId('agent-table')).getByText(firstAgent.publicId), - ).toBeInTheDocument(); - expect( - within(getByTestId('agent-table')).getByText('View'), - ).toBeInTheDocument(); - }); + expect( + within(allAgentsTable).getByText(firstAgent.tokenId), + ).toBeInTheDocument(); + expect( + within(allAgentsTable).getByText(/0x8626...9C1199/), + ).toBeInTheDocument(); + expect( + within(allAgentsTable).getByText(/0x9cf4...315ab0/), + ).toBeInTheDocument(); + expect( + within(allAgentsTable).getByText(firstAgent.publicId), + ).toBeInTheDocument(); + expect(within(allAgentsTable).getByText('View')).toBeInTheDocument(); }); }); describe('My Agents', () => { - it('should display mint button', async () => { - const { getByRole } = render(wrapProvider()); - - expect(getByRole('button', { name: 'Mint' })).toBeInTheDocument(); - }); - it('should display my agents', async () => { - const { container } = render(wrapProvider()); + const { container, findByTestId } = render(wrapProvider()); const myAgentsTab = container.querySelector('.ant-tabs-tab:nth-child(2)'); if (!myAgentsTab) { @@ -195,7 +176,7 @@ describe('listAgents/index.jsx', () => { } // click the `My agents` tab - userEvent.click(myAgentsTab); + await userEvent.click(myAgentsTab); // check if the selected tab is `My` & has the correct content await waitFor(async () => @@ -205,24 +186,57 @@ describe('listAgents/index.jsx', () => { ); const firstAgent = myAgentsResponse[0]; + const myAgentsTable = await findByTestId('my-agents-table'); - await waitFor(async () => { - expect(container.querySelector(getTableTd(1))?.textContent).toBe( - firstAgent.tokenId, - ); - expect(container.querySelector(getTableTd(2))?.textContent).toBe( - '0x8626...9C1000', - ); - expect(container.querySelector(getTableTd(3))?.textContent).toBe( - '0x9cf4...315ab0', - ); - expect(container.querySelector(getTableTd(4))?.textContent).toBe( - firstAgent.publicId, - ); - expect(container.querySelector(getTableTd(5))?.textContent).toBe( - 'View', - ); - }); + expect( + within(myAgentsTable).getByText(firstAgent.tokenId), + ).toBeInTheDocument(); + expect( + within(myAgentsTable).getByText(/0x8626...9C1000/), + ).toBeInTheDocument(); + expect( + within(myAgentsTable).getByText(/0x9cf4...315ab0/), + ).toBeInTheDocument(); + expect( + within(myAgentsTable).getByText(firstAgent.publicId), + ).toBeInTheDocument(); + expect(within(myAgentsTable).getByText('View')).toBeInTheDocument(); + }); + + it('should display my agents search', async () => { + const { container, getByRole, findByTestId, getByPlaceholderText } = + render(wrapProvider()); + + const myAgentsTab = container.querySelector('.ant-tabs-tab:nth-child(2)'); + if (!myAgentsTab) { + throw new Error('`My agents` tab is null'); + } + + // click the `My agents` tab + await userEvent.click(myAgentsTab); + + const searchInput = getByPlaceholderText('Search...'); + await userEvent.type(searchInput, '!'); + + const searchButton = getByRole('button', { name: 'Search' }); + await userEvent.click(searchButton); + + const firstAgent = allAgentsSearchResponse[0]; + const myAgentsTable = await findByTestId('my-agents-table'); + + expect( + within(myAgentsTable).getByText(firstAgent.tokenId), + ).toBeInTheDocument(); + expect( + within(myAgentsTable).getByText(/0x8626...9C1199/), + ).toBeInTheDocument(); + expect( + within(myAgentsTable).getByText(/0x9cf4...315ab0/), + ).toBeInTheDocument(); + expect( + within(myAgentsTable).getByText(firstAgent.publicId), + ).toBeInTheDocument(); + expect(within(myAgentsTable).getByText('View')).toBeInTheDocument(); }); }); }); diff --git a/apps/autonolas-registry/tests/components/ListComponents/index.test.jsx b/apps/autonolas-registry/tests/components/ListComponents/index.test.jsx index c947730f..a0a7b7a5 100644 --- a/apps/autonolas-registry/tests/components/ListComponents/index.test.jsx +++ b/apps/autonolas-registry/tests/components/ListComponents/index.test.jsx @@ -1,5 +1,6 @@ import { within, render, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; +import '@testing-library/jest-dom'; import ListComponents from '../../../components/ListComponents'; import { @@ -45,6 +46,14 @@ const allComponentsSearchResponse = [ }, ]; + +jest.mock('../../../components/ListComponents/utils', () => ({ + getComponents: jest.fn(), + getFilteredComponents: jest.fn(), + getTotalForAllComponents: jest.fn(), + getTotalForMyComponents: jest.fn(), +})); + jest.mock('../../../components/ListComponents/useComponents', () => ({ useAllComponents: () => () => Promise.resolve(allComponentsResponse), useMyComponents: () => () => Promise.resolve(myComponentsResponse), @@ -59,13 +68,6 @@ jest.mock('../../../common-util/hooks/useSvmConnectivity', () => ({ useSvmConnectivity: () => svmConnectivityEmptyMock, })); -jest.mock('../../../components/ListComponents/utils', () => ({ - getComponents: jest.fn(), - getFilteredComponents: jest.fn(), - getTotalForAllComponents: jest.fn(), - getTotalForMyComponents: jest.fn(), -})); - describe.skip('listComponents/index.jsx', () => { beforeEach(() => { jest.clearAllMocks(); @@ -76,30 +78,38 @@ describe.skip('listComponents/index.jsx', () => { }); it('should display the column names', async () => { - const { container, getByText } = render(wrapProvider()); + const { container, findByTestId } = render( + wrapProvider(), + ); if (!container) { throw new Error('`All tab` is null'); } + const allComponentsTable = await findByTestId('all-components-table'); + await waitFor(async () => { - expect(getByText('ID')).toBeInTheDocument(); - expect(getByText('Owner')).toBeInTheDocument(); - expect(getByText('Hash')).toBeInTheDocument(); - expect(getByText('Package Name')).toBeInTheDocument(); - expect(getByText('Action')).toBeInTheDocument(); + expect(within(allComponentsTable).getByText('ID')).toBeInTheDocument(); + expect(within(allComponentsTable).getByText('Owner')).toBeInTheDocument(); + expect(within(allComponentsTable).getByText('Hash')).toBeInTheDocument(); + expect( + within(allComponentsTable).getByText('Package Name'), + ).toBeInTheDocument(); + expect(within(allComponentsTable).getByText('Action')).toBeInTheDocument(); }); }); - describe('All Components', () => { - it('should display mint button', async () => { - const { getByRole } = render(wrapProvider()); + it('should display mint button', async () => { + const { getByRole } = render(wrapProvider()); - expect(getByRole('button', { name: 'Mint' })).toBeInTheDocument(); - }); + expect(getByRole('button', { name: 'Mint' })).toBeInTheDocument(); + }); + describe('All Components', () => { it('should display all components', async () => { - const { container, getByTestId } = render(wrapProvider()); + const { container, findByTestId } = render( + wrapProvider(), + ); if (!container) { throw new Error('`All tab` is null'); @@ -112,27 +122,27 @@ describe.skip('listComponents/index.jsx', () => { const firstAgent = allComponentsResponse[0]; - await waitFor(async () => { - expect( - within(getByTestId('agent-table')).getByText(firstAgent.tokenId), - ).toBeInTheDocument(); - expect( - within(getByTestId('agent-table')).getByText(/0x8626...9C1199/), - ).toBeInTheDocument(); - expect( - within(getByTestId('agent-table')).getByText(/0x9cf4...315ab0/), - ).toBeInTheDocument(); - expect( - within(getByTestId('agent-table')).getByText(firstAgent.publicId), - ).toBeInTheDocument(); - expect( - within(getByTestId('agent-table')).getByText('View'), - ).toBeInTheDocument(); - }); + expect( + within(await findByTestId('agent-table')).getByText(firstAgent.tokenId), + ).toBeInTheDocument(); + expect( + within(await findByTestId('agent-table')).getByText(/0x8626...9C1199/), + ).toBeInTheDocument(); + expect( + within(await findByTestId('agent-table')).getByText(/0x9cf4...315ab0/), + ).toBeInTheDocument(); + expect( + within(await findByTestId('agent-table')).getByText( + firstAgent.publicId, + ), + ).toBeInTheDocument(); + expect( + within(await findByTestId('agent-table')).getByText('View'), + ).toBeInTheDocument(); }); it('should display all components search', async () => { - const { container, getByTestId, getByRole, getByPlaceholderText } = + const { container, getByRole, findByTestId, getByPlaceholderText } = render(wrapProvider()); if (!container) { @@ -140,30 +150,38 @@ describe.skip('listComponents/index.jsx', () => { } const searchInput = getByPlaceholderText('Search...'); - await userEvent.type(searchInput, 'good_package_name_components_search'); + await userEvent.type(searchInput, '!'); const searchButton = getByRole('button', { name: 'Search' }); await userEvent.click(searchButton); const firstAgent = allComponentsSearchResponse[0]; - await waitFor(async () => { - expect( - within(getByTestId('agent-table')).getByText(firstAgent.tokenId), - ).toBeInTheDocument(); - expect( - within(getByTestId('agent-table')).getByText(/0x8626...9C1199/), - ).toBeInTheDocument(); - expect( - within(getByTestId('agent-table')).getByText(/0x9cf4...315ab0/), - ).toBeInTheDocument(); - expect( - within(getByTestId('agent-table')).getByText(firstAgent.publicId), - ).toBeInTheDocument(); - expect( - within(getByTestId('agent-table')).getByText('View'), - ).toBeInTheDocument(); - }); + expect( + within(await findByTestId('agent-table')).getByText(firstAgent.tokenId), + ).toBeInTheDocument(); + expect( + within(await findByTestId('agent-table')).getByText(/0x8626...9C1199/), + ).toBeInTheDocument(); + expect( + within(await findByTestId('agent-table')).getByText(/0x9cf4...315ab0/), + ).toBeInTheDocument(); + expect( + within(await findByTestId('agent-table')).getByText( + firstAgent.publicId, + ), + ).toBeInTheDocument(); + expect( + within(await findByTestId('agent-table')).getByText('View'), + ).toBeInTheDocument(); + }); + }); + + describe('My Components', () => { + it('should display mint button', async () => { + const { findByRole } = render(wrapProvider()); + + expect(await findByRole('button', { name: 'Mint' })).toBeInTheDocument(); }); }); }); From 32483c95ca11e23f046ecfddfc11750ab69d21d5 Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Fri, 5 Apr 2024 16:45:35 +0530 Subject: [PATCH 23/39] tiny --- apps/autonolas-registry/common-util/List/ListTable/helpers.jsx | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/autonolas-registry/common-util/List/ListTable/helpers.jsx b/apps/autonolas-registry/common-util/List/ListTable/helpers.jsx index efd60e01..fb6dd59d 100644 --- a/apps/autonolas-registry/common-util/List/ListTable/helpers.jsx +++ b/apps/autonolas-registry/common-util/List/ListTable/helpers.jsx @@ -283,7 +283,6 @@ export const useExtraTabContent = ({
  • Name
  • Description
  • Owner
  • -
  • Public ID
  • Package Hash
  • From 8b0a5e1342479ff258678434dc40af464935ff8f Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Sat, 6 Apr 2024 17:05:36 +0530 Subject: [PATCH 24/39] fixes for service --- .../common-util/hooks/useSubgraph.jsx | 14 +- .../components/ListAgents/index.jsx | 1 + .../components/ListComponents/index.jsx | 8 +- .../ListServices/hooks/useServiceList.jsx | 143 ++++++++---------- .../components/ListServices/index.jsx | 72 +++++---- .../{index.test.jsx => index.test.tsx} | 121 +++++++++++---- 6 files changed, 201 insertions(+), 158 deletions(-) rename apps/autonolas-registry/tests/components/ListComponents/{index.test.jsx => index.test.tsx} (52%) diff --git a/apps/autonolas-registry/common-util/hooks/useSubgraph.jsx b/apps/autonolas-registry/common-util/hooks/useSubgraph.jsx index 6d3e84de..355ad44e 100644 --- a/apps/autonolas-registry/common-util/hooks/useSubgraph.jsx +++ b/apps/autonolas-registry/common-util/hooks/useSubgraph.jsx @@ -1,25 +1,23 @@ import { useMemo } from 'react'; import { GraphQLClient } from 'graphql-request'; +import { HASH_PREFIX } from '../../util/constants'; export const useSubgraph = () => { const graphQlClient = useMemo( - () => new GraphQLClient( - process.env.NEXT_PUBLIC_AUTONOLAS_SUB_GRAPH_URL, - { + () => + new GraphQLClient(process.env.NEXT_PUBLIC_AUTONOLAS_SUB_GRAPH_URL, { method: 'POST', jsonSerializer: { parse: JSON.parse, stringify: JSON.stringify, }, - }, - ), - [] + }), + [], ); return graphQlClient; }; - export const columnsForAgentsAndComponents = `{ id tokenId @@ -39,12 +37,14 @@ export const columnsForAgentsAndComponents = `{ * @returns {string} search filter sub query */ export const getSearchFilterSubQueryForAgentsAndComponents = (searchValue) => { + const completeMetadataHash = searchValue.replace(/0x/g, HASH_PREFIX); return `{ or: [ { publicId_contains_nocase: "${searchValue}" } { description_contains_nocase: "${searchValue}" } { packageHash_contains_nocase: "${searchValue}" } { owner_contains_nocase: "${searchValue}" } + { metadataHash_contains_nocase: "${completeMetadataHash}" } ] }`; }; diff --git a/apps/autonolas-registry/components/ListAgents/index.jsx b/apps/autonolas-registry/components/ListAgents/index.jsx index 2fc00a18..166118c6 100644 --- a/apps/autonolas-registry/components/ListAgents/index.jsx +++ b/apps/autonolas-registry/components/ListAgents/index.jsx @@ -158,6 +158,7 @@ const ListAgents = () => { ); setList(filteredList); } + setTotal(0); // total won't be used if search is used setCurrentPage(1); } catch (e) { diff --git a/apps/autonolas-registry/components/ListComponents/index.jsx b/apps/autonolas-registry/components/ListComponents/index.jsx index be6e6ce5..513279c9 100644 --- a/apps/autonolas-registry/components/ListComponents/index.jsx +++ b/apps/autonolas-registry/components/ListComponents/index.jsx @@ -100,7 +100,6 @@ const ListComponents = () => { try { // All components if (currentTab === ALL_COMPONENTS) { - setList([]); const everyComps = chainId === 1 ? await getAllComponents(currentPage) @@ -127,16 +126,16 @@ const ListComponents = () => { } })(); }, [ + isSvm, + searchValue, + isL1OnlyNetwork, account, chainId, - isL1OnlyNetwork, total, currentPage, - isSvm, getMyComponents, getAllComponents, currentTab, - searchValue, ]); /** @@ -200,7 +199,6 @@ const ListComponents = () => { onChange={(e) => { setCurrentTab(e); - setList([]); setTotal(0); setCurrentPage(1); setIsLoading(true); diff --git a/apps/autonolas-registry/components/ListServices/hooks/useServiceList.jsx b/apps/autonolas-registry/components/ListServices/hooks/useServiceList.jsx index ed19a9d2..05db3793 100644 --- a/apps/autonolas-registry/components/ListServices/hooks/useServiceList.jsx +++ b/apps/autonolas-registry/components/ListServices/hooks/useServiceList.jsx @@ -19,30 +19,48 @@ const transformToTableData = (data) => { })); }; +const serviceColumns = `{ + id + serviceId + tokenId + packageHash + metadataHash + state +}`; + +/** + * Searches by + * - publicId (package name) + * - description, + * - tokenId + * - packageHash + * - owner + * @returns {string} search filter sub query + */ +export const getSearchFilterSubQueryForServices = (searchValue) => { + return `{ + or: [ + { publicId_contains_nocase: "${searchValue}" } + { description_contains_nocase: "${searchValue}" } + { packageHash_contains_nocase: "${searchValue}" } + { owner_contains_nocase: "${searchValue}" } + ] + }`; +}; + /** * Hook to get ALL units * @returns {function} function to get all units * */ -export const useAllUnits = () => { +export const useAllServices = () => { const graphQlClient = useSubgraph(); return useCallback( - async (type, currentPage) => { + async (currentPage) => { const query = gql` { - units( - first: ${TOTAL_VIEW_COUNT}, - skip: ${TOTAL_VIEW_COUNT * (currentPage - 1)}, - where: { packageType: "${type}" }, - orderBy: tokenId - ) { - id - packageType - tokenId - packageHash - metadataHash - } + services ${serviceColumns} } `; @@ -54,37 +72,24 @@ export const useAllUnits = () => { }; /** - * Hook to get ALL units by search - * @returns {function} function to get all units by search + * Hook to get MY units + * @returns {function} function to get my units */ -export const useAllUnitsBySearch = () => { +export const useMyServices = () => { const graphQlClient = useSubgraph(); return useCallback( - async (type, searchValue, currentPage) => { + async (type, ownerAddress, currentPage) => { const query = gql` { - units( + services ( first: ${TOTAL_VIEW_COUNT}, skip: ${TOTAL_VIEW_COUNT * (currentPage - 1)}, - OR: [ - { - packageType: "${type}", - name_contains: "${searchValue}" - }, - { - packageType: "${type}", - packageHash_contains: "${searchValue}" - } - ], - orderBy: tokenId - ) { - id - packageType - tokenId - packageHash - metadataHash - } + where: { + owner_contains_nocase: "${ownerAddress}" + }, + orderBy: tokenId, + ) ${serviceColumns} } `; @@ -96,31 +101,22 @@ export const useAllUnitsBySearch = () => { }; /** - * Hook to get MY units - * @returns {function} function to get my units + * Hook to get ALL units by search + * @returns {function} function to get all units by search */ -export const useMyUnits = () => { +export const useAllServicesBySearch = () => { const graphQlClient = useSubgraph(); return useCallback( - async (type, ownerAddress, currentPage) => { + async (type, searchValue, currentPage) => { const query = gql` { - units( + services ( first: ${TOTAL_VIEW_COUNT}, skip: ${TOTAL_VIEW_COUNT * (currentPage - 1)}, - where: { - owner: "${ownerAddress}", - packageType: "${type}" - }, - orderBy: tokenId, - ) { - id - packageType - tokenId - packageHash - metadataHash - } + where: ${getSearchFilterSubQueryForServices(searchValue)}, + orderBy: tokenId + ) ${serviceColumns} } `; @@ -135,35 +131,24 @@ export const useMyUnits = () => { * Hook to get MY units by search * @returns {function} function to search units */ -export const useMyUnitsBySearch = () => { +export const useMyServicesBySearch = () => { const graphQlClient = useSubgraph(); return useCallback( async (type, ownerAddress, searchValue, currentPage) => { const query = gql` { - units( + services ( first: ${TOTAL_VIEW_COUNT}, skip: ${TOTAL_VIEW_COUNT * (currentPage - 1)}, - where: { owner: "${ownerAddress}" } - OR: [ - { - packageType: "${type}", - name_contains: "${searchValue}" - }, - { - packageType: "${type}", - packageHash_contains: "${searchValue}" - } - ], + where: { + and: [ + owner_contains_nocase: "${ownerAddress}" + ${getSearchFilterSubQueryForServices(searchValue)} + ] + } orderBy: tokenId, - ) { - id - packageType - tokenId - packageHash - metadataHash - } + ) ${serviceColumns} } `; @@ -174,14 +159,14 @@ export const useMyUnitsBySearch = () => { ); }; -export const useSearchUnits = () => { - const getAllUnitsBySearch = useAllUnitsBySearch(); - const getMyUnitsBySearch = useMyUnitsBySearch(); +export const useSearchServices = () => { + const getAllUnitsBySearch = useAllServicesBySearch(); + const getMyServicesBySearch = useMyServicesBySearch(); return useCallback( async (type, searchValue, currentPage, ownerAddress) => { if (ownerAddress) { - return await getMyUnitsBySearch( + return await getMyServicesBySearch( type, ownerAddress, searchValue, @@ -190,6 +175,6 @@ export const useSearchUnits = () => { } return await getAllUnitsBySearch(type, searchValue, currentPage); }, - [getAllUnitsBySearch, getMyUnitsBySearch], + [getAllUnitsBySearch, getMyServicesBySearch], ); }; diff --git a/apps/autonolas-registry/components/ListServices/index.jsx b/apps/autonolas-registry/components/ListServices/index.jsx index cdecbd42..99db67ab 100644 --- a/apps/autonolas-registry/components/ListServices/index.jsx +++ b/apps/autonolas-registry/components/ListServices/index.jsx @@ -13,9 +13,9 @@ import { import { getMyListOnPagination } from '../../common-util/ContractUtils/myList'; import { useHelpers } from '../../common-util/hooks'; import { - useAllUnits, - useMyUnits, - useSearchUnits, + useAllServices, + useMyServices, + useSearchServices, } from './hooks/useServiceList'; import { useServiceInfo } from './hooks/useSvmService'; import { @@ -37,9 +37,9 @@ const ListServices = () => { const { account, chainName, links, isSvm, chainId } = useHelpers(); - const getAllUnits = useAllUnits(); - const getMyUnits = useMyUnits(); - const getUnitsBySearch = useSearchUnits(); + const getAllServices = useAllServices(); + const getMyUnits = useMyServices(); + const getUnitsBySearch = useSearchServices(); /** * extra tab content & view click @@ -62,7 +62,6 @@ const ListServices = () => { // update current tab based on the "hash" in the URL useEffect(() => { setCurrentTab(isMyTab(hash) ? MY_SERVICES : ALL_SERVICES); - setList([]); }, [router.asPath, hash]); const { @@ -112,8 +111,6 @@ const ListServices = () => { getSvmServices, ]); - const isListEmpty = list.length === 0; - // fetch the list (All services, My Services) - WITHOUT search useEffect(() => { const getList = async () => { @@ -123,7 +120,7 @@ const ListServices = () => { // All services if (currentTab === ALL_SERVICES) { if (chainId === 1) { - const e = await getAllUnits(NAV_TYPES.SERVICE, currentPage); + const e = await getAllServices(NAV_TYPES.SERVICE, currentPage); setList(e); } else { const e = isSvm @@ -131,7 +128,7 @@ const ListServices = () => { : await getServices(total, currentPage); setList(e); } - } else if (currentTab === MY_SERVICES && isListEmpty && account) { + } else if (currentTab === MY_SERVICES && account) { /** * My services * - search by `account` as searchValue @@ -173,10 +170,9 @@ const ListServices = () => { searchValue, isSvm, getMyUnits, - getAllUnits, + getAllServices, getSvmServices, getMySvmServices, - isListEmpty, ]); /** @@ -186,34 +182,34 @@ const ListServices = () => { */ useEffect(() => { (async () => { - if (searchValue) { - setIsLoading(true); + if (!searchValue) return; - try { - if (chainId === 1) { - const filteredList = await getUnitsBySearch( - NAV_TYPES.SERVICE, - searchValue, - currentPage, - currentTab === MY_SERVICES ? account : null, - ); - setList(filteredList); - } else { - const filteredList = await getFilteredServices( - searchValue, - currentTab === MY_SERVICES ? account : null, - ); - setList(filteredList); - } + setIsLoading(true); - setTotal(0); // total won't be used if search is used - setCurrentPage(1); - } catch (e) { - console.error(e); - notifyError('Error fetching services'); - } finally { - setIsLoading(false); + try { + if (chainId === 1) { + const filteredList = await getUnitsBySearch( + NAV_TYPES.SERVICE, + searchValue, + currentPage, + currentTab === MY_SERVICES ? account : null, + ); + setList(filteredList); + } else { + const filteredList = await getFilteredServices( + searchValue, + currentTab === MY_SERVICES ? account : null, + ); + setList(filteredList); } + + setTotal(0); // total won't be used if search is used + setCurrentPage(1); + } catch (e) { + console.error(e); + notifyError('Error fetching services'); + } finally { + setIsLoading(false); } })(); }, [ diff --git a/apps/autonolas-registry/tests/components/ListComponents/index.test.jsx b/apps/autonolas-registry/tests/components/ListComponents/index.test.tsx similarity index 52% rename from apps/autonolas-registry/tests/components/ListComponents/index.test.jsx rename to apps/autonolas-registry/tests/components/ListComponents/index.test.tsx index a0a7b7a5..7551091c 100644 --- a/apps/autonolas-registry/tests/components/ListComponents/index.test.jsx +++ b/apps/autonolas-registry/tests/components/ListComponents/index.test.tsx @@ -46,7 +46,6 @@ const allComponentsSearchResponse = [ }, ]; - jest.mock('../../../components/ListComponents/utils', () => ({ getComponents: jest.fn(), getFilteredComponents: jest.fn(), @@ -68,13 +67,15 @@ jest.mock('../../../common-util/hooks/useSvmConnectivity', () => ({ useSvmConnectivity: () => svmConnectivityEmptyMock, })); -describe.skip('listComponents/index.jsx', () => { +describe('listComponents/index.jsx', () => { beforeEach(() => { jest.clearAllMocks(); - getComponents.mockResolvedValue(allComponentsResponse); - getFilteredComponents.mockResolvedValue(myComponentsResponse); - getTotalForAllComponents.mockResolvedValue(1); - getTotalForMyComponents.mockResolvedValue(1); + (getComponents as jest.Mock).mockResolvedValue(allComponentsResponse); + (getFilteredComponents as jest.Mock).mockResolvedValue( + myComponentsResponse, + ); + (getTotalForAllComponents as jest.Mock).mockResolvedValue(1); + (getTotalForMyComponents as jest.Mock).mockResolvedValue(1); }); it('should display the column names', async () => { @@ -95,14 +96,16 @@ describe.skip('listComponents/index.jsx', () => { expect( within(allComponentsTable).getByText('Package Name'), ).toBeInTheDocument(); - expect(within(allComponentsTable).getByText('Action')).toBeInTheDocument(); + expect( + within(allComponentsTable).getByText('Action'), + ).toBeInTheDocument(); }); }); it('should display mint button', async () => { - const { getByRole } = render(wrapProvider()); + const { findByRole } = render(wrapProvider()); - expect(getByRole('button', { name: 'Mint' })).toBeInTheDocument(); + expect(await findByRole('button', { name: 'Mint' })).toBeInTheDocument(); }); describe('All Components', () => { @@ -121,24 +124,21 @@ describe.skip('listComponents/index.jsx', () => { ); const firstAgent = allComponentsResponse[0]; + const allComponentsTable = await findByTestId('all-components-table'); expect( - within(await findByTestId('agent-table')).getByText(firstAgent.tokenId), - ).toBeInTheDocument(); - expect( - within(await findByTestId('agent-table')).getByText(/0x8626...9C1199/), + within(allComponentsTable).getByText(firstAgent.tokenId), ).toBeInTheDocument(); expect( - within(await findByTestId('agent-table')).getByText(/0x9cf4...315ab0/), + within(allComponentsTable).getByText(/0x8626...9C1199/), ).toBeInTheDocument(); expect( - within(await findByTestId('agent-table')).getByText( - firstAgent.publicId, - ), + within(allComponentsTable).getByText(/0x9cf4...315ab0/), ).toBeInTheDocument(); expect( - within(await findByTestId('agent-table')).getByText('View'), + within(allComponentsTable).getByText(firstAgent.publicId), ).toBeInTheDocument(); + expect(within(allComponentsTable).getByText('View')).toBeInTheDocument(); }); it('should display all components search', async () => { @@ -156,32 +156,95 @@ describe.skip('listComponents/index.jsx', () => { await userEvent.click(searchButton); const firstAgent = allComponentsSearchResponse[0]; + const allComponentsTable = await findByTestId('all-components-table'); expect( - within(await findByTestId('agent-table')).getByText(firstAgent.tokenId), + within(allComponentsTable).getByText(firstAgent.tokenId), ).toBeInTheDocument(); expect( - within(await findByTestId('agent-table')).getByText(/0x8626...9C1199/), + within(allComponentsTable).getByText(/0x8626...9C1199/), ).toBeInTheDocument(); expect( - within(await findByTestId('agent-table')).getByText(/0x9cf4...315ab0/), + within(allComponentsTable).getByText(/0x9cf4...315ab0/), ).toBeInTheDocument(); expect( - within(await findByTestId('agent-table')).getByText( - firstAgent.publicId, + within(allComponentsTable).getByText(firstAgent.publicId), + ).toBeInTheDocument(); + expect(within(allComponentsTable).getByText('View')).toBeInTheDocument(); + }); + }); + + describe('My Components', () => { + it('should display my components', async () => { + const { container, findByTestId } = render(wrapProvider()); + + const myComponentsTab = container.querySelector('.ant-tabs-tab:nth-child(2)'); + if (!myComponentsTab) { + throw new Error('`My components` tab is null'); + } + + // click the `My components` tab + await userEvent.click(myComponentsTab); + + // check if the selected tab is `My` & has the correct content + await waitFor(async () => + expect(container.querySelector(ACTIVE_TAB)?.textContent).toBe( + 'My Components', ), + ); + + const firstAgent = myComponentsResponse[0]; + const myComponentsTable = await findByTestId('my-components-table'); + + expect( + within(myComponentsTable).getByText(firstAgent.tokenId), + ).toBeInTheDocument(); + expect( + within(myComponentsTable).getByText(/0x8626...9C1000/), + ).toBeInTheDocument(); + expect( + within(myComponentsTable).getByText(/0x9cf4...315ab0/), ).toBeInTheDocument(); expect( - within(await findByTestId('agent-table')).getByText('View'), + within(myComponentsTable).getByText(firstAgent.publicId), ).toBeInTheDocument(); + expect(within(myComponentsTable).getByText('View')).toBeInTheDocument(); }); - }); - describe('My Components', () => { - it('should display mint button', async () => { - const { findByRole } = render(wrapProvider()); + it('should display my components search', async () => { + const { container, getByRole, findByTestId, getByPlaceholderText } = + render(wrapProvider()); + + const myComponentsTab = container.querySelector('.ant-tabs-tab:nth-child(2)'); + if (!myComponentsTab) { + throw new Error('`My components` tab is null'); + } + + // click the `My components` tab + await userEvent.click(myComponentsTab); + + const searchInput = getByPlaceholderText('Search...'); + await userEvent.type(searchInput, '!'); + + const searchButton = getByRole('button', { name: 'Search' }); + await userEvent.click(searchButton); + + const firstAgent = allComponentsSearchResponse[0]; + const myComponentsTable = await findByTestId('my-components-table'); - expect(await findByRole('button', { name: 'Mint' })).toBeInTheDocument(); + expect( + within(myComponentsTable).getByText(firstAgent.tokenId), + ).toBeInTheDocument(); + expect( + within(myComponentsTable).getByText(/0x8626...9C1199/), + ).toBeInTheDocument(); + expect( + within(myComponentsTable).getByText(/0x9cf4...315ab0/), + ).toBeInTheDocument(); + expect( + within(myComponentsTable).getByText(firstAgent.publicId), + ).toBeInTheDocument(); + expect(within(myComponentsTable).getByText('View')).toBeInTheDocument(); }); }); }); From b51044377676e83bcf2b9b5ce775254261ac62ad Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Sat, 6 Apr 2024 17:21:23 +0530 Subject: [PATCH 25/39] comment out services changes --- .../components/ListServices/index.jsx | 96 ++++++++++--------- 1 file changed, 49 insertions(+), 47 deletions(-) diff --git a/apps/autonolas-registry/components/ListServices/index.jsx b/apps/autonolas-registry/components/ListServices/index.jsx index 99db67ab..4e951dd6 100644 --- a/apps/autonolas-registry/components/ListServices/index.jsx +++ b/apps/autonolas-registry/components/ListServices/index.jsx @@ -12,11 +12,11 @@ import { } from '../../common-util/List/ListTable/helpers'; import { getMyListOnPagination } from '../../common-util/ContractUtils/myList'; import { useHelpers } from '../../common-util/hooks'; -import { - useAllServices, - useMyServices, - useSearchServices, -} from './hooks/useServiceList'; +// import { +// useAllServices, +// useMyServices, +// useSearchServices, +// } from './hooks/useServiceList'; import { useServiceInfo } from './hooks/useSvmService'; import { getServices, @@ -37,9 +37,9 @@ const ListServices = () => { const { account, chainName, links, isSvm, chainId } = useHelpers(); - const getAllServices = useAllServices(); - const getMyUnits = useMyServices(); - const getUnitsBySearch = useSearchServices(); + // const getAllServices = useAllServices(); + // const getMyServices = useMyServices(); + // const getServicesBySearch = useSearchServices(); /** * extra tab content & view click @@ -119,35 +119,36 @@ const ListServices = () => { try { // All services if (currentTab === ALL_SERVICES) { - if (chainId === 1) { - const e = await getAllServices(NAV_TYPES.SERVICE, currentPage); - setList(e); - } else { - const e = isSvm - ? await getSvmServices(total, currentPage) - : await getServices(total, currentPage); - setList(e); - } + // if (chainId === 1) { + // const e = await getAllServices(NAV_TYPES.SERVICE, currentPage); + // setList(e); + // } else { + const e = isSvm + ? await getSvmServices(total, currentPage) + : await getServices(total, currentPage); + setList(e); + // } } else if (currentTab === MY_SERVICES && account) { /** * My services * - search by `account` as searchValue * - API will be called only once & store the complete list */ - if (chainId === 1) { - const e = await getMyUnits(NAV_TYPES.SERVICE, account); - setList(e); - } else { - const e = isSvm - ? await getMySvmServices(account, total) - : await getFilteredServices(account); - setList(e); + // if (chainId === 1) { + // const e = await getMyServices(NAV_TYPES.SERVICE, account); + // setList(e); + // } else + // { + const e = isSvm + ? await getMySvmServices(account, total) + : await getFilteredServices(account); + setList(e); - // TODO: remove this once `getTotalForMySvmServices` is fixed - if (isSvm) { - setTotal(e.length); - } + // TODO: remove this once `getTotalForMySvmServices` is fixed + if (isSvm) { + setTotal(e.length); } + // } } } catch (e) { console.error(e); @@ -169,8 +170,8 @@ const ListServices = () => { currentTab, searchValue, isSvm, - getMyUnits, - getAllServices, + // getMyServices, + // getAllServices, getSvmServices, getMySvmServices, ]); @@ -187,21 +188,22 @@ const ListServices = () => { setIsLoading(true); try { - if (chainId === 1) { - const filteredList = await getUnitsBySearch( - NAV_TYPES.SERVICE, - searchValue, - currentPage, - currentTab === MY_SERVICES ? account : null, - ); - setList(filteredList); - } else { - const filteredList = await getFilteredServices( - searchValue, - currentTab === MY_SERVICES ? account : null, - ); - setList(filteredList); - } + // if (chainId === 1) { + // const filteredList = await getServicesBySearch( + // NAV_TYPES.SERVICE, + // searchValue, + // currentPage, + // currentTab === MY_SERVICES ? account : null, + // ); + // setList(filteredList); + // } + // else { + const filteredList = await getFilteredServices( + searchValue, + currentTab === MY_SERVICES ? account : null, + ); + setList(filteredList); + // } setTotal(0); // total won't be used if search is used setCurrentPage(1); @@ -219,7 +221,7 @@ const ListServices = () => { currentTab, chainId, currentPage, - getUnitsBySearch, + // getServicesBySearch, ]); const tableCommonProps = { From daf79feec6f15aa2264f2301e7c5320bb5501985 Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Mon, 8 Apr 2024 16:00:56 +0530 Subject: [PATCH 26/39] add condition for mainnet in useHelpers --- .../common-util/List/ListTable/helpers.jsx | 16 +++++++++--- .../common-util/List/ListTable/index.jsx | 5 ++-- .../common-util/hooks/useHelpers.jsx | 1 + .../components/ListAgents/index.jsx | 25 +++++++++---------- .../components/ListComponents/index.jsx | 23 ++++++++--------- 5 files changed, 39 insertions(+), 31 deletions(-) diff --git a/apps/autonolas-registry/common-util/List/ListTable/helpers.jsx b/apps/autonolas-registry/common-util/List/ListTable/helpers.jsx index fb6dd59d..d6e33057 100644 --- a/apps/autonolas-registry/common-util/List/ListTable/helpers.jsx +++ b/apps/autonolas-registry/common-util/List/ListTable/helpers.jsx @@ -20,7 +20,15 @@ const { Title } = Typography; export const getTableColumns = ( type, - { onViewClick, onUpdateClick, isMobile, chainName, account, chainId }, + { + onViewClick, + onUpdateClick, + isMobile, + chainName, + account, + chainId, + isMainnet, + }, ) => { const addressLinkProps = { chainId, @@ -101,7 +109,7 @@ export const getTableColumns = ( ), }; - return chainId === 1 + return isMainnet ? [tokenIdColumn, ownerColumn, ...otherEthColumns, actionColumn] : [tokenIdColumn, ownerColumn, dependencyColumn, actionColumn]; } @@ -176,7 +184,7 @@ export const getTableColumns = ( return []; }; -export const fetchDataSource = (type, rawData, { current, chainId }) => { +export const fetchDataSource = (type, rawData, { current, isMainnet }) => { /** * @example * TOTAL_VIEW_COUNT = 10, current = 1 @@ -191,7 +199,7 @@ export const fetchDataSource = (type, rawData, { current, chainId }) => { const startIndex = (current - 1) * TOTAL_VIEW_COUNT + 1; // for mainnet - if (chainId === 1) { + if (isMainnet) { if (type === NAV_TYPES.COMPONENT || type === NAV_TYPES.AGENT) { return rawData.map((item) => ({ id: item.tokenId, diff --git a/apps/autonolas-registry/common-util/List/ListTable/index.jsx b/apps/autonolas-registry/common-util/List/ListTable/index.jsx index 7104bc50..950b8044 100644 --- a/apps/autonolas-registry/common-util/List/ListTable/index.jsx +++ b/apps/autonolas-registry/common-util/List/ListTable/index.jsx @@ -22,7 +22,7 @@ const ListTable = ({ extra, tableDataTestId, }) => { - const { chainName, account, isSvm, chainId } = useHelpers(); + const { chainName, account, isSvm, chainId, isMainnet } = useHelpers(); /** * no pagination on search as we won't know total beforehand */ @@ -52,10 +52,11 @@ const ListTable = ({ chainName, chainId, account, + isMainnet, }); const dataSource = fetchDataSource(type, list, { current: currentPage, - chainId, + isMainnet, }); const pagination = { total, diff --git a/apps/autonolas-registry/common-util/hooks/useHelpers.jsx b/apps/autonolas-registry/common-util/hooks/useHelpers.jsx index 09f50b4d..3839d013 100644 --- a/apps/autonolas-registry/common-util/hooks/useHelpers.jsx +++ b/apps/autonolas-registry/common-util/hooks/useHelpers.jsx @@ -65,6 +65,7 @@ export const useHelpers = () => { doesNetworkHaveValidServiceManagerTokenFn(chainId), links: updatedLinks, isConnectedToWrongNetwork, + isMainnet: chainId === 1, isSvm, }; }; diff --git a/apps/autonolas-registry/components/ListAgents/index.jsx b/apps/autonolas-registry/components/ListAgents/index.jsx index 166118c6..4e2c66e1 100644 --- a/apps/autonolas-registry/components/ListAgents/index.jsx +++ b/apps/autonolas-registry/components/ListAgents/index.jsx @@ -29,7 +29,8 @@ const ListAgents = () => { isMyTab(hash) ? MY_AGENTS : ALL_AGENTS, ); - const { account, chainId, links, isL1OnlyNetwork, isSvm } = useHelpers(); + const { account, chainId, links, isL1OnlyNetwork, isSvm, isMainnet } = + useHelpers(); const getAllAgents = useAllAgents(); const getMyAgents = useMyAgents(); @@ -96,10 +97,9 @@ const ListAgents = () => { try { // All agents if (currentTab === ALL_AGENTS) { - const everyAgents = - chainId === 1 - ? await getAllAgents(currentPage) - : await getAgents(total, currentPage); + const everyAgents = isMainnet + ? await getAllAgents(currentPage) + : await getAgents(total, currentPage); setList(everyAgents); } else if (currentTab === MY_AGENTS && account) { /** @@ -107,10 +107,9 @@ const ListAgents = () => { * - search by `account` as searchValue * - API will be called only once & store the complete list */ - const e = - chainId === 1 - ? await getMyAgents(account, currentPage) - : await getFilteredAgents(account); + const e = isMainnet + ? await getMyAgents(account, currentPage) + : await getFilteredAgents(account); setList(e); } } catch (e) { @@ -126,12 +125,12 @@ const ListAgents = () => { searchValue, isL1OnlyNetwork, account, - chainId, total, currentPage, getMyAgents, getAllAgents, currentTab, + isMainnet, ]); /** @@ -145,7 +144,7 @@ const ListAgents = () => { setIsLoading(true); try { - if (chainId === 1) { + if (isMainnet) { const filteredList = await getAgentsBySearch( searchValue, currentTab === MY_AGENTS ? account : null, @@ -158,7 +157,7 @@ const ListAgents = () => { ); setList(filteredList); } - + setTotal(0); // total won't be used if search is used setCurrentPage(1); } catch (e) { @@ -170,11 +169,11 @@ const ListAgents = () => { })(); }, [ account, - chainId, searchValue, currentTab, currentPage, getAgentsBySearch, + isMainnet, ]); const tableCommonProps = { diff --git a/apps/autonolas-registry/components/ListComponents/index.jsx b/apps/autonolas-registry/components/ListComponents/index.jsx index 513279c9..c8bb0256 100644 --- a/apps/autonolas-registry/components/ListComponents/index.jsx +++ b/apps/autonolas-registry/components/ListComponents/index.jsx @@ -33,7 +33,8 @@ const ListComponents = () => { isMyTab(hash) ? MY_COMPONENTS : ALL_COMPONENTS, ); - const { account, chainId, links, isL1OnlyNetwork, isSvm } = useHelpers(); + const { account, chainId, links, isL1OnlyNetwork, isSvm, isMainnet } = + useHelpers(); const getAllComponents = useAllComponents(); const getMyComponents = useMyComponents(); @@ -100,10 +101,9 @@ const ListComponents = () => { try { // All components if (currentTab === ALL_COMPONENTS) { - const everyComps = - chainId === 1 - ? await getAllComponents(currentPage) - : await getComponents(total, currentPage); + const everyComps = isMainnet + ? await getAllComponents(currentPage) + : await getComponents(total, currentPage); setList(everyComps); } else if (currentTab === MY_COMPONENTS && account) { /** @@ -111,10 +111,9 @@ const ListComponents = () => { * - search by `account` as searchValue * - API will be called only once & store the complete list */ - const e = - chainId === 1 - ? await getMyComponents(account, currentPage) - : await getFilteredComponents(account); + const e = isMainnet + ? await getMyComponents(account, currentPage) + : await getFilteredComponents(account); setList(e); } } catch (e) { @@ -130,12 +129,12 @@ const ListComponents = () => { searchValue, isL1OnlyNetwork, account, - chainId, total, currentPage, getMyComponents, getAllComponents, currentTab, + isMainnet, ]); /** @@ -149,7 +148,7 @@ const ListComponents = () => { setIsLoading(true); try { - if (chainId === 1) { + if (isMainnet) { const filteredList = await getComponentsBySearch( searchValue, currentTab === MY_COMPONENTS ? account : null, @@ -173,11 +172,11 @@ const ListComponents = () => { })(); }, [ account, - chainId, searchValue, currentTab, currentPage, getComponentsBySearch, + isMainnet, ]); const tableCommonProps = { From fa96df5103e928e06b60beab274e37a9535edda7 Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Mon, 8 Apr 2024 16:41:45 +0530 Subject: [PATCH 27/39] address Oak's comment --- .../common-util/Details/index.jsx | 41 ++++++++------- .../common-util/List/ListTable/helpers.jsx | 50 +++++++++---------- .../common-util/hooks/useMetadata.jsx | 1 + 3 files changed, 50 insertions(+), 42 deletions(-) diff --git a/apps/autonolas-registry/common-util/Details/index.jsx b/apps/autonolas-registry/common-util/Details/index.jsx index dd2320f1..67fec010 100644 --- a/apps/autonolas-registry/common-util/Details/index.jsx +++ b/apps/autonolas-registry/common-util/Details/index.jsx @@ -1,14 +1,13 @@ import { useState, useCallback } from 'react'; import PropTypes from 'prop-types'; import capitalize from 'lodash/capitalize'; -import { - Row, Col, Button, Typography, -} from 'antd'; +import { Row, Col, Button, Typography } from 'antd'; import { get } from 'lodash'; import { Loader, NA } from '@autonolas/frontend-library'; import { NAV_TYPES } from '../../util/constants'; import { useMetadata } from '../hooks/useMetadata'; +import { useHelpers } from '../hooks'; import { typePropType } from '../propTypes'; import { IpfsHashGenerationModal } from '../List/IpfsHashGenerationModal'; import { useDetails } from './useDetails'; @@ -31,16 +30,16 @@ export const Details = ({ }) => { const [isModalVisible, setIsModalVisible] = useState(false); - const { - isLoading, isOwner, info, ownerAddress, tokenUri, updateDetails, - } = useDetails({ - id, - type, - getDetails, - getOwner, - getTokenUri, - }); - const { nftImageUrl } = useMetadata(tokenUri); + const { isMainnet } = useHelpers(); + const { isLoading, isOwner, info, ownerAddress, tokenUri, updateDetails } = + useDetails({ + id, + type, + getDetails, + getOwner, + getTokenUri, + }); + const { nftImageUrl, packageName } = useMetadata(tokenUri); // Update button to be show only if the connected account is the owner // and only for agent and component @@ -58,10 +57,18 @@ export const Details = ({ <>
    - {`${capitalize(type)} Name`} - - {`${capitalize(type)} ID ${id}`} - + {isMainnet ? ( + <> + {packageName} + + ) : ( + <> + {`${capitalize(type)} Name`} + + {`${capitalize(type)} ID ${id}`} + + + )}
    diff --git a/apps/autonolas-registry/common-util/List/ListTable/helpers.jsx b/apps/autonolas-registry/common-util/List/ListTable/helpers.jsx index d6e33057..8e7d0a44 100644 --- a/apps/autonolas-registry/common-util/List/ListTable/helpers.jsx +++ b/apps/autonolas-registry/common-util/List/ListTable/helpers.jsx @@ -9,7 +9,6 @@ import { import styled from 'styled-components'; import { - GATEWAY_URL, HASH_PREFIX, NAV_TYPES, SERVICE_STATE, @@ -43,6 +42,21 @@ export const getTableColumns = ( width: isMobile ? 30 : 50, }; + const packageName = { + title: 'Package Name', + dataIndex: 'packageName', + key: 'packageName', + width: 180, + render: (text, record) => { + if (!text || text === NA) return NA; + return ( + + ); + }, + }; + const ownerColumn = { title: 'Owner', dataIndex: 'owner', @@ -75,24 +89,6 @@ export const getTableColumns = ( ); }, }, - { - title: 'Package Name', - dataIndex: 'packageName', - key: 'packageName', - width: 180, - render: (text, row) => { - if (!text || text === NA) return NA; - return ( - - {text} - - ); - }, - }, ]; const actionColumn = { @@ -101,16 +97,20 @@ export const getTableColumns = ( key: 'action', fixed: 'right', render: (_text, record) => ( - - - + ), }; return isMainnet - ? [tokenIdColumn, ownerColumn, ...otherEthColumns, actionColumn] + ? [ + tokenIdColumn, + packageName, + ownerColumn, + ...otherEthColumns, + actionColumn, + ] : [tokenIdColumn, ownerColumn, dependencyColumn, actionColumn]; } diff --git a/apps/autonolas-registry/common-util/hooks/useMetadata.jsx b/apps/autonolas-registry/common-util/hooks/useMetadata.jsx index a4589a0f..d8aacdd6 100644 --- a/apps/autonolas-registry/common-util/hooks/useMetadata.jsx +++ b/apps/autonolas-registry/common-util/hooks/useMetadata.jsx @@ -59,5 +59,6 @@ export const useMetadata = (tokenUri) => { codeHref, description: metadata?.description || NA, version: metadata?.attributes?.[0]?.value || NA, + packageName: metadata?.name || NA, }; }; From 241455526027817ea2f6e32c6acaa0fff3f04631 Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Mon, 8 Apr 2024 19:54:33 +0530 Subject: [PATCH 28/39] fixes --- .../common-util/List/ListTable/helpers.jsx | 244 ++++++++------- ...useServiceList.jsx => useServicesList.jsx} | 44 ++- .../components/ListServices/index.jsx | 122 ++++---- .../components/ListAgents/details.test.jsx | 4 +- .../components/ListAgents/index.test.tsx | 6 +- .../ListComponents/details.test.jsx | 2 +- .../components/ListComponents/index.test.tsx | 2 +- .../components/ListServices/details.test.jsx | 4 +- .../components/ListServices/index.test.jsx | 177 ----------- .../components/ListServices/index.test.tsx | 287 ++++++++++++++++++ .../tests/tests-helpers/index.jsx | 3 +- 11 files changed, 514 insertions(+), 381 deletions(-) rename apps/autonolas-registry/components/ListServices/hooks/{useServiceList.jsx => useServicesList.jsx} (81%) delete mode 100644 apps/autonolas-registry/tests/components/ListServices/index.test.jsx create mode 100644 apps/autonolas-registry/tests/components/ListServices/index.test.tsx diff --git a/apps/autonolas-registry/common-util/List/ListTable/helpers.jsx b/apps/autonolas-registry/common-util/List/ListTable/helpers.jsx index 8e7d0a44..8f595a3e 100644 --- a/apps/autonolas-registry/common-util/List/ListTable/helpers.jsx +++ b/apps/autonolas-registry/common-util/List/ListTable/helpers.jsx @@ -34,40 +34,54 @@ export const getTableColumns = ( suffixCount: isMobile ? 4 : 6, }; - if (type === NAV_TYPES.COMPONENT || type === NAV_TYPES.AGENT) { - const tokenIdColumn = { - title: 'ID', - dataIndex: 'tokenId', - key: 'tokenId', - width: isMobile ? 30 : 50, - }; + const tokenIdColumn = { + title: 'ID', + dataIndex: 'tokenId', + key: 'tokenId', + width: isMobile ? 30 : 50, + }; - const packageName = { - title: 'Package Name', - dataIndex: 'packageName', - key: 'packageName', - width: 180, - render: (text, record) => { - if (!text || text === NA) return NA; - return ( - - ); - }, - }; + const packageName = { + title: 'Name', + dataIndex: 'packageName', + key: 'packageName', + width: type === NAV_TYPES.SERVICE ? 200 : 180, + render: (text, record) => { + if (!text || text === NA) return NA; + return ( + + ); + }, + }; - const ownerColumn = { - title: 'Owner', - dataIndex: 'owner', - key: 'owner', - width: 160, - render: (text) => { - if (!text || text === NA) return NA; - return ; - }, - }; + const ownerColumn = { + title: 'Owner', + dataIndex: 'owner', + key: 'owner', + width: 160, + render: (text) => { + if (!text || text === NA) return NA; + return ; + }, + }; + const hashColumn = { + title: 'Hash', + dataIndex: 'hash', + key: 'hash', + width: 180, + render: (text) => { + if (!text || text === NA) return NA; + const updatedText = text.replace(HASH_PREFIX, '0x'); // .toUpperCase(); + return ( + + ); + }, + }; + + if (type === NAV_TYPES.COMPONENT || type === NAV_TYPES.AGENT) { const dependencyColumn = { title: 'No. of component dependencies', dataIndex: 'dependency', @@ -75,22 +89,6 @@ export const getTableColumns = ( key: 'dependency', }; - const otherEthColumns = [ - { - title: 'Hash', - dataIndex: 'hash', - key: 'hash', - width: 180, - render: (text) => { - if (!text || text === NA) return NA; - const updatedText = text.replace(HASH_PREFIX, '0x'); // .toUpperCase(); - return ( - - ); - }, - }, - ]; - const actionColumn = { width: isMobile ? 40 : 120, title: 'Action', @@ -104,81 +102,87 @@ export const getTableColumns = ( }; return isMainnet - ? [ - tokenIdColumn, - packageName, - ownerColumn, - ...otherEthColumns, - actionColumn, - ] + ? [tokenIdColumn, packageName, ownerColumn, hashColumn, actionColumn] : [tokenIdColumn, ownerColumn, dependencyColumn, actionColumn]; } if (type === NAV_TYPES.SERVICE) { - return [ - { - title: 'ID', - dataIndex: 'id', - key: 'id', - width: isMobile ? 30 : 50, - }, - { - title: 'Owner', - dataIndex: 'owner', - key: 'owner', - width: 200, - render: (text) => { - if (!text || text === NA) return NA; - return ( - - ); - }, - }, - { - title: 'State', - dataIndex: 'state', - key: 'state', - width: 150, - render: (e) => { - if (!e) return NA; - return SERVICE_STATE[e]; - }, + const stateColumn = { + title: 'State', + dataIndex: 'state', + key: 'state', + width: 150, + render: (e) => { + if (!e) return NA; + return SERVICE_STATE[e]; }, - { - width: isMobile ? 40 : 220, - title: 'Action', - key: 'action', - fixed: 'right', - render: (_text, record) => { - // only show update button for pre-registration state - const canUpdate = - ['1'].includes(record.state) && - areAddressesEqual(record.owner, account); + }; + const actionAndUpdateColumn = { + width: isMobile ? 40 : 200, + title: 'Action', + key: 'action', + fixed: 'right', + render: (_text, record) => { + // only show update button for pre-registration state + const canUpdate = + ['1'].includes(record.state) && + areAddressesEqual(record.owner, account); - return ( - - + return ( + + - {canUpdate && onUpdateClick && ( - - )} - - ); - }, + {canUpdate && onUpdateClick && ( + + )} + + ); }, - ]; + }; + + return isMainnet + ? [ + tokenIdColumn, + packageName, + ownerColumn, + hashColumn, + stateColumn, + actionAndUpdateColumn, + ] + : [ + { + title: 'ID', + dataIndex: 'id', + key: 'id', + width: isMobile ? 30 : 50, + }, + { + title: 'Owner', + dataIndex: 'owner', + key: 'owner', + width: 200, + render: (text) => { + if (!text || text === NA) return NA; + return ( + + ); + }, + }, + stateColumn, + actionAndUpdateColumn, + ]; } return []; @@ -210,6 +214,18 @@ export const fetchDataSource = (type, rawData, { current, isMainnet }) => { packageHash: item.packageHash, })); } + + if (type === NAV_TYPES.SERVICE) { + return rawData.map((item) => ({ + id: item.serviceId, + tokenId: item.serviceId, + owner: item.owner, + hash: item.metadataHash, + packageName: item.publicId, + packageHash: item.packageHash, + state: item.state, + })); + } } // non-mainnet chain diff --git a/apps/autonolas-registry/components/ListServices/hooks/useServiceList.jsx b/apps/autonolas-registry/components/ListServices/hooks/useServicesList.jsx similarity index 81% rename from apps/autonolas-registry/components/ListServices/hooks/useServiceList.jsx rename to apps/autonolas-registry/components/ListServices/hooks/useServicesList.jsx index 05db3793..43122730 100644 --- a/apps/autonolas-registry/components/ListServices/hooks/useServiceList.jsx +++ b/apps/autonolas-registry/components/ListServices/hooks/useServicesList.jsx @@ -11,18 +11,11 @@ import { gql } from 'graphql-request'; import { useSubgraph } from '../../../common-util/hooks/useSubgraph'; import { TOTAL_VIEW_COUNT } from '../../../util/constants'; -const transformToTableData = (data) => { - return data.map((item) => ({ - id: item.tokenId, - owner: item.owner, - unitHash: item.metadataHash, - })); -}; - const serviceColumns = `{ id serviceId - tokenId + publicId + owner packageHash metadataHash state @@ -32,7 +25,7 @@ const serviceColumns = `{ * Searches by * - publicId (package name) * - description, - * - tokenId + * - serviceId * - packageHash * - owner * @returns {string} search filter sub query @@ -60,12 +53,16 @@ export const useAllServices = () => { async (currentPage) => { const query = gql` { - services ${serviceColumns} + services( + first: ${TOTAL_VIEW_COUNT}, + skip: ${TOTAL_VIEW_COUNT * (currentPage - 1)}, + orderBy: serviceId + ) ${serviceColumns} } `; const response = await graphQlClient.request(query); - return transformToTableData(response?.units || []); + return response?.services || []; }, [graphQlClient], ); @@ -79,7 +76,7 @@ export const useMyServices = () => { const graphQlClient = useSubgraph(); return useCallback( - async (type, ownerAddress, currentPage) => { + async (ownerAddress, currentPage) => { const query = gql` { services ( @@ -88,13 +85,13 @@ export const useMyServices = () => { where: { owner_contains_nocase: "${ownerAddress}" }, - orderBy: tokenId, + orderBy: serviceId, ) ${serviceColumns} } `; const response = await graphQlClient.request(query); - return response?.units || []; + return response?.services || []; }, [graphQlClient], ); @@ -108,20 +105,20 @@ export const useAllServicesBySearch = () => { const graphQlClient = useSubgraph(); return useCallback( - async (type, searchValue, currentPage) => { + async (searchValue, currentPage) => { const query = gql` { services ( first: ${TOTAL_VIEW_COUNT}, skip: ${TOTAL_VIEW_COUNT * (currentPage - 1)}, where: ${getSearchFilterSubQueryForServices(searchValue)}, - orderBy: tokenId + orderBy: serviceId ) ${serviceColumns} } `; const response = await graphQlClient.request(query); - return response?.units || []; + return response?.services || []; }, [graphQlClient], ); @@ -135,7 +132,7 @@ export const useMyServicesBySearch = () => { const graphQlClient = useSubgraph(); return useCallback( - async (type, ownerAddress, searchValue, currentPage) => { + async (ownerAddress, searchValue, currentPage) => { const query = gql` { services ( @@ -147,13 +144,13 @@ export const useMyServicesBySearch = () => { ${getSearchFilterSubQueryForServices(searchValue)} ] } - orderBy: tokenId, + orderBy: serviceId, ) ${serviceColumns} } `; const response = await graphQlClient.request(query); - return response?.units || []; + return response?.services || []; }, [graphQlClient], ); @@ -164,16 +161,15 @@ export const useSearchServices = () => { const getMyServicesBySearch = useMyServicesBySearch(); return useCallback( - async (type, searchValue, currentPage, ownerAddress) => { + async (searchValue, currentPage, ownerAddress) => { if (ownerAddress) { return await getMyServicesBySearch( - type, ownerAddress, searchValue, currentPage, ); } - return await getAllUnitsBySearch(type, searchValue, currentPage); + return await getAllUnitsBySearch(searchValue, currentPage); }, [getAllUnitsBySearch, getMyServicesBySearch], ); diff --git a/apps/autonolas-registry/components/ListServices/index.jsx b/apps/autonolas-registry/components/ListServices/index.jsx index 4e951dd6..b9a9c977 100644 --- a/apps/autonolas-registry/components/ListServices/index.jsx +++ b/apps/autonolas-registry/components/ListServices/index.jsx @@ -12,11 +12,11 @@ import { } from '../../common-util/List/ListTable/helpers'; import { getMyListOnPagination } from '../../common-util/ContractUtils/myList'; import { useHelpers } from '../../common-util/hooks'; -// import { -// useAllServices, -// useMyServices, -// useSearchServices, -// } from './hooks/useServiceList'; +import { + useAllServices, + useMyServices, + useSearchServices, +} from './hooks/useServicesList'; import { useServiceInfo } from './hooks/useSvmService'; import { getServices, @@ -35,11 +35,11 @@ const ListServices = () => { isMyTab(hash) ? MY_SERVICES : ALL_SERVICES, ); - const { account, chainName, links, isSvm, chainId } = useHelpers(); + const { account, chainName, links, isSvm, chainId, isMainnet } = useHelpers(); - // const getAllServices = useAllServices(); - // const getMyServices = useMyServices(); - // const getServicesBySearch = useSearchServices(); + const getAllServices = useAllServices(); + const getMyServices = useMyServices(); + const getServicesBySearch = useSearchServices(); /** * extra tab content & view click @@ -119,36 +119,35 @@ const ListServices = () => { try { // All services if (currentTab === ALL_SERVICES) { - // if (chainId === 1) { - // const e = await getAllServices(NAV_TYPES.SERVICE, currentPage); - // setList(e); - // } else { - const e = isSvm - ? await getSvmServices(total, currentPage) - : await getServices(total, currentPage); - setList(e); - // } + if (isMainnet) { + const e = await getAllServices(currentPage); + setList(e); + } else { + const e = isSvm + ? await getSvmServices(total, currentPage) + : await getServices(total, currentPage); + setList(e); + } } else if (currentTab === MY_SERVICES && account) { /** * My services * - search by `account` as searchValue * - API will be called only once & store the complete list */ - // if (chainId === 1) { - // const e = await getMyServices(NAV_TYPES.SERVICE, account); - // setList(e); - // } else - // { - const e = isSvm - ? await getMySvmServices(account, total) - : await getFilteredServices(account); - setList(e); + if (chainId === 1) { + const e = await getMyServices(account); + setList(e); + } else { + const e = isSvm + ? await getMySvmServices(account, total) + : await getFilteredServices(account); + setList(e); - // TODO: remove this once `getTotalForMySvmServices` is fixed - if (isSvm) { - setTotal(e.length); + // TODO: remove this once `getTotalForMySvmServices` is fixed + if (isSvm) { + setTotal(e.length); + } } - // } } } catch (e) { console.error(e); @@ -170,10 +169,11 @@ const ListServices = () => { currentTab, searchValue, isSvm, - // getMyServices, - // getAllServices, + getMyServices, + getAllServices, getSvmServices, getMySvmServices, + isMainnet, ]); /** @@ -186,24 +186,21 @@ const ListServices = () => { if (!searchValue) return; setIsLoading(true); - try { - // if (chainId === 1) { - // const filteredList = await getServicesBySearch( - // NAV_TYPES.SERVICE, - // searchValue, - // currentPage, - // currentTab === MY_SERVICES ? account : null, - // ); - // setList(filteredList); - // } - // else { - const filteredList = await getFilteredServices( - searchValue, - currentTab === MY_SERVICES ? account : null, - ); - setList(filteredList); - // } + if (chainId === 1) { + const filteredList = await getServicesBySearch( + searchValue, + currentPage, + currentTab === MY_SERVICES ? account : null, + ); + setList(filteredList); + } else { + const filteredList = await getFilteredServices( + searchValue, + currentTab === MY_SERVICES ? account : null, + ); + setList(filteredList); + } setTotal(0); // total won't be used if search is used setCurrentPage(1); @@ -221,7 +218,7 @@ const ListServices = () => { currentTab, chainId, currentPage, - // getServicesBySearch, + getServicesBySearch, ]); const tableCommonProps = { @@ -236,9 +233,15 @@ const ListServices = () => { router.push(`${links.UPDATE_SERVICE}/${serviceId}`), }; - const myServiceList = searchValue - ? list - : getMyListOnPagination({ total, nextPage: currentPage, list }); + const getMyServiceList = () => { + if (isMainnet) { + return list; + } + + return searchValue + ? list + : getMyListOnPagination({ total, nextPage: currentPage, list }); + }; return ( { key: ALL_SERVICES, label: 'All', disabled: isLoading, - children: , + children: ( + + ), }, { key: MY_SERVICES, @@ -277,9 +286,10 @@ const ListServices = () => { children: ( ), }, diff --git a/apps/autonolas-registry/tests/components/ListAgents/details.test.jsx b/apps/autonolas-registry/tests/components/ListAgents/details.test.jsx index 3f89d9e7..8fd4153a 100644 --- a/apps/autonolas-registry/tests/components/ListAgents/details.test.jsx +++ b/apps/autonolas-registry/tests/components/ListAgents/details.test.jsx @@ -61,7 +61,7 @@ const dummyHashes = { const dummyIpfs = { image: `ipfs://${mockNftImageHash}`, - name: 'Some name', + name: 'Some package name', description: 'Some description', code_uri: `ipfs://${mockCodeUri}`, attributes: [{ trait_type: 'version', value: '0.0.0.1' }], @@ -95,7 +95,7 @@ describe('listAgents/details.jsx', () => { ); await waitFor(async () => { // left column content - expect(getByText('Agent ID 1')).toBeInTheDocument(); + expect(getByText('Some package name')).toBeInTheDocument(); expect(getByTestId('view-hash-link').getAttribute('href')).toBe( `${GATEWAY_URL}12345`, ); diff --git a/apps/autonolas-registry/tests/components/ListAgents/index.test.tsx b/apps/autonolas-registry/tests/components/ListAgents/index.test.tsx index 51e89443..c6f9e50f 100644 --- a/apps/autonolas-registry/tests/components/ListAgents/index.test.tsx +++ b/apps/autonolas-registry/tests/components/ListAgents/index.test.tsx @@ -87,11 +87,11 @@ describe('listAgents/index.jsx', () => { await waitFor(async () => { expect(within(allAgentsTable).getByText('ID')).toBeInTheDocument(); - expect(within(allAgentsTable).getByText('Owner')).toBeInTheDocument(); - expect(within(allAgentsTable).getByText('Hash')).toBeInTheDocument(); expect( - within(allAgentsTable).getByText('Package Name'), + within(allAgentsTable).getByText('Name'), ).toBeInTheDocument(); + expect(within(allAgentsTable).getByText('Owner')).toBeInTheDocument(); + expect(within(allAgentsTable).getByText('Hash')).toBeInTheDocument(); expect(within(allAgentsTable).getByText('Action')).toBeInTheDocument(); }); }); diff --git a/apps/autonolas-registry/tests/components/ListComponents/details.test.jsx b/apps/autonolas-registry/tests/components/ListComponents/details.test.jsx index bc2e769b..045c17f1 100644 --- a/apps/autonolas-registry/tests/components/ListComponents/details.test.jsx +++ b/apps/autonolas-registry/tests/components/ListComponents/details.test.jsx @@ -87,7 +87,7 @@ describe('listComponents/details.jsx', () => { ); await waitFor(async () => { // left column content - expect(getByText('Component ID 1')).toBeInTheDocument(); + expect(getByText('Some package name')).toBeInTheDocument(); expect(getByTestId('view-hash-link').getAttribute('href')).toBe( `${GATEWAY_URL}12345`, ); diff --git a/apps/autonolas-registry/tests/components/ListComponents/index.test.tsx b/apps/autonolas-registry/tests/components/ListComponents/index.test.tsx index 7551091c..5600f484 100644 --- a/apps/autonolas-registry/tests/components/ListComponents/index.test.tsx +++ b/apps/autonolas-registry/tests/components/ListComponents/index.test.tsx @@ -94,7 +94,7 @@ describe('listComponents/index.jsx', () => { expect(within(allComponentsTable).getByText('Owner')).toBeInTheDocument(); expect(within(allComponentsTable).getByText('Hash')).toBeInTheDocument(); expect( - within(allComponentsTable).getByText('Package Name'), + within(allComponentsTable).getByText('Name'), ).toBeInTheDocument(); expect( within(allComponentsTable).getByText('Action'), diff --git a/apps/autonolas-registry/tests/components/ListServices/details.test.jsx b/apps/autonolas-registry/tests/components/ListServices/details.test.jsx index 16351bfc..2b8d33c1 100644 --- a/apps/autonolas-registry/tests/components/ListServices/details.test.jsx +++ b/apps/autonolas-registry/tests/components/ListServices/details.test.jsx @@ -227,7 +227,7 @@ describe('listServices/details.jsx', () => { it('should render service details (left side)', async () => { const { getByText, getByTestId } = render(wrapProvider()); await waitFor(async () => { - expect(getByText('Service ID 1')).toBeInTheDocument(); + // expect(getByText('Service ID 1')).toBeInTheDocument(); expect(getByTestId('service-status').textContent).toBe('Inactive'); expect(getByTestId('view-hash-link').getAttribute('href')).toBe( `${GATEWAY_URL}12345`, @@ -348,7 +348,7 @@ describe('listServices/details.jsx', () => { it('should render service details (left side)', async () => { const { getByText, getByTestId } = render(wrapProvider()); await waitFor(async () => { - expect(getByText('Service ID 1')).toBeInTheDocument(); + // expect(getByText('Service ID 1')).toBeInTheDocument(); expect(getByTestId('service-status').textContent).toBe('Inactive'); expect(getByTestId('view-hash-link').getAttribute('href')).toBe( `${GATEWAY_URL}12345`, diff --git a/apps/autonolas-registry/tests/components/ListServices/index.test.jsx b/apps/autonolas-registry/tests/components/ListServices/index.test.jsx deleted file mode 100644 index 145da47e..00000000 --- a/apps/autonolas-registry/tests/components/ListServices/index.test.jsx +++ /dev/null @@ -1,177 +0,0 @@ -import { render, waitFor } from '@testing-library/react'; -import ListServices from '../../../components/ListServices'; -import { useServiceInfo } from '../../../components/ListServices/hooks/useSvmService'; -import { useHelpers } from '../../../common-util/hooks/useHelpers'; -import { - getServices, - getFilteredServices, - getTotalForAllServices, - getTotalForMyServices, -} from '../../../components/ListServices/utils'; -import { - wrapProvider, - ACTIVE_TAB, - getTableTd, - svmConnectivityEmptyMock, - getTableTh, - dummyAddress, - mockSvmAddress, - useHelpersEvmMock, -} from '../../tests-helpers'; - -jest.mock('../../../components/ListServices/utils', () => ({ - getServices: jest.fn(), - getFilteredServices: jest.fn(), - getTotalForAllServices: jest.fn(), - getTotalForMyServices: jest.fn(), -})); - -jest.mock('../../../common-util/hooks/useHelpers', () => ({ - useHelpers: jest.fn(), -})); - -jest.mock('../../../common-util/hooks/useSvmConnectivity', () => ({ - useSvmConnectivity: jest.fn(() => svmConnectivityEmptyMock), -})); - -jest.mock('../../../components/ListServices/hooks/useSvmService', () => ({ - useServiceInfo: jest.fn(), -})); - -describe.skip('listServices/index.jsx', () => { - describe('EVM', () => { - beforeEach(() => { - jest.clearAllMocks(); - - useHelpers.mockReturnValue(useHelpersEvmMock); - useServiceInfo.mockReturnValue(jest.fn(() => {})); - getTotalForAllServices.mockResolvedValue(1); - getTotalForMyServices.mockResolvedValue(1); - getServices.mockResolvedValue([ - { id: '1', owner: dummyAddress, state: '5' }, - ]); - getFilteredServices.mockResolvedValue([ - { id: '2', owner: dummyAddress, state: '2' }, - ]); - }); - - it('should render tabs with `All Tab` & Mint button', async () => { - const { container, getByRole } = render(wrapProvider()); - // check if the selected tab is `All` & has the correct content - await waitFor(async () => { - expect(container.querySelector(ACTIVE_TAB).textContent).toBe('All'); - - // Mint button - expect(getByRole('button', { name: 'Mint' })).toBeInTheDocument(); - }); - }); - - it('should show search input', async () => { - const { getByRole } = render(wrapProvider()); - await waitFor(async () => { - expect(getByRole('textbox')).toBeInTheDocument(); - }); - }); - - it('should render service columns and rows', async () => { - const { container } = render(wrapProvider()); - await waitFor(async () => { - // column names - expect(container.querySelector(getTableTh(1)).textContent).toBe('ID'); - expect(container.querySelector(getTableTh(2)).textContent).toBe( - 'Owner', - ); - expect(container.querySelector(getTableTh(3)).textContent).toBe( - 'State', - ); - expect(container.querySelector(getTableTh(4)).textContent).toBe( - 'Action', - ); - - // rows - expect(container.querySelector(getTableTd(1)).textContent).toBe('1'); - expect(container.querySelector(getTableTd(2)).textContent).toBe( - '0x8626...9C1199', - ); - expect(container.querySelector(getTableTd(3)).textContent).toBe( - 'Terminated Bonded', - ); - expect(container.querySelector(getTableTd(4)).textContent).toBe('View'); - }); - }); - }); - - describe('SVM', () => { - beforeEach(() => { - jest.clearAllMocks(); - - useHelpers.mockReturnValue({ - account: mockSvmAddress, - chainName: 'SVM', - links: { SERVICES: '/services' }, - isSvm: true, - }); - useServiceInfo.mockReturnValue({ - getTotalForAllSvmServices: jest.fn(() => 1), - getTotalForMySvmServices: jest.fn(() => 1), - getSvmServices: jest.fn(() => [ - { id: '1', owner: mockSvmAddress, state: '5' }, - ]), - getMySvmServices: jest.fn(() => [ - { id: '2', owner: mockSvmAddress, state: '5' }, - ]), - }); - - // below functions are required to be mocked as they are used by EVM - getTotalForAllServices.mockResolvedValue(0); - getTotalForMyServices.mockResolvedValue(0); - getServices.mockResolvedValue([]); - getFilteredServices.mockResolvedValue([]); - }); - - it('should render tabs with `All Tab` & Mint button', async () => { - const { container, getByRole } = render(wrapProvider()); - // check if the selected tab is `All` & has the correct content - await waitFor(async () => { - expect(container.querySelector(ACTIVE_TAB).textContent).toBe('All'); - - // Mint button - expect(getByRole('button', { name: 'Mint' })).toBeInTheDocument(); - }); - }); - - it('should NOT show search input', async () => { - const { queryByRole } = render(wrapProvider()); - await waitFor(async () => { - expect(queryByRole('textbox')).toBeNull(); - }); - }); - - it('should render service columns and rows', async () => { - const { container } = render(wrapProvider()); - await waitFor(async () => { - // column names - expect(container.querySelector(getTableTh(1)).textContent).toBe('ID'); - expect(container.querySelector(getTableTh(2)).textContent).toBe( - 'Owner', - ); - expect(container.querySelector(getTableTh(3)).textContent).toBe( - 'State', - ); - expect(container.querySelector(getTableTh(4)).textContent).toBe( - 'Action', - ); - - // rows - expect(container.querySelector(getTableTd(1)).textContent).toBe('1'); - expect(container.querySelector(getTableTd(2)).textContent).toBe( - 'DrGvsA...D3Wm5x', - ); - expect(container.querySelector(getTableTd(3)).textContent).toBe( - 'Terminated Bonded', - ); - expect(container.querySelector(getTableTd(4)).textContent).toBe('View'); - }); - }); - }); -}); diff --git a/apps/autonolas-registry/tests/components/ListServices/index.test.tsx b/apps/autonolas-registry/tests/components/ListServices/index.test.tsx new file mode 100644 index 00000000..c2c65afa --- /dev/null +++ b/apps/autonolas-registry/tests/components/ListServices/index.test.tsx @@ -0,0 +1,287 @@ +import { render, waitFor, within } from '@testing-library/react'; +// import userEvent from '@testing-library/user-event'; +import '@testing-library/jest-dom'; + +import ListServices from '../../../components/ListServices'; +import { useServiceInfo } from '../../../components/ListServices/hooks/useSvmService'; +import { useHelpers } from '../../../common-util/hooks/useHelpers'; +import { + getServices, + getFilteredServices, + getTotalForAllServices, + getTotalForMyServices, +} from '../../../components/ListServices/utils'; +import { + wrapProvider, + ACTIVE_TAB, + svmConnectivityEmptyMock, + dummyAddress, + mockSvmAddress, + useHelpersEvmMock, + useHelpersBaseMock, + dummyHash1, + mockCodeUri, + dummyAddress1, +} from '../../tests-helpers'; + +const allServicesResponse = [ + { + id: '1', + tokenId: '1', + owner: dummyAddress, + publicId: 'good_package_name_all_services', + packageHash: dummyHash1, + metadataHash: mockCodeUri, + }, +]; +const myServicesResponse = [ + { + ...allServicesResponse[0], + tokenId: '2', + owner: dummyAddress1, + publicId: 'good_package_name_my_services', + }, +]; +const allServicesSearchResponse = [ + { + ...allServicesResponse[0], + tokenId: '3', + publicId: 'good_package_name_services_search', + }, +]; + +jest.mock('../../../components/ListServices/utils', () => ({ + getServices: jest.fn(), + getFilteredServices: jest.fn(), + getTotalForAllServices: jest.fn(), + getTotalForMyServices: jest.fn(), +})); + +jest.mock('../../../components/ListServices/hooks/useServicesList', () => ({ + useAllServices: () => () => Promise.resolve(allServicesResponse), + useMyServices: () => () => Promise.resolve(myServicesResponse), + useSearchServices: () => () => Promise.resolve(allServicesSearchResponse), +})); + +jest.mock('../../../common-util/hooks/useHelpers', () => ({ + useHelpers: jest.fn(), +})); + +jest.mock('../../../common-util/hooks/useSvmConnectivity', () => ({ + useSvmConnectivity: jest.fn(() => svmConnectivityEmptyMock), +})); + +jest.mock('../../../components/ListServices/hooks/useSvmService', () => ({ + useServiceInfo: jest.fn(), +})); + +describe('listServices/index.jsx', () => { + describe('EVM', () => { + beforeEach(() => { + jest.clearAllMocks(); + + (useHelpers as jest.Mock).mockReturnValue(useHelpersEvmMock); + (useServiceInfo as jest.Mock).mockReturnValue(jest.fn(() => {})); + }); + + it('should render tabs with `All Tab` & Mint button', async () => { + const { container, getByRole } = render(wrapProvider()); + // check if the selected tab is `All` & has the correct content + await waitFor(async () => { + expect(container.querySelector(ACTIVE_TAB)?.textContent).toBe('All'); + + // Mint button + expect(getByRole('button', { name: 'Mint' })).toBeInTheDocument(); + }); + }); + + it('should show search input', async () => { + const { getByRole } = render(wrapProvider()); + await waitFor(async () => { + expect(getByRole('textbox')).toBeInTheDocument(); + }); + }); + + describe.skip('mainnet', () => { + beforeEach(() => { + jest.clearAllMocks(); + + (useHelpers as jest.Mock).mockReturnValue(useHelpersEvmMock); + (useServiceInfo as jest.Mock).mockReturnValue(jest.fn(() => {})); + // (useAllServices as jest.Mock).mock(() => Promise.resolve(myServicesResponse)); + (getTotalForAllServices as jest.Mock).mockResolvedValue(1); + (getTotalForMyServices as jest.Mock).mockResolvedValue(1); + }); + + it('should display all services', async () => { + const { container, findByTestId } = render( + wrapProvider(), + ); + + if (!container) { + throw new Error('`All tab` is null'); + } + + // check if the selected tab is `All` & has the correct content + await waitFor(async () => + expect(container.querySelector(ACTIVE_TAB)?.textContent).toBe('All'), + ); + + const firstAgent = allServicesResponse[0]; + const allServicesTable = await findByTestId('all-services-table'); + + expect( + within(allServicesTable).getByText(firstAgent.tokenId), + ).toBeInTheDocument(); + // expect( + // within(allServicesTable).getByText(/0x8626...9C1199/), + // ).toBeInTheDocument(); + // expect( + // within(allServicesTable).getByText(/0x9cf4...315ab0/), + // ).toBeInTheDocument(); + // expect( + // within(allServicesTable).getByText(firstAgent.publicId), + // ).toBeInTheDocument(); + // expect(within(allServicesTable).getByText('View')).toBeInTheDocument(); + }); + }); + + describe('non-mainnet', () => { + beforeEach(() => { + jest.clearAllMocks(); + + (useHelpers as jest.Mock).mockReturnValue(useHelpersBaseMock); + (useServiceInfo as jest.Mock).mockReturnValue(jest.fn(() => {})); + (getTotalForAllServices as jest.Mock).mockResolvedValue(1); + (getTotalForMyServices as jest.Mock).mockResolvedValue(1); + (getServices as jest.Mock).mockResolvedValue([ + { id: '1', owner: dummyAddress, state: '5' }, + ]); + (getFilteredServices as jest.Mock).mockResolvedValue([ + { id: '2', owner: dummyAddress, state: '2' }, + ]); + }); + + it('should render service columns and rows', async () => { + const { container, findByTestId } = render( + wrapProvider(), + ); + const allServicesTable = await findByTestId('all-services-table'); + + if (!container) { + throw new Error('`All tab` is null'); + } + + await waitFor(async () => { + // column names + expect(within(allServicesTable).getByText('ID')).toBeInTheDocument(); + expect( + within(allServicesTable).getByText('Owner'), + ).toBeInTheDocument(); + expect( + within(allServicesTable).getByText('State'), + ).toBeInTheDocument(); + expect( + within(allServicesTable).getByText('Action'), + ).toBeInTheDocument(); + + // rows + expect(within(allServicesTable).getByText('1')).toBeInTheDocument(); + expect( + within(allServicesTable).getByText('0x8626...9C1199'), + ).toBeInTheDocument(); + expect( + within(allServicesTable).getByText('Terminated Bonded'), + ).toBeInTheDocument(); + expect( + within(allServicesTable).getByText('View'), + ).toBeInTheDocument(); + }); + }); + }); + }); + + describe('SVM', () => { + beforeEach(() => { + jest.clearAllMocks(); + + (useHelpers as jest.Mock).mockReturnValue({ + account: mockSvmAddress, + chainName: 'SVM', + links: { SERVICES: '/services' }, + isSvm: true, + }); + (useServiceInfo as jest.Mock).mockReturnValue({ + getTotalForAllSvmServices: jest.fn(() => 1), + getTotalForMySvmServices: jest.fn(() => 1), + getSvmServices: jest.fn(() => [ + { id: '1', owner: mockSvmAddress, state: '5' }, + ]), + getMySvmServices: jest.fn(() => [ + { id: '2', owner: mockSvmAddress, state: '5' }, + ]), + }); + + // below functions are required to be mocked as they are used by EVM + (getTotalForAllServices as jest.Mock).mockResolvedValue(0); + (getTotalForMyServices as jest.Mock).mockResolvedValue(0); + (getServices as jest.Mock).mockResolvedValue([]); + (getFilteredServices as jest.Mock).mockResolvedValue([]); + }); + + it('should render tabs with `All Tab` & Mint button', async () => { + const { container, getByRole } = render(wrapProvider()); + + if (!container) { + throw new Error('`All tab` is null'); + } + + // check if the selected tab is `All` & has the correct content + await waitFor(async () => { + expect(container.querySelector(ACTIVE_TAB)?.textContent).toBe('All'); + + // Mint button + expect(getByRole('button', { name: 'Mint' })).toBeInTheDocument(); + }); + }); + + it('should NOT show search input', async () => { + const { queryByRole } = render(wrapProvider()); + await waitFor(async () => { + expect(queryByRole('textbox')).toBeNull(); + }); + }); + + it('should render service columns and rows', async () => { + const { container, findByTestId } = render( + wrapProvider(), + ); + + if (!container) { + throw new Error('`All tab` is null'); + } + + const allServicesTable = await findByTestId('all-services-table'); + + await waitFor(async () => { + // column names + expect(within(allServicesTable).getByText('ID')).toBeInTheDocument(); + expect(within(allServicesTable).getByText('Owner')).toBeInTheDocument(); + expect(within(allServicesTable).getByText('State')).toBeInTheDocument(); + expect( + within(allServicesTable).getByText('Action'), + ).toBeInTheDocument(); + + // rows + expect(within(allServicesTable).getByText('1')).toBeInTheDocument(); + expect( + within(allServicesTable).getByText('DrGvsA...D3Wm5x'), + ).toBeInTheDocument(); + expect( + within(allServicesTable).getByText('Terminated Bonded'), + ).toBeInTheDocument(); + expect(within(allServicesTable).getByText('View')).toBeInTheDocument(); + }); + }); + }); +}); diff --git a/apps/autonolas-registry/tests/tests-helpers/index.jsx b/apps/autonolas-registry/tests/tests-helpers/index.jsx index c7b6f402..ec52a8d1 100644 --- a/apps/autonolas-registry/tests/tests-helpers/index.jsx +++ b/apps/autonolas-registry/tests/tests-helpers/index.jsx @@ -50,7 +50,7 @@ export const mockCodeUri = export const mockIpfs = { image: `ipfs://${mockNftImageHash}`, - name: 'Some name', + name: 'Some package name', description: 'Some description', code_uri: `ipfs://${mockCodeUri}`, attributes: [{ trait_type: 'version', value: '0.0.0.1' }], @@ -68,6 +68,7 @@ export const useHelpersEvmMock = { links: { AGENTS: '/ethereum/agents' }, isConnectedToWrongNetwork: false, isSvm: false, + isMainnet: true, }; export const useHelpersBaseMock = { From 73d7f2a748718e90fd6b2ec969b606aee7bfc635 Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Mon, 8 Apr 2024 20:07:01 +0530 Subject: [PATCH 29/39] add custom for agents --- apps/autonolas-registry/components/ListAgents/index.jsx | 2 +- .../components/ListAgents/{useAgents.jsx => useAgentsList.jsx} | 0 apps/autonolas-registry/components/ListComponents/index.jsx | 2 +- .../ListComponents/{useComponents.jsx => useComponentsList.jsx} | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) rename apps/autonolas-registry/components/ListAgents/{useAgents.jsx => useAgentsList.jsx} (100%) rename apps/autonolas-registry/components/ListComponents/{useComponents.jsx => useComponentsList.jsx} (98%) diff --git a/apps/autonolas-registry/components/ListAgents/index.jsx b/apps/autonolas-registry/components/ListAgents/index.jsx index 4e2c66e1..97b917c6 100644 --- a/apps/autonolas-registry/components/ListAgents/index.jsx +++ b/apps/autonolas-registry/components/ListAgents/index.jsx @@ -11,7 +11,7 @@ import { isMyTab, } from '../../common-util/List/ListTable/helpers'; import { useHelpers } from '../../common-util/hooks'; -import { useAllAgents, useMyAgents, useSearchAgents } from './useAgents'; +import { useAllAgents, useMyAgents, useSearchAgents } from './useAgentsList'; import { getAgents, getFilteredAgents, diff --git a/apps/autonolas-registry/components/ListAgents/useAgents.jsx b/apps/autonolas-registry/components/ListAgents/useAgentsList.jsx similarity index 100% rename from apps/autonolas-registry/components/ListAgents/useAgents.jsx rename to apps/autonolas-registry/components/ListAgents/useAgentsList.jsx diff --git a/apps/autonolas-registry/components/ListComponents/index.jsx b/apps/autonolas-registry/components/ListComponents/index.jsx index c8bb0256..275e34f5 100644 --- a/apps/autonolas-registry/components/ListComponents/index.jsx +++ b/apps/autonolas-registry/components/ListComponents/index.jsx @@ -15,7 +15,7 @@ import { useAllComponents, useMyComponents, useSearchComponents, -} from './useComponents'; +} from './useComponentsList'; import { getComponents, getFilteredComponents, diff --git a/apps/autonolas-registry/components/ListComponents/useComponents.jsx b/apps/autonolas-registry/components/ListComponents/useComponentsList.jsx similarity index 98% rename from apps/autonolas-registry/components/ListComponents/useComponents.jsx rename to apps/autonolas-registry/components/ListComponents/useComponentsList.jsx index 55ce9263..00f60b16 100644 --- a/apps/autonolas-registry/components/ListComponents/useComponents.jsx +++ b/apps/autonolas-registry/components/ListComponents/useComponentsList.jsx @@ -14,7 +14,7 @@ import { import { TOTAL_VIEW_COUNT } from '../../util/constants'; const componentPackageType = - 'packageType_in: [connection,skill,protocol,contract]'; + 'packageType_in: [connection,skill,protocol,contract,custom]'; /** * Hook to get ALL components From cdf92852cef6625a3540523d31f6f7d658b7186d Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Mon, 8 Apr 2024 20:49:32 +0530 Subject: [PATCH 30/39] fix tests --- apps/autonolas-registry/components/ListServices/index.jsx | 2 +- .../tests/components/ListAgents/index.test.tsx | 2 +- .../tests/components/ListComponents/index.test.tsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/autonolas-registry/components/ListServices/index.jsx b/apps/autonolas-registry/components/ListServices/index.jsx index b9a9c977..5cfe1dcd 100644 --- a/apps/autonolas-registry/components/ListServices/index.jsx +++ b/apps/autonolas-registry/components/ListServices/index.jsx @@ -135,7 +135,7 @@ const ListServices = () => { * - API will be called only once & store the complete list */ if (chainId === 1) { - const e = await getMyServices(account); + const e = await getMyServices(account, currentPage); setList(e); } else { const e = isSvm diff --git a/apps/autonolas-registry/tests/components/ListAgents/index.test.tsx b/apps/autonolas-registry/tests/components/ListAgents/index.test.tsx index c6f9e50f..d63619c1 100644 --- a/apps/autonolas-registry/tests/components/ListAgents/index.test.tsx +++ b/apps/autonolas-registry/tests/components/ListAgents/index.test.tsx @@ -53,7 +53,7 @@ jest.mock('../../../components/ListAgents/utils', () => ({ getTotalForMyAgents: jest.fn(), })); -jest.mock('../../../components/ListAgents/useAgents', () => ({ +jest.mock('../../../components/ListAgents/useAgentsList', () => ({ useAllAgents: () => () => Promise.resolve(allAgentsResponse), useMyAgents: () => () => Promise.resolve(myAgentsResponse), useSearchAgents: () => () => Promise.resolve(allAgentsSearchResponse), diff --git a/apps/autonolas-registry/tests/components/ListComponents/index.test.tsx b/apps/autonolas-registry/tests/components/ListComponents/index.test.tsx index 5600f484..3bb7370e 100644 --- a/apps/autonolas-registry/tests/components/ListComponents/index.test.tsx +++ b/apps/autonolas-registry/tests/components/ListComponents/index.test.tsx @@ -53,7 +53,7 @@ jest.mock('../../../components/ListComponents/utils', () => ({ getTotalForMyComponents: jest.fn(), })); -jest.mock('../../../components/ListComponents/useComponents', () => ({ +jest.mock('../../../components/ListComponents/useComponentsList', () => ({ useAllComponents: () => () => Promise.resolve(allComponentsResponse), useMyComponents: () => () => Promise.resolve(myComponentsResponse), useSearchComponents: () => () => Promise.resolve(allComponentsSearchResponse), From 04f10f54ab7dc1d93e04aea820a87512ae8825c0 Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Mon, 8 Apr 2024 22:27:09 +0530 Subject: [PATCH 31/39] services fix --- .../components/ListAgents/index.jsx | 1 + .../components/ListComponents/index.jsx | 1 + .../ListServices/hooks/useServicesList.jsx | 16 ++++++++++++---- .../components/ListServices/index.jsx | 2 +- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/apps/autonolas-registry/components/ListAgents/index.jsx b/apps/autonolas-registry/components/ListAgents/index.jsx index 97b917c6..ee5c9148 100644 --- a/apps/autonolas-registry/components/ListAgents/index.jsx +++ b/apps/autonolas-registry/components/ListAgents/index.jsx @@ -76,6 +76,7 @@ const ListAgents = () => { setTotal(Number(totalTemp)); if (Number(totalTemp) === 0) { setIsLoading(false); + setList([]); } } catch (e) { console.error(e); diff --git a/apps/autonolas-registry/components/ListComponents/index.jsx b/apps/autonolas-registry/components/ListComponents/index.jsx index 275e34f5..cbcb1157 100644 --- a/apps/autonolas-registry/components/ListComponents/index.jsx +++ b/apps/autonolas-registry/components/ListComponents/index.jsx @@ -80,6 +80,7 @@ const ListComponents = () => { setTotal(Number(totalTemp)); if (Number(totalTemp) === 0) { setIsLoading(false); + setList([]); } } catch (e) { console.error(e); diff --git a/apps/autonolas-registry/components/ListServices/hooks/useServicesList.jsx b/apps/autonolas-registry/components/ListServices/hooks/useServicesList.jsx index 43122730..a6d51d52 100644 --- a/apps/autonolas-registry/components/ListServices/hooks/useServicesList.jsx +++ b/apps/autonolas-registry/components/ListServices/hooks/useServicesList.jsx @@ -9,7 +9,7 @@ import { useCallback } from 'react'; import { gql } from 'graphql-request'; import { useSubgraph } from '../../../common-util/hooks/useSubgraph'; -import { TOTAL_VIEW_COUNT } from '../../../util/constants'; +import { HASH_PREFIX, TOTAL_VIEW_COUNT } from '../../../util/constants'; const serviceColumns = `{ id @@ -31,16 +31,20 @@ const serviceColumns = `{ * @returns {string} search filter sub query */ export const getSearchFilterSubQueryForServices = (searchValue) => { + const completeMetadataHash = searchValue.replace(/0x/g, HASH_PREFIX); return `{ or: [ { publicId_contains_nocase: "${searchValue}" } - { description_contains_nocase: "${searchValue}" } { packageHash_contains_nocase: "${searchValue}" } { owner_contains_nocase: "${searchValue}" } + { metadataHash_contains_nocase: "${completeMetadataHash}" } ] }`; }; +// TODO: description needs to be added +// { description_contains_nocase: "${searchValue}" } + /** * Hook to get ALL units * @returns {function} function to get all units @@ -111,7 +115,11 @@ export const useAllServicesBySearch = () => { services ( first: ${TOTAL_VIEW_COUNT}, skip: ${TOTAL_VIEW_COUNT * (currentPage - 1)}, - where: ${getSearchFilterSubQueryForServices(searchValue)}, + where: { + and: [ + ${getSearchFilterSubQueryForServices(searchValue)}, + ] + } orderBy: serviceId ) ${serviceColumns} } @@ -140,7 +148,7 @@ export const useMyServicesBySearch = () => { skip: ${TOTAL_VIEW_COUNT * (currentPage - 1)}, where: { and: [ - owner_contains_nocase: "${ownerAddress}" + { owner_contains_nocase: "${ownerAddress}" } ${getSearchFilterSubQueryForServices(searchValue)} ] } diff --git a/apps/autonolas-registry/components/ListServices/index.jsx b/apps/autonolas-registry/components/ListServices/index.jsx index 5cfe1dcd..c9e03fa7 100644 --- a/apps/autonolas-registry/components/ListServices/index.jsx +++ b/apps/autonolas-registry/components/ListServices/index.jsx @@ -90,6 +90,7 @@ const ListServices = () => { setTotal(Number(totalTemp)); if (Number(totalTemp) === 0) { setIsLoading(false); + setList([]); } } catch (e) { console.error(e); @@ -115,7 +116,6 @@ const ListServices = () => { useEffect(() => { const getList = async () => { setIsLoading(true); - try { // All services if (currentTab === ALL_SERVICES) { From 9d6e29dbafb8eea73befcdc9fad7dfd1837166cc Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Mon, 8 Apr 2024 23:21:58 +0530 Subject: [PATCH 32/39] on input search and hide description for service --- .../common-util/List/ListTable/helpers.jsx | 6 +++++- apps/autonolas-registry/components/ListServices/index.jsx | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/autonolas-registry/common-util/List/ListTable/helpers.jsx b/apps/autonolas-registry/common-util/List/ListTable/helpers.jsx index 8f595a3e..9471d057 100644 --- a/apps/autonolas-registry/common-util/List/ListTable/helpers.jsx +++ b/apps/autonolas-registry/common-util/List/ListTable/helpers.jsx @@ -278,6 +278,7 @@ export const useExtraTabContent = ({ title, onRegisterClick = () => {}, isSvm = false, + type, }) => { const [searchValue, setSearchValue] = useState(''); const [value, setValue] = useState(''); @@ -298,6 +299,9 @@ export const useExtraTabContent = ({ placeholder="Search..." value={value} onChange={(e) => setValue(e.target.value)} + onKeyDown={(e) => + e.key === 'Enter' && setSearchValue(value || '') + } suffix={ Search by:
    • Name
    • -
    • Description
    • + {type !== NAV_TYPES.SERVICE &&
    • Description
    • }
    • Owner
    • Package Hash
    diff --git a/apps/autonolas-registry/components/ListServices/index.jsx b/apps/autonolas-registry/components/ListServices/index.jsx index c9e03fa7..e0ce984d 100644 --- a/apps/autonolas-registry/components/ListServices/index.jsx +++ b/apps/autonolas-registry/components/ListServices/index.jsx @@ -48,6 +48,7 @@ const ListServices = () => { title: 'Services', onRegisterClick: () => router.push(links.MINT_SERVICE), isSvm, + type: NAV_TYPES.SERVICE, }); const onViewClick = (id) => router.push(`${links.SERVICES}/${id}`); From 811c4591fb38d075e885d5babfb8db49c9c0ddb6 Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Tue, 9 Apr 2024 06:41:02 +0530 Subject: [PATCH 33/39] address some comments --- .env.example | 1 + .../common-util/hooks/useSubgraph.jsx | 26 ++-- .../components/ListAgents/index.jsx | 2 +- .../components/ListAgents/useAgentsList.jsx | 62 +++------ .../components/ListComponents/index.jsx | 2 +- .../ListComponents/useComponentsList.jsx | 62 +++------ .../ListServices/hooks/useServicesList.jsx | 64 +++------ .../components/ListServices/index.jsx | 25 ++-- .../components/ListServices/details.test.jsx | 48 ++++++- .../components/ListServices/index.test.tsx | 130 +++++++++++------- 10 files changed, 209 insertions(+), 213 deletions(-) diff --git a/.env.example b/.env.example index 376d6f54..016ff6b2 100644 --- a/.env.example +++ b/.env.example @@ -9,6 +9,7 @@ NEXT_PUBLIC_ARBITRUM_URL=__value__ NEXT_PUBLIC_ARBITRUM_SEPOLIA_URL=__value__ NEXT_PUBLIC_WALLET_PROJECT_ID=__URL__ NEXT_PUBLIC_SOLANA_MAINNET_BETA_URL=__value__ +NEXT_PUBLIC_AUTONOLAS_SUB_GRAPH_URL=__URL__ # autonolas-registry-frontend NEXT_PUBLIC_REGISTRY_URL=__value__ diff --git a/apps/autonolas-registry/common-util/hooks/useSubgraph.jsx b/apps/autonolas-registry/common-util/hooks/useSubgraph.jsx index 355ad44e..baa2f5fe 100644 --- a/apps/autonolas-registry/common-util/hooks/useSubgraph.jsx +++ b/apps/autonolas-registry/common-util/hooks/useSubgraph.jsx @@ -1,22 +1,16 @@ -import { useMemo } from 'react'; import { GraphQLClient } from 'graphql-request'; import { HASH_PREFIX } from '../../util/constants'; -export const useSubgraph = () => { - const graphQlClient = useMemo( - () => - new GraphQLClient(process.env.NEXT_PUBLIC_AUTONOLAS_SUB_GRAPH_URL, { - method: 'POST', - jsonSerializer: { - parse: JSON.parse, - stringify: JSON.stringify, - }, - }), - [], - ); - - return graphQlClient; -}; +export const GRAPHQL_CLIENT = new GraphQLClient( + process.env.NEXT_PUBLIC_AUTONOLAS_SUB_GRAPH_URL, + { + method: 'POST', + jsonSerializer: { + parse: JSON.parse, + stringify: JSON.stringify, + }, + }, +); export const columnsForAgentsAndComponents = `{ id diff --git a/apps/autonolas-registry/components/ListAgents/index.jsx b/apps/autonolas-registry/components/ListAgents/index.jsx index ee5c9148..c6a980d4 100644 --- a/apps/autonolas-registry/components/ListAgents/index.jsx +++ b/apps/autonolas-registry/components/ListAgents/index.jsx @@ -56,7 +56,7 @@ const ListAgents = () => { // update current tab based on the "hash" in the links useEffect(() => { setCurrentTab(isMyTab(hash) ? MY_AGENTS : ALL_AGENTS); - }, [router.asPath, hash]); + }, [hash]); // fetch total useEffect(() => { diff --git a/apps/autonolas-registry/components/ListAgents/useAgentsList.jsx b/apps/autonolas-registry/components/ListAgents/useAgentsList.jsx index 6ebe70c3..863e56c9 100644 --- a/apps/autonolas-registry/components/ListAgents/useAgentsList.jsx +++ b/apps/autonolas-registry/components/ListAgents/useAgentsList.jsx @@ -7,7 +7,7 @@ import { useCallback } from 'react'; import { gql } from 'graphql-request'; import { - useSubgraph, + GRAPHQL_CLIENT, columnsForAgentsAndComponents, getSearchFilterSubQueryForAgentsAndComponents, } from '../../common-util/hooks/useSubgraph'; @@ -19,11 +19,8 @@ import { TOTAL_VIEW_COUNT } from '../../util/constants'; * */ export const useAllAgents = () => { - const graphQlClient = useSubgraph(); - - return useCallback( - async (currentPage) => { - const query = gql` + return useCallback(async (currentPage) => { + const query = gql` { units( first: ${TOTAL_VIEW_COUNT}, @@ -34,11 +31,9 @@ export const useAllAgents = () => { } `; - const response = await graphQlClient.request(query); - return response?.units; - }, - [graphQlClient], - ); + const response = await GRAPHQL_CLIENT.request(query); + return response?.units; + }, []); }; /** @@ -46,11 +41,8 @@ export const useAllAgents = () => { * @returns {function} function to get my units */ export const useMyAgents = () => { - const graphQlClient = useSubgraph(); - - return useCallback( - async (ownerAddress, currentPage) => { - const query = gql` + return useCallback(async (ownerAddress, currentPage) => { + const query = gql` { units( first: ${TOTAL_VIEW_COUNT}, @@ -64,11 +56,9 @@ export const useMyAgents = () => { } `; - const response = await graphQlClient.request(query); - return response?.units; - }, - [graphQlClient], - ); + const response = await GRAPHQL_CLIENT.request(query); + return response?.units; + }, []); }; /** @@ -76,11 +66,8 @@ export const useMyAgents = () => { * @returns {function} function to get all units by search */ const useAllAgentsBySearch = () => { - const graphQlClient = useSubgraph(); - - return useCallback( - async (searchValue) => { - const query = gql` + return useCallback(async (searchValue) => { + const query = gql` { units( where: { @@ -94,11 +81,9 @@ const useAllAgentsBySearch = () => { } `; - const response = await graphQlClient.request(query); - return response?.units; - }, - [graphQlClient], - ); + const response = await GRAPHQL_CLIENT.request(query); + return response?.units; + }, []); }; /** @@ -106,11 +91,8 @@ const useAllAgentsBySearch = () => { * @returns {function} function to search units */ const useMyAgentsBySearch = () => { - const graphQlClient = useSubgraph(); - - return useCallback( - async (ownerAddress, searchValue) => { - const query = gql` + return useCallback(async (ownerAddress, searchValue) => { + const query = gql` { units( where: { @@ -125,11 +107,9 @@ const useMyAgentsBySearch = () => { } `; - const response = await graphQlClient.request(query); - return response?.units; - }, - [graphQlClient], - ); + const response = await GRAPHQL_CLIENT.request(query); + return response?.units; + }, []); }; /** diff --git a/apps/autonolas-registry/components/ListComponents/index.jsx b/apps/autonolas-registry/components/ListComponents/index.jsx index cbcb1157..46014470 100644 --- a/apps/autonolas-registry/components/ListComponents/index.jsx +++ b/apps/autonolas-registry/components/ListComponents/index.jsx @@ -60,7 +60,7 @@ const ListComponents = () => { // update current tab based on the "hash" in the URL useEffect(() => { setCurrentTab(isMyTab(hash) ? MY_COMPONENTS : ALL_COMPONENTS); - }, [router.asPath, hash]); + }, [hash]); // fetch total useEffect(() => { diff --git a/apps/autonolas-registry/components/ListComponents/useComponentsList.jsx b/apps/autonolas-registry/components/ListComponents/useComponentsList.jsx index 00f60b16..cd77b7df 100644 --- a/apps/autonolas-registry/components/ListComponents/useComponentsList.jsx +++ b/apps/autonolas-registry/components/ListComponents/useComponentsList.jsx @@ -7,7 +7,7 @@ import { useCallback } from 'react'; import { gql } from 'graphql-request'; import { - useSubgraph, + GRAPHQL_CLIENT, columnsForAgentsAndComponents, getSearchFilterSubQueryForAgentsAndComponents, } from '../../common-util/hooks/useSubgraph'; @@ -22,11 +22,8 @@ const componentPackageType = * */ export const useAllComponents = () => { - const graphQlClient = useSubgraph(); - - return useCallback( - async (currentPage) => { - const query = gql` + return useCallback(async (currentPage) => { + const query = gql` { units( first: ${TOTAL_VIEW_COUNT}, @@ -37,11 +34,9 @@ export const useAllComponents = () => { } `; - const response = await graphQlClient.request(query); - return response?.units; - }, - [graphQlClient], - ); + const response = await GRAPHQL_CLIENT.request(query); + return response?.units; + }, []); }; /** @@ -49,11 +44,8 @@ export const useAllComponents = () => { * @returns {function} function to get my units */ export const useMyComponents = () => { - const graphQlClient = useSubgraph(); - - return useCallback( - async (ownerAddress, currentPage) => { - const query = gql` + return useCallback(async (ownerAddress, currentPage) => { + const query = gql` { units( first: ${TOTAL_VIEW_COUNT}, @@ -67,11 +59,9 @@ export const useMyComponents = () => { } `; - const response = await graphQlClient.request(query); - return response?.units; - }, - [graphQlClient], - ); + const response = await GRAPHQL_CLIENT.request(query); + return response?.units; + }, []); }; /** @@ -79,11 +69,8 @@ export const useMyComponents = () => { * @returns {function} function to get all units by search */ const useAllComponentsBySearch = () => { - const graphQlClient = useSubgraph(); - - return useCallback( - async (searchValue) => { - const query = gql` + return useCallback(async (searchValue) => { + const query = gql` { units( where: { @@ -97,11 +84,9 @@ const useAllComponentsBySearch = () => { } `; - const response = await graphQlClient.request(query); - return response?.units; - }, - [graphQlClient], - ); + const response = await GRAPHQL_CLIENT.request(query); + return response?.units; + }, []); }; /** @@ -109,11 +94,8 @@ const useAllComponentsBySearch = () => { * @returns {function} function to search units */ const useMyComponentsBySearch = () => { - const graphQlClient = useSubgraph(); - - return useCallback( - async (ownerAddress, searchValue) => { - const query = gql` + return useCallback(async (ownerAddress, searchValue) => { + const query = gql` { units( where: { @@ -128,11 +110,9 @@ const useMyComponentsBySearch = () => { } `; - const response = await graphQlClient.request(query); - return response?.units; - }, - [graphQlClient], - ); + const response = await GRAPHQL_CLIENT.request(query); + return response?.units; + }, []); }; /** diff --git a/apps/autonolas-registry/components/ListServices/hooks/useServicesList.jsx b/apps/autonolas-registry/components/ListServices/hooks/useServicesList.jsx index a6d51d52..e9963626 100644 --- a/apps/autonolas-registry/components/ListServices/hooks/useServicesList.jsx +++ b/apps/autonolas-registry/components/ListServices/hooks/useServicesList.jsx @@ -1,5 +1,3 @@ -// TODO: check all query - /** * * Helper hook to manage list of items (e.g. components, agents & services) @@ -8,7 +6,7 @@ import { useCallback } from 'react'; import { gql } from 'graphql-request'; -import { useSubgraph } from '../../../common-util/hooks/useSubgraph'; +import { GRAPHQL_CLIENT } from '../../../common-util/hooks/useSubgraph'; import { HASH_PREFIX, TOTAL_VIEW_COUNT } from '../../../util/constants'; const serviceColumns = `{ @@ -51,11 +49,8 @@ export const getSearchFilterSubQueryForServices = (searchValue) => { * */ export const useAllServices = () => { - const graphQlClient = useSubgraph(); - - return useCallback( - async (currentPage) => { - const query = gql` + return useCallback(async (currentPage) => { + const query = gql` { services( first: ${TOTAL_VIEW_COUNT}, @@ -65,11 +60,9 @@ export const useAllServices = () => { } `; - const response = await graphQlClient.request(query); - return response?.services || []; - }, - [graphQlClient], - ); + const response = await GRAPHQL_CLIENT.request(query); + return response?.services || []; + }, []); }; /** @@ -77,11 +70,8 @@ export const useAllServices = () => { * @returns {function} function to get my units */ export const useMyServices = () => { - const graphQlClient = useSubgraph(); - - return useCallback( - async (ownerAddress, currentPage) => { - const query = gql` + return useCallback(async (ownerAddress, currentPage) => { + const query = gql` { services ( first: ${TOTAL_VIEW_COUNT}, @@ -94,11 +84,9 @@ export const useMyServices = () => { } `; - const response = await graphQlClient.request(query); - return response?.services || []; - }, - [graphQlClient], - ); + const response = await GRAPHQL_CLIENT.request(query); + return response?.services || []; + }, []); }; /** @@ -106,11 +94,8 @@ export const useMyServices = () => { * @returns {function} function to get all units by search */ export const useAllServicesBySearch = () => { - const graphQlClient = useSubgraph(); - - return useCallback( - async (searchValue, currentPage) => { - const query = gql` + return useCallback(async (searchValue, currentPage) => { + const query = gql` { services ( first: ${TOTAL_VIEW_COUNT}, @@ -125,11 +110,9 @@ export const useAllServicesBySearch = () => { } `; - const response = await graphQlClient.request(query); - return response?.services || []; - }, - [graphQlClient], - ); + const response = await GRAPHQL_CLIENT.request(query); + return response?.services || []; + }, []); }; /** @@ -137,11 +120,8 @@ export const useAllServicesBySearch = () => { * @returns {function} function to search units */ export const useMyServicesBySearch = () => { - const graphQlClient = useSubgraph(); - - return useCallback( - async (ownerAddress, searchValue, currentPage) => { - const query = gql` + return useCallback(async (ownerAddress, searchValue, currentPage) => { + const query = gql` { services ( first: ${TOTAL_VIEW_COUNT}, @@ -157,11 +137,9 @@ export const useMyServicesBySearch = () => { } `; - const response = await graphQlClient.request(query); - return response?.services || []; - }, - [graphQlClient], - ); + const response = await GRAPHQL_CLIENT.request(query); + return response?.services || []; + }, []); }; export const useSearchServices = () => { diff --git a/apps/autonolas-registry/components/ListServices/index.jsx b/apps/autonolas-registry/components/ListServices/index.jsx index e0ce984d..2f5213ef 100644 --- a/apps/autonolas-registry/components/ListServices/index.jsx +++ b/apps/autonolas-registry/components/ListServices/index.jsx @@ -35,7 +35,7 @@ const ListServices = () => { isMyTab(hash) ? MY_SERVICES : ALL_SERVICES, ); - const { account, chainName, links, isSvm, chainId, isMainnet } = useHelpers(); + const { account, links, isSvm, chainId, isMainnet } = useHelpers(); const getAllServices = useAllServices(); const getMyServices = useMyServices(); @@ -63,7 +63,7 @@ const ListServices = () => { // update current tab based on the "hash" in the URL useEffect(() => { setCurrentTab(isMyTab(hash) ? MY_SERVICES : ALL_SERVICES); - }, [router.asPath, hash]); + }, [hash]); const { getTotalForAllSvmServices, @@ -104,19 +104,21 @@ const ListServices = () => { } }, [ account, - chainName, currentTab, searchValue, isSvm, getTotalForAllSvmServices, getTotalForMySvmServices, getSvmServices, + chainId, ]); // fetch the list (All services, My Services) - WITHOUT search useEffect(() => { const getList = async () => { setIsLoading(true); + setList([]); + try { // All services if (currentTab === ALL_SERVICES) { @@ -135,7 +137,7 @@ const ListServices = () => { * - search by `account` as searchValue * - API will be called only once & store the complete list */ - if (chainId === 1) { + if (isMainnet) { const e = await getMyServices(account, currentPage); setList(e); } else { @@ -163,8 +165,6 @@ const ListServices = () => { } }, [ account, - chainId, - chainName, total, currentPage, currentTab, @@ -175,6 +175,7 @@ const ListServices = () => { getSvmServices, getMySvmServices, isMainnet, + chainId, ]); /** @@ -187,8 +188,10 @@ const ListServices = () => { if (!searchValue) return; setIsLoading(true); + setList([]); + try { - if (chainId === 1) { + if (isMainnet) { const filteredList = await getServicesBySearch( searchValue, currentPage, @@ -214,12 +217,12 @@ const ListServices = () => { })(); }, [ account, - chainName, searchValue, currentTab, - chainId, currentPage, getServicesBySearch, + isMainnet, + chainId, ]); const tableCommonProps = { @@ -235,9 +238,7 @@ const ListServices = () => { }; const getMyServiceList = () => { - if (isMainnet) { - return list; - } + if (isMainnet) return list; return searchValue ? list diff --git a/apps/autonolas-registry/tests/components/ListServices/details.test.jsx b/apps/autonolas-registry/tests/components/ListServices/details.test.jsx index 2b8d33c1..998fe3f3 100644 --- a/apps/autonolas-registry/tests/components/ListServices/details.test.jsx +++ b/apps/autonolas-registry/tests/components/ListServices/details.test.jsx @@ -39,6 +39,7 @@ import { useHelpersEvmMock, useHelpersSvmMock, svmServiceStateMock, + useHelpersBaseMock, } from '../../tests-helpers'; jest.mock('next/router', () => ({ @@ -69,6 +70,7 @@ jest.mock('../../../common-util/hooks/useMetadata', () => ({ nftImageUrl: `${GATEWAY_URL}${mockNftImageHash}`, description: mockIpfs.description, version: mockIpfs.attributes[0].value, + packageName: mockIpfs.name, })), })); @@ -224,10 +226,13 @@ describe('listServices/details.jsx', () => { ); }); - it('should render service details (left side)', async () => { - const { getByText, getByTestId } = render(wrapProvider()); + it('should display service details (left side)', async () => { + const { getByText, getByTestId, debug } = render( + wrapProvider(), + ); + debug(); await waitFor(async () => { - // expect(getByText('Service ID 1')).toBeInTheDocument(); + expect(getByText('Some package name')).toBeInTheDocument(); expect(getByTestId('service-status').textContent).toBe('Inactive'); expect(getByTestId('view-hash-link').getAttribute('href')).toBe( `${GATEWAY_URL}12345`, @@ -257,7 +262,7 @@ describe('listServices/details.jsx', () => { // TODO: add brief tests for operator whitelisting - it('should render service state (right side)', async () => { + it('should display service state (right side)', async () => { const { container } = render(wrapProvider()); await waitFor(async () => { const getTitle = (i) => @@ -276,10 +281,36 @@ describe('listServices/details.jsx', () => { ).toHaveTextContent('Terminated Bonded'); }); }); + + describe('mainnet', () => { + it('should display the package name', async () => { + const { findByText } = render(wrapProvider()); + + expect(await findByText('Some package name')).toBeInTheDocument(); + }); + }); + + describe('non-mainnet', () => { + beforeEach(() => { + jest.clearAllMocks(); + + useHelpers.mockReturnValue(useHelpersBaseMock); + }); + + it('should display the service name', async () => { + const { findByText, debug } = render(wrapProvider()); + + debug(); + expect(await findByText(/Service Name/)).toBeInTheDocument(); + // expect(await findByText(/Service ID/)).toBeInTheDocument(); + }); + }); }); describe('SVM', () => { beforeEach(() => { + jest.clearAllMocks(); + // mock hooks useHelpers.mockReturnValue(useHelpersSvmMock); useSvmConnectivity.mockReturnValue(svmConnectivityEmptyMock); @@ -345,10 +376,12 @@ describe('listServices/details.jsx', () => { getTokenBondRequest.mockReturnValueOnce([]); }); - it('should render service details (left side)', async () => { + it('should display service details (left side)', async () => { const { getByText, getByTestId } = render(wrapProvider()); + await waitFor(async () => { - // expect(getByText('Service ID 1')).toBeInTheDocument(); + expect(getByText('Service Name')).toBeInTheDocument(); + expect(getByText('Service ID 1')).toBeInTheDocument(); expect(getByTestId('service-status').textContent).toBe('Inactive'); expect(getByTestId('view-hash-link').getAttribute('href')).toBe( `${GATEWAY_URL}12345`, @@ -376,8 +409,9 @@ describe('listServices/details.jsx', () => { }); }); - it('should render service state (right side)', async () => { + it('should display service state (right side)', async () => { const { container, getByText } = render(wrapProvider()); + await waitFor(async () => { const getTitle = (i) => container.querySelector( diff --git a/apps/autonolas-registry/tests/components/ListServices/index.test.tsx b/apps/autonolas-registry/tests/components/ListServices/index.test.tsx index c2c65afa..82220b22 100644 --- a/apps/autonolas-registry/tests/components/ListServices/index.test.tsx +++ b/apps/autonolas-registry/tests/components/ListServices/index.test.tsx @@ -26,26 +26,28 @@ import { const allServicesResponse = [ { - id: '1', - tokenId: '1', + id: '301', + serviceId: '301', owner: dummyAddress, publicId: 'good_package_name_all_services', packageHash: dummyHash1, metadataHash: mockCodeUri, + state: 4, }, ]; const myServicesResponse = [ { ...allServicesResponse[0], - tokenId: '2', + serviceId: '302', owner: dummyAddress1, publicId: 'good_package_name_my_services', + state: 1, }, ]; const allServicesSearchResponse = [ { ...allServicesResponse[0], - tokenId: '3', + serviceId: '3', publicId: 'good_package_name_services_search', }, ]; @@ -84,7 +86,7 @@ describe('listServices/index.jsx', () => { (useServiceInfo as jest.Mock).mockReturnValue(jest.fn(() => {})); }); - it('should render tabs with `All Tab` & Mint button', async () => { + it('should display tabs with `All Tab` & Mint button', async () => { const { container, getByRole } = render(wrapProvider()); // check if the selected tab is `All` & has the correct content await waitFor(async () => { @@ -102,7 +104,7 @@ describe('listServices/index.jsx', () => { }); }); - describe.skip('mainnet', () => { + describe('mainnet', () => { beforeEach(() => { jest.clearAllMocks(); @@ -113,7 +115,27 @@ describe('listServices/index.jsx', () => { (getTotalForMyServices as jest.Mock).mockResolvedValue(1); }); - it('should display all services', async () => { + it('should display columns for mainnet', async () => { + const { container, findByTestId } = render( + wrapProvider(), + ); + const allServicesTable = await findByTestId('all-services-table'); + + if (!container) { + throw new Error('`All tab` is null'); + } + + expect(within(allServicesTable).getByText('ID')).toBeInTheDocument(); + expect(within(allServicesTable).getByText('Name')).toBeInTheDocument(); + expect(within(allServicesTable).getByText('Owner')).toBeInTheDocument(); + expect(within(allServicesTable).getByText('Hash')).toBeInTheDocument(); + expect(within(allServicesTable).getByText('State')).toBeInTheDocument(); + expect( + within(allServicesTable).getByText('Action'), + ).toBeInTheDocument(); + }); + + it('should display all services information', async () => { const { container, findByTestId } = render( wrapProvider(), ); @@ -127,22 +149,22 @@ describe('listServices/index.jsx', () => { expect(container.querySelector(ACTIVE_TAB)?.textContent).toBe('All'), ); - const firstAgent = allServicesResponse[0]; + const firstService = allServicesResponse[0]; const allServicesTable = await findByTestId('all-services-table'); expect( - within(allServicesTable).getByText(firstAgent.tokenId), + within(allServicesTable).getByText(firstService.serviceId), + ).toBeInTheDocument(); + expect( + within(allServicesTable).getByText(/0x8626...9C1199/), + ).toBeInTheDocument(); + expect( + within(allServicesTable).getByText(/0x9cf4...315ab0/), ).toBeInTheDocument(); - // expect( - // within(allServicesTable).getByText(/0x8626...9C1199/), - // ).toBeInTheDocument(); - // expect( - // within(allServicesTable).getByText(/0x9cf4...315ab0/), - // ).toBeInTheDocument(); - // expect( - // within(allServicesTable).getByText(firstAgent.publicId), - // ).toBeInTheDocument(); - // expect(within(allServicesTable).getByText('View')).toBeInTheDocument(); + expect( + within(allServicesTable).getByText('Deployed'), + ).toBeInTheDocument(); + expect(within(allServicesTable).getByText('View')).toBeInTheDocument(); }); }); @@ -155,14 +177,11 @@ describe('listServices/index.jsx', () => { (getTotalForAllServices as jest.Mock).mockResolvedValue(1); (getTotalForMyServices as jest.Mock).mockResolvedValue(1); (getServices as jest.Mock).mockResolvedValue([ - { id: '1', owner: dummyAddress, state: '5' }, - ]); - (getFilteredServices as jest.Mock).mockResolvedValue([ - { id: '2', owner: dummyAddress, state: '2' }, + { id: '5001', owner: dummyAddress, state: '5' }, ]); }); - it('should render service columns and rows', async () => { + it('should display service columns', async () => { const { container, findByTestId } = render( wrapProvider(), ); @@ -172,31 +191,40 @@ describe('listServices/index.jsx', () => { throw new Error('`All tab` is null'); } - await waitFor(async () => { - // column names - expect(within(allServicesTable).getByText('ID')).toBeInTheDocument(); - expect( - within(allServicesTable).getByText('Owner'), - ).toBeInTheDocument(); - expect( - within(allServicesTable).getByText('State'), - ).toBeInTheDocument(); - expect( - within(allServicesTable).getByText('Action'), - ).toBeInTheDocument(); - - // rows - expect(within(allServicesTable).getByText('1')).toBeInTheDocument(); - expect( - within(allServicesTable).getByText('0x8626...9C1199'), - ).toBeInTheDocument(); - expect( - within(allServicesTable).getByText('Terminated Bonded'), - ).toBeInTheDocument(); - expect( - within(allServicesTable).getByText('View'), - ).toBeInTheDocument(); - }); + expect(within(allServicesTable).getByText('ID')).toBeInTheDocument(); + expect(within(allServicesTable).queryByText('Name')).toBeNull(); + expect(within(allServicesTable).getByText('Owner')).toBeInTheDocument(); + expect(within(allServicesTable).queryByText('Hash')).toBeNull(); + expect(within(allServicesTable).getByText('State')).toBeInTheDocument(); + expect( + within(allServicesTable).getByText('Action'), + ).toBeInTheDocument(); + }); + + it('should display all services information', async () => { + const { container, findByTestId } = render( + wrapProvider(), + ); + + if (!container) { + throw new Error('`All tab` is null'); + } + + // check if the selected tab is `All` & has the correct content + await waitFor(async () => + expect(container.querySelector(ACTIVE_TAB)?.textContent).toBe('All'), + ); + + const allServicesTable = await findByTestId('all-services-table'); + + expect(within(allServicesTable).getByText('5001')).toBeInTheDocument(); + expect( + within(allServicesTable).getByText(/0x8626...9C1199/), + ).toBeInTheDocument(); + expect( + within(allServicesTable).getByText('Terminated Bonded'), + ).toBeInTheDocument(); + expect(within(allServicesTable).getByText('View')).toBeInTheDocument(); }); }); }); @@ -229,7 +257,7 @@ describe('listServices/index.jsx', () => { (getFilteredServices as jest.Mock).mockResolvedValue([]); }); - it('should render tabs with `All Tab` & Mint button', async () => { + it('should display tabs with `All Tab` & Mint button', async () => { const { container, getByRole } = render(wrapProvider()); if (!container) { @@ -252,7 +280,7 @@ describe('listServices/index.jsx', () => { }); }); - it('should render service columns and rows', async () => { + it('should display service columns and rows', async () => { const { container, findByTestId } = render( wrapProvider(), ); From 4069101613e3faea06141de694628db2bb4d0c2d Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Tue, 9 Apr 2024 15:46:17 +0530 Subject: [PATCH 34/39] address few comments --- .../common-util/Details/index.jsx | 4 +- .../components/ListAgents/index.jsx | 10 +- .../components/ListAgents/useAgentsList.jsx | 91 ++++++++----------- .../components/ListComponents/index.jsx | 10 +- .../ListServices/hooks/useServicesList.jsx | 10 +- 5 files changed, 53 insertions(+), 72 deletions(-) diff --git a/apps/autonolas-registry/common-util/Details/index.jsx b/apps/autonolas-registry/common-util/Details/index.jsx index 67fec010..b2ed218f 100644 --- a/apps/autonolas-registry/common-util/Details/index.jsx +++ b/apps/autonolas-registry/common-util/Details/index.jsx @@ -58,9 +58,7 @@ export const Details = ({
    {isMainnet ? ( - <> - {packageName} - + {packageName} ) : ( <> {`${capitalize(type)} Name`} diff --git a/apps/autonolas-registry/components/ListAgents/index.jsx b/apps/autonolas-registry/components/ListAgents/index.jsx index c6a980d4..c6968de5 100644 --- a/apps/autonolas-registry/components/ListAgents/index.jsx +++ b/apps/autonolas-registry/components/ListAgents/index.jsx @@ -108,10 +108,10 @@ const ListAgents = () => { * - search by `account` as searchValue * - API will be called only once & store the complete list */ - const e = isMainnet + const myAgents = isMainnet ? await getMyAgents(account, currentPage) : await getFilteredAgents(account); - setList(e); + setList(myAgents); } } catch (e) { console.error(e); @@ -193,8 +193,8 @@ const ListAgents = () => { type="card" activeKey={currentTab} tabBarExtraContent={extraTabContent} - onChange={(e) => { - setCurrentTab(e); + onChange={(tabName) => { + setCurrentTab(tabName); setTotal(0); setCurrentPage(1); @@ -205,7 +205,7 @@ const ListAgents = () => { // update the links to keep track of my-agents router.push( - e === MY_AGENTS ? `${links.AGENTS}#${MY_AGENTS}` : links.AGENTS, + tabName === MY_AGENTS ? `${links.AGENTS}#${MY_AGENTS}` : links.AGENTS, ); }} items={[ diff --git a/apps/autonolas-registry/components/ListAgents/useAgentsList.jsx b/apps/autonolas-registry/components/ListAgents/useAgentsList.jsx index 863e56c9..1be6d551 100644 --- a/apps/autonolas-registry/components/ListAgents/useAgentsList.jsx +++ b/apps/autonolas-registry/components/ListAgents/useAgentsList.jsx @@ -13,6 +13,39 @@ import { } from '../../common-util/hooks/useSubgraph'; import { TOTAL_VIEW_COUNT } from '../../util/constants'; +const getAllAndMyAgentsQuery = (currentPage, ownerAddress = null) => { + return gql` + { + units( + first: ${TOTAL_VIEW_COUNT}, + skip: ${TOTAL_VIEW_COUNT * (currentPage - 1)}, + where: { + packageType: agent + ${ownerAddress ? `owner_contains_nocase: "${ownerAddress}"` : ''} + }, + orderBy: tokenId + ) ${columnsForAgentsAndComponents} + } + `; +}; + +const getAgentsBySearchQuery = (searchValue, ownerAddress = null) => { + return gql` + { + units( + where: { + and: [ + { packageType: "agent" } + ${getSearchFilterSubQueryForAgentsAndComponents(searchValue)} + ${ownerAddress ? `owner_contains_nocase: "${ownerAddress}"` : ''} + ] + } + orderBy: tokenId + ) ${columnsForAgentsAndComponents} + } + `; +}; + /** * Hook to get ALL units * @returns {function} function to get all units @@ -20,17 +53,7 @@ import { TOTAL_VIEW_COUNT } from '../../util/constants'; */ export const useAllAgents = () => { return useCallback(async (currentPage) => { - const query = gql` - { - units( - first: ${TOTAL_VIEW_COUNT}, - skip: ${TOTAL_VIEW_COUNT * (currentPage - 1)}, - where: { packageType: agent }, - orderBy: tokenId - ) ${columnsForAgentsAndComponents} - } - `; - + const query = getAllAndMyAgentsQuery(currentPage); const response = await GRAPHQL_CLIENT.request(query); return response?.units; }, []); @@ -42,20 +65,7 @@ export const useAllAgents = () => { */ export const useMyAgents = () => { return useCallback(async (ownerAddress, currentPage) => { - const query = gql` - { - units( - first: ${TOTAL_VIEW_COUNT}, - skip: ${TOTAL_VIEW_COUNT * (currentPage - 1)}, - where: { - packageType: agent - owner_contains_nocase: "${ownerAddress}", - }, - orderBy: tokenId, - ) ${columnsForAgentsAndComponents} - } - `; - + const query = getAllAndMyAgentsQuery(currentPage, ownerAddress); const response = await GRAPHQL_CLIENT.request(query); return response?.units; }, []); @@ -67,20 +77,7 @@ export const useMyAgents = () => { */ const useAllAgentsBySearch = () => { return useCallback(async (searchValue) => { - const query = gql` - { - units( - where: { - and: [ - { packageType: "agent" } - ${getSearchFilterSubQueryForAgentsAndComponents(searchValue)} - ] - } - orderBy: tokenId - ) ${columnsForAgentsAndComponents} - } - `; - + const query = getAgentsBySearchQuery(searchValue); const response = await GRAPHQL_CLIENT.request(query); return response?.units; }, []); @@ -92,21 +89,7 @@ const useAllAgentsBySearch = () => { */ const useMyAgentsBySearch = () => { return useCallback(async (ownerAddress, searchValue) => { - const query = gql` - { - units( - where: { - and: [ - { packageType: "agent" } - { owner_contains_nocase: "${ownerAddress}" } - ${getSearchFilterSubQueryForAgentsAndComponents(searchValue)} - ] - } - orderBy: tokenId - ) ${columnsForAgentsAndComponents} - } - `; - + const query = getAgentsBySearchQuery(searchValue, ownerAddress); const response = await GRAPHQL_CLIENT.request(query); return response?.units; }, []); diff --git a/apps/autonolas-registry/components/ListComponents/index.jsx b/apps/autonolas-registry/components/ListComponents/index.jsx index 46014470..f31b1dc8 100644 --- a/apps/autonolas-registry/components/ListComponents/index.jsx +++ b/apps/autonolas-registry/components/ListComponents/index.jsx @@ -112,10 +112,10 @@ const ListComponents = () => { * - search by `account` as searchValue * - API will be called only once & store the complete list */ - const e = isMainnet + const myComps = isMainnet ? await getMyComponents(account, currentPage) : await getFilteredComponents(account); - setList(e); + setList(myComps); } } catch (e) { console.error(e); @@ -196,8 +196,8 @@ const ListComponents = () => { type="card" activeKey={currentTab} tabBarExtraContent={extraTabContent} - onChange={(e) => { - setCurrentTab(e); + onChange={(tabName) => { + setCurrentTab(tabName); setTotal(0); setCurrentPage(1); @@ -208,7 +208,7 @@ const ListComponents = () => { // update the URL to keep track of my-components router.push( - e === MY_COMPONENTS + tabName === MY_COMPONENTS ? `${links.COMPONENTS}#${MY_COMPONENTS}` : links.COMPONENTS, ); diff --git a/apps/autonolas-registry/components/ListServices/hooks/useServicesList.jsx b/apps/autonolas-registry/components/ListServices/hooks/useServicesList.jsx index e9963626..e8a26497 100644 --- a/apps/autonolas-registry/components/ListServices/hooks/useServicesList.jsx +++ b/apps/autonolas-registry/components/ListServices/hooks/useServicesList.jsx @@ -9,7 +9,7 @@ import { gql } from 'graphql-request'; import { GRAPHQL_CLIENT } from '../../../common-util/hooks/useSubgraph'; import { HASH_PREFIX, TOTAL_VIEW_COUNT } from '../../../util/constants'; -const serviceColumns = `{ +const SERVICE_FIELDS = `{ id serviceId publicId @@ -56,7 +56,7 @@ export const useAllServices = () => { first: ${TOTAL_VIEW_COUNT}, skip: ${TOTAL_VIEW_COUNT * (currentPage - 1)}, orderBy: serviceId - ) ${serviceColumns} + ) ${SERVICE_FIELDS} } `; @@ -80,7 +80,7 @@ export const useMyServices = () => { owner_contains_nocase: "${ownerAddress}" }, orderBy: serviceId, - ) ${serviceColumns} + ) ${SERVICE_FIELDS} } `; @@ -106,7 +106,7 @@ export const useAllServicesBySearch = () => { ] } orderBy: serviceId - ) ${serviceColumns} + ) ${SERVICE_FIELDS} } `; @@ -133,7 +133,7 @@ export const useMyServicesBySearch = () => { ] } orderBy: serviceId, - ) ${serviceColumns} + ) ${SERVICE_FIELDS} } `; From 555f06b2d35bbd78bd8cdca34d422baa09aeee7a Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Wed, 10 Apr 2024 03:15:31 +0530 Subject: [PATCH 35/39] address review comments --- .../common-util/List/ListTable/ListTable.jsx | 120 +++++++++++++ .../common-util/List/ListTable/helpers.jsx | 157 +++++------------- .../common-util/List/ListTable/index.jsx | 127 +------------- .../List/ListTable/useExtraTabContent.jsx | 80 +++++++++ .../common-util/hooks/useHelpers.jsx | 11 +- .../common-util/hooks/useSubgraph.jsx | 2 +- .../components/ListAgents/index.jsx | 4 +- .../components/ListAgents/useAgentsList.jsx | 6 +- .../components/ListComponents/index.jsx | 4 +- .../ListComponents/useComponentsList.jsx | 10 +- .../ListServices/hooks/useService.jsx | 14 +- .../components/ListServices/index.jsx | 28 ++-- 12 files changed, 280 insertions(+), 283 deletions(-) create mode 100644 apps/autonolas-registry/common-util/List/ListTable/ListTable.jsx create mode 100644 apps/autonolas-registry/common-util/List/ListTable/useExtraTabContent.jsx diff --git a/apps/autonolas-registry/common-util/List/ListTable/ListTable.jsx b/apps/autonolas-registry/common-util/List/ListTable/ListTable.jsx new file mode 100644 index 00000000..11d4bc7c --- /dev/null +++ b/apps/autonolas-registry/common-util/List/ListTable/ListTable.jsx @@ -0,0 +1,120 @@ +import PropTypes from 'prop-types'; +import { Table } from 'antd'; +import { Loader, useScreen } from '@autonolas/frontend-library'; + +import { TOTAL_VIEW_COUNT } from '../../../util/constants'; +import { ListEmptyMessage } from '../ListCommon'; +import { useHelpers } from '../../hooks'; +import { convertTableRawData, getTableColumns } from './helpers'; + +export const ListTable = ({ + isLoading, + type, + searchValue, + isPaginationRequired, + list, + total, + currentPage, + setCurrentPage, + isAccountRequired, + onViewClick, + onUpdateClick, + extra, + tableDataTestId, +}) => { + const { chainName, account, isSvm, chainId, isMainnet } = useHelpers(); + + /** + * no pagination on search as we won't know total beforehand + */ + const canShowPagination = isPaginationRequired ? !searchValue : false; + const { isMobile } = useScreen(); + + const { scrollX } = extra; + + if (isLoading) { + if (isSvm) { + return ; + } + + return ( + + ); + } + + const columns = getTableColumns(type, { + onViewClick, + onUpdateClick, + isMobile, + chainName, + chainId, + account, + isMainnet, + }); + const dataSource = convertTableRawData(type, list, { + currentPage, + isMainnet, + }); + const pagination = { + total, + current: currentPage, + defaultPageSize: canShowPagination ? TOTAL_VIEW_COUNT : total, + onChange: (e) => setCurrentPage(e), + showSizeChanger: false, + }; + + return ( + <> + {list.length === 0 ? ( + + ) : ( + `${type}-row-${record.id}`} + data-testid={tableDataTestId || `${type}-table`} + /> + )} + + ); +}; + +ListTable.propTypes = { + type: PropTypes.string.isRequired, + searchValue: PropTypes.string.isRequired, + isPaginationRequired: PropTypes.bool, + isLoading: PropTypes.bool, + list: PropTypes.arrayOf(PropTypes.object), + total: PropTypes.number, + currentPage: PropTypes.number, + setCurrentPage: PropTypes.func, + isAccountRequired: PropTypes.bool, + onViewClick: PropTypes.func, + onUpdateClick: PropTypes.func, + tableDataTestId: PropTypes.string, + extra: PropTypes.shape({ + scrollX: PropTypes.number, + }), +}; + +ListTable.defaultProps = { + isLoading: false, + isPaginationRequired: true, + list: [], + total: 0, + currentPage: 0, + setCurrentPage: () => {}, + isAccountRequired: false, + onViewClick: () => {}, + onUpdateClick: null, + extra: { scrollX: 1200 }, +}; diff --git a/apps/autonolas-registry/common-util/List/ListTable/helpers.jsx b/apps/autonolas-registry/common-util/List/ListTable/helpers.jsx index 9471d057..bf0a578c 100644 --- a/apps/autonolas-registry/common-util/List/ListTable/helpers.jsx +++ b/apps/autonolas-registry/common-util/List/ListTable/helpers.jsx @@ -1,22 +1,18 @@ -import { useState } from 'react'; -import { Input, Space, Button, Typography, Tooltip } from 'antd'; -import { SearchOutlined, InfoCircleOutlined } from '@ant-design/icons'; +import { Space, Button } from 'antd'; import { AddressLink, areAddressesEqual, NA, } from '@autonolas/frontend-library'; -import styled from 'styled-components'; import { HASH_PREFIX, NAV_TYPES, SERVICE_STATE, + SERVICE_STATE_KEY_MAP, TOTAL_VIEW_COUNT, } from '../../../util/constants'; -const { Title } = Typography; - export const getTableColumns = ( type, { @@ -112,9 +108,9 @@ export const getTableColumns = ( dataIndex: 'state', key: 'state', width: 150, - render: (e) => { - if (!e) return NA; - return SERVICE_STATE[e]; + render: (text) => { + if (!text) return NA; + return SERVICE_STATE[text]; }, }; const actionAndUpdateColumn = { @@ -123,9 +119,10 @@ export const getTableColumns = ( key: 'action', fixed: 'right', render: (_text, record) => { - // only show update button for pre-registration state + // only show update button for pre-registration state and + // if the owner is the same as the current account const canUpdate = - ['1'].includes(record.state) && + record.state === SERVICE_STATE_KEY_MAP.preRegistration && areAddressesEqual(record.owner, account); return ( @@ -148,6 +145,30 @@ export const getTableColumns = ( }, }; + const idColumn = { + title: 'ID', + dataIndex: 'id', + key: 'id', + width: isMobile ? 30 : 50, + }; + + const nonMainnetOwnerColumn = { + title: 'Owner', + dataIndex: 'owner', + key: 'owner', + width: 200, + render: (text) => { + if (!text || text === NA) return NA; + return ( + + ); + }, + }; + return isMainnet ? [ tokenIdColumn, @@ -157,38 +178,17 @@ export const getTableColumns = ( stateColumn, actionAndUpdateColumn, ] - : [ - { - title: 'ID', - dataIndex: 'id', - key: 'id', - width: isMobile ? 30 : 50, - }, - { - title: 'Owner', - dataIndex: 'owner', - key: 'owner', - width: 200, - render: (text) => { - if (!text || text === NA) return NA; - return ( - - ); - }, - }, - stateColumn, - actionAndUpdateColumn, - ]; + : [idColumn, nonMainnetOwnerColumn, stateColumn, actionAndUpdateColumn]; } return []; }; -export const fetchDataSource = (type, rawData, { current, isMainnet }) => { +export const convertTableRawData = ( + type, + rawData, + { currentPage, isMainnet }, +) => { /** * @example * TOTAL_VIEW_COUNT = 10, current = 1 @@ -200,7 +200,7 @@ export const fetchDataSource = (type, rawData, { current, isMainnet }) => { * = 40 + 1 * = 41 */ - const startIndex = (current - 1) * TOTAL_VIEW_COUNT + 1; + const startIndex = (currentPage - 1) * TOTAL_VIEW_COUNT + 1; // for mainnet if (isMainnet) { @@ -261,84 +261,7 @@ export const fetchDataSource = (type, rawData, { current, isMainnet }) => { })); } - return []; -}; - -const SearchTooltip = styled.div` - ul { - margin: 0; - padding: 0 0 0 16px; - } -`; - -/** - * tab content - */ -export const useExtraTabContent = ({ - title, - onRegisterClick = () => {}, - isSvm = false, - type, -}) => { - const [searchValue, setSearchValue] = useState(''); - const [value, setValue] = useState(''); - const clearSearch = () => { - setValue(''); - setSearchValue(''); - }; - - const extraTabContent = { - left: {title}, - right: ( - <> - {/* TODO: hiding search util feature is introduced */} - {isSvm ? null : ( - <> - } - placeholder="Search..." - value={value} - onChange={(e) => setValue(e.target.value)} - onKeyDown={(e) => - e.key === 'Enter' && setSearchValue(value || '') - } - suffix={ - -
    Search by:
    -
      -
    • Name
    • - {type !== NAV_TYPES.SERVICE &&
    • Description
    • } -
    • Owner
    • -
    • Package Hash
    • -
    - - } - > - -
    - } - /> - - - - )} - - - - ), - }; - - return { searchValue, extraTabContent, clearSearch }; + throw new Error('Invalid type parameter'); }; /** diff --git a/apps/autonolas-registry/common-util/List/ListTable/index.jsx b/apps/autonolas-registry/common-util/List/ListTable/index.jsx index 950b8044..00f2a195 100644 --- a/apps/autonolas-registry/common-util/List/ListTable/index.jsx +++ b/apps/autonolas-registry/common-util/List/ListTable/index.jsx @@ -1,124 +1,3 @@ -import PropTypes from 'prop-types'; -import { Table } from 'antd'; -import { Loader, useScreen } from '@autonolas/frontend-library'; - -import { TOTAL_VIEW_COUNT } from '../../../util/constants'; -import { ListEmptyMessage } from '../../List/ListCommon'; -import { useHelpers } from '../../hooks'; -import { fetchDataSource, getTableColumns } from './helpers'; - -const ListTable = ({ - isLoading, - type, - searchValue, - isPaginationRequired, - list, - total, - currentPage, - setCurrentPage, - isAccountRequired, - onViewClick, - onUpdateClick, - extra, - tableDataTestId, -}) => { - const { chainName, account, isSvm, chainId, isMainnet } = useHelpers(); - /** - * no pagination on search as we won't know total beforehand - */ - const canShowPagination = isPaginationRequired ? !searchValue : false; - const { isMobile } = useScreen(); - - const { scrollX } = extra; - - if (isLoading) { - if (isSvm) { - return ; - } - - return ( - - ); - } - - const columns = getTableColumns(type, { - onViewClick, - onUpdateClick, - isMobile, - chainName, - chainId, - account, - isMainnet, - }); - const dataSource = fetchDataSource(type, list, { - current: currentPage, - isMainnet, - }); - const pagination = { - total, - current: currentPage, - defaultPageSize: canShowPagination ? TOTAL_VIEW_COUNT : total, - onChange: (e) => setCurrentPage(e), - showSizeChanger: false, - }; - - return ( - <> - {list.length === 0 ? ( - - ) : ( -
    `${type}-row-${record.id}`} - data-testid={tableDataTestId || `${type}-table`} - /> - )} - - ); -}; - -ListTable.propTypes = { - type: PropTypes.string.isRequired, - searchValue: PropTypes.string.isRequired, - isPaginationRequired: PropTypes.bool, - isLoading: PropTypes.bool, - list: PropTypes.arrayOf(PropTypes.object), - total: PropTypes.number, - currentPage: PropTypes.number, - setCurrentPage: PropTypes.func, - isAccountRequired: PropTypes.bool, - onViewClick: PropTypes.func, - onUpdateClick: PropTypes.func, - tableDataTestId: PropTypes.string, - extra: PropTypes.shape({ - scrollX: PropTypes.number, - }), -}; - -ListTable.defaultProps = { - isLoading: false, - isPaginationRequired: true, - list: [], - total: 0, - currentPage: 0, - setCurrentPage: () => {}, - isAccountRequired: false, - onViewClick: () => {}, - onUpdateClick: null, - tableDataTestId: null, - extra: { - scrollX: 1200, - }, -}; - -export default ListTable; +export { ListTable } from './ListTable'; +export { useExtraTabContent } from './useExtraTabContent'; +export { getHash, isMyTab } from './helpers'; diff --git a/apps/autonolas-registry/common-util/List/ListTable/useExtraTabContent.jsx b/apps/autonolas-registry/common-util/List/ListTable/useExtraTabContent.jsx new file mode 100644 index 00000000..86d314c2 --- /dev/null +++ b/apps/autonolas-registry/common-util/List/ListTable/useExtraTabContent.jsx @@ -0,0 +1,80 @@ +import { useState } from 'react'; +import { Input, Button, Typography, Tooltip } from 'antd'; +import { SearchOutlined, InfoCircleOutlined } from '@ant-design/icons'; +import styled from 'styled-components'; + +import { NAV_TYPES } from '../../../util/constants'; + +const { Title } = Typography; + +const SearchUl = styled.ul` + margin: 0; + padding: 0 0 0 16px; +`; + +export const useExtraTabContent = ({ + title, + onRegisterClick, + isSvm = false, + type, +}) => { + const [searchValue, setSearchValue] = useState(''); + const [value, setValue] = useState(''); + const clearSearch = () => { + setValue(''); + setSearchValue(''); + }; + + const extraTabContent = { + left: {title}, + right: ( + <> + {/* TODO: hiding search util feature is introduced */} + {isSvm ? null : ( + <> + } + placeholder="Search..." + value={value} + onChange={(e) => setValue(e.target.value)} + onKeyDown={(e) => + e.key === 'Enter' && setSearchValue(value || '') + } + suffix={ + +
    Search by:
    + +
  • Name
  • + {type !== NAV_TYPES.SERVICE &&
  • Description
  • } +
  • Owner
  • +
  • Package Hash
  • +
    + + } + > + +
    + } + /> + + + + )} + + + + ), + }; + + return { searchValue, extraTabContent, clearSearch }; +}; diff --git a/apps/autonolas-registry/common-util/hooks/useHelpers.jsx b/apps/autonolas-registry/common-util/hooks/useHelpers.jsx index 3839d013..8de63bbf 100644 --- a/apps/autonolas-registry/common-util/hooks/useHelpers.jsx +++ b/apps/autonolas-registry/common-util/hooks/useHelpers.jsx @@ -13,16 +13,9 @@ import { doesNetworkHaveValidServiceManagerTokenFn } from '../functions'; export const useHelpers = () => { const wallet = useAnchorWallet(); - - const account = useSelector((state) => state?.setup?.account); - const vmType = useSelector((state) => state?.setup?.vmType); - - // chainId - selected in the dropdown - const chainId = useSelector((state) => state?.setup?.chainId); - const chainDisplayName = useSelector( - (state) => state?.setup?.chainDisplayName, + const { account, vmType, chainId, chainDisplayName, chainName } = useSelector( + (state) => state?.setup, ); - const chainName = useSelector((state) => state?.setup?.chainName); const { chain: chainFromWallet } = useNetwork(); const chainIdFromWallet = chainFromWallet?.id; diff --git a/apps/autonolas-registry/common-util/hooks/useSubgraph.jsx b/apps/autonolas-registry/common-util/hooks/useSubgraph.jsx index baa2f5fe..b2b83b89 100644 --- a/apps/autonolas-registry/common-util/hooks/useSubgraph.jsx +++ b/apps/autonolas-registry/common-util/hooks/useSubgraph.jsx @@ -12,7 +12,7 @@ export const GRAPHQL_CLIENT = new GraphQLClient( }, ); -export const columnsForAgentsAndComponents = `{ +export const UNIT_FIELDS = `{ id tokenId owner diff --git a/apps/autonolas-registry/components/ListAgents/index.jsx b/apps/autonolas-registry/components/ListAgents/index.jsx index c6968de5..d5ee6e26 100644 --- a/apps/autonolas-registry/components/ListAgents/index.jsx +++ b/apps/autonolas-registry/components/ListAgents/index.jsx @@ -4,12 +4,12 @@ import { useRouter } from 'next/router'; import { notifyError } from '@autonolas/frontend-library'; import { NAV_TYPES } from '../../util/constants'; -import ListTable from '../../common-util/List/ListTable'; import { + ListTable, useExtraTabContent, getHash, isMyTab, -} from '../../common-util/List/ListTable/helpers'; +} from '../../common-util/List/ListTable'; import { useHelpers } from '../../common-util/hooks'; import { useAllAgents, useMyAgents, useSearchAgents } from './useAgentsList'; import { diff --git a/apps/autonolas-registry/components/ListAgents/useAgentsList.jsx b/apps/autonolas-registry/components/ListAgents/useAgentsList.jsx index 1be6d551..df5117bb 100644 --- a/apps/autonolas-registry/components/ListAgents/useAgentsList.jsx +++ b/apps/autonolas-registry/components/ListAgents/useAgentsList.jsx @@ -8,7 +8,7 @@ import { gql } from 'graphql-request'; import { GRAPHQL_CLIENT, - columnsForAgentsAndComponents, + UNIT_FIELDS, getSearchFilterSubQueryForAgentsAndComponents, } from '../../common-util/hooks/useSubgraph'; import { TOTAL_VIEW_COUNT } from '../../util/constants'; @@ -24,7 +24,7 @@ const getAllAndMyAgentsQuery = (currentPage, ownerAddress = null) => { ${ownerAddress ? `owner_contains_nocase: "${ownerAddress}"` : ''} }, orderBy: tokenId - ) ${columnsForAgentsAndComponents} + ) ${UNIT_FIELDS} } `; }; @@ -41,7 +41,7 @@ const getAgentsBySearchQuery = (searchValue, ownerAddress = null) => { ] } orderBy: tokenId - ) ${columnsForAgentsAndComponents} + ) ${UNIT_FIELDS} } `; }; diff --git a/apps/autonolas-registry/components/ListComponents/index.jsx b/apps/autonolas-registry/components/ListComponents/index.jsx index f31b1dc8..afb02ace 100644 --- a/apps/autonolas-registry/components/ListComponents/index.jsx +++ b/apps/autonolas-registry/components/ListComponents/index.jsx @@ -4,12 +4,12 @@ import { useRouter } from 'next/router'; import { notifyError } from '@autonolas/frontend-library'; import { NAV_TYPES } from '../../util/constants'; -import ListTable from '../../common-util/List/ListTable'; import { + ListTable, useExtraTabContent, getHash, isMyTab, -} from '../../common-util/List/ListTable/helpers'; +} from '../../common-util/List/ListTable'; import { useHelpers } from '../../common-util/hooks'; import { useAllComponents, diff --git a/apps/autonolas-registry/components/ListComponents/useComponentsList.jsx b/apps/autonolas-registry/components/ListComponents/useComponentsList.jsx index cd77b7df..c50143cc 100644 --- a/apps/autonolas-registry/components/ListComponents/useComponentsList.jsx +++ b/apps/autonolas-registry/components/ListComponents/useComponentsList.jsx @@ -8,7 +8,7 @@ import { gql } from 'graphql-request'; import { GRAPHQL_CLIENT, - columnsForAgentsAndComponents, + UNIT_FIELDS, getSearchFilterSubQueryForAgentsAndComponents, } from '../../common-util/hooks/useSubgraph'; import { TOTAL_VIEW_COUNT } from '../../util/constants'; @@ -30,7 +30,7 @@ export const useAllComponents = () => { skip: ${TOTAL_VIEW_COUNT * (currentPage - 1)}, where: { ${componentPackageType} }, orderBy: tokenId - ) ${columnsForAgentsAndComponents} + ) ${UNIT_FIELDS} } `; @@ -55,7 +55,7 @@ export const useMyComponents = () => { owner_contains_nocase: "${ownerAddress}", }, orderBy: tokenId, - ) ${columnsForAgentsAndComponents} + ) ${UNIT_FIELDS} } `; @@ -80,7 +80,7 @@ const useAllComponentsBySearch = () => { ] } orderBy: tokenId - ) ${columnsForAgentsAndComponents} + ) ${UNIT_FIELDS} } `; @@ -106,7 +106,7 @@ const useMyComponentsBySearch = () => { ] } orderBy: tokenId - ) ${columnsForAgentsAndComponents} + ) ${UNIT_FIELDS} } `; diff --git a/apps/autonolas-registry/components/ListServices/hooks/useService.jsx b/apps/autonolas-registry/components/ListServices/hooks/useService.jsx index d24bc734..30672bf8 100644 --- a/apps/autonolas-registry/components/ListServices/hooks/useService.jsx +++ b/apps/autonolas-registry/components/ListServices/hooks/useService.jsx @@ -25,10 +25,10 @@ export const useGetServiceDetails = () => { async (id) => { if (!id) notifyError('No service id provided'); - const e = isSvm + const serviceDetails = isSvm ? await getSvmServiceDetails(id) : await getServiceDetails(id); - return e; + return serviceDetails; }, [isSvm, getSvmServiceDetails], ); @@ -46,10 +46,10 @@ export const useGetServiceOwner = () => { async (id) => { if (!id) notifyError('No service id provided'); - const e = isSvm + const serviceOwner = isSvm ? await getSvmServiceOwner(id) : await getServiceOwner(id); - return e; + return serviceOwner; }, [isSvm, getSvmServiceOwner], ); @@ -67,8 +67,10 @@ export const useGetServiceTokenUri = () => { async (id) => { if (!id) notifyError('No service id provided'); - const e = isSvm ? await getSvmTokenUri(id) : await getTokenUri(id); - return e; + const serviceTokenUri = isSvm + ? await getSvmTokenUri(id) + : await getTokenUri(id); + return serviceTokenUri; }, [isSvm, getSvmTokenUri], ); diff --git a/apps/autonolas-registry/components/ListServices/index.jsx b/apps/autonolas-registry/components/ListServices/index.jsx index 2f5213ef..3eb3d6cc 100644 --- a/apps/autonolas-registry/components/ListServices/index.jsx +++ b/apps/autonolas-registry/components/ListServices/index.jsx @@ -4,12 +4,12 @@ import { useRouter } from 'next/router'; import { notifyError } from '@autonolas/frontend-library'; import { NAV_TYPES } from '../../util/constants'; -import ListTable from '../../common-util/List/ListTable'; import { + ListTable, useExtraTabContent, getHash, isMyTab, -} from '../../common-util/List/ListTable/helpers'; +} from '../../common-util/List/ListTable'; import { getMyListOnPagination } from '../../common-util/ContractUtils/myList'; import { useHelpers } from '../../common-util/hooks'; import { @@ -123,13 +123,13 @@ const ListServices = () => { // All services if (currentTab === ALL_SERVICES) { if (isMainnet) { - const e = await getAllServices(currentPage); - setList(e); + const mainnetServices = await getAllServices(currentPage); + setList(mainnetServices); } else { - const e = isSvm + const nonMainnetServices = isSvm ? await getSvmServices(total, currentPage) : await getServices(total, currentPage); - setList(e); + setList(nonMainnetServices); } } else if (currentTab === MY_SERVICES && account) { /** @@ -138,17 +138,17 @@ const ListServices = () => { * - API will be called only once & store the complete list */ if (isMainnet) { - const e = await getMyServices(account, currentPage); - setList(e); + const mainnetMyServices = await getMyServices(account, currentPage); + setList(mainnetMyServices); } else { - const e = isSvm + const nonMainnetMyServices = isSvm ? await getMySvmServices(account, total) : await getFilteredServices(account); - setList(e); + setList(nonMainnetMyServices); // TODO: remove this once `getTotalForMySvmServices` is fixed if (isSvm) { - setTotal(e.length); + setTotal(nonMainnetMyServices.length); } } } @@ -251,8 +251,8 @@ const ListServices = () => { type="card" activeKey={currentTab} tabBarExtraContent={extraTabContent} - onChange={(e) => { - setCurrentTab(e); + onChange={(activeTab) => { + setCurrentTab(activeTab); setTotal(0); setCurrentPage(1); @@ -263,7 +263,7 @@ const ListServices = () => { // update the URL to keep track of my-services router.push( - e === MY_SERVICES + activeTab === MY_SERVICES ? `${links.SERVICES}#${MY_SERVICES}` : links.SERVICES, ); From ffb02ce20894069cf89d93660d8d29c00ec375be Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Wed, 10 Apr 2024 15:29:39 +0530 Subject: [PATCH 36/39] address comments --- .../components/ListAgents/useAgentsList.jsx | 4 +- .../ListComponents/useComponentsList.jsx | 95 +++++++--------- .../ListServices/hooks/useServicesList.jsx | 106 +++++++++--------- 3 files changed, 93 insertions(+), 112 deletions(-) diff --git a/apps/autonolas-registry/components/ListAgents/useAgentsList.jsx b/apps/autonolas-registry/components/ListAgents/useAgentsList.jsx index df5117bb..d4fa8078 100644 --- a/apps/autonolas-registry/components/ListAgents/useAgentsList.jsx +++ b/apps/autonolas-registry/components/ListAgents/useAgentsList.jsx @@ -37,7 +37,9 @@ const getAgentsBySearchQuery = (searchValue, ownerAddress = null) => { and: [ { packageType: "agent" } ${getSearchFilterSubQueryForAgentsAndComponents(searchValue)} - ${ownerAddress ? `owner_contains_nocase: "${ownerAddress}"` : ''} + ${ + ownerAddress ? `{ owner_contains_nocase: "${ownerAddress}" }` : '' + } ] } orderBy: tokenId diff --git a/apps/autonolas-registry/components/ListComponents/useComponentsList.jsx b/apps/autonolas-registry/components/ListComponents/useComponentsList.jsx index c50143cc..fa5f3ff4 100644 --- a/apps/autonolas-registry/components/ListComponents/useComponentsList.jsx +++ b/apps/autonolas-registry/components/ListComponents/useComponentsList.jsx @@ -14,7 +14,42 @@ import { import { TOTAL_VIEW_COUNT } from '../../util/constants'; const componentPackageType = - 'packageType_in: [connection,skill,protocol,contract,custom]'; + 'packageType_in: [connection,skill,protocol,contract,custom,unknown]'; + +const getAllAndMyComponentsQuery = (currentPage, ownerAddress = null) => { + return gql` + { + units( + first: ${TOTAL_VIEW_COUNT}, + skip: ${TOTAL_VIEW_COUNT * (currentPage - 1)}, + where: { + ${componentPackageType} + ${ownerAddress ? `owner_contains_nocase: "${ownerAddress}"` : ''} + }, + orderBy: tokenId + ) ${UNIT_FIELDS} + } + `; +}; + +const getComponentsBySearchQuery = (searchValue, ownerAddress = null) => { + return gql` + { + units( + where: { + and: [ + { ${componentPackageType} } + ${getSearchFilterSubQueryForAgentsAndComponents(searchValue)} + ${ + ownerAddress ? `{ owner_contains_nocase: "${ownerAddress}" }` : '' + } + ] + } + orderBy: tokenId + ) ${UNIT_FIELDS} + } + `; +}; /** * Hook to get ALL components @@ -23,17 +58,7 @@ const componentPackageType = */ export const useAllComponents = () => { return useCallback(async (currentPage) => { - const query = gql` - { - units( - first: ${TOTAL_VIEW_COUNT}, - skip: ${TOTAL_VIEW_COUNT * (currentPage - 1)}, - where: { ${componentPackageType} }, - orderBy: tokenId - ) ${UNIT_FIELDS} - } - `; - + const query = getAllAndMyComponentsQuery(currentPage); const response = await GRAPHQL_CLIENT.request(query); return response?.units; }, []); @@ -45,20 +70,7 @@ export const useAllComponents = () => { */ export const useMyComponents = () => { return useCallback(async (ownerAddress, currentPage) => { - const query = gql` - { - units( - first: ${TOTAL_VIEW_COUNT}, - skip: ${TOTAL_VIEW_COUNT * (currentPage - 1)}, - where: { - ${componentPackageType} - owner_contains_nocase: "${ownerAddress}", - }, - orderBy: tokenId, - ) ${UNIT_FIELDS} - } - `; - + const query = getAllAndMyComponentsQuery(currentPage, ownerAddress); const response = await GRAPHQL_CLIENT.request(query); return response?.units; }, []); @@ -70,20 +82,7 @@ export const useMyComponents = () => { */ const useAllComponentsBySearch = () => { return useCallback(async (searchValue) => { - const query = gql` - { - units( - where: { - and: [ - { ${componentPackageType} } - ${getSearchFilterSubQueryForAgentsAndComponents(searchValue)} - ] - } - orderBy: tokenId - ) ${UNIT_FIELDS} - } - `; - + const query = getComponentsBySearchQuery(searchValue); const response = await GRAPHQL_CLIENT.request(query); return response?.units; }, []); @@ -95,21 +94,7 @@ const useAllComponentsBySearch = () => { */ const useMyComponentsBySearch = () => { return useCallback(async (ownerAddress, searchValue) => { - const query = gql` - { - units( - where: { - and: [ - { ${componentPackageType} } - { owner_contains_nocase: "${ownerAddress}" } - ${getSearchFilterSubQueryForAgentsAndComponents(searchValue)} - ] - } - orderBy: tokenId - ) ${UNIT_FIELDS} - } - `; - + const query = getComponentsBySearchQuery(searchValue, ownerAddress); const response = await GRAPHQL_CLIENT.request(query); return response?.units; }, []); diff --git a/apps/autonolas-registry/components/ListServices/hooks/useServicesList.jsx b/apps/autonolas-registry/components/ListServices/hooks/useServicesList.jsx index e8a26497..140900ac 100644 --- a/apps/autonolas-registry/components/ListServices/hooks/useServicesList.jsx +++ b/apps/autonolas-registry/components/ListServices/hooks/useServicesList.jsx @@ -17,8 +17,26 @@ const SERVICE_FIELDS = `{ packageHash metadataHash state + description }`; +const getAllAndMyServicesQuery = (currentPage, ownerAddress = null) => { + return gql` + { + services( + first: ${TOTAL_VIEW_COUNT}, + skip: ${TOTAL_VIEW_COUNT * (currentPage - 1)}, + orderBy: serviceId + ${ + ownerAddress + ? `where: { owner_contains_nocase: "${ownerAddress}" }` + : '' + } + ) ${SERVICE_FIELDS} + } + `; +}; + /** * Searches by * - publicId (package name) @@ -36,12 +54,34 @@ export const getSearchFilterSubQueryForServices = (searchValue) => { { packageHash_contains_nocase: "${searchValue}" } { owner_contains_nocase: "${searchValue}" } { metadataHash_contains_nocase: "${completeMetadataHash}" } + { description_contains_nocase: "${searchValue}" } ] }`; }; -// TODO: description needs to be added -// { description_contains_nocase: "${searchValue}" } +const getServicesBySearchQuery = ( + searchValue, + currentPage, + ownerAddress = null, +) => { + return gql` + { + services ( + first: ${TOTAL_VIEW_COUNT}, + skip: ${TOTAL_VIEW_COUNT * (currentPage - 1)}, + where: { + and: [ + ${ + ownerAddress ? `{ owner_contains_nocase: "${ownerAddress}" }` : '' + } + ${getSearchFilterSubQueryForServices(searchValue)}, + ] + } + orderBy: serviceId + ) ${SERVICE_FIELDS} + } + `; +}; /** * Hook to get ALL units @@ -50,16 +90,7 @@ export const getSearchFilterSubQueryForServices = (searchValue) => { */ export const useAllServices = () => { return useCallback(async (currentPage) => { - const query = gql` - { - services( - first: ${TOTAL_VIEW_COUNT}, - skip: ${TOTAL_VIEW_COUNT * (currentPage - 1)}, - orderBy: serviceId - ) ${SERVICE_FIELDS} - } - `; - + const query = getAllAndMyServicesQuery(currentPage); const response = await GRAPHQL_CLIENT.request(query); return response?.services || []; }, []); @@ -71,19 +102,7 @@ export const useAllServices = () => { */ export const useMyServices = () => { return useCallback(async (ownerAddress, currentPage) => { - const query = gql` - { - services ( - first: ${TOTAL_VIEW_COUNT}, - skip: ${TOTAL_VIEW_COUNT * (currentPage - 1)}, - where: { - owner_contains_nocase: "${ownerAddress}" - }, - orderBy: serviceId, - ) ${SERVICE_FIELDS} - } - `; - + const query = getAllAndMyServicesQuery(currentPage, ownerAddress); const response = await GRAPHQL_CLIENT.request(query); return response?.services || []; }, []); @@ -95,21 +114,7 @@ export const useMyServices = () => { */ export const useAllServicesBySearch = () => { return useCallback(async (searchValue, currentPage) => { - const query = gql` - { - services ( - first: ${TOTAL_VIEW_COUNT}, - skip: ${TOTAL_VIEW_COUNT * (currentPage - 1)}, - where: { - and: [ - ${getSearchFilterSubQueryForServices(searchValue)}, - ] - } - orderBy: serviceId - ) ${SERVICE_FIELDS} - } - `; - + const query = getServicesBySearchQuery(searchValue, currentPage); const response = await GRAPHQL_CLIENT.request(query); return response?.services || []; }, []); @@ -121,22 +126,11 @@ export const useAllServicesBySearch = () => { */ export const useMyServicesBySearch = () => { return useCallback(async (ownerAddress, searchValue, currentPage) => { - const query = gql` - { - services ( - first: ${TOTAL_VIEW_COUNT}, - skip: ${TOTAL_VIEW_COUNT * (currentPage - 1)}, - where: { - and: [ - { owner_contains_nocase: "${ownerAddress}" } - ${getSearchFilterSubQueryForServices(searchValue)} - ] - } - orderBy: serviceId, - ) ${SERVICE_FIELDS} - } - `; - + const query = getServicesBySearchQuery( + searchValue, + currentPage, + ownerAddress, + ); const response = await GRAPHQL_CLIENT.request(query); return response?.services || []; }, []); From 49b8912d58bbc7f49cf03c36bfc689197576c633 Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Wed, 10 Apr 2024 16:45:21 +0530 Subject: [PATCH 37/39] move to ts --- .../{useExtraTabContent.jsx => useExtraTabContent.tsx} | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) rename apps/autonolas-registry/common-util/List/ListTable/{useExtraTabContent.jsx => useExtraTabContent.tsx} (93%) diff --git a/apps/autonolas-registry/common-util/List/ListTable/useExtraTabContent.jsx b/apps/autonolas-registry/common-util/List/ListTable/useExtraTabContent.tsx similarity index 93% rename from apps/autonolas-registry/common-util/List/ListTable/useExtraTabContent.jsx rename to apps/autonolas-registry/common-util/List/ListTable/useExtraTabContent.tsx index 86d314c2..34058cb1 100644 --- a/apps/autonolas-registry/common-util/List/ListTable/useExtraTabContent.jsx +++ b/apps/autonolas-registry/common-util/List/ListTable/useExtraTabContent.tsx @@ -12,12 +12,19 @@ const SearchUl = styled.ul` padding: 0 0 0 16px; `; +type UseExtraTabContentProps = { + title: string; + onRegisterClick?: () => void; + isSvm?: boolean; + type: string; +}; + export const useExtraTabContent = ({ title, onRegisterClick, isSvm = false, type, -}) => { +}: UseExtraTabContentProps) => { const [searchValue, setSearchValue] = useState(''); const [value, setValue] = useState(''); const clearSearch = () => { From 05b8cc13ba69b57705111df36d09ea0ccaf4f6f1 Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Wed, 10 Apr 2024 21:39:33 +0530 Subject: [PATCH 38/39] other changes --- .../List/ListTable/useExtraTabContent.tsx | 10 ++- .../common-util/hooks/useSubgraph.jsx | 2 +- .../components/Layout/index.jsx | 71 ++++++++++--------- .../components/ListAgents/index.jsx | 7 +- .../components/ListAgents/useAgentsList.jsx | 13 ++-- .../components/ListComponents/index.jsx | 1 + .../ListComponents/useComponentsList.jsx | 13 ++-- .../ListServices/hooks/useServicesList.jsx | 13 ++-- .../components/ListServices/index.jsx | 5 +- .../IpfsHashGenerationModal/index.test.tsx | 2 +- .../tests/common-util/YellowButton.test.tsx | 2 +- .../components/ListAgents/details.test.jsx | 2 +- .../ListComponents/details.test.jsx | 2 +- .../components/ListServices/details.test.jsx | 10 +-- .../components/ListServices/index.test.tsx | 17 +++-- 15 files changed, 85 insertions(+), 85 deletions(-) diff --git a/apps/autonolas-registry/common-util/List/ListTable/useExtraTabContent.tsx b/apps/autonolas-registry/common-util/List/ListTable/useExtraTabContent.tsx index 34058cb1..a5cecf9b 100644 --- a/apps/autonolas-registry/common-util/List/ListTable/useExtraTabContent.tsx +++ b/apps/autonolas-registry/common-util/List/ListTable/useExtraTabContent.tsx @@ -3,7 +3,7 @@ import { Input, Button, Typography, Tooltip } from 'antd'; import { SearchOutlined, InfoCircleOutlined } from '@ant-design/icons'; import styled from 'styled-components'; -import { NAV_TYPES } from '../../../util/constants'; +import { useHelpers } from '../../hooks'; const { Title } = Typography; @@ -17,6 +17,7 @@ type UseExtraTabContentProps = { onRegisterClick?: () => void; isSvm?: boolean; type: string; + isMyTab: boolean; }; export const useExtraTabContent = ({ @@ -24,7 +25,10 @@ export const useExtraTabContent = ({ onRegisterClick, isSvm = false, type, + isMyTab = true, }: UseExtraTabContentProps) => { + const { account } = useHelpers(); + const [searchValue, setSearchValue] = useState(''); const [value, setValue] = useState(''); const clearSearch = () => { @@ -37,7 +41,7 @@ export const useExtraTabContent = ({ right: ( <> {/* TODO: hiding search util feature is introduced */} - {isSvm ? null : ( + {isSvm || (isMyTab && !account) ? null : ( <> } @@ -54,7 +58,7 @@ export const useExtraTabContent = ({
    Search by:
  • Name
  • - {type !== NAV_TYPES.SERVICE &&
  • Description
  • } +
  • Description
  • Owner
  • Package Hash
  • diff --git a/apps/autonolas-registry/common-util/hooks/useSubgraph.jsx b/apps/autonolas-registry/common-util/hooks/useSubgraph.jsx index b2b83b89..45745f99 100644 --- a/apps/autonolas-registry/common-util/hooks/useSubgraph.jsx +++ b/apps/autonolas-registry/common-util/hooks/useSubgraph.jsx @@ -30,7 +30,7 @@ export const UNIT_FIELDS = `{ * - owner * @returns {string} search filter sub query */ -export const getSearchFilterSubQueryForAgentsAndComponents = (searchValue) => { +export const getSearchFilterSubQueryForUnitFields = (searchValue) => { const completeMetadataHash = searchValue.replace(/0x/g, HASH_PREFIX); return `{ or: [ diff --git a/apps/autonolas-registry/components/Layout/index.jsx b/apps/autonolas-registry/components/Layout/index.jsx index a76db4dd..19bef8b6 100644 --- a/apps/autonolas-registry/components/Layout/index.jsx +++ b/apps/autonolas-registry/components/Layout/index.jsx @@ -11,10 +11,13 @@ import { } from '@solana/wallet-adapter-react'; import { PhantomWalletAdapter } from '@solana/wallet-adapter-wallets'; -import { PAGES_TO_LOAD_WITHOUT_CHAINID } from 'util/constants'; -import { useHelpers } from 'common-util/hooks'; -import { ALL_SUPPORTED_CHAINS, getSvmEndpoint } from 'common-util/Login/config'; -import { useHandleRoute } from 'common-util/hooks/useHandleRoute'; +import { PAGES_TO_LOAD_WITHOUT_CHAINID } from '../../util/constants'; +import { useHelpers } from '../../common-util/hooks'; +import { + ALL_SUPPORTED_CHAINS, + getSvmEndpoint, +} from '../../common-util/Login/config'; +import { useHandleRoute } from '../../common-util/hooks/useHandleRoute'; import { LogoSvg, LogoIconSvg } from '../Logos'; import { CustomLayout, @@ -33,9 +36,7 @@ const { Content } = AntdLayout; const Layout = ({ children }) => { const router = useRouter(); const { isMobile, isTablet } = useScreen(); - const { - vmType, isSvm, chainId, chainName, - } = useHelpers(); + const { vmType, isSvm, chainId, chainName } = useHelpers(); const path = router?.pathname || ''; const { onHomeClick, updateChainId } = useHandleRoute(); @@ -58,7 +59,9 @@ const Layout = ({ children }) => { style={{ width: isMobile ? 140 : 200 }} value={chainName} placeholder="Select Network" - disabled={PAGES_TO_LOAD_WITHOUT_CHAINID.some((e) => path.includes(e))} + disabled={PAGES_TO_LOAD_WITHOUT_CHAINID.some((e) => + path.includes(e), + )} options={ALL_SUPPORTED_CHAINS.map((e) => ({ label: e.networkDisplayName, value: e.networkName, @@ -68,29 +71,31 @@ const Layout = ({ children }) => { (e) => e.networkName === value, ); - if (currentChainInfo) { - // update session storage - sessionStorage.setItem('chainId', currentChainInfo.id); - - if (PAGES_TO_LOAD_WITHOUT_CHAINID.find((e) => e === path)) { - // eg. /disclaimer will be redirect to same page ie. /disclaimer - updateChainId(currentChainInfo.id); - router.push(`/${path}`); + if (!currentChainInfo) return; + + // update session storage + sessionStorage.setItem('chainId', currentChainInfo.id); + + if (PAGES_TO_LOAD_WITHOUT_CHAINID.find((e) => e === path)) { + // eg. /disclaimer will be redirect to same page ie. /disclaimer + updateChainId(currentChainInfo.id); + router.push(`/${path}`); + } else { + // eg. /components, /agents, /services will be redirect to + // //components, //agents, //services + const replacedPath = router.asPath.replace(chainName, value); + + // reload the page if vmType is different + // ie. user switched from svm to eth or vice versa + // or if the current chain selected is ethereum + if ( + vmType === VM_TYPE.SVM || + vmType !== currentChainInfo.vmType || + currentChainInfo.networkName === 'ethereum' + ) { + window.open(replacedPath, '_self'); } else { - // eg. /components, /agents, /services will be redirect to - // //components, //agents, //services - const replacedPath = router.asPath.replace(chainName, value); - - // reload the page if vmType is different - // ie. user switched from svm to eth or vice versa - if ( - vmType === VM_TYPE.SVM - || vmType !== currentChainInfo.vmType - ) { - window.open(replacedPath, '_self'); - } else { - router.push(replacedPath); - } + router.push(replacedPath); } } }} @@ -111,9 +116,9 @@ const Layout = ({ children }) => { {/* chainId has to be set in redux before rendering any components OR the page doesn't depends on the chain Id OR it is SOLANA */} - {chainId - || isSvm - || PAGES_TO_LOAD_WITHOUT_CHAINID.some((e) => e === path) + {chainId || + isSvm || + PAGES_TO_LOAD_WITHOUT_CHAINID.some((e) => e === path) ? children : null} diff --git a/apps/autonolas-registry/components/ListAgents/index.jsx b/apps/autonolas-registry/components/ListAgents/index.jsx index d5ee6e26..ebc8ff7e 100644 --- a/apps/autonolas-registry/components/ListAgents/index.jsx +++ b/apps/autonolas-registry/components/ListAgents/index.jsx @@ -42,6 +42,7 @@ const ListAgents = () => { const { searchValue, extraTabContent, clearSearch } = useExtraTabContent({ title: 'Agents', onRegisterClick: () => router.push(links.MINT_AGENT), + isMyTab: currentTab === MY_AGENTS, }); const onViewClick = (id) => router.push(`${links.AGENTS}/${id}`); @@ -79,8 +80,8 @@ const ListAgents = () => { setList([]); } } catch (e) { - console.error(e); notifyError('Error fetching agents'); + console.error(e); } })(); }, [account, chainId, isL1OnlyNetwork, currentTab, searchValue, isSvm]); @@ -114,8 +115,8 @@ const ListAgents = () => { setList(myAgents); } } catch (e) { - console.error(e); notifyError('Error fetching agents'); + console.error(e); } finally { setIsLoading(false); } @@ -162,8 +163,8 @@ const ListAgents = () => { setTotal(0); // total won't be used if search is used setCurrentPage(1); } catch (e) { - console.error(e); notifyError('Error fetching agents'); + console.error(e); } finally { setIsLoading(false); } diff --git a/apps/autonolas-registry/components/ListAgents/useAgentsList.jsx b/apps/autonolas-registry/components/ListAgents/useAgentsList.jsx index d4fa8078..5c4633e8 100644 --- a/apps/autonolas-registry/components/ListAgents/useAgentsList.jsx +++ b/apps/autonolas-registry/components/ListAgents/useAgentsList.jsx @@ -9,7 +9,7 @@ import { gql } from 'graphql-request'; import { GRAPHQL_CLIENT, UNIT_FIELDS, - getSearchFilterSubQueryForAgentsAndComponents, + getSearchFilterSubQueryForUnitFields, } from '../../common-util/hooks/useSubgraph'; import { TOTAL_VIEW_COUNT } from '../../util/constants'; @@ -36,7 +36,7 @@ const getAgentsBySearchQuery = (searchValue, ownerAddress = null) => { where: { and: [ { packageType: "agent" } - ${getSearchFilterSubQueryForAgentsAndComponents(searchValue)} + ${getSearchFilterSubQueryForUnitFields(searchValue)} ${ ownerAddress ? `{ owner_contains_nocase: "${ownerAddress}" }` : '' } @@ -90,7 +90,7 @@ const useAllAgentsBySearch = () => { * @returns {function} function to search units */ const useMyAgentsBySearch = () => { - return useCallback(async (ownerAddress, searchValue) => { + return useCallback(async (searchValue, ownerAddress) => { const query = getAgentsBySearchQuery(searchValue, ownerAddress); const response = await GRAPHQL_CLIENT.request(query); return response?.units; @@ -106,10 +106,9 @@ export const useSearchAgents = () => { return useCallback( async (searchValue, ownerAddress) => { - if (ownerAddress) { - return await getMyAgentsBySearch(ownerAddress, searchValue); - } - return await getAllAgentsBySearch(searchValue); + return ownerAddress + ? await getMyAgentsBySearch(searchValue, ownerAddress) + : await getAllAgentsBySearch(searchValue); }, [getAllAgentsBySearch, getMyAgentsBySearch], ); diff --git a/apps/autonolas-registry/components/ListComponents/index.jsx b/apps/autonolas-registry/components/ListComponents/index.jsx index afb02ace..44d6a921 100644 --- a/apps/autonolas-registry/components/ListComponents/index.jsx +++ b/apps/autonolas-registry/components/ListComponents/index.jsx @@ -46,6 +46,7 @@ const ListComponents = () => { const { searchValue, extraTabContent, clearSearch } = useExtraTabContent({ title: 'Components', onRegisterClick: () => router.push(links.MINT_COMPONENT), + isMyTab: currentTab === MY_COMPONENTS, }); const onViewClick = (id) => router.push(`${links.COMPONENTS}/${id}`); diff --git a/apps/autonolas-registry/components/ListComponents/useComponentsList.jsx b/apps/autonolas-registry/components/ListComponents/useComponentsList.jsx index fa5f3ff4..c3296222 100644 --- a/apps/autonolas-registry/components/ListComponents/useComponentsList.jsx +++ b/apps/autonolas-registry/components/ListComponents/useComponentsList.jsx @@ -9,7 +9,7 @@ import { gql } from 'graphql-request'; import { GRAPHQL_CLIENT, UNIT_FIELDS, - getSearchFilterSubQueryForAgentsAndComponents, + getSearchFilterSubQueryForUnitFields, } from '../../common-util/hooks/useSubgraph'; import { TOTAL_VIEW_COUNT } from '../../util/constants'; @@ -39,7 +39,7 @@ const getComponentsBySearchQuery = (searchValue, ownerAddress = null) => { where: { and: [ { ${componentPackageType} } - ${getSearchFilterSubQueryForAgentsAndComponents(searchValue)} + ${getSearchFilterSubQueryForUnitFields(searchValue)} ${ ownerAddress ? `{ owner_contains_nocase: "${ownerAddress}" }` : '' } @@ -93,7 +93,7 @@ const useAllComponentsBySearch = () => { * @returns {function} function to search units */ const useMyComponentsBySearch = () => { - return useCallback(async (ownerAddress, searchValue) => { + return useCallback(async (searchValue, ownerAddress) => { const query = getComponentsBySearchQuery(searchValue, ownerAddress); const response = await GRAPHQL_CLIENT.request(query); return response?.units; @@ -109,10 +109,9 @@ export const useSearchComponents = () => { return useCallback( async (searchValue, ownerAddress) => { - if (ownerAddress) { - return await getMyComponentsBySearch(ownerAddress, searchValue); - } - return await getAllComponentsBySearch(searchValue); + return ownerAddress + ? await getMyComponentsBySearch(searchValue, ownerAddress) + : await getAllComponentsBySearch(searchValue); }, [getAllComponentsBySearch, getMyComponentsBySearch], ); diff --git a/apps/autonolas-registry/components/ListServices/hooks/useServicesList.jsx b/apps/autonolas-registry/components/ListServices/hooks/useServicesList.jsx index 140900ac..3ef9cf8c 100644 --- a/apps/autonolas-registry/components/ListServices/hooks/useServicesList.jsx +++ b/apps/autonolas-registry/components/ListServices/hooks/useServicesList.jsx @@ -125,7 +125,7 @@ export const useAllServicesBySearch = () => { * @returns {function} function to search units */ export const useMyServicesBySearch = () => { - return useCallback(async (ownerAddress, searchValue, currentPage) => { + return useCallback(async (searchValue, currentPage, ownerAddress) => { const query = getServicesBySearchQuery( searchValue, currentPage, @@ -142,14 +142,9 @@ export const useSearchServices = () => { return useCallback( async (searchValue, currentPage, ownerAddress) => { - if (ownerAddress) { - return await getMyServicesBySearch( - ownerAddress, - searchValue, - currentPage, - ); - } - return await getAllUnitsBySearch(searchValue, currentPage); + return ownerAddress + ? await getMyServicesBySearch(searchValue, currentPage, ownerAddress) + : await getAllUnitsBySearch(searchValue, currentPage); }, [getAllUnitsBySearch, getMyServicesBySearch], ); diff --git a/apps/autonolas-registry/components/ListServices/index.jsx b/apps/autonolas-registry/components/ListServices/index.jsx index 3eb3d6cc..7abc962b 100644 --- a/apps/autonolas-registry/components/ListServices/index.jsx +++ b/apps/autonolas-registry/components/ListServices/index.jsx @@ -49,6 +49,7 @@ const ListServices = () => { onRegisterClick: () => router.push(links.MINT_SERVICE), isSvm, type: NAV_TYPES.SERVICE, + isMyTab: currentTab === MY_SERVICES, }); const onViewClick = (id) => router.push(`${links.SERVICES}/${id}`); @@ -94,8 +95,8 @@ const ListServices = () => { setList([]); } } catch (e) { - console.error(e); notifyError('Error fetching services'); + console.error(e); } }; @@ -209,8 +210,8 @@ const ListServices = () => { setTotal(0); // total won't be used if search is used setCurrentPage(1); } catch (e) { - console.error(e); notifyError('Error fetching services'); + console.error(e); } finally { setIsLoading(false); } diff --git a/apps/autonolas-registry/tests/common-util/List/IpfsHashGenerationModal/index.test.tsx b/apps/autonolas-registry/tests/common-util/List/IpfsHashGenerationModal/index.test.tsx index 3d71b0b7..41b4d8bc 100644 --- a/apps/autonolas-registry/tests/common-util/List/IpfsHashGenerationModal/index.test.tsx +++ b/apps/autonolas-registry/tests/common-util/List/IpfsHashGenerationModal/index.test.tsx @@ -20,7 +20,7 @@ const callbackMock = jest.fn(); const handleCancelMock = jest.fn(); describe('', () => { - it('should render a hash generation modal and', async () => { + it('should display a hash generation modal and', async () => { const { getByText } = render( wrapProvider( { - it('should render a yellow button', () => { + it('should display a yellow button', () => { const { getByText } = render(Button); expect(getByText('Button')).toBeInTheDocument(); }); diff --git a/apps/autonolas-registry/tests/components/ListAgents/details.test.jsx b/apps/autonolas-registry/tests/components/ListAgents/details.test.jsx index 8fd4153a..2978cad3 100644 --- a/apps/autonolas-registry/tests/components/ListAgents/details.test.jsx +++ b/apps/autonolas-registry/tests/components/ListAgents/details.test.jsx @@ -89,7 +89,7 @@ describe('listAgents/details.jsx', () => { global.fetch = unmockedFetch; }); - it('should render agent details', async () => { + it('should display agent details', async () => { const { getByText, getByTestId, queryByRole } = render( wrapProvider(), ); diff --git a/apps/autonolas-registry/tests/components/ListComponents/details.test.jsx b/apps/autonolas-registry/tests/components/ListComponents/details.test.jsx index 045c17f1..6472b0a6 100644 --- a/apps/autonolas-registry/tests/components/ListComponents/details.test.jsx +++ b/apps/autonolas-registry/tests/components/ListComponents/details.test.jsx @@ -81,7 +81,7 @@ describe('listComponents/details.jsx', () => { global.fetch = unmockedFetch; }); - it('should render component details', async () => { + it('should display component details', async () => { const { getByText, queryByRole, getByTestId } = render( wrapProvider(), ); diff --git a/apps/autonolas-registry/tests/components/ListServices/details.test.jsx b/apps/autonolas-registry/tests/components/ListServices/details.test.jsx index 998fe3f3..a143cf8e 100644 --- a/apps/autonolas-registry/tests/components/ListServices/details.test.jsx +++ b/apps/autonolas-registry/tests/components/ListServices/details.test.jsx @@ -227,10 +227,8 @@ describe('listServices/details.jsx', () => { }); it('should display service details (left side)', async () => { - const { getByText, getByTestId, debug } = render( - wrapProvider(), - ); - debug(); + const { getByText, getByTestId } = render(wrapProvider()); + await waitFor(async () => { expect(getByText('Some package name')).toBeInTheDocument(); expect(getByTestId('service-status').textContent).toBe('Inactive'); @@ -298,11 +296,9 @@ describe('listServices/details.jsx', () => { }); it('should display the service name', async () => { - const { findByText, debug } = render(wrapProvider()); + const { findByText } = render(wrapProvider()); - debug(); expect(await findByText(/Service Name/)).toBeInTheDocument(); - // expect(await findByText(/Service ID/)).toBeInTheDocument(); }); }); }); diff --git a/apps/autonolas-registry/tests/components/ListServices/index.test.tsx b/apps/autonolas-registry/tests/components/ListServices/index.test.tsx index 82220b22..14c0ff02 100644 --- a/apps/autonolas-registry/tests/components/ListServices/index.test.tsx +++ b/apps/autonolas-registry/tests/components/ListServices/index.test.tsx @@ -92,13 +92,13 @@ describe('listServices/index.jsx', () => { await waitFor(async () => { expect(container.querySelector(ACTIVE_TAB)?.textContent).toBe('All'); - // Mint button expect(getByRole('button', { name: 'Mint' })).toBeInTheDocument(); }); }); it('should show search input', async () => { const { getByRole } = render(wrapProvider()); + await waitFor(async () => { expect(getByRole('textbox')).toBeInTheDocument(); }); @@ -162,9 +162,9 @@ describe('listServices/index.jsx', () => { within(allServicesTable).getByText(/0x9cf4...315ab0/), ).toBeInTheDocument(); expect( - within(allServicesTable).getByText('Deployed'), + within(allServicesTable).getByText(/Deployed/), ).toBeInTheDocument(); - expect(within(allServicesTable).getByText('View')).toBeInTheDocument(); + expect(within(allServicesTable).getByText(/View/)).toBeInTheDocument(); }); }); @@ -222,9 +222,9 @@ describe('listServices/index.jsx', () => { within(allServicesTable).getByText(/0x8626...9C1199/), ).toBeInTheDocument(); expect( - within(allServicesTable).getByText('Terminated Bonded'), + within(allServicesTable).getByText(/Terminated Bonded/), ).toBeInTheDocument(); - expect(within(allServicesTable).getByText('View')).toBeInTheDocument(); + expect(within(allServicesTable).getByText(/View/)).toBeInTheDocument(); }); }); }); @@ -268,7 +268,6 @@ describe('listServices/index.jsx', () => { await waitFor(async () => { expect(container.querySelector(ACTIVE_TAB)?.textContent).toBe('All'); - // Mint button expect(getByRole('button', { name: 'Mint' })).toBeInTheDocument(); }); }); @@ -303,12 +302,12 @@ describe('listServices/index.jsx', () => { // rows expect(within(allServicesTable).getByText('1')).toBeInTheDocument(); expect( - within(allServicesTable).getByText('DrGvsA...D3Wm5x'), + within(allServicesTable).getByText(/DrGvsA...D3Wm5x/), ).toBeInTheDocument(); expect( - within(allServicesTable).getByText('Terminated Bonded'), + within(allServicesTable).getByText(/Terminated Bonded/), ).toBeInTheDocument(); - expect(within(allServicesTable).getByText('View')).toBeInTheDocument(); + expect(within(allServicesTable).getByText(/View/)).toBeInTheDocument(); }); }); }); From f15d10a9f1a51038ec8deaf943b115ef3b1b0208 Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Wed, 10 Apr 2024 21:57:45 +0530 Subject: [PATCH 39/39] test-cases asycn --- .../components/ListServices/index.test.tsx | 100 +++++++++++------- 1 file changed, 63 insertions(+), 37 deletions(-) diff --git a/apps/autonolas-registry/tests/components/ListServices/index.test.tsx b/apps/autonolas-registry/tests/components/ListServices/index.test.tsx index 14c0ff02..5a723c25 100644 --- a/apps/autonolas-registry/tests/components/ListServices/index.test.tsx +++ b/apps/autonolas-registry/tests/components/ListServices/index.test.tsx @@ -125,14 +125,24 @@ describe('listServices/index.jsx', () => { throw new Error('`All tab` is null'); } - expect(within(allServicesTable).getByText('ID')).toBeInTheDocument(); - expect(within(allServicesTable).getByText('Name')).toBeInTheDocument(); - expect(within(allServicesTable).getByText('Owner')).toBeInTheDocument(); - expect(within(allServicesTable).getByText('Hash')).toBeInTheDocument(); - expect(within(allServicesTable).getByText('State')).toBeInTheDocument(); - expect( - within(allServicesTable).getByText('Action'), - ).toBeInTheDocument(); + await waitFor(async () => { + expect(within(allServicesTable).getByText('ID')).toBeInTheDocument(); + expect( + within(allServicesTable).getByText('Name'), + ).toBeInTheDocument(); + expect( + within(allServicesTable).getByText('Owner'), + ).toBeInTheDocument(); + expect( + within(allServicesTable).getByText('Hash'), + ).toBeInTheDocument(); + expect( + within(allServicesTable).getByText('State'), + ).toBeInTheDocument(); + expect( + within(allServicesTable).getByText('Action'), + ).toBeInTheDocument(); + }); }); it('should display all services information', async () => { @@ -152,19 +162,23 @@ describe('listServices/index.jsx', () => { const firstService = allServicesResponse[0]; const allServicesTable = await findByTestId('all-services-table'); - expect( - within(allServicesTable).getByText(firstService.serviceId), - ).toBeInTheDocument(); - expect( - within(allServicesTable).getByText(/0x8626...9C1199/), - ).toBeInTheDocument(); - expect( - within(allServicesTable).getByText(/0x9cf4...315ab0/), - ).toBeInTheDocument(); - expect( - within(allServicesTable).getByText(/Deployed/), - ).toBeInTheDocument(); - expect(within(allServicesTable).getByText(/View/)).toBeInTheDocument(); + await waitFor(async () => { + expect( + within(allServicesTable).getByText(firstService.serviceId), + ).toBeInTheDocument(); + expect( + within(allServicesTable).getByText(/0x8626...9C1199/), + ).toBeInTheDocument(); + expect( + within(allServicesTable).getByText(/0x9cf4...315ab0/), + ).toBeInTheDocument(); + expect( + within(allServicesTable).getByText(/Deployed/), + ).toBeInTheDocument(); + expect( + within(allServicesTable).getByText(/View/), + ).toBeInTheDocument(); + }); }); }); @@ -191,14 +205,20 @@ describe('listServices/index.jsx', () => { throw new Error('`All tab` is null'); } - expect(within(allServicesTable).getByText('ID')).toBeInTheDocument(); - expect(within(allServicesTable).queryByText('Name')).toBeNull(); - expect(within(allServicesTable).getByText('Owner')).toBeInTheDocument(); - expect(within(allServicesTable).queryByText('Hash')).toBeNull(); - expect(within(allServicesTable).getByText('State')).toBeInTheDocument(); - expect( - within(allServicesTable).getByText('Action'), - ).toBeInTheDocument(); + await waitFor(async () => { + expect(within(allServicesTable).getByText('ID')).toBeInTheDocument(); + expect(within(allServicesTable).queryByText('Name')).toBeNull(); + expect( + within(allServicesTable).getByText('Owner'), + ).toBeInTheDocument(); + expect(within(allServicesTable).queryByText('Hash')).toBeNull(); + expect( + within(allServicesTable).getByText('State'), + ).toBeInTheDocument(); + expect( + within(allServicesTable).getByText('Action'), + ).toBeInTheDocument(); + }); }); it('should display all services information', async () => { @@ -217,14 +237,20 @@ describe('listServices/index.jsx', () => { const allServicesTable = await findByTestId('all-services-table'); - expect(within(allServicesTable).getByText('5001')).toBeInTheDocument(); - expect( - within(allServicesTable).getByText(/0x8626...9C1199/), - ).toBeInTheDocument(); - expect( - within(allServicesTable).getByText(/Terminated Bonded/), - ).toBeInTheDocument(); - expect(within(allServicesTable).getByText(/View/)).toBeInTheDocument(); + await waitFor(async () => { + expect( + within(allServicesTable).getByText('5001'), + ).toBeInTheDocument(); + expect( + within(allServicesTable).getByText(/0x8626...9C1199/), + ).toBeInTheDocument(); + expect( + within(allServicesTable).getByText(/Terminated Bonded/), + ).toBeInTheDocument(); + expect( + within(allServicesTable).getByText(/View/), + ).toBeInTheDocument(); + }); }); }); });