test: add unit tests for image, utils, and credentials modules (22 cases)
This commit is contained in:
61
src/lib/__tests__/credentials.test.ts
Normal file
61
src/lib/__tests__/credentials.test.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
||||
import { getStoredCredentials, storeCredentials, clearCredentials } from '../credentials';
|
||||
|
||||
// Mock localStorage
|
||||
const store: Record<string, string> = {};
|
||||
const localStorageMock = {
|
||||
getItem: vi.fn((key: string) => store[key] ?? null),
|
||||
setItem: vi.fn((key: string, value: string) => { store[key] = value; }),
|
||||
removeItem: vi.fn((key: string) => { delete store[key]; }),
|
||||
};
|
||||
|
||||
Object.defineProperty(globalThis, 'localStorage', { value: localStorageMock });
|
||||
|
||||
beforeEach(() => {
|
||||
for (const key of Object.keys(store)) delete store[key];
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('getStoredCredentials', () => {
|
||||
it('returns null when nothing stored', () => {
|
||||
expect(getStoredCredentials()).toBeNull();
|
||||
});
|
||||
|
||||
it('returns credentials when valid JSON stored', () => {
|
||||
store['pinchchat_credentials'] = JSON.stringify({ url: 'wss://gw.test', token: 'abc' });
|
||||
expect(getStoredCredentials()).toEqual({ url: 'wss://gw.test', token: 'abc' });
|
||||
});
|
||||
|
||||
it('returns null for malformed JSON', () => {
|
||||
store['pinchchat_credentials'] = 'not-json';
|
||||
expect(getStoredCredentials()).toBeNull();
|
||||
});
|
||||
|
||||
it('returns null if url is missing', () => {
|
||||
store['pinchchat_credentials'] = JSON.stringify({ token: 'abc' });
|
||||
expect(getStoredCredentials()).toBeNull();
|
||||
});
|
||||
|
||||
it('returns null if token is missing', () => {
|
||||
store['pinchchat_credentials'] = JSON.stringify({ url: 'wss://gw' });
|
||||
expect(getStoredCredentials()).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('storeCredentials', () => {
|
||||
it('stores credentials as JSON', () => {
|
||||
storeCredentials('wss://gw', 'tok');
|
||||
expect(localStorageMock.setItem).toHaveBeenCalledWith(
|
||||
'pinchchat_credentials',
|
||||
JSON.stringify({ url: 'wss://gw', token: 'tok' }),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('clearCredentials', () => {
|
||||
it('removes the key from localStorage', () => {
|
||||
store['pinchchat_credentials'] = 'something';
|
||||
clearCredentials();
|
||||
expect(localStorageMock.removeItem).toHaveBeenCalledWith('pinchchat_credentials');
|
||||
});
|
||||
});
|
||||
32
src/lib/__tests__/image.test.ts
Normal file
32
src/lib/__tests__/image.test.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { buildImageSrc } from '../image';
|
||||
|
||||
describe('buildImageSrc', () => {
|
||||
it('returns URL when url is provided', () => {
|
||||
expect(buildImageSrc('image/png', undefined, 'https://example.com/img.png'))
|
||||
.toBe('https://example.com/img.png');
|
||||
});
|
||||
|
||||
it('prefers url over base64 data', () => {
|
||||
expect(buildImageSrc('image/png', 'abc123', 'https://example.com/img.png'))
|
||||
.toBe('https://example.com/img.png');
|
||||
});
|
||||
|
||||
it('builds data URL from base64 data', () => {
|
||||
expect(buildImageSrc('image/png', 'abc123'))
|
||||
.toBe('data:image/png;base64,abc123');
|
||||
});
|
||||
|
||||
it('builds data URL for jpeg', () => {
|
||||
expect(buildImageSrc('image/jpeg', 'xyz'))
|
||||
.toBe('data:image/jpeg;base64,xyz');
|
||||
});
|
||||
|
||||
it('returns empty string when neither url nor data provided', () => {
|
||||
expect(buildImageSrc('image/png')).toBe('');
|
||||
});
|
||||
|
||||
it('returns empty string with undefined data and no url', () => {
|
||||
expect(buildImageSrc('image/webp', undefined, undefined)).toBe('');
|
||||
});
|
||||
});
|
||||
52
src/lib/__tests__/utils.test.ts
Normal file
52
src/lib/__tests__/utils.test.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { cn, genId, genIdempotencyKey } from '../utils';
|
||||
|
||||
describe('cn', () => {
|
||||
it('merges class names', () => {
|
||||
expect(cn('foo', 'bar')).toBe('foo bar');
|
||||
});
|
||||
|
||||
it('handles conditional classes', () => {
|
||||
const showHidden = false;
|
||||
expect(cn('base', showHidden && 'hidden', 'extra')).toBe('base extra');
|
||||
});
|
||||
|
||||
it('resolves tailwind conflicts (twMerge)', () => {
|
||||
// twMerge deduplicates conflicting tailwind utilities
|
||||
expect(cn('p-4', 'p-2')).toBe('p-2');
|
||||
});
|
||||
|
||||
it('handles empty input', () => {
|
||||
expect(cn()).toBe('');
|
||||
});
|
||||
|
||||
it('handles undefined and null values', () => {
|
||||
expect(cn('a', undefined, null, 'b')).toBe('a b');
|
||||
});
|
||||
});
|
||||
|
||||
describe('genId', () => {
|
||||
it('generates unique ids with default prefix', () => {
|
||||
const a = genId();
|
||||
const b = genId();
|
||||
expect(a).toMatch(/^req-\d+-\d+$/);
|
||||
expect(a).not.toBe(b);
|
||||
});
|
||||
|
||||
it('uses custom prefix', () => {
|
||||
expect(genId('msg')).toMatch(/^msg-\d+-\d+$/);
|
||||
});
|
||||
});
|
||||
|
||||
describe('genIdempotencyKey', () => {
|
||||
it('returns a non-empty string', () => {
|
||||
const key = genIdempotencyKey();
|
||||
expect(key.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('generates unique keys', () => {
|
||||
const a = genIdempotencyKey();
|
||||
const b = genIdempotencyKey();
|
||||
expect(a).not.toBe(b);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user