Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
113 commits
Select commit Hold shift + click to select a range
ca65a00
Add layout.test.tsx
arjun-dureja Jan 10, 2026
5de938b
Add tests for app/(basenames)/names/page.tsx
arjun-dureja Jan 10, 2026
65d34fb
Add tests for app/(basenames)/names/RegistrationProviders.tsx
arjun-dureja Jan 10, 2026
c601f11
Add tests for app/(basenames)/manage-names/page.tsx
arjun-dureja Jan 10, 2026
514fa88
Add tests for app/(basenames)/name/not-found/page.tsx
arjun-dureja Jan 10, 2026
849d683
Add tests for app/(basenames)/name/[username]/page.tsx
arjun-dureja Jan 10, 2026
ea3cb7e
Add tests for app/(basenames)/name/[username]/renew/page.tsx
arjun-dureja Jan 10, 2026
bae37be
Add tests for app/(basenames)/name/[username]/ProfileProviders.tsx
arjun-dureja Jan 10, 2026
e5c119e
Add tests for app/(basenames)/name/[username]/opengraph-image.tsx
arjun-dureja Jan 10, 2026
e373c0d
Add tests for app/(basenames)/api/basenames/[name]/assets/cardImage.s…
arjun-dureja Jan 10, 2026
f1f6dbd
Add tests for app/(basenames)/api/basenames/getUsernames/route.ts
arjun-dureja Jan 10, 2026
7515683
Add tests for app/(basenames)/api/basenames/contract-uri/route.ts
arjun-dureja Jan 10, 2026
b307670
Add tests for app/(basenames)/api/basenames/contract-uri.json/route.ts
arjun-dureja Jan 10, 2026
626b818
Add tests for app/(basenames)/api/basenames/metadata/[tokenId]/route.ts
arjun-dureja Jan 10, 2026
ecc28e3
Add tests for app/(basenames)/api/basenames/talentprotocol/[address]/…
arjun-dureja Jan 10, 2026
713218a
Add tests for app/(basenames)/api/basenames/avatar/ipfsUpload/route.ts
arjun-dureja Jan 10, 2026
f18321a
Add tests for app/(basenames)/api/proofs/discountCode/route.ts
arjun-dureja Jan 10, 2026
59ac80b
Add tests for app/(basenames)/api/proofs/discountCode/consume/route.ts
arjun-dureja Jan 10, 2026
824cdda
Add tests for app/(basenames)/api/proofs/cb1/route.ts
arjun-dureja Jan 10, 2026
da1d01b
Add tests for app/(basenames)/api/proofs/cbid/route.ts
arjun-dureja Jan 10, 2026
4f57d62
Add tests for app/(basenames)/api/proofs/bns/route.ts
arjun-dureja Jan 10, 2026
d6d53e2
Add tests for app/(basenames)/api/proofs/coinbase/route.ts
arjun-dureja Jan 10, 2026
a823f16
Add tests for app/(basenames)/api/proofs/baseEthHolders/route.ts
arjun-dureja Jan 10, 2026
9c8c66c
Add tests for app/(basenames)/api/proxy/route.ts
arjun-dureja Jan 10, 2026
e229182
Add tests for src/utils/basenames/getChain.ts
arjun-dureja Jan 10, 2026
3875508
Add tests for src/utils/basenames/getDomain.ts
arjun-dureja Jan 10, 2026
6bdc7a4
Add tests for src/utils/frames/basenames.ts
arjun-dureja Jan 10, 2026
d50d374
Add tests for src/hooks/useBasenameChain.ts
arjun-dureja Jan 10, 2026
f8ed96e
Add tests for src/hooks/useBasenameExpirationBanner.tsx
arjun-dureja Jan 10, 2026
1e58a74
Add tests for src/hooks/useBasenameResolver.ts
arjun-dureja Jan 10, 2026
3fbd4fc
Add tests for src/hooks/useSetPrimaryBasename.ts
arjun-dureja Jan 10, 2026
85caca2
Add tests for src/hooks/useBasenamesNameExpiresWithGracePeriod.ts
arjun-dureja Jan 10, 2026
a510dfe
Add tests for src/components/BasenameIdentity/index.tsx
arjun-dureja Jan 10, 2026
9f83b3d
Add tests for src/components/Basenames/BasenameAvatar/index.tsx
arjun-dureja Jan 10, 2026
ade10a6
Add tests for src/components/Basenames/FloatingENSPills.tsx
arjun-dureja Jan 10, 2026
b04bdb5
Add tests for src/components/Basenames/PoweredByEns/index.tsx
arjun-dureja Jan 10, 2026
47b268a
Skip tests for src/components/Basenames/ProfilePromo/dynamic.tsx
arjun-dureja Jan 10, 2026
91a4b20
Add tests for src/components/Basenames/ProfilePromo/index.tsx
arjun-dureja Jan 10, 2026
601322d
Add tests for src/components/Basenames/RegistrationBackground/index.tsx
arjun-dureja Jan 10, 2026
48ef876
Add tests for src/components/Basenames/RegistrationBrand/index.tsx
arjun-dureja Jan 10, 2026
7ab65b4
Add tests for src/components/Basenames/RegistrationContext.tsx
arjun-dureja Jan 10, 2026
a2c7185
Add tests for src/components/Basenames/RegistrationFaq/index.tsx
arjun-dureja Jan 10, 2026
0cae0de
Add tests for src/components/Basenames/RegistrationFlow.tsx
arjun-dureja Jan 10, 2026
979bf7e
Add tests for src/components/Basenames/RegistrationForm/index.tsx
arjun-dureja Jan 10, 2026
ec1ce5f
Add tests for src/components/Basenames/RegistrationForm/RegistrationB…
arjun-dureja Jan 10, 2026
da87296
Add tests for src/components/Basenames/RegistrationLandingExplore/ind…
arjun-dureja Jan 10, 2026
9dcf57d
Add tests for src/components/Basenames/RegistrationLearnMoreModal/ind…
arjun-dureja Jan 10, 2026
8225391
Add tests for src/components/Basenames/RegistrationProfileForm/index.tsx
arjun-dureja Jan 10, 2026
aeb880d
Add tests for src/components/Basenames/RegistrationSearchInput/index.tsx
arjun-dureja Jan 10, 2026
c13bdfc
Add tests for src/components/Basenames/RegistrationShareOnSocials/ind…
arjun-dureja Jan 10, 2026
419b69e
Add tests for src/components/Basenames/RegistrationStateSwitcher/inde…
arjun-dureja Jan 10, 2026
957b1ec
Add tests for src/components/Basenames/RegistrationSuccessMessage/ind…
arjun-dureja Jan 10, 2026
7ee9a72
Add tests for src/components/Basenames/RegistrationSuccessMessage/USD…
arjun-dureja Jan 10, 2026
ba6f3f8
Add tests for src/components/Basenames/RegistrationValueProp/index.tsx
arjun-dureja Jan 10, 2026
fc24316
Add tests for src/components/Basenames/RenewalContext.tsx
arjun-dureja Jan 10, 2026
27f9d66
Add tests for src/components/Basenames/RenewalFlow.tsx
arjun-dureja Jan 10, 2026
4611293
Add tests for src/components/Basenames/RenewalForm/index.tsx
arjun-dureja Jan 10, 2026
b1f32e2
Add tests for src/components/Basenames/RenewalForm/RenewalButton.tsx
arjun-dureja Jan 10, 2026
357860c
Add tests for src/components/Basenames/RenewalSuccessMessage/index.tsx
arjun-dureja Jan 10, 2026
af6addb
Add tests for src/components/Basenames/PremiumExplainerModal/index.tsx
arjun-dureja Jan 10, 2026
039b631
Add tests for src/components/Basenames/ManageNames/NamesList.tsx
arjun-dureja Jan 10, 2026
f237b6a
Add tests for src/components/Basenames/ManageNames/NameDisplay.tsx
arjun-dureja Jan 10, 2026
6e56b4a
Add tests for src/components/Basenames/ManageNames/hooks.tsx
arjun-dureja Jan 10, 2026
350428a
Add tests for src/components/Basenames/UsernameAvatarField/index.tsx
arjun-dureja Jan 10, 2026
7eb71ea
Add tests for src/components/Basenames/UsernameCastsField/index.tsx
arjun-dureja Jan 10, 2026
4c96783
Add tests for src/components/Basenames/UsernameDescriptionField/index…
arjun-dureja Jan 10, 2026
61d426d
Add tests for src/components/Basenames/UsernameKeywordsField/index.tsx
arjun-dureja Jan 10, 2026
2395de7
Add tests for src/components/Basenames/UsernameLocationField/index.tsx
arjun-dureja Jan 10, 2026
12b66f7
Add tests for src/components/Basenames/UsernamePill/index.tsx
arjun-dureja Jan 10, 2026
fe42bbb
Add tests for src/components/Basenames/UsernameProfile/index.tsx
arjun-dureja Jan 10, 2026
42fbba7
Add tests for src/components/Basenames/UsernameProfileCard/index.tsx
arjun-dureja Jan 10, 2026
0b99062
Add tests for src/components/Basenames/UsernameProfileCasts/index.tsx
arjun-dureja Jan 10, 2026
0b97403
Add tests for src/components/Basenames/UsernameProfileContent/index.tsx
arjun-dureja Jan 10, 2026
d691a01
Add tests for src/components/Basenames/UsernameProfileContext/index.tsx
arjun-dureja Jan 10, 2026
f8b2873
Add tests for src/components/Basenames/UsernameProfileKeywords/index.tsx
arjun-dureja Jan 10, 2026
503a263
Add tests for src/components/Basenames/UsernameProfileNotFound/index.tsx
arjun-dureja Jan 10, 2026
24d2fd9
Add tests for src/components/Basenames/UsernameProfileRenewalModal/in…
arjun-dureja Jan 10, 2026
2b921eb
Add tests for src/components/Basenames/UsernameProfileSectionBadges/i…
arjun-dureja Jan 10, 2026
381a1cc
Add tests for src/components/Basenames/UsernameProfileSectionBadges/B…
arjun-dureja Jan 10, 2026
ff58d36
Add tests for src/components/Basenames/UsernameProfileSectionBadges/B…
arjun-dureja Jan 10, 2026
db9c1f0
Add tests for src/components/Basenames/UsernameProfileSectionBadges/h…
arjun-dureja Jan 10, 2026
18ac0af
Add tests for src/components/Basenames/UsernameProfileSectionBadges/h…
arjun-dureja Jan 10, 2026
140a5ca
Add tests for src/components/Basenames/UsernameProfileSectionBadges/h…
arjun-dureja Jan 10, 2026
9b262c3
Add tests for src/components/Basenames/UsernameProfileSectionBadges/h…
arjun-dureja Jan 10, 2026
d869823
Add tests for src/components/Basenames/UsernameProfileSectionBadges/h…
arjun-dureja Jan 10, 2026
7d5a629
Add tests for src/components/Basenames/UsernameProfileSectionExplore/…
arjun-dureja Jan 10, 2026
39e1700
Add tests for src/components/Basenames/UsernameProfileSectionHeatmap/…
arjun-dureja Jan 10, 2026
1c1b7f7
Add tests for src/components/Basenames/UsernameProfileSectionHeatmap/…
arjun-dureja Jan 10, 2026
b3e8b5f
Add tests for src/components/Basenames/UsernameProfileSectionTitle/in…
arjun-dureja Jan 10, 2026
51e71e6
Add tests for src/components/Basenames/UsernameProfileSettings/index.tsx
arjun-dureja Jan 10, 2026
fe52256
Add tests for src/components/Basenames/UsernameProfileSettingsAvatar/…
arjun-dureja Jan 10, 2026
0ed089a
Add tests for src/components/Basenames/UsernameProfileSettingsContext…
arjun-dureja Jan 10, 2026
a9d1c6a
Add tests for src/components/Basenames/UsernameProfileSettingsManageP…
arjun-dureja Jan 10, 2026
afb3662
Add tests for src/components/Basenames/UsernameProfileSettingsMenu/in…
arjun-dureja Jan 10, 2026
bdf4784
Add tests for src/components/Basenames/UsernameProfileSettingsName/in…
arjun-dureja Jan 10, 2026
28afa64
Add tests for src/components/Basenames/UsernameProfileSettingsOwnersh…
arjun-dureja Jan 10, 2026
6c022ee
Add tests for src/components/Basenames/UsernameProfileSidebar/index.tsx
arjun-dureja Jan 10, 2026
0e2f475
Add tests for src/components/Basenames/UsernameProfileTransferOwnersh…
arjun-dureja Jan 10, 2026
4e324e9
Add tests for src/components/Basenames/UsernameProfileTransferOwnersh…
arjun-dureja Jan 10, 2026
3855f5d
Add tests for src/components/Basenames/UsernameProfileTransferOwnersh…
arjun-dureja Jan 10, 2026
d93b6bf
Add tests for src/components/Basenames/UsernameTextRecordInlineField/…
arjun-dureja Jan 10, 2026
96368af
Add tests for src/components/Basenames/YearSelector/index.tsx
arjun-dureja Jan 10, 2026
72fa99b
Add tests for src/components/Basenames/shared/SuccessMessage/index.tsx
arjun-dureja Jan 10, 2026
c4b04d2
Bump testing library version
arjun-dureja Jan 10, 2026
9ff8c92
Update
arjun-dureja Jan 11, 2026
8fd6efb
Update
arjun-dureja Jan 11, 2026
9b6d9cf
update
arjun-dureja Jan 11, 2026
4d6d791
update
arjun-dureja Jan 11, 2026
f885ce5
update
arjun-dureja Jan 11, 2026
19d9181
update
arjun-dureja Jan 12, 2026
2aeaf45
update
arjun-dureja Jan 12, 2026
cf9012c
update
arjun-dureja Jan 12, 2026
589b257
update
arjun-dureja Jan 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions apps/web/__mocks__/ox/BlockOverrides.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Mock for ox/BlockOverrides module
module.exports = {
fromRpc: jest.fn(),
toRpc: jest.fn(),
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,355 @@
/**
* @jest-environment node
*/
import { GET } from './route';
import satori from 'satori';
import twemoji from 'twemoji';
import { readFile } from 'node:fs/promises';

// Mock satori
jest.mock('satori', () => jest.fn().mockResolvedValue('<svg>mock svg</svg>'));

// Mock twemoji
jest.mock('twemoji', () => ({
convert: {
toCodePoint: jest.fn().mockReturnValue('1f600'),
},
}));

// Mock fs/promises for font loading
jest.mock('node:fs/promises', () => ({
readFile: jest.fn().mockResolvedValue(Buffer.from('mock font data')),
}));

const mockSatori = satori as jest.MockedFunction<typeof satori>;
const mockReadFile = readFile as jest.MockedFunction<typeof readFile>;

// Mock usernames utils
const mockGetBasenameImage = jest.fn();
const mockGetChainForBasename = jest.fn();
const mockFetchResolverAddress = jest.fn();
jest.mock('apps/web/src/utils/usernames', () => ({
getBasenameImage: (...args: unknown[]) => mockGetBasenameImage(...args) as unknown,
getChainForBasename: (...args: unknown[]) => mockGetChainForBasename(...args) as unknown,
fetchResolverAddress: (...args: unknown[]) => mockFetchResolverAddress(...args) as unknown,
UsernameTextRecordKeys: {
Avatar: 'avatar',
},
}));

// Mock useBasenameChain
const mockGetEnsText = jest.fn();
const mockGetBasenamePublicClient = jest.fn();
jest.mock('apps/web/src/hooks/useBasenameChain', () => ({
getBasenamePublicClient: (...args: unknown[]) => mockGetBasenamePublicClient(...args) as unknown,
}));

// Mock constants
jest.mock('apps/web/src/constants', () => ({
isDevelopment: false,
}));

// Mock urls utility
jest.mock('apps/web/src/utils/urls', () => ({
IsValidIpfsUrl: jest.fn().mockReturnValue(false),
getIpfsGatewayUrl: jest.fn(),
}));

// Mock images utility
jest.mock('apps/web/src/utils/images', () => ({
getCloudinaryMediaUrl: jest.fn(({ media }) => `https://cloudinary.com/${media}`),
}));

// Mock ImageRaw component
jest.mock('apps/web/src/components/ImageRaw', () => ({
__esModule: true,
default: ({ src, alt }: { src: string; alt: string }) => `ImageRaw: ${src} - ${alt}`,
}));

// Mock logger
jest.mock('apps/web/src/utils/logger', () => ({
logger: {
error: jest.fn(),
},
}));

describe('cardImage.svg route', () => {
beforeEach(() => {
jest.clearAllMocks();

// Default mock implementations
mockGetBasenameImage.mockReturnValue({ src: '/default-avatar.png' });
mockGetChainForBasename.mockReturnValue({ id: 8453 });
mockFetchResolverAddress.mockResolvedValue('0x1234567890123456789012345678901234567890');
mockGetBasenamePublicClient.mockReturnValue({
getEnsText: mockGetEnsText,
});
mockGetEnsText.mockResolvedValue(null);
});

describe('GET', () => {
it('should return an SVG response with correct content type', async () => {
const request = new Request('https://www.base.org/api/basenames/alice/assets/cardImage.svg');
const params = Promise.resolve({ name: 'alice' });

const response = await GET(request, { params });

expect(response.headers.get('Content-Type')).toBe('image/svg+xml');
});

it('should return SVG content in the response body', async () => {
const request = new Request('https://www.base.org/api/basenames/alice/assets/cardImage.svg');
const params = Promise.resolve({ name: 'alice' });

const response = await GET(request, { params });
const body = await response.text();

expect(mockSatori).toHaveBeenCalled();
expect(body).toBe('<svg>mock svg</svg>');
});

it('should use username from params', async () => {
const request = new Request('https://www.base.org/api/basenames/testuser/assets/cardImage.svg');
const params = Promise.resolve({ name: 'testuser' });

await GET(request, { params });

expect(mockGetChainForBasename).toHaveBeenCalledWith('testuser');
});

it('should default to "yourname" when name param is missing', async () => {
const request = new Request('https://www.base.org/api/basenames/assets/cardImage.svg');
const params = Promise.resolve({ name: undefined as unknown as string });

await GET(request, { params });

expect(mockGetChainForBasename).toHaveBeenCalledWith('yourname');
});

it('should fetch avatar from ENS text record', async () => {
const request = new Request('https://www.base.org/api/basenames/alice/assets/cardImage.svg');
const params = Promise.resolve({ name: 'alice' });

await GET(request, { params });

expect(mockGetBasenamePublicClient).toHaveBeenCalledWith(8453);
expect(mockGetEnsText).toHaveBeenCalledWith({
name: 'alice',
key: 'avatar',
universalResolverAddress: '0x1234567890123456789012345678901234567890',
});
});

it('should use default image when no avatar is set', async () => {
mockGetEnsText.mockResolvedValue(null);

const request = new Request('https://www.base.org/api/basenames/alice/assets/cardImage.svg');
const params = Promise.resolve({ name: 'alice' });

await GET(request, { params });

expect(mockGetBasenameImage).toHaveBeenCalledWith('alice');
});

it('should handle custom avatar URL', async () => {
// eslint-disable-next-line @typescript-eslint/no-require-imports
const { getCloudinaryMediaUrl } = require('apps/web/src/utils/images') as { getCloudinaryMediaUrl: jest.Mock };
mockGetEnsText.mockResolvedValue('https://example.com/avatar.png');

const request = new Request('https://www.base.org/api/basenames/alice/assets/cardImage.svg');
const params = Promise.resolve({ name: 'alice' });

await GET(request, { params });

expect(getCloudinaryMediaUrl).toHaveBeenCalledWith({
media: 'https://example.com/avatar.png',
format: 'png',
width: 120,
});
});

it('should handle IPFS avatar URL', async () => {
// eslint-disable-next-line @typescript-eslint/no-require-imports
const { IsValidIpfsUrl, getIpfsGatewayUrl } = require('apps/web/src/utils/urls') as { IsValidIpfsUrl: jest.Mock; getIpfsGatewayUrl: jest.Mock };
// eslint-disable-next-line @typescript-eslint/no-require-imports
const { getCloudinaryMediaUrl } = require('apps/web/src/utils/images') as { getCloudinaryMediaUrl: jest.Mock };
IsValidIpfsUrl.mockReturnValue(true);
getIpfsGatewayUrl.mockReturnValue('https://ipfs.io/ipfs/Qm123');
mockGetEnsText.mockResolvedValue('ipfs://Qm123');

const request = new Request('https://www.base.org/api/basenames/alice/assets/cardImage.svg');
const params = Promise.resolve({ name: 'alice' });

await GET(request, { params });

expect(IsValidIpfsUrl).toHaveBeenCalledWith('ipfs://Qm123');
expect(getIpfsGatewayUrl).toHaveBeenCalledWith('ipfs://Qm123');
expect(getCloudinaryMediaUrl).toHaveBeenCalledWith({
media: 'https://ipfs.io/ipfs/Qm123',
format: 'png',
width: 120,
});
});

it('should fallback to default image when IPFS gateway URL is null', async () => {
// eslint-disable-next-line @typescript-eslint/no-require-imports
const { IsValidIpfsUrl, getIpfsGatewayUrl } = require('apps/web/src/utils/urls') as { IsValidIpfsUrl: jest.Mock; getIpfsGatewayUrl: jest.Mock };
// eslint-disable-next-line @typescript-eslint/no-require-imports
const { getCloudinaryMediaUrl } = require('apps/web/src/utils/images') as { getCloudinaryMediaUrl: jest.Mock };
IsValidIpfsUrl.mockReturnValue(true);
getIpfsGatewayUrl.mockReturnValue(null);
mockGetEnsText.mockResolvedValue('ipfs://Qm123');

const request = new Request('https://www.base.org/api/basenames/alice/assets/cardImage.svg');
const params = Promise.resolve({ name: 'alice' });

await GET(request, { params });

expect(IsValidIpfsUrl).toHaveBeenCalledWith('ipfs://Qm123');
expect(getIpfsGatewayUrl).toHaveBeenCalledWith('ipfs://Qm123');
// When gateway returns null, image source remains unchanged (default image with base.org domain prefix)
expect(getCloudinaryMediaUrl).toHaveBeenCalledWith({
media: 'https://www.base.org/default-avatar.png',
format: 'png',
width: 120,
});
});

it('should handle errors when fetching avatar gracefully', async () => {
// eslint-disable-next-line @typescript-eslint/no-require-imports
const { logger } = require('apps/web/src/utils/logger') as { logger: { error: jest.Mock } };
const error = new Error('Failed to fetch avatar');
mockGetEnsText.mockRejectedValue(error);

const request = new Request('https://www.base.org/api/basenames/alice/assets/cardImage.svg');
const params = Promise.resolve({ name: 'alice' });

// Should not throw
const response = await GET(request, { params });
expect(response).toBeDefined();
expect(response.headers.get('Content-Type')).toBe('image/svg+xml');

expect(logger.error).toHaveBeenCalledWith('Error fetching basename Avatar:', error);
});

it('should use development domain when isDevelopment is true', async () => {
jest.resetModules();
jest.doMock('apps/web/src/constants', () => ({
isDevelopment: true,
}));

// Re-import the module to get fresh mocks
// eslint-disable-next-line @typescript-eslint/no-require-imports
const { GET: GETDev } = require('./route') as { GET: typeof GET };

const request = new Request('http://localhost:3000/api/basenames/alice/assets/cardImage.svg');
const params = Promise.resolve({ name: 'alice' });

await GETDev(request, { params });

// In development mode, the domain should be extracted from the request URL
expect(mockGetBasenameImage).toHaveBeenCalledWith('alice');

// Restore the original mock
jest.resetModules();
jest.doMock('apps/web/src/constants', () => ({
isDevelopment: false,
}));
});

it('should call satori with correct dimensions', async () => {
const request = new Request('https://www.base.org/api/basenames/alice/assets/cardImage.svg');
const params = Promise.resolve({ name: 'alice' });

await GET(request, { params });

expect(mockSatori).toHaveBeenCalledWith(
expect.anything(),
expect.objectContaining({
width: 1000,
height: 1000,
})
);
});

it('should load custom font for the image', async () => {
const request = new Request('https://www.base.org/api/basenames/alice/assets/cardImage.svg');
const params = Promise.resolve({ name: 'alice' });

await GET(request, { params });

expect(mockReadFile).toHaveBeenCalled();
expect(mockSatori).toHaveBeenCalledWith(
expect.anything(),
expect.objectContaining({
fonts: expect.arrayContaining([
expect.objectContaining({
name: 'CoinbaseDisplay',
weight: 500,
style: 'normal',
}),
]) as unknown,
})
);
});

it('should handle emoji loading in loadAdditionalAsset', async () => {
// Mock fetch for emoji loading
global.fetch = jest.fn().mockResolvedValue({
text: jest.fn().mockResolvedValue('<svg>emoji svg</svg>'),
});

const request = new Request('https://www.base.org/api/basenames/alice/assets/cardImage.svg');
const params = Promise.resolve({ name: 'alice' });

await GET(request, { params });

const satoriCall = mockSatori.mock.calls[0];
const loadAdditionalAsset = satoriCall[1].loadAdditionalAsset;

// Test emoji loading
const emojiResult = await loadAdditionalAsset('emoji', '😀');
expect(twemoji.convert.toCodePoint).toHaveBeenCalledWith('😀');
expect(global.fetch).toHaveBeenCalledWith(
'https://cdnjs.cloudflare.com/ajax/libs/twemoji/14.0.2/svg/1f600.svg'
);
expect(emojiResult).toBe('data:image/svg+xml;base64,' + btoa('<svg>emoji svg</svg>'));
});

it('should return code for non-emoji assets', async () => {
const request = new Request('https://www.base.org/api/basenames/alice/assets/cardImage.svg');
const params = Promise.resolve({ name: 'alice' });

await GET(request, { params });

const satoriCall = mockSatori.mock.calls[0];
const loadAdditionalAsset = satoriCall[1].loadAdditionalAsset;

// Test non-emoji asset loading
const result = await loadAdditionalAsset('font', 'test');
expect(result).toBe('font');
});

it('should cache emoji fetches', async () => {
global.fetch = jest.fn().mockResolvedValue({
text: jest.fn().mockResolvedValue('<svg>emoji svg</svg>'),
});

const request = new Request('https://www.base.org/api/basenames/alice/assets/cardImage.svg');
const params = Promise.resolve({ name: 'alice' });

await GET(request, { params });

const satoriCall = mockSatori.mock.calls[0];
const loadAdditionalAsset = satoriCall[1].loadAdditionalAsset;

// First call should fetch
await loadAdditionalAsset('emoji', '😀');
const fetchCallCount = (global.fetch as jest.Mock).mock.calls.length;

// Second call with same emoji should use cache
await loadAdditionalAsset('emoji', '😀');
expect((global.fetch as jest.Mock).mock.calls.length).toBe(fetchCallCount);
});
});
});
Loading