169 lines
5.8 KiB
TypeScript
169 lines
5.8 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
import { StringService } from './string-service';
|
|
|
|
describe('StringService', () => {
|
|
// ----------------------------------------------------------------
|
|
// Instantiation & Static Methods
|
|
// ----------------------------------------------------------------
|
|
describe('Initialization', () => {
|
|
it('should handle string input correctly', () => {
|
|
const svc = new StringService('Hello');
|
|
expect(svc.value()).toBe('Hello');
|
|
});
|
|
|
|
it('should handle number input by converting to string', () => {
|
|
const svc = new StringService(123);
|
|
expect(svc.value()).toBe('123');
|
|
});
|
|
|
|
it('should handle null input gracefully (default to empty string)', () => {
|
|
const svc = new StringService(null);
|
|
expect(svc.value()).toBe('');
|
|
});
|
|
|
|
it('should handle undefined input gracefully', () => {
|
|
const svc = new StringService(undefined);
|
|
expect(svc.value()).toBe('');
|
|
});
|
|
|
|
it('should support static factory method .of()', () => {
|
|
const svc = StringService.of('Factory');
|
|
expect(svc.value()).toBe('Factory');
|
|
});
|
|
});
|
|
|
|
describe('random()', () => {
|
|
it('should generate string with specified length', () => {
|
|
const random = StringService.random(15);
|
|
expect(random.value()).toHaveLength(15);
|
|
});
|
|
|
|
it('should generate alphanumeric characters only', () => {
|
|
const random = StringService.random(100);
|
|
expect(random.value()).toMatch(/^[A-Za-z0-9]+$/);
|
|
});
|
|
});
|
|
|
|
// ----------------------------------------------------------------
|
|
// Core Manipulations
|
|
// ----------------------------------------------------------------
|
|
describe('Transformations', () => {
|
|
it('should convert to upperCase', () => {
|
|
expect(StringService.of('hello').upperCase().value()).toBe('HELLO');
|
|
});
|
|
|
|
it('should convert to lowerCase', () => {
|
|
expect(StringService.of('HELLO').lowerCase().value()).toBe('hello');
|
|
});
|
|
|
|
it('should trim whitespace', () => {
|
|
expect(StringService.of(' hello ').trim().value()).toBe('hello');
|
|
});
|
|
|
|
it('should support method chaining (Immutable)', () => {
|
|
const original = StringService.of(' hello ');
|
|
const modified = original.trim().upperCase();
|
|
|
|
expect(original.value()).toBe(' hello '); // Original untouched
|
|
expect(modified.value()).toBe('HELLO'); // New instance modified
|
|
});
|
|
});
|
|
|
|
describe('Capitalization', () => {
|
|
it('should capitalize first letter only', () => {
|
|
expect(StringService.of('hELLO world').capitalizeFirst().value()).toBe('Hello world');
|
|
});
|
|
|
|
it('should capitalize each word', () => {
|
|
expect(StringService.of('hello world').capitalizeEachWord().value()).toBe('Hello World');
|
|
});
|
|
|
|
it('should handle double spaces in capitalizeEachWord', () => {
|
|
// Test regex logic for splitting words
|
|
expect(StringService.of('hello world').capitalizeEachWord().value()).toBe('Hello World');
|
|
});
|
|
});
|
|
|
|
// ----------------------------------------------------------------
|
|
// Utilities (Slug, Limit, Mask)
|
|
// ----------------------------------------------------------------
|
|
describe('slugify()', () => {
|
|
it('should create valid slugs', () => {
|
|
expect(StringService.of('Hello World!').slugify().value()).toBe('hello-world');
|
|
});
|
|
|
|
it('should handle complex characters', () => {
|
|
expect(StringService.of('C# & .NET Core').slugify().value()).toBe('c-net-core');
|
|
});
|
|
|
|
it('should remove leading/trailing separators', () => {
|
|
expect(StringService.of('---Hello---').slugify().value()).toBe('hello');
|
|
});
|
|
});
|
|
|
|
describe('limit()', () => {
|
|
it('should truncate string if longer than max', () => {
|
|
expect(StringService.of('Hello World').limit(5).value()).toBe('Hello...');
|
|
});
|
|
|
|
it('should not truncate if shorter than max', () => {
|
|
expect(StringService.of('Hi').limit(5).value()).toBe('Hi');
|
|
});
|
|
|
|
it('should support custom suffix', () => {
|
|
expect(StringService.of('Hello World').limit(5, '!!!').value()).toBe('Hello!!!');
|
|
});
|
|
});
|
|
|
|
describe('mask()', () => {
|
|
it('should mask middle characters', () => {
|
|
// 0812 3456 7890 (Length 12)
|
|
// Start 4: 0812
|
|
// End 3: 890
|
|
// Middle masked: *****
|
|
expect(StringService.of('081234567890').mask(4, 3).value()).toBe('0812*****890');
|
|
});
|
|
|
|
it('should handle custom mask char', () => {
|
|
expect(StringService.of('123456').mask(2, 2, 'X').value()).toBe('12XX56');
|
|
});
|
|
|
|
it('should return original if string is shorter than visible parts', () => {
|
|
expect(StringService.of('123').mask(5, 5).value()).toBe('123');
|
|
});
|
|
});
|
|
|
|
// ----------------------------------------------------------------
|
|
// Inspection & Outputs
|
|
// ----------------------------------------------------------------
|
|
describe('Inspection & Outputs', () => {
|
|
it('should detect empty strings correctly', () => {
|
|
expect(StringService.of('').isEmpty()).toBe(true);
|
|
expect(StringService.of(' ').isEmpty()).toBe(true); // Trim check
|
|
expect(StringService.of(null).isEmpty()).toBe(true);
|
|
expect(StringService.of('a').isEmpty()).toBe(false);
|
|
});
|
|
|
|
it('should return default value with orElse', () => {
|
|
expect(StringService.of(null).orElse('Default')).toBe('Default');
|
|
expect(StringService.of('Valid').orElse('Default')).toBe('Valid');
|
|
});
|
|
|
|
it('should support native string interpolation (toString)', () => {
|
|
const name = StringService.of('World');
|
|
expect(`Hello ${name}`).toBe('Hello World');
|
|
});
|
|
|
|
it('should support JSON serialization (toJSON)', () => {
|
|
const data = {
|
|
id: 1,
|
|
name: StringService.of('Product A'),
|
|
};
|
|
|
|
// JSON.stringify automatically calls .toJSON()
|
|
const json = JSON.stringify(data);
|
|
expect(json).toBe('{"id":1,"name":"Product A"}');
|
|
});
|
|
});
|
|
});
|