-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
399 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
const renderPNG = require('../lib/blockiesPNG'); | ||
const renderSVG = require('../lib/blockiesSVG'); | ||
|
||
describe('Blockies Image Generation', () => { | ||
describe('SVG Generation', () => { | ||
test('generates consistent SVG for same seed', () => { | ||
const svg1 = renderSVG({ seed: 'test123', size: 8, scale: 4 }); | ||
const svg2 = renderSVG({ seed: 'test123', size: 8, scale: 4 }); | ||
expect(svg1).toBe(svg2); | ||
}); | ||
|
||
test('generates different SVG for different seeds', () => { | ||
const svg1 = renderSVG({ seed: 'test123', size: 8, scale: 4 }); | ||
const svg2 = renderSVG({ seed: 'test456', size: 8, scale: 4 }); | ||
expect(svg1).not.toBe(svg2); | ||
}); | ||
|
||
test('respects size parameter', () => { | ||
const svg = renderSVG({ seed: 'test123', size: 16, scale: 4 }); | ||
expect(svg).toMatch(/viewBox="0 0 64 64"/); | ||
}); | ||
|
||
test('respects scale parameter', () => { | ||
const svg = renderSVG({ seed: 'test123', size: 8, scale: 8 }); | ||
expect(svg).toMatch(/viewBox="0 0 64 64"/); | ||
}); | ||
|
||
test('generates valid SVG markup', () => { | ||
const svg = renderSVG({ seed: 'test123' }); | ||
expect(svg).toMatch(/^<svg.*<\/svg>$/); | ||
expect(svg).toContain('xmlns="http://www.w3.org/2000/svg"'); | ||
}); | ||
}); | ||
|
||
describe('PNG Generation', () => { | ||
test('generates consistent PNG for same seed', () => { | ||
const png1 = renderPNG({ seed: 'test123', size: 8, scale: 4 }); | ||
const png2 = renderPNG({ seed: 'test123', size: 8, scale: 4 }); | ||
expect(Buffer.compare(png1, png2)).toBe(0); | ||
}); | ||
|
||
test('generates different PNG for different seeds', () => { | ||
const png1 = renderPNG({ seed: 'test123', size: 8, scale: 4 }); | ||
const png2 = renderPNG({ seed: 'test456', size: 8, scale: 4 }); | ||
expect(Buffer.compare(png1, png2)).not.toBe(0); | ||
}); | ||
|
||
test('returns Buffer instance', () => { | ||
const png = renderPNG({ seed: 'test123' }); | ||
expect(Buffer.isBuffer(png)).toBe(true); | ||
}); | ||
|
||
test('generates PNG with correct dimensions', () => { | ||
const size = 8; | ||
const scale = 4; | ||
const png = renderPNG({ seed: 'test123', size, scale }); | ||
expect(png.length).toBeGreaterThan(0); | ||
}); | ||
}); | ||
|
||
describe('Error Handling', () => { | ||
test('throws error when no seed provided for SVG', () => { | ||
expect(() => renderSVG({})).toThrow(); | ||
}); | ||
|
||
test('throws error when no seed provided for PNG', () => { | ||
expect(() => renderPNG({})).toThrow(); | ||
}); | ||
|
||
test('handles invalid size parameter', () => { | ||
expect(() => renderSVG({ seed: 'test', size: -1 })).toThrow(); | ||
expect(() => renderPNG({ seed: 'test', size: -1 })).toThrow(); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
const { AssetId } = require("caip"); | ||
const { getENSAvatar } = require('../index.js'); | ||
|
||
// Mock the provider and other dependencies | ||
jest.mock('@ethersproject/providers', () => ({ | ||
AlchemyProvider: jest.fn().mockImplementation(() => ({ | ||
lookupAddress: jest.fn().mockImplementation(async (address) => { | ||
if (address === '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045') { | ||
return 'vitalik.eth'; | ||
} | ||
throw new Error('Address not found'); | ||
}), | ||
getResolver: jest.fn().mockImplementation(async (name) => ({ | ||
getText: jest.fn().mockImplementation(async (key) => { | ||
if (name === 'vitalik.eth') { | ||
switch (key) { | ||
case 'avatar': | ||
// Different avatar URLs for different test cases | ||
if (process.env.TEST_AVATAR_TYPE === 'ipfs') { | ||
return 'ipfs://QmQsaxGxkKMXxvV1aBB7Dk2eSqNMGrGYzvMJNrGffu8iw3'; | ||
} else if (process.env.TEST_AVATAR_TYPE === 'ipns') { | ||
return 'ipns://k51qzi5uqu5dkkciu33khkzbcmxtyhn376i1e83tya8kuy7z9euedzyr5nk5vv'; | ||
} else if (process.env.TEST_AVATAR_TYPE === 'arweave') { | ||
return 'ar://_YXq8jxJ7lBsUZfUKgfbBTuR0UWEHFKd_wHvIyEUr0s'; | ||
} else if (process.env.TEST_AVATAR_TYPE === 'http') { | ||
return 'https://example.com/avatar.png'; | ||
} else if (process.env.TEST_AVATAR_TYPE === 'eip155') { | ||
return 'eip155:1/erc721:0x123456789/1'; | ||
} | ||
return undefined; | ||
} | ||
} | ||
return undefined; | ||
}) | ||
})) | ||
})) | ||
})); | ||
|
||
// Mock ethers | ||
jest.mock('ethers', () => ({ | ||
getAddress: jest.fn(addr => addr), | ||
Contract: jest.fn().mockImplementation(() => ({ | ||
ownerOf: jest.fn().mockResolvedValue('0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045'), | ||
tokenURI: jest.fn().mockResolvedValue('https://example.com/token/1') | ||
})) | ||
})); | ||
|
||
// Mock axios for HTTP requests | ||
jest.mock('axios', () => ({ | ||
default: { | ||
get: jest.fn().mockImplementation(async (url) => { | ||
if (url.includes('token')) { | ||
return { data: { image: 'https://example.com/nft-image.png' } }; | ||
} | ||
throw new Error('Failed to fetch'); | ||
}) | ||
} | ||
})); | ||
|
||
describe('getENSAvatar', () => { | ||
beforeEach(() => { | ||
jest.clearAllMocks(); | ||
delete process.env.TEST_AVATAR_TYPE; | ||
}); | ||
|
||
test('resolves IPFS avatar URL', async () => { | ||
process.env.TEST_AVATAR_TYPE = 'ipfs'; | ||
const result = await getENSAvatar('0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045'); | ||
expect(result).toBe('https://ipfs.infura.io/ipfs/QmQsaxGxkKMXxvV1aBB7Dk2eSqNMGrGYzvMJNrGffu8iw3'); | ||
}); | ||
|
||
test('resolves IPNS avatar URL', async () => { | ||
process.env.TEST_AVATAR_TYPE = 'ipns'; | ||
const result = await getENSAvatar('0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045'); | ||
expect(result).toBe('https://ipfs.infura.io/ipns/k51qzi5uqu5dkkciu33khkzbcmxtyhn376i1e83tya8kuy7z9euedzyr5nk5vv'); | ||
}); | ||
|
||
test('resolves Arweave avatar URL', async () => { | ||
process.env.TEST_AVATAR_TYPE = 'arweave'; | ||
const result = await getENSAvatar('0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045'); | ||
expect(result).toBe('https://arweave.net/_YXq8jxJ7lBsUZfUKgfbBTuR0UWEHFKd_wHvIyEUr0s'); | ||
}); | ||
|
||
test('resolves HTTP/HTTPS avatar URL', async () => { | ||
process.env.TEST_AVATAR_TYPE = 'http'; | ||
const result = await getENSAvatar('0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045'); | ||
expect(result).toBe('https://example.com/avatar.png'); | ||
}); | ||
|
||
test('handles missing avatar record', async () => { | ||
const result = await getENSAvatar('0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045'); | ||
expect(result).toBeUndefined(); | ||
}); | ||
|
||
test('handles invalid address', async () => { | ||
const result = await getENSAvatar('0xinvalid'); | ||
expect(result).toBeUndefined(); | ||
}); | ||
|
||
test('handles network errors', async () => { | ||
// Mock provider to throw network error | ||
const provider = require('@ethersproject/providers'); | ||
provider.AlchemyProvider.mockImplementationOnce(() => ({ | ||
lookupAddress: jest.fn().mockRejectedValue(new Error('Network error')), | ||
getResolver: jest.fn() | ||
})); | ||
|
||
const result = await getENSAvatar('0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045'); | ||
expect(result).toBeUndefined(); | ||
}); | ||
|
||
test('resolves EIP-155 asset avatar', async () => { | ||
// Mock ethers Contract | ||
const mockContract = { | ||
ownerOf: jest.fn().mockResolvedValue('0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045'), | ||
tokenURI: jest.fn().mockResolvedValue('https://example.com/token/1') | ||
}; | ||
|
||
const ethers = require('ethers'); | ||
ethers.Contract = jest.fn().mockImplementation(() => mockContract); | ||
|
||
process.env.TEST_AVATAR_TYPE = 'eip155'; | ||
const result = await getENSAvatar('0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045'); | ||
expect(result).toBe('https://example.com/nft-image.png'); | ||
}); | ||
|
||
test('handles malformed avatar text records', async () => { | ||
// Mock resolver to return malformed avatar text | ||
const provider = require('@ethersproject/providers'); | ||
provider.AlchemyProvider.mockImplementationOnce(() => ({ | ||
lookupAddress: jest.fn().mockResolvedValue('vitalik.eth'), | ||
getResolver: jest.fn().mockResolvedValue({ | ||
getText: jest.fn().mockResolvedValue('malformed://avatar/url') | ||
}) | ||
})); | ||
|
||
const result = await getENSAvatar('0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045'); | ||
expect(result).toBe('malformed://avatar/url'); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
const { ethers } = require('ethers'); | ||
const { getEthereumAddress } = require('../index'); | ||
|
||
// Mock the provider | ||
jest.mock('@ethersproject/providers', () => ({ | ||
AlchemyProvider: jest.fn().mockImplementation(() => ({ | ||
resolveName: jest.fn().mockImplementation(async (ensName) => { | ||
// Mock ENS resolution | ||
// Case-insensitive ENS name comparison | ||
const normalizedName = ensName.toLowerCase(); | ||
if (normalizedName === 'vitalik.eth') { | ||
return '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045'; | ||
} | ||
if (normalizedName === 'nick.eth') { | ||
return '0xb8c2C29ee19D8307cb7255e1Cd9CbDE883A267d5'; | ||
} | ||
throw new Error('ENS name not found'); | ||
}) | ||
})) | ||
})); | ||
|
||
describe('getEthereumAddress', () => { | ||
beforeEach(() => { | ||
jest.clearAllMocks(); | ||
}); | ||
|
||
test('resolves valid Ethereum address', async () => { | ||
const address = '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045'; | ||
const result = await getEthereumAddress(address); | ||
expect(result).toBe(address); | ||
}); | ||
|
||
test('resolves ENS name to address', async () => { | ||
const result = await getEthereumAddress('vitalik.eth'); | ||
expect(result).toBe('0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045'); | ||
}); | ||
|
||
test('handles checksum addresses', async () => { | ||
const lowercase = '0xd8da6bf26964af9d7eed9e03e53415d37aa96045'; | ||
const checksum = '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045'; | ||
const result = await getEthereumAddress(lowercase); | ||
expect(result).toBe(checksum); | ||
}); | ||
|
||
test('handles invalid Ethereum addresses', async () => { | ||
await expect(getEthereumAddress('0xinvalid')).rejects.toThrow(); | ||
}); | ||
|
||
test('handles non-existent ENS names', async () => { | ||
await expect(getEthereumAddress('nonexistent.eth')).rejects.toThrow(); | ||
}); | ||
|
||
test('handles malformed ENS names', async () => { | ||
await expect(getEthereumAddress('.eth')).rejects.toThrow(); | ||
}); | ||
|
||
test('handles empty input', async () => { | ||
await expect(getEthereumAddress('')).rejects.toThrow(); | ||
}); | ||
|
||
test('handles case sensitivity in ENS names', async () => { | ||
const result = await getEthereumAddress('VITALIK.eth'); | ||
expect(result).toBe('0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045'); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
const { parseURL } = require('../index'); | ||
|
||
describe('parseURL', () => { | ||
test('parses standard Ethereum address with svg extension', () => { | ||
const result = parseURL('/a/0x1234567890123456789012345678901234567890.svg'); | ||
expect(result).toEqual({ | ||
addressFromUrl: '0x1234567890123456789012345678901234567890', | ||
type: 'svg' | ||
}); | ||
}); | ||
|
||
test('parses standard Ethereum address with png extension', () => { | ||
const result = parseURL('/a/0x1234567890123456789012345678901234567890.png'); | ||
expect(result).toEqual({ | ||
addressFromUrl: '0x1234567890123456789012345678901234567890', | ||
type: 'png' | ||
}); | ||
}); | ||
|
||
test('parses basic ENS domain', () => { | ||
const result = parseURL('/a/vitalik.eth'); | ||
expect(result).toEqual({ | ||
addressFromUrl: 'vitalik.eth', | ||
type: 'svg' | ||
}); | ||
}); | ||
|
||
test('parses ENS subdomain', () => { | ||
const result = parseURL('/a/xyz.abc.eth.png'); | ||
expect(result).toEqual({ | ||
addressFromUrl: 'xyz.abc.eth', | ||
type: 'png' | ||
}); | ||
}); | ||
|
||
test('handles missing extension', () => { | ||
const result = parseURL('/a/0x1234567890123456789012345678901234567890'); | ||
expect(result).toEqual({ | ||
addressFromUrl: '0x1234567890123456789012345678901234567890', | ||
type: 'svg' | ||
}); | ||
}); | ||
|
||
test('handles case sensitivity', () => { | ||
const result = parseURL('/a/ViTaLik.ETH.PNG'); | ||
expect(result).toEqual({ | ||
addressFromUrl: 'ViTaLik.ETH', | ||
type: 'png' | ||
}); | ||
}); | ||
|
||
test('handles special characters in ENS names', () => { | ||
const result = parseURL('/a/my-cool-name.eth'); | ||
expect(result).toEqual({ | ||
addressFromUrl: 'my-cool-name.eth', | ||
type: 'svg' | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.