import { describe, it, expect } from 'vitest'; import { BlockHeader } from '~/src/block-header'; import { Bytes } from '~/src/bytes'; describe('Success cases', () => { // Test cases with different block header representations type BlockHeaderCase = { raw: { version: number; previousBlockHash: Uint8Array; merkleRoot: Uint8Array; timestamp: number; bits: number; nonce: number; }; representations: { bytes: Uint8Array; hex: string; }; }; const testCases: BlockHeaderCase[] = [ { raw: { version: 592633856, previousBlockHash: Bytes.fromHex( 'df4da87b838b2dde9aaf26cb08380f15a57f32d99f2007000000000000000000', ).toBytes(), merkleRoot: Bytes.fromHex( '5e8a3ccc570da3eddb5c67853385e72aad4c830b2eedb4f23943d09513a0b476', ).toBytes(), timestamp: 1737338908, bits: 402807112, nonce: 3478133258, }, representations: { bytes: Bytes.fromHex( '00e05223df4da87b838b2dde9aaf26cb08380f15a57f32d99f20070000000000000000005e8a3ccc570da3eddb5c67853385e72aad4c830b2eedb4f23943d09513a0b4761cb08d67485902180a1a50cf', ).toBytes(), hex: '00e05223df4da87b838b2dde9aaf26cb08380f15a57f32d99f20070000000000000000005e8a3ccc570da3eddb5c67853385e72aad4c830b2eedb4f23943d09513a0b4761cb08d67485902180a1a50cf', }, }, ]; // Test from methods with their respective types const fromMethods = [ { name: 'fromBytes', key: 'bytes' }, { name: 'fromHex', key: 'hex' }, ] as const; fromMethods.forEach(({ name, key }) => { it.each(testCases)(`${name}()`, ({ raw, representations }) => { const blockHeader = BlockHeader[name](representations[key]); expect(blockHeader.toRaw()).toStrictEqual(raw); }); }); // Test generic from method it.each(testCases)('from(Uint8Array)', ({ raw, representations }) => { const blockHeader = BlockHeader.from(representations.bytes); expect(blockHeader.toRaw()).toStrictEqual(raw); }); it.each(testCases)('from(string)', ({ raw, representations }) => { const blockHeader = BlockHeader.from(representations.hex); expect(blockHeader.toRaw()).toStrictEqual(raw); }); // Test to methods with their respective types const toMethods = [ { name: 'toBytes', key: 'bytes' }, { name: 'toHex', key: 'hex' }, ] as const; toMethods.forEach(({ name, key }) => { it.each(testCases)(`${name}()`, ({ raw, representations }) => { const blockHeader = BlockHeader.fromRaw(raw); expect(blockHeader[name]()).toStrictEqual(representations[key]); }); }); // Test getter methods it.each(testCases)('getter methods return correct values', ({ raw }) => { const blockHeader = BlockHeader.fromRaw(raw); expect(blockHeader.getVersion()).toBe(raw.version); expect(blockHeader.getPreviousBlockHash()).toStrictEqual( raw.previousBlockHash, ); expect(blockHeader.getMerkleRoot()).toStrictEqual(raw.merkleRoot); expect(blockHeader.getTimestamp()).toBe(raw.timestamp); expect(blockHeader.getBits()).toBe(raw.bits); expect(blockHeader.getNonce()).toBe(raw.nonce); }); // Test hex getter methods it.each(testCases)('hex getter methods return correct values', ({ raw }) => { const blockHeader = BlockHeader.fromRaw(raw); expect(blockHeader.getPreviousBlockHashHex()).toBe( Bytes.fromBytes(raw.previousBlockHash).toHex(), ); expect(blockHeader.getMerkleRootHex()).toBe( Bytes.fromBytes(raw.merkleRoot).toHex(), ); }); // Test hash methods it.each(testCases)('getHash() returns correct hash', ({ raw }) => { const blockHeader = BlockHeader.fromRaw(raw); const hash = blockHeader.getHash(); expect(hash).toBeInstanceOf(Uint8Array); expect(hash.length).toBe(32); }); it.each(testCases)('getHashHex() returns correct hash hex', ({ raw }) => { const blockHeader = BlockHeader.fromRaw(raw); const hashHex = blockHeader.getHashHex(); expect(typeof hashHex).toBe('string'); expect(hashHex.length).toBe(64); }); // Test validation method it.each(testCases)( 'isValid() returns true for valid inputs', ({ representations }) => { expect(BlockHeader.isValid(representations.bytes)).toBe(true); expect(BlockHeader.isValid(representations.hex)).toBe(true); }, ); }); describe('Error cases', () => { const invalidCases = [ { method: 'fromBytes', input: new Uint8Array(79), // Wrong length (should be 80 bytes) }, { method: 'fromHex', input: 'invalid_hex', }, { method: 'fromHex', input: '00'.repeat(79), // Wrong length (should be 80 bytes / 160 hex chars) }, ]; invalidCases.forEach(({ method, input }) => { it(`${method}() throws on invalid input`, () => { expect(() => BlockHeader[method](input)).toThrow(); }); }); it('isValid() returns false for invalid inputs', () => { expect(BlockHeader.isValid(new Uint8Array(79))).toBe(false); expect(BlockHeader.isValid('invalid_hex')).toBe(false); expect(BlockHeader.isValid('00'.repeat(79))).toBe(false); }); });