import { type Mock, beforeEach, describe, expect, it, vi } from 'vitest';
import '@testing-library/jest-dom';
import { useAttestations } from '@/identity/hooks/useAttestations';
import { useName } from '@/identity/hooks/useName';
import { render, screen, waitFor } from '@testing-library/react';
import { base, baseSepolia, optimism } from 'viem/chains';
import { getSlicedAddress } from '../utils/getSlicedAddress';
import { Badge } from './Badge';
import { useIdentityContext } from './IdentityProvider';
import { Name } from './Name';
vi.mock('@/identity/hooks/useAttestations', () => ({
useAttestations: vi.fn(),
}));
vi.mock('@/identity/hooks/useName', () => ({
useName: vi.fn(),
}));
vi.mock('@/identity/utils/getSlicedAddress', () => ({
getSlicedAddress: vi.fn(),
}));
vi.mock('@/identity/components/IdentityProvider', () => ({
useIdentityContext: vi.fn(),
}));
describe('Name', () => {
const testName = 'testname.eth';
const testIdentityProviderAddress = '0xIdentityAddress';
const testNameComponentAddress = '0xNameComponentAddress';
const mockUseName = useName as Mock;
beforeEach(() => {
vi.clearAllMocks();
vi.spyOn(console, 'error').mockImplementation(vi.fn());
});
it('should console.error and return null when no address is provided', () => {
(useName as Mock).mockReturnValue({ data: undefined });
vi.mocked(useIdentityContext).mockReturnValue({
// @ts-expect-error - Testing undefined address case
address: undefined,
chain: undefined,
});
const consoleErrorSpy = vi
.spyOn(console, 'error')
.mockImplementation(() => {});
const { container } = render();
expect(consoleErrorSpy).toHaveBeenCalledWith(
'Name: an Ethereum address must be provided to the Identity or Name component.',
);
expect(container.firstChild).toBeNull();
});
it('displays ENS name when available', () => {
(useIdentityContext as Mock).mockReturnValue({
schemaId: '0x123',
});
mockUseName.mockReturnValue({
data: testName,
isLoading: false,
});
render();
expect(screen.getByText(testName)).toBeInTheDocument();
});
it('use identity context address if provided', () => {
(useIdentityContext as Mock).mockReturnValue({
schemaId: '0x123',
address: testIdentityProviderAddress,
});
mockUseName.mockReturnValue({
data: testName,
isLoading: false,
});
render();
expect(mockUseName).toHaveBeenCalledWith({
address: testIdentityProviderAddress,
chain: undefined,
});
});
it('use identity context chain if provided', () => {
(useIdentityContext as Mock).mockReturnValue({
schemaId: '0x123',
chain: optimism,
});
mockUseName.mockReturnValue({
data: testName,
isLoading: false,
});
render();
expect(mockUseName).toHaveBeenCalledWith({
address: testNameComponentAddress,
chain: optimism,
});
});
it('use component address over identity context if both are provided', () => {
(useIdentityContext as Mock).mockReturnValue({
schemaId: '0x123',
chain: optimism,
address: testIdentityProviderAddress,
});
mockUseName.mockReturnValue({
data: testName,
isLoading: false,
});
render();
expect(mockUseName).toHaveBeenCalledWith({
address: testNameComponentAddress,
chain: optimism,
});
});
it('use component chain over identity context if both are provided', () => {
(useIdentityContext as Mock).mockReturnValue({
schemaId: '0x123',
chain: optimism,
address: testIdentityProviderAddress,
});
mockUseName.mockReturnValue({
data: testName,
isLoading: false,
});
render();
expect(mockUseName).toHaveBeenCalledWith({
address: testNameComponentAddress,
chain: base,
});
});
it('displays custom chain ENS name when available', () => {
(useIdentityContext as Mock).mockReturnValue({
schemaId: '0x123',
});
mockUseName.mockReturnValue({
data: testName,
isLoading: false,
});
render();
expect(screen.getByText(testName)).toBeInTheDocument();
});
it('displays sliced address when ENS name is not available', () => {
(useIdentityContext as Mock).mockReturnValue({
schemaId: '0x123',
});
mockUseName.mockReturnValue({
data: null,
isLoading: false,
});
(getSlicedAddress as Mock).mockReturnValue('0xName...ess');
render();
expect(screen.getByText('0xName...ess')).toBeInTheDocument();
});
it('displays empty when ens still fetching', () => {
mockUseName.mockReturnValue({ data: null, isLoading: true });
render();
expect(screen.queryByText(testName)).not.toBeInTheDocument();
expect(getSlicedAddress).toHaveBeenCalledTimes(0);
});
it('renders badge when Badge is passed, user is attested and address set in Identity', async () => {
(useIdentityContext as Mock).mockReturnValue({
address: testNameComponentAddress,
schemaId: '0x123',
});
(useAttestations as Mock).mockReturnValue(['attestation']);
mockUseName.mockReturnValue({
data: 'ens_name',
isLoading: false,
});
render(
,
);
await waitFor(() => {
const badge = screen.getByTestId('ockBadge');
expect(badge).toBeInTheDocument();
});
});
it('renders badge when Badge is passed, user is attested and address set in Name', async () => {
(useIdentityContext as Mock).mockReturnValue({
schemaId: '0x123',
});
(useAttestations as Mock).mockReturnValue(['attestation']);
mockUseName.mockReturnValue({
address: testNameComponentAddress,
data: 'ens_name',
isLoading: false,
});
render(
,
);
await waitFor(() => {
const badge = screen.getByTestId('ockBadge');
expect(badge).toBeInTheDocument();
});
});
});