UNPKG

camote-utils

Version:

A comprehensive TypeScript utility library featuring advanced string and number formatting, data structures, and algorithms

802 lines (651 loc) 26.2 kB
import { capitalize, truncate, toCamelCase, toKebabCase, toSnakeCase, slugify, wordCount, pad, format, reverse, clean, pluralize, toUpperCase, toLowerCase, chopStart, chopEnd, mask, capitalizeWords, trim, explode, toUnicodes, toHtmlEntities, swapCase, slugifyRevert } from '../src/formatters/string'; import { generateUUID } from '../src/random'; import { isUrl, isUuid, contains, exactly, } from '../src/checkers'; describe('String Formatters', () => { describe('capitalize', () => { it('should capitalize the first letter', () => { expect(capitalize('hello')).toBe('Hello') expect(capitalize('world')).toBe('World') }) it('should handle empty string', () => { expect(capitalize('')).toBe('') }) it('should handle already capitalized string', () => { expect(capitalize('Hello')).toBe('Hello') }) }) describe('truncate', () => { it('should truncate string with default ellipsis', () => { expect(truncate('Hello World', 8)).toBe('Hello...') }) it('should truncate string with custom ellipsis', () => { expect(truncate('Hello World', 8, '!')).toBe('Hello W!') }) it('should not truncate if string length is less than limit', () => { expect(truncate('Hello', 10)).toBe('Hello') }) }) describe('toCamelCase', () => { it('should convert hyphenated string to camelCase', () => { expect(toCamelCase('hello-world')).toBe('helloWorld') }) it('should convert space-separated string to camelCase', () => { expect(toCamelCase('Hello World')).toBe('helloWorld') }) it('should handle underscore-separated string', () => { expect(toCamelCase('hello_world')).toBe('helloWorld') }) }) describe('toKebabCase', () => { it('should convert camelCase to kebab-case', () => { expect(toKebabCase('helloWorld')).toBe('hello-world') }) it('should convert space-separated string to kebab-case', () => { expect(toKebabCase('Hello World')).toBe('hello-world') }) it('should handle underscore-separated string', () => { expect(toKebabCase('hello_world')).toBe('hello-world') }) }) describe('toSnakeCase', () => { it('should convert camelCase to snake_case', () => { expect(toSnakeCase('helloWorld')).toBe('hello_world') }) it('should convert space-separated string to snake_case', () => { expect(toSnakeCase('Hello World')).toBe('hello_world') }) it('should handle hyphenated string', () => { expect(toSnakeCase('hello-world')).toBe('hello_world') }) }) describe('slugify', () => { it('should convert string to URL-friendly slug', () => { expect(slugify('Hello World!')).toBe('hello-world') }) it('should handle special characters', () => { expect(slugify("What's Up?")).toBe('whats-up') }) it('should handle multiple spaces and dashes', () => { expect(slugify(' hello world ')).toBe('hello-world') }) }) describe('wordCount', () => { it('should count words in a string', () => { expect(wordCount('Hello world')).toBe(2) }) it('should handle multiple spaces', () => { expect(wordCount('Hello world test')).toBe(3) }) it('should handle empty string', () => { expect(wordCount('')).toBe(0) }) }) describe('pad', () => { it('should pad end by default', () => { expect(pad('hello', 8)).toBe('hello ') }) it('should pad start when specified', () => { expect(pad('hello', 8, '*', 'start')).toBe('***hello') }) it('should pad both sides when specified', () => { expect(pad('hello', 8, '*', 'both')).toBe('*hello**') }) it('should not pad if string length equals desired length', () => { expect(pad('hello', 5)).toBe('hello') }) }) describe('format', () => { it('should replace placeholders with values', () => { expect(format('Hello {name}!', { name: 'World' })).toBe('Hello World!') }) it('should handle multiple placeholders', () => { expect(format('{greeting} {name}!', { greeting: 'Hi', name: 'User' })) .toBe('Hi User!') }) it('should keep placeholder if value not provided', () => { expect(format('Hello {name}!', {})).toBe('Hello {name}!') }) }) describe('reverse', () => { it('should reverse a string', () => { expect(reverse('hello')).toBe('olleh') }) it('should handle empty string', () => { expect(reverse('')).toBe('') }) it('should handle palindrome', () => { expect(reverse('radar')).toBe('radar') }) }) describe('clean', () => { it('should remove extra whitespace', () => { expect(clean(' hello world ')).toBe('hello world') }) it('should handle string with only spaces', () => { expect(clean(' ')).toBe('') }) it('should handle empty string', () => { expect(clean('')).toBe('') }) }) describe('pluralize', () => { test('returns singular form when count is 1', () => { expect(pluralize('cat', 1)).toBe('cat'); expect(pluralize('dog', 1)).toBe('dog'); }); test('uses custom plural form when provided', () => { expect(pluralize('person', 2, 'people')).toBe('people'); expect(pluralize('child', 2, 'children')).toBe('children'); }); test('handles words ending in y correctly', () => { expect(pluralize('baby', 2)).toBe('babies'); expect(pluralize('toy', 2)).toBe('toys'); }); test('handles words requiring es suffix', () => { expect(pluralize('box', 2)).toBe('boxes'); expect(pluralize('church', 2)).toBe('churches'); expect(pluralize('buzz', 2)).toBe('buzzes'); }); test('adds s for regular plurals', () => { expect(pluralize('cat', 2)).toBe('cats'); expect(pluralize('dog', 2)).toBe('dogs'); }); test('uses plural form when count is undefined', () => { expect(pluralize('cat')).toBe('cats'); expect(pluralize('person', undefined, 'people')).toBe('people'); }); }); describe('isUuid', () => { it('should return true for valid UUIDs', () => { expect(isUuid('123e4567-e89b-12d3-a456-426614174000')).toBe(true) expect(isUuid('550e8400-e29b-41d4-a716-446655440000')).toBe(true) expect(isUuid('6ba7b810-9dad-41d4-80b4-00c04fd430c8')).toBe(true) }) it('should return false for invalid UUIDs', () => { expect(isUuid('not-a-uuid')).toBe(false) expect(isUuid('http:/example.com')).toBe(false) expect(isUuid('')).toBe(false) expect(isUuid('123e4567-e89b-12d3-a456')).toBe(false) expect(isUuid('123e4567-e89b-12d3-a456-42661417400')).toBe(false) expect(isUuid('123e4567-e89b-12d3-a456-4266141740000')).toBe(false) }) }) describe('toUpperCase', () => { it('should convert string to uppercase', () => { expect(toUpperCase('hello')).toBe('HELLO') expect(toUpperCase('Hello World')).toBe('HELLO WORLD') }) it('should handle empty string', () => { expect(toUpperCase('')).toBe('') }) it('should support locale-specific uppercase conversion', () => { expect(toUpperCase('philippines', 'en-PH')).toBe('PHILIPPINES') }) }) describe('toLowerCase', () => { it('should convert string to lowercase', () => { expect(toLowerCase('HELLO')).toBe('hello') expect(toLowerCase('Hello World')).toBe('hello world') }) it('should handle empty string', () => { expect(toLowerCase('')).toBe('') }) it('should support locale-specific lowercase conversion', () => { expect(toLowerCase('PHILIPPINES', 'en-PH')).toBe('philippines') }) }) describe('chopStart', () => { it('should remove one character from start by default', () => { expect(chopStart('hello')).toBe('ello') expect(chopStart('world')).toBe('orld') }) it('should remove specified number of characters from start', () => { expect(chopStart('hello', 2)).toBe('llo') expect(chopStart('world', 3)).toBe('ld') }) it('should handle empty string', () => { expect(chopStart('')).toBe('') }) it('should handle count greater than string length', () => { expect(chopStart('hello', 10)).toBe('') }) it('should handle zero or negative count', () => { expect(chopStart('hello', 0)).toBe('hello') expect(chopStart('hello', -1)).toBe('hello') }) }) describe('chopEnd', () => { it('should remove one character from end by default', () => { expect(chopEnd('hello')).toBe('hell') expect(chopEnd('world')).toBe('worl') }) it('should remove specified number of characters from end', () => { expect(chopEnd('hello', 2)).toBe('hel') expect(chopEnd('world', 3)).toBe('wo') }) it('should handle empty string', () => { expect(chopEnd('')).toBe('') }) it('should handle count greater than string length', () => { expect(chopEnd('hello', 10)).toBe('') }) it('should handle zero or negative count', () => { expect(chopEnd('hello', 0)).toBe('hello') expect(chopEnd('hello', -1)).toBe('hello') }) }) describe('contains', () => { it('should find substring with case sensitivity by default', () => { expect(contains('Hello World', 'World')).toBe(true) expect(contains('Hello World', 'world')).toBe(false) expect(contains('Hello World', 'lo')).toBe(true) }) it('should find substring ignoring case when specified', () => { expect(contains('Hello World', 'world', false)).toBe(true) expect(contains('Hello World', 'HELLO', false)).toBe(true) expect(contains('HELLO WORLD', 'hello', false)).toBe(true) }) it('should handle empty strings', () => { expect(contains('', 'test')).toBe(false) expect(contains('test', '')).toBe(false) expect(contains('', '')).toBe(false) }) it('should return false for non-existing substrings', () => { expect(contains('Hello World', 'xyz')).toBe(false) expect(contains('Hello World', 'xyz', false)).toBe(false) }) }) describe('exactly', () => { it('should match exact strings with case sensitivity by default', () => { expect(exactly('Hello', 'Hello')).toBe(true) expect(exactly('Hello', 'hello')).toBe(false) expect(exactly('World', 'World')).toBe(true) }) it('should match strings ignoring case when specified', () => { expect(exactly('Hello', 'hello', false)).toBe(true) expect(exactly('WORLD', 'world', false)).toBe(true) expect(exactly('HeLLo', 'hEllO', false)).toBe(true) }) it('should handle empty strings', () => { expect(exactly('', '', true)).toBe(true) expect(exactly('', '', false)).toBe(true) expect(exactly('test', '', false)).toBe(false) expect(exactly('', 'test', false)).toBe(false) }) it('should handle undefined values', () => { expect(exactly(undefined as any, 'test')).toBe(false); expect(exactly('test', undefined as any)).toBe(false); expect(exactly(undefined as any, undefined as any)).toBe(false); }); it('should handle different strings', () => { expect(exactly('Hello', 'World', true)).toBe(false) expect(exactly('Hello', 'World', false)).toBe(false) expect(exactly('test', 'testing', true)).toBe(false) }) }) describe('generateUUID', () => { it('should generate valid UUID v4 strings', () => { const uuid1 = generateUUID() const uuid2 = generateUUID() // Should be valid UUIDs expect(isUuid(uuid1)).toBe(true) expect(isUuid(uuid2)).toBe(true) // Should be different UUIDs expect(uuid1).not.toBe(uuid2) }) it('should generate UUIDs with correct format', () => { const uuid = generateUUID() // Check UUID v4 format expect(uuid).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i) // Version should be 4 expect(uuid.charAt(14)).toBe('4') // Variant should be 8, 9, a, or b expect('89ab').toContain(uuid.charAt(19)) }) it('should generate multiple unique UUIDs', () => { const uuids = new Set(Array.from({ length: 1000 }, () => generateUUID())) expect(uuids.size).toBe(1000) // All should be unique }) }) describe('isUrl', () => { it('should return true for valid URLs', () => { expect(isUrl('https://example.com')).toBe(true) expect(isUrl('http://localhost:3000')).toBe(true) expect(isUrl('https://sub.domain.com/path?query=1#hash')).toBe(true) expect(isUrl('ftp://ftp.example.com')).toBe(true) }) it('should return false for invalid URLs', () => { expect(isUrl('not-a-url')).toBe(false) expect(isUrl('http:/example.com')).toBe(false) expect(isUrl('')).toBe(false) expect(isUrl('example.com')).toBe(false) }) }) describe('toUpperCase', () => { it('should convert string to uppercase', () => { expect(toUpperCase('hello')).toBe('HELLO'); expect(toUpperCase('world')).toBe('WORLD'); }); }); describe('toLowerCase', () => { it('should convert string to lowercase', () => { expect(toLowerCase('HELLO')).toBe('hello'); expect(toLowerCase('WORLD')).toBe('world'); }); }); describe('chopStart', () => { it('should remove characters from the start of the string', () => { expect(chopStart('hello', 2)).toBe('llo'); expect(chopStart('world', 3)).toBe('ld'); }); }); describe('chopEnd', () => { it('should remove characters from the end of the string', () => { expect(chopEnd('hello', 2)).toBe('hel'); expect(chopEnd('world', 3)).toBe('wo'); }); }); describe('contains', () => { it('should check if string contains a substring', () => { expect(contains('hello world', 'world')).toBe(true); expect(contains('hello world', 'WORLD', false)).toBe(true); expect(contains('hello world', 'WORLD')).toBe(false); }); }); describe('exactly', () => { it('should check if two strings match exactly', () => { expect(exactly('hello', 'hello')).toBe(true); expect(exactly('hello', 'HELLO')).toBe(false); expect(exactly('hello', 'HELLO', false)).toBe(true); }); }); describe('mask', () => { it('should mask all but the first 6 characters by default', () => { expect(mask('1234567890')).toBe('123456****'); }); it('should mask with a custom character', () => { expect(mask('1234567890', '#')).toBe('123456####'); }); it('should mask correctly with specified visible count', () => { expect(mask('1234567890', '*', 4)).toBe('1234******'); }); it('should mask correctly with start position', () => { expect(mask('1234567890', '*', 6, 'start')).toBe('****567890'); }); it('should handle empty string', () => { expect(mask('')).toBe(''); }); it('should show all characters if visibleCount is greater than string length', () => { expect(mask('Hi')).toBe('Hi'); }); it('should not mask if active is false', () => { expect(mask('1234567890', '*', 6, 'start', false)).toBe('1234567890'); }); it('should mask correctly with end position', () => { expect(mask('1234567890', '*', 16, 'end')).toBe('1234567890'); }); }); describe('trim', () => { it('should trim whitespace from both ends of a string', () => { const input = ' hello world '; const expectedOutput = 'hello world'; expect(trim(input)).toBe(expectedOutput); }); it('should handle an empty string', () => { const input = ''; const expectedOutput = ''; expect(trim(input)).toBe(expectedOutput); }); it('should not change a string without whitespace', () => { const input = 'hello'; const expectedOutput = 'hello'; expect(trim(input)).toBe(expectedOutput); }); }); describe('explode', () => { it('should split a string into an array of substrings based on a specified delimiter', () => { const result = explode("Hello,World,Again", ","); expect(result).toEqual(["Hello", "World", "Again"]); }); it('should return an array with a single element for a string without delimiters', () => { const result = explode("HelloWorld", ","); expect(result).toEqual(["HelloWorld"]); }); it('should handle consecutive delimiters', () => { const result = explode("Hello,,World", ","); expect(result).toEqual(["Hello", "", "World"]); }); it('should return an empty array for an empty string', () => { const result = explode("", ","); expect(result).toEqual([]); }); it('should return the original string in an array if the delimiter is not found', () => { const result = explode("HelloWorld", ","); expect(result).toEqual(["HelloWorld"]); }); it('should handle a string with leading and trailing delimiters', () => { const result = explode(",Hello,World,Again,", ","); expect(result).toEqual(["", "Hello", "World", "Again", ""]); }); it('should handle a string with multiple delimiters in a row', () => { const result = explode("Hello,,,World", ","); expect(result).toEqual(["Hello", "", "", "World"]); }); it('should handle a single character as a delimiter', () => { const result = explode("a-b-c", "-"); expect(result).toEqual(["a", "b", "c"]); }); it('should handle a longer substring as a delimiter', () => { const result = explode("Hello---World---Again", "---"); expect(result).toEqual(["Hello", "World", "Again"]); }); it('should handle a string with special characters', () => { const result = explode("Hello@World#Again$,", ","); expect(result).toEqual(["Hello@World#Again$", ""]); }); it('should handle a string with leading and trailing delimiters', () => { const result = explode(",Hello,World,Again,", ","); expect(result).toEqual(["", "Hello", "World", "Again", ""]); }); it('should handle a string with multiple delimiters in a row', () => { const result = explode("Hello,,,World", ","); expect(result).toEqual(["Hello", "", "", "World"]); }); it('should handle a single character as a delimiter', () => { const result = explode("a-b-c", "-"); expect(result).toEqual(["a", "b", "c"]); }); it('should handle a longer substring as a delimiter', () => { const result = explode("Hello---World---Again", "---"); expect(result).toEqual(["Hello", "World", "Again"]); }); it('should handle a string with special characters', () => { const result = explode("Hello@World#Again$,", ","); expect(result).toEqual(["Hello@World#Again$", ""]); }); }); describe('capitalizeWords', () => { it('should capitalize the first letter of each word', () => { const input = 'hello world'; const expectedOutput = 'Hello World'; expect(capitalizeWords(input)).toBe(expectedOutput); }); it('should handle an empty string', () => { const input = ''; const expectedOutput = ''; expect(capitalizeWords(input)).toBe(expectedOutput); }); it('should handle a single word', () => { const input = 'test'; const expectedOutput = 'Test'; expect(capitalizeWords(input)).toBe(expectedOutput); }); }); describe('Unicodes', () => { it('should turn the character into unicode', () => { const input = 'Hello World'; const expectedOutput = '\\u{0048}\\u{0065}\\u{006C}\\u{006C}\\u{006F}\\u{0020}\\u{0057}\\u{006F}\\u{0072}\\u{006C}\\u{0064}'; expect(toUnicodes(input)).toBe(expectedOutput); }) it('should turn the converted unicode to original character', () => { const input = 'Hello World'; const expectedOutput = toUnicodes(input).replace(/\\u{([0-9A-F]+)}/g, (_, hex) => { return String.fromCodePoint(parseInt(hex, 16)); // Convert back to character }); expect(input).toBe(expectedOutput); }) it('should handle an empty string', () => { const input = ''; const expectedOutput = '' expect(toUnicodes(input)).toBe(expectedOutput); }) it('should not turn the excluded character as string into unicode', () => { const input = 'Hello World'; const exclude = 'Hed'; const expectedOutput = 'He\\u{006C}\\u{006C}\\u{006F}\\u{0020}\\u{0057}\\u{006F}\\u{0072}\\u{006C}d'; expect(toUnicodes(input, exclude)).toBe(expectedOutput); }) it('should not turn the excluded character from string array into unicode', () => { const input = 'Hello World'; const exclude = ['H', 'e', 'd']; const expectedOutput = 'He\\u{006C}\\u{006C}\\u{006F}\\u{0020}\\u{0057}\\u{006F}\\u{0072}\\u{006C}d'; expect(toUnicodes(input, exclude)).toBe(expectedOutput); }) }) describe('HTML Entities', () => { it('should turn the character into html entities', () => { const input = 'Hello World'; const expectedOutput = 'Hello World'; expect(toHtmlEntities(input)).toBe(expectedOutput); }) it('should turn the converted html entities to original character', () => { const input = 'Hello World'; const expectedOutput = toHtmlEntities(input).replace(/&#(\d+);/g, (_ , numStr) => { const codePoint = parseInt(numStr, 10); // Convert to base 10 return String.fromCodePoint(codePoint); // Convert back to character }); expect(input).toBe(expectedOutput); }) it('should handle an empty string', () => { const input = ''; const expectedOutput = '' expect(toHtmlEntities(input)).toBe(expectedOutput); }) it('should not turn the excluded character as string into html entities', () => { const input = 'Hello World'; const exclude = 'Hed'; const expectedOutput = 'Hello World'; expect(toHtmlEntities(input, exclude)).toBe(expectedOutput); }) it('should not turn the excluded character from string array into html entities', () => { const input = 'Hello World'; const exclude = ['H', 'e', 'd']; const expectedOutput = 'Hello World'; expect(toHtmlEntities(input, exclude)).toBe(expectedOutput); }) }) }) describe('swapCase', () => { it('should swap the case of each character in the string', () => { const input = 'Hello World'; const expectedOutput = 'hELLO wORLD'; expect(swapCase(input)).toBe(expectedOutput); }); it('should swap the case for all characters in a mixed case string', () => { const input = 'JavaScript'; const expectedOutput = 'jAVAsCRIPT'; expect(swapCase(input)).toBe(expectedOutput); }); it('should leave non-alphabetic characters unchanged', () => { const input = '123 ABC!'; const expectedOutput = '123 abc!'; expect(swapCase(input)).toBe(expectedOutput); }); it('should return an empty string when given an empty string', () => { const input = ''; const expectedOutput = ''; expect(swapCase(input)).toBe(expectedOutput); }); it('should swap case for strings with special characters and spaces', () => { const input = 'A!b@ C#d$'; const expectedOutput = 'a!B@ c#D$'; expect(swapCase(input)).toBe(expectedOutput); }); it('should handle a string with only lowercase characters', () => { const input = 'lowercase'; const expectedOutput = 'LOWERCASE'; expect(swapCase(input)).toBe(expectedOutput); }); it('should handle a string with only uppercase characters', () => { const input = 'UPPERCASE'; const expectedOutput = 'uppercase'; expect(swapCase(input)).toBe(expectedOutput); }); }); describe('slugifyRevert', () => { it('should convert a simple slug to title case', () => { const input = 'hello-world'; const expectedOutput = 'Hello World'; expect(slugifyRevert(input)).toBe(expectedOutput); }); it('should handle multiple hyphens and underscores', () => { const input = 'hello--world___test'; const expectedOutput = 'Hello World Test'; expect(slugifyRevert(input)).toBe(expectedOutput); }); it('should handle empty string', () => { const input = ''; const expectedOutput = ''; expect(slugifyRevert(input)).toBe(expectedOutput); }); it('should handle string with numbers', () => { const input = 'hello-world-2025'; const expectedOutput = 'Hello World 2025'; expect(slugifyRevert(input)).toBe(expectedOutput); }); it('should handle string with special characters', () => { const input = 'hello-world-2025!'; const expectedOutput = 'Hello World 2025!'; expect(slugifyRevert(input)).toBe(expectedOutput); }); it('should handle single word slug', () => { const input = 'hello'; const expectedOutput = 'Hello'; expect(slugifyRevert(input)).toBe(expectedOutput); }); it('should handle mixed case input', () => { const input = 'hElLo-wOrLd'; const expectedOutput = 'Hello World'; expect(slugifyRevert(input)).toBe(expectedOutput); }); });