import { describe, it, expect } from 'vitest'; import { Bytes, decodeBase64, fromJS } from '../src/index'; import './test-utils'; describe('immutable byte arrays', () => { describe('Uint8Array methods', () => { const bs = Bytes.of(10, 20, 30, 40); it('should yield entries', () => { expect(fromJS(Array.from(bs.entries()))) .isPreserves(fromJS([[0,10],[1,20],[2,30],[3,40]])); }); it('should implement every', () => { expect(bs.every((b) => !(b & 1))).toBe(true); expect(bs.every((b) => b !== 50)).toBe(true); expect(!(bs.every((b) => b !== 20))).toBe(true); }); it('should implement find', () => { expect(bs.find((b) => b > 20)).toBe(30); expect(bs.find((b) => b > 50)).toBe(void 0); }); it('should implement findIndex', () => { expect(bs.findIndex((b) => b > 20)).toBe(2); expect(bs.findIndex((b) => b > 50)).toBe(-1); }); it('should implement forEach', () => { const vs: number[] = []; bs.forEach((b) => vs.push(b)); expect(fromJS(vs)).isPreserves(fromJS([10, 20, 30, 40])); }); it('should implement includes', () => { expect(bs.includes(20)).toBe(true); expect(!bs.includes(50)).toBe(true); }); it('should implement indexOf', () => { expect(bs.indexOf(20)).toBe(1); expect(bs.indexOf(50)).toBe(-1); }); it('should implement join', () => { expect(bs.join('-')).toBe('10-20-30-40'); }); it('should implement keys', () => { expect(fromJS(Array.from(bs.keys()))).isPreserves(fromJS([0,1,2,3])); }); it('should implement values', () => { expect(fromJS(Array.from(bs.values()))).isPreserves(fromJS([10,20,30,40])); }); it('should implement filter', () => { expect(bs.filter((b) => b !== 30)).isPreserves(Bytes.of(10,20,40)); }); it('should implement slice', () => { const vs = bs.slice(2); expect(Object.is(vs._view.buffer, bs._view.buffer)).toBe(false); expect(vs._view.buffer.byteLength).toBe(2); expect(vs.get(0)).toBe(30); expect(vs.get(1)).toBe(40); expect(vs.length).toBe(2); }); it('should implement subarray', () => { const vs = bs.subarray(2); expect(Object.is(vs._view.buffer, bs._view.buffer)).toBe(true); expect(vs._view.buffer.byteLength).toBe(4); expect(vs.get(0)).toBe(30); expect(vs.get(1)).toBe(40); expect(vs.length).toBe(2); }); it('should implement reverse', () => { const vs = bs.reverse(); expect(Object.is(vs._view.buffer, bs._view.buffer)).toBe(false); expect(bs.get(0)).toBe(10); expect(bs.get(3)).toBe(40); expect(vs.get(0)).toBe(40); expect(vs.get(3)).toBe(10); }); it('should implement sort', () => { const vs = bs.reverse().sort(); expect(Object.is(vs._view.buffer, bs._view.buffer)).toBe(false); expect(bs.get(0)).toBe(10); expect(bs.get(3)).toBe(40); expect(vs.get(0)).toBe(10); expect(vs.get(3)).toBe(40); }); }); }); describe('base64 decoder', () => { const d64 = (s: string) => Bytes.from(decodeBase64(s)); describe('RFC4648 tests', () => { it('10.0', () => expect(d64("")).isPreserves(Bytes.of())); it('10.1', () => expect(d64("Zg==")).isPreserves(Bytes.of(102))); it('10.2', () => expect(d64("Zm8=")).isPreserves(Bytes.of(102, 111))); it('10.3', () => expect(d64("Zm9v")).isPreserves(Bytes.of(102, 111, 111))); it('10.4', () => expect(d64("Zm9vYg==")).isPreserves(Bytes.of(102, 111, 111, 98))); it('10.5', () => expect(d64("Zm9vYmE=")).isPreserves(Bytes.of(102, 111, 111, 98, 97))); it('10.6', () => expect(d64("Zm9vYmFy")).isPreserves(Bytes.of(102, 111, 111, 98, 97, 114))); it('10.1b', () => expect(d64("Zg")).isPreserves(Bytes.of(102))); it('10.2b', () => expect(d64("Zm8")).isPreserves(Bytes.of(102, 111))); it('10.4b', () => expect(d64("Zm9vYg")).isPreserves(Bytes.of(102, 111, 111, 98))); it('10.5b', () => expect(d64("Zm9vYmE")).isPreserves(Bytes.of(102, 111, 111, 98, 97))); }); describe('RFC4648 examples', () => { it('example0', () => expect(d64('FPucA9l+')).isPreserves(Bytes.of(0x14, 0xfb, 0x9c, 0x03, 0xd9, 0x7e))); it('example1', () => expect(d64('FPucA9k=')).isPreserves(Bytes.of(0x14, 0xfb, 0x9c, 0x03, 0xd9))); it('example1b', () => expect(d64('FPucA9k')).isPreserves(Bytes.of(0x14, 0xfb, 0x9c, 0x03, 0xd9))); it('example2', () => expect(d64('FPucAw==')).isPreserves(Bytes.of(0x14, 0xfb, 0x9c, 0x03))); it('example2b', () => expect(d64('FPucAw=')).isPreserves(Bytes.of(0x14, 0xfb, 0x9c, 0x03))); it('example2c', () => expect(d64('FPucAw')).isPreserves(Bytes.of(0x14, 0xfb, 0x9c, 0x03))); }); describe('Misc test cases', () => { it('gQ==', () => expect(d64('gQ==')).isPreserves(Bytes.of(0x81))); }); }); describe('latin1 quasi-decoder', () => { it('decodes ascii', () => expect(Bytes.fromLatin1('abc')).isPreserves(Bytes.of(97, 98, 99))); it('encodes ascii', () => expect(Bytes.of(97, 98, 99).toLatin1()).isPreserves('abc')); it('decodes unprintables', () => expect(Bytes.fromLatin1('\x00\x01a\xfe\xff')).isPreserves(Bytes.of(0, 1, 97, 254, 255))); it('encodes unprintables', () => expect(Bytes.of(0, 1, 97, 254, 255).toLatin1()).isPreserves('\x00\x01a\xfe\xff')); it('rejects out-of-bounds', () => expect(() => Bytes.fromLatin1('ac╔b')).toThrowError('Codepoint out of range')); });