diff --git a/explorer/client/src/__tests__/e2e.test.ts b/explorer/client/src/__tests__/e2e.test.ts index a7aca7ef5c985..703c84233dece 100644 --- a/explorer/client/src/__tests__/e2e.test.ts +++ b/explorer/client/src/__tests__/e2e.test.ts @@ -53,6 +53,19 @@ const searchText = async (page: any, text: string) => { await page.click('#searchBtn'); }; +//Standardized CSS Selectors + +const coinGroup = (num: number) => { + const trunk = `#groupCollection > div:nth-child(${num})`; + return { + base: () => trunk, + field: (numField: number) => + `${trunk} > div > div:nth-child(${numField})`, + }; +}; + +const nftObject = (num: number) => `div#ownedObjects > div:nth-child(${num})`; + describe('End-to-end Tests', () => { beforeAll(async () => { browser = await puppeteer.launch(); @@ -275,9 +288,7 @@ describe('End-to-end Tests', () => { await page.goto(`${BASE_URL}/${parentIsA}/${parentValue}`); //Click on child in Owned Objects List: - const objectLink = await page.$( - `div#ownedObjects > div:nth-child(${parentToChildNo})` - ); + const objectLink = await page.$(nftObject(parentToChildNo)); await objectLink.click(); //Check ID of child object: @@ -321,9 +332,7 @@ describe('End-to-end Tests', () => { await page.goto(`${BASE_URL}/objects/${parentValue}`); //Click on child in Owned Objects List: - const objectLink = await page.$( - `div#ownedObjects > div:nth-child(1)` - ); + const objectLink = await page.$(nftObject(1)); await objectLink.click(); // First see Please Wait Message: @@ -369,9 +378,7 @@ describe('End-to-end Tests', () => { await page.goto(`${BASE_URL}/addresses/${address}`); const btn = await page.$('#nextBtn'); await btn.click(); - const objectLink = await page.$( - 'div#ownedObjects > div:nth-child(1)' - ); + const objectLink = await page.$(nftObject(1)); await objectLink.click(); const objectIDEl = await page.$('#objectID'); @@ -388,9 +395,7 @@ describe('End-to-end Tests', () => { const btn = await page.$('#lastBtn'); await btn.click(); - const objectLink = await page.$( - 'div#ownedObjects > div:nth-child(1)' - ); + const objectLink = await page.$(nftObject(1)); await objectLink.click(); const objectIDEl = await page.$('#objectID'); @@ -426,9 +431,7 @@ describe('End-to-end Tests', () => { await page.$('#backBtn').then((btn: any) => btn.click()); - const objectLink = await page.$( - 'div#ownedObjects > div:nth-child(1)' - ); + const objectLink = await page.$(nftObject(1)); await objectLink.click(); const objectIDEl = await page.$('#objectID'); @@ -450,9 +453,7 @@ describe('End-to-end Tests', () => { await page.$('#firstBtn').then((btn: any) => btn.click()); - const objectLink = await page.$( - 'div#ownedObjects > div:nth-child(1)' - ); + const objectLink = await page.$(nftObject(1)); await objectLink.click(); const objectIDEl = await page.$('#objectID'); @@ -466,7 +467,7 @@ describe('End-to-end Tests', () => { it('where first and back disappear in first page', async () => { const address = 'ownsAllAddress'; await page.goto(`${BASE_URL}/addresses/${address}`); - const btn1 = await page.$('#groupCollection > div:nth-child(1)'); + const btn1 = await page.$(coinGroup(1).base()); await btn1.click(); //Next and Last buttons are not disabled: @@ -484,28 +485,28 @@ describe('End-to-end Tests', () => { expect( await page.$eval( - '#groupCollection > div:nth-child(1) > div:nth-child(1)', + coinGroup(1).field(1), (el: any) => el.textContent ) - ).toBe('TypeCoin::Coin<0x2::USD::USD>'); + ).toBe('Type0x2::USD::USD'); expect( await page.$eval( - '#groupCollection > div:nth-child(1) > div:nth-child(2)', + coinGroup(1).field(2), (el: any) => el.textContent ) ).toBe('Balance300'); expect( await page.$eval( - '#groupCollection > div:nth-child(2) > div:nth-child(1)', + coinGroup(2).field(1), (el: any) => el.textContent ) - ).toBe('TypeCoin::Coin<0x2::SUI::SUI>'); + ).toBe('TypeSUI'); expect( await page.$eval( - '#groupCollection > div:nth-child(2) > div:nth-child(2)', + coinGroup(2).field(2), (el: any) => el.textContent ) ).toBe('Balance200'); diff --git a/explorer/client/src/components/ownedobjects/OwnedObjects.module.css b/explorer/client/src/components/ownedobjects/OwnedObjects.module.css index d869c6ab491a5..8770edb600f9b 100644 --- a/explorer/client/src/components/ownedobjects/OwnedObjects.module.css +++ b/explorer/client/src/components/ownedobjects/OwnedObjects.module.css @@ -8,29 +8,24 @@ @apply w-[100%] lg:flex lg:flex-wrap lg:justify-between; } -.groupcollection > div { - @apply border-solid border-stone-300 rounded-lg my-2 p-2 cursor-pointer hover:shadow-md; -} - .fillerbox { @apply invisible; } .objectbox { - @apply border-solid border-stone-300 rounded-lg my-2 lg:self-center hover:shadow-md cursor-pointer break-all lg:w-[20vw]; + @apply border-solid border-stone-300 rounded-lg my-2 lg:self-center hover:shadow-md cursor-pointer break-all lg:w-[21.8vw]; } .objectbox > div { - @apply pt-2 pl-2 pr-1; + @apply py-1 px-1; } .objectbox > div:first-child > div { @apply border-none; } -.objectbox > div > div > span:first-child, -.groupcollection > div > div > span:first-child { - @apply mr-[1rem] uppercase font-sans font-semibold block xl:inline; +.objectbox > div > div > span:first-child { + @apply mr-[0.25vw] uppercase font-sans font-bold block xl:inline; } .previewimage > div > img { diff --git a/explorer/client/src/components/ownedobjects/OwnedObjects.tsx b/explorer/client/src/components/ownedobjects/OwnedObjects.tsx index 425a2a94630a7..57072fe00ee3f 100644 --- a/explorer/client/src/components/ownedobjects/OwnedObjects.tsx +++ b/explorer/client/src/components/ownedobjects/OwnedObjects.tsx @@ -12,7 +12,11 @@ import { findDataFromID, findOwnedObjectsfromID, } from '../../utils/static/searchUtil'; -import { processDisplayValue, trimStdLibPrefix } from '../../utils/stringUtils'; +import { + handleCoinType, + processDisplayValue, + trimStdLibPrefix, +} from '../../utils/stringUtils'; import DisplayBox from '../displaybox/DisplayBox'; import styles from './OwnedObjects.module.css'; @@ -34,6 +38,9 @@ const DATATYPE_DEFAULT: resultType = [ const IS_COIN_TYPE = (typeDesc: string): boolean => /::Coin::/.test(typeDesc); +const lastRowHas2Elements = (itemList: any[]): boolean => + itemList.length % 3 === 2; + function OwnedObject({ id }: { id: string }) { if (process.env.REACT_APP_DATA === 'static') { return ; @@ -162,22 +169,25 @@ function GroupView({ results }: { results: resultType }) { const goBack = useCallback(() => setIsGroup(true), []); + const uniqueTypes = Array.from(new Set(results.map(({ Type }) => Type))); + if (isGroup) { return ( -
- {Array.from(new Set(results.map(({ Type }) => Type))).map( - (typeV) => { - const subObjList = results.filter( - ({ Type }) => Type === typeV - ); - return ( -
+
+ {uniqueTypes.map((typeV) => { + const subObjList = results.filter( + ({ Type }) => Type === typeV + ); + return ( +
+
Type - {trimStdLibPrefix(typeV)} + {handleCoinType(typeV)}
Balance @@ -195,8 +205,13 @@ function GroupView({ results }: { results: resultType }) {
- ); - } +
+ ); + })} + {lastRowHas2Elements(uniqueTypes) && ( +
)}
); @@ -205,7 +220,7 @@ function GroupView({ results }: { results: resultType }) {
-

{trimStdLibPrefix(subObjs[0].Type)}

+

{handleCoinType(subObjs[0].Type)}

@@ -395,7 +410,7 @@ function OwnedObjectView({ results }: { results: resultType }) { ))}
))} - {results.length % 3 === 2 && ( + {lastRowHas2Elements(results) && (
)}
diff --git a/explorer/client/src/utils/stringUtils.ts b/explorer/client/src/utils/stringUtils.ts index 99c63c879afee..131bc71d0b6d0 100644 --- a/explorer/client/src/utils/stringUtils.ts +++ b/explorer/client/src/utils/stringUtils.ts @@ -19,6 +19,11 @@ export function hexToAscii(hex: string) { export const trimStdLibPrefix = (str: string): string => str.replace(/^0x2::/, ''); +export const handleCoinType = (str: string): string => + str === '0x2::Coin::Coin<0x2::SUI::SUI>' + ? 'SUI' + : str.match(/(?<=<)[a-zA-Z0-9:]+(?=>)/)?.[0] || str; + export const processDisplayValue = (display: { bytes: number[] } | string) => { const url = typeof display === 'object' && 'bytes' in display