Skip to content

Commit

Permalink
Merge branch 'image-tests'
Browse files Browse the repository at this point in the history
  • Loading branch information
harperreed committed Nov 28, 2024
2 parents 9714071 + 1f07fa5 commit 0c5941a
Show file tree
Hide file tree
Showing 8 changed files with 399 additions and 21 deletions.
75 changes: 75 additions & 0 deletions functions/__tests__/blockies.test.js
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();
});
});
});
140 changes: 140 additions & 0 deletions functions/__tests__/getENSAvatar.test.js
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');
});
});
65 changes: 65 additions & 0 deletions functions/__tests__/getEthereumAddress.test.js
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');
});
});
59 changes: 59 additions & 0 deletions functions/__tests__/parseURL.test.js
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'
});
});
});
Loading

0 comments on commit 0c5941a

Please # to comment.