diff --git a/deploy/00_register_legacy.ts b/deploy/00_register_legacy.ts index 0e996a477..b5e8874bf 100644 --- a/deploy/00_register_legacy.ts +++ b/deploy/00_register_legacy.ts @@ -353,6 +353,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { subnames, ...rest }: Name) => { + // eslint-disable-next-line no-restricted-syntax const secret = '0x0000000000000000000000000000000000000000000000000000000000000000' const registrant = allNamedAccts[namedOwner] const owner = namedController ? allNamedAccts[namedController] : undefined diff --git a/playwright/pageObjects/ownershipPage.ts b/playwright/pageObjects/ownershipPage.ts index 868e4b9e9..faa0b61fb 100644 --- a/playwright/pageObjects/ownershipPage.ts +++ b/playwright/pageObjects/ownershipPage.ts @@ -44,7 +44,6 @@ export class OwnershipPage { const timestamp = await this.page .getByTestId('expiry-panel-expiry') .getAttribute('data-timestamp') - console.log('>>>>', timestamp) const parsed = parseInt(timestamp || '') return parsed } diff --git a/src/components/@molecules/AvatarWithIdentifier/AvatarWithIdentifier.test.tsx b/src/components/@molecules/AvatarWithIdentifier/AvatarWithIdentifier.test.tsx index 753d7ab84..8854b4a7e 100644 --- a/src/components/@molecules/AvatarWithIdentifier/AvatarWithIdentifier.test.tsx +++ b/src/components/@molecules/AvatarWithIdentifier/AvatarWithIdentifier.test.tsx @@ -3,7 +3,6 @@ import { render, screen} from '@app/test-utils' import { AvatarWithIdentifier } from './AvatarWithIdentifier' const mockUsePrimary = jest.fn().mockImplementation((address) => { - console.log('mockUsePrimary', address) return ({ data: address === '0xaddressWithoutAPrimaryName' ? undefined : { beautifiedName: 'test.eth', name: 'test.eth' }, isLoading: false diff --git a/src/components/pages/profile/[name]/tabs/MoreTab/MoreTab.tsx b/src/components/pages/profile/[name]/tabs/MoreTab/MoreTab.tsx index eff1bc18d..5cdf312f6 100644 --- a/src/components/pages/profile/[name]/tabs/MoreTab/MoreTab.tsx +++ b/src/components/pages/profile/[name]/tabs/MoreTab/MoreTab.tsx @@ -3,11 +3,7 @@ import styled, { css } from 'styled-components' import { CacheableComponent } from '@app/components/@atoms/CacheableComponent' import type { useAbilities } from '@app/hooks/abilities/useAbilities' import { useNameDetails } from '@app/hooks/useNameDetails' -import useOwners from '@app/hooks/useOwners' -import { validateExpiry } from '@app/utils/utils' -import Miscellaneous from './Miscellaneous/Miscellaneous' -import Ownership from './Ownership' import Resolver from './Resolver' import Token from './Token/Token' @@ -30,48 +26,11 @@ type Props = { } const MoreTab = ({ name, nameDetails, abilities }: Props) => { - const { - canBeWrapped, - ownerData, - wrapperData, - dnsOwner, - isWrapped, - basicIsCachedData, - profileIsCachedData, - profile, - expiryDate, - pccExpired, - } = nameDetails - - const owners = useOwners({ - ownerData: ownerData!, - wrapperData: wrapperData!, - dnsOwner, - abilities, - }) + const { canBeWrapped, ownerData, wrapperData, isWrapped, profileIsCachedData, profile } = + nameDetails return ( - - {owners && owners.length > 0 && ( - - )} {ownerData && ( { const nameType = useNameType(name) const warning = useOwnershipWarning({ name, details, nameType }) const isLoading = roles.isLoading || details.isLoading - if (isLoading) return null return ( diff --git a/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/ExpirySection/ExpirySection.test.tsx b/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/ExpirySection/ExpirySection.test.tsx new file mode 100644 index 000000000..ac44f8935 --- /dev/null +++ b/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/ExpirySection/ExpirySection.test.tsx @@ -0,0 +1,58 @@ +import { render, screen, userEvent, waitFor } from '@app/test-utils' +import { GRACE_PERIOD } from '@app/utils/constants' +import { ExpirySection } from './ExpirySection'; + + +jest.mock('./hooks/useExpiryDetails', () => ({ + useExpiryDetails: ({name}: any) => { + if (name === 'test.eth') return { + data: [{type: 'expiry', date: new Date(3255803954000)}, {type: 'grace-period', date: new Date(3255803954000 + GRACE_PERIOD)}, {type: 'registration', date: new Date(3255803954000)}], + isLoading: false + }} +})) + +const mockShowInput = jest.fn() +jest.mock('./hooks/useExpiryActions', () => ({ + useExpiryActions: ({name}: any) => { + if (name === 'test.eth') return [ { + label: 'action.setReminder', + type: 'set-reminder', + icon:
ICON
, + primary: false, + expiryDate: new Date() + }, + { + label: 'action.extend', + type: 'extend', + icon:
ICON
, + primary: true, + onClick: () => { + mockShowInput() + }, + }]}}) +) + +describe('ExpirySection', () => { + it('should be able to open earnify button modal', async () => { + render() + expect(screen.getByText('action.setReminder')).toBeVisible() + expect(screen.getByText('action.extend')).toBeVisible() + await userEvent.click(screen.getByText('action.setReminder')) + await waitFor(async () => { + expect(screen.getByText('tabs.more.misc.reminderOptions.earnifi')).toBeVisible() + await userEvent.click(screen.getByText('tabs.more.misc.reminderOptions.earnifi')) + }) + await waitFor(() => { + expect(screen.getByText('tabs.more.misc.earnfi.title')).toBeVisible() + }) + }) + + it('should be able to call show extend modal', async () => { + render() + expect(screen.getByText('action.extend')).toBeVisible() + await userEvent.click(screen.getByText('action.extend')) + await waitFor(() => { + expect(mockShowInput).toHaveBeenCalled() + }) + }) +}) \ No newline at end of file diff --git a/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/ExpirySection/ExpirySection.tsx b/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/ExpirySection/ExpirySection.tsx index 5982ca71b..77ae1571f 100644 --- a/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/ExpirySection/ExpirySection.tsx +++ b/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/ExpirySection/ExpirySection.tsx @@ -117,11 +117,10 @@ type Props = { export const ExpirySection = ({ name, details }: Props) => { const { t } = useTranslation('profile') const expiry = useExpiryDetails({ name, details }) + const actions = useExpiryActions({ name, expiryDetails: expiry.data }) const [showEarnifiDialog, setShowEarnifiDialog] = useState(false) - const actions = useExpiryActions({ name, expiryDetails: expiry.data }) - if (!expiry.data || expiry.data?.length === 0) return null return ( <> diff --git a/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/ExpirySection/components/ExpiryPanel.test.tsx b/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/ExpirySection/components/ExpiryPanel.test.tsx index 85e6d4364..7a2b4f3be 100644 --- a/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/ExpirySection/components/ExpiryPanel.test.tsx +++ b/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/ExpirySection/components/ExpiryPanel.test.tsx @@ -1,6 +1,14 @@ -import { render, screen } from "@app/test-utils" +import { render, screen, userEvent } from "@app/test-utils" import { ExpiryPanel } from "./ExpiryPanel" +jest.mock('@ensdomains/thorin', () => { + const _thorin = jest.requireActual('@ensdomains/thorin') + return { + _esModule: true, + ..._thorin, + QuestionCircleSVG: () =>
ICON
+}}) + describe('ExpiryPanel', () => { it('should render', async () => { render() @@ -11,4 +19,22 @@ describe('ExpiryPanel', () => { render() expect(screen.getByTestId('expiry-panel-expiry')).toHaveTextContent(/Mar (2|3|4), 2073/) }) + + it('should not display link only if link is provided', async () => { + const {rerender} = render() + expect(screen.getByText('action.view')).toBeVisible() + rerender() + expect(screen.queryByText('action.view')).toEqual(null) + }) + + it('should not display tooltip only if tooltip is provided', async () => { + const {rerender} = render() + expect(screen.getByText('ICON')).toBeVisible() + expect(screen.queryByText('TOOLTIP')).toEqual(null) + await userEvent.hover(screen.getByText('ICON')) + expect(screen.getByText('TOOLTIP')).toBeVisible() + rerender() + expect(screen.queryByText('ICON')).toEqual(null) + expect(screen.queryByText('TOOLTIP')).toEqual(null) + }) }) \ No newline at end of file diff --git a/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/ExpirySection/hooks/useExpiryActions.test.tsx b/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/ExpirySection/hooks/useExpiryActions.test.tsx new file mode 100644 index 000000000..6d12df7f1 --- /dev/null +++ b/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/ExpirySection/hooks/useExpiryActions.test.tsx @@ -0,0 +1,24 @@ +import { renderHook } from "@app/test-utils" +import { useExpiryActions } from "./useExpiryActions" + +describe('useExpiryActions', () => { + it('should render if expiryDetails contains a expiry type data with a valid expiry date', () => { + const { result} = renderHook(() => useExpiryActions({ name: 'test.eth', expiryDetails: [{ type: 'expiry', date: new Date('3255803954000') }]})) + expect(result.current).toEqual(expect.arrayContaining([expect.objectContaining({type: 'extend'})])) + }) + + it('should render null if name is subname and if expiryDetails contains a expiry type data with a valid expiry date', () => { + const { result} = renderHook(() => useExpiryActions({ name: 'sub.test.eth', expiryDetails: [{ type: 'expiry', date: new Date('3255803954000') }]})) + expect(result.current).toEqual(null) + }) + + it('should return null if expiryDetails contains a expiry type data but an invalid expiry date', () => { + const { result} = renderHook(() => useExpiryActions({ name: 'test.eth', expiryDetails: [{ type: 'expiry', date: undefined }]})) + expect(result.current).toEqual(null) + }) + + it('should return null if expiryDetails does not contain a expiry type data', () => { + const { result} = renderHook(() => useExpiryActions({ name: 'test.eth', expiryDetails: [{ type: 'expiry', date: undefined }]})) + expect(result.current).toEqual(null) + }) +}) \ No newline at end of file diff --git a/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/ExpirySection/hooks/useExpiryDetails.test.ts b/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/ExpirySection/hooks/useExpiryDetails.test.ts new file mode 100644 index 000000000..827ce85f9 --- /dev/null +++ b/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/ExpirySection/hooks/useExpiryDetails.test.ts @@ -0,0 +1,109 @@ +import { renderHook } from "@testing-library/react-hooks" +import { useExpiryDetails } from "./useExpiryDetails" +import { checkETH2LDFromName } from "@app/utils/utils" + +const mockUseNameType = jest.fn() +jest.mock('@app/hooks/useNameType', () => ({ + useNameType: () => mockUseNameType() +})) + +const mockUseBasicName = jest.fn() +jest.mock('@app/hooks/useBasicName', () => ({ + useBasicName: (_: string, {enabled}: any) => { + return enabled ? mockUseBasicName() : {isLoading: false} } +})) + +const mockUseRegistrationData = jest.fn().mockReturnValue({ + data: { + registrationDate: new Date(3255803954000), + transactionHash: '0xhash' + } , + isLoading: false +}) +jest.mock('@app/hooks/useRegistrationData', () => (name: string, {enabled}: any) => enabled && checkETH2LDFromName(name) ? mockUseRegistrationData() : { isLoading: false}) + +jest.mock('@app/hooks/useChainName', () => ({ + useChainName: () => 'goerli' +})) + +beforeEach(() => { + jest.clearAllMocks() +}) + +describe('useExpiryDetails', () => { + describe('eth 2lds', () => { + ['eth-unwrapped-2ld', 'eth-emancipated-2ld', 'eth-locked-2ld'].forEach((nameType) => { + it(`should return expiry, grace-period and `, () => { + mockUseNameType.mockReturnValue({ + data: nameType, + isLoading: false + }) + const { result } = renderHook(() => useExpiryDetails({name: 'test.eth', details: { + expiryDate: new Date(3255803954000), + isLoading: false + } as any})) + + expect(mockUseRegistrationData).toHaveBeenCalled() + expect(mockUseBasicName).not.toHaveBeenCalled() + expect(result.current.data).toEqual(expect.arrayContaining([expect.objectContaining({type: 'expiry'})])) + expect(result.current.data).toEqual(expect.arrayContaining([expect.objectContaining({type: 'grace-period'})])) + expect(result.current.data).toEqual(expect.arrayContaining([expect.objectContaining({type: 'registration'})])) + + }) + }) + }) + + describe('pcc burned eth subnamess', () => { + ['eth-emancipated-subname', 'eth-locked-subname'].forEach((nameType) => { + it(`should return expiry, grace-period and `, () => { + mockUseNameType.mockReturnValue({ + data: nameType, + isLoading: false + }) + mockUseBasicName.mockReturnValue({ + wrapperData: { + expiryDate: new Date(3255803954000) + }, + isLoading: false + }) + + const { result } = renderHook(() => useExpiryDetails({name: 'sub.test.eth', details: { + wrapperData: { + expiryDate: new Date(3255803954000) + }, + isLoading: false + } as any})) + + expect(mockUseRegistrationData).not.toHaveBeenCalled() + expect(mockUseBasicName).toHaveBeenCalled() + expect(result.current.data).toEqual(expect.arrayContaining([expect.objectContaining({type: 'expiry'})])) + expect(result.current.data).toEqual(expect.arrayContaining([expect.objectContaining({type: 'parent-expiry'})])) + }) + }) + }) + + describe('pcc not burned eth subnamess', () => { + ['eth-unwrapped-subname', 'eth-wrapped-subname', 'eth-pcc-expired-subname'].forEach((nameType) => { + it(`should return expiry, grace-period and `, () => { + mockUseNameType.mockReturnValue({ + data: nameType, + isLoading: false + }) + mockUseBasicName.mockReturnValue({ + expiryDate: new Date(3255803954000), + isLoading: false + }) + + const { result } = renderHook(() => useExpiryDetails({name: 'sub.test.eth', details: { + expiryDate: new Date(3255803954000), + isLoading: false + } as any})) + + expect(mockUseRegistrationData).not.toHaveBeenCalled() + expect(mockUseBasicName).toHaveBeenCalled() + expect(result.current.data).toEqual(expect.arrayContaining([expect.objectContaining({type: 'parent-grace-period'})])) + expect(result.current.data).toEqual(expect.arrayContaining([expect.objectContaining({type: 'parent-expiry'})])) + }) + }) + }) +}) \ No newline at end of file diff --git a/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/ExpirySection/hooks/useExpiryDetails.ts b/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/ExpirySection/hooks/useExpiryDetails.ts index bd81dc961..d323f0633 100644 --- a/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/ExpirySection/hooks/useExpiryDetails.ts +++ b/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/ExpirySection/hooks/useExpiryDetails.ts @@ -2,13 +2,14 @@ import { useMemo } from 'react' import { useTranslation } from 'react-i18next' import { P, match } from 'ts-pattern' +import { useBasicName } from '@app/hooks/useBasicName' import { useChainName } from '@app/hooks/useChainName' import type { useNameDetails } from '@app/hooks/useNameDetails' import { useNameType } from '@app/hooks/useNameType' -import useParentBasicName from '@app/hooks/useParentBasicName' import useRegistrationData from '@app/hooks/useRegistrationData' import { GRACE_PERIOD } from '@app/utils/constants' import { safeDateObj } from '@app/utils/date' +import { parentName } from '@app/utils/name' import { makeEtherscanLink } from '@app/utils/utils' type Input = { @@ -26,9 +27,14 @@ export const useExpiryDetails = ({ name, details }: Input, options: Options = {} const { t } = useTranslation('profile') const nameType = useNameType(name, { enabled }) - const parentData = useParentBasicName(name) + const parentData = useBasicName(parentName(name), { + skipGraph: false, + enabled: enabled && !!nameType.data && nameType.data!.includes('subname'), + }) const chainName = useChainName() - const registrationData = useRegistrationData(name) + const registrationData = useRegistrationData(name, { + enabled, + }) const isLoading = nameType.isLoading || details.isLoading || parentData.isLoading || registrationData.isLoading diff --git a/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/RolesSection/RolesSection.tsx b/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/RolesSection/RolesSection.tsx index 041f874da..f92ebda7a 100644 --- a/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/RolesSection/RolesSection.tsx +++ b/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/RolesSection/RolesSection.tsx @@ -39,7 +39,12 @@ export const RolesSection = ({ name, roles, details }: Props) => {
!!address).length || 0} /> {roles?.map((role) => ( - + ))}