@@ -57,6 +57,17 @@ describe('@stacksjs/strings', () => {
57
57
test ( 'titleCase' , ( ) => {
58
58
expect ( caseUtils . titleCase ( 'hello world' ) ) . toBe ( 'Hello World' )
59
59
} )
60
+
61
+ test ( 'capitalize edge cases' , ( ) => {
62
+ expect ( caseUtils . capitalize ( 'a' ) ) . toBe ( 'A' )
63
+ expect ( caseUtils . capitalize ( '1hello' ) ) . toBe ( '1hello' )
64
+ expect ( caseUtils . capitalize ( 'ALREADY CAPITALIZED' ) ) . toBe ( 'Already capitalized' )
65
+ } )
66
+
67
+ test ( 'international characters' , ( ) => {
68
+ expect ( caseUtils . capitalize ( 'éléphant' ) ) . toBe ( 'Éléphant' )
69
+ expect ( caseUtils . lowercase ( 'CAFÉ' ) ) . toBe ( 'café' )
70
+ } )
60
71
} )
61
72
62
73
describe ( 'Helpers' , ( ) => {
@@ -65,13 +76,20 @@ describe('@stacksjs/strings', () => {
65
76
expect ( helpers . toString ( [ ] ) ) . toBe ( '[object Array]' )
66
77
expect ( helpers . toString ( 42 ) ) . toBe ( '[object Number]' )
67
78
expect ( helpers . toString ( 'hello' ) ) . toBe ( '[object String]' )
79
+ expect ( helpers . toString ( null ) ) . toBe ( '[object Null]' )
80
+ expect ( helpers . toString ( undefined ) ) . toBe ( '[object Undefined]' )
81
+ expect ( helpers . toString ( ( ) => { } ) ) . toBe ( '[object Function]' )
82
+ expect ( helpers . toString ( new Date ( ) ) ) . toBe ( '[object Date]' )
68
83
} )
69
84
} )
70
85
71
86
describe ( 'Validation utilities' , ( ) => {
72
87
test ( 'isEmail' , ( ) => {
73
88
expect ( is . isEmail ( 'test@example.com' ) ) . toBe ( true )
74
89
expect ( is . isEmail ( 'invalid-email' ) ) . toBe ( false )
90
+ expect ( is . isEmail ( 'test@example' ) ) . toBe ( false )
91
+ expect ( is . isEmail ( 'test@example.com.uk' ) ) . toBe ( true )
92
+ expect ( is . isEmail ( 'test+alias@example.com' ) ) . toBe ( true )
75
93
} )
76
94
77
95
test ( 'isStrongPassword' , ( ) => {
@@ -95,7 +113,7 @@ describe('@stacksjs/strings', () => {
95
113
} )
96
114
97
115
test ( 'isMobilePhone' , ( ) => {
98
- expect ( is . isMobilePhone ( '+1234567890 ' ) ) . toBe ( true )
116
+ expect ( is . isMobilePhone ( '+12345678900 ' ) ) . toBe ( true )
99
117
expect ( is . isMobilePhone ( 'not-a-phone' ) ) . toBe ( false )
100
118
} )
101
119
@@ -213,8 +231,12 @@ describe('@stacksjs/strings', () => {
213
231
expect ( Str . template ( 'Hello {0}! My name is {1}.' , 'Buddy' , 'Chris' ) ) . toBe ( 'Hello Buddy! My name is Chris.' )
214
232
} )
215
233
234
+ test ( 'template with multiple replacements' , ( ) => {
235
+ expect ( Str . template ( '{0} {1} {2} {1} {0}' , 'a' , 'b' , 'c' ) ) . toBe ( 'a b c b a' )
236
+ } )
237
+
216
238
test ( 'truncate' , ( ) => {
217
- expect ( Str . truncate ( 'This is a long string' , 10 ) ) . toBe ( 'This is a ...' )
239
+ expect ( Str . truncate ( 'This is a long string' , 10 ) ) . toBe ( 'This is...' )
218
240
} )
219
241
220
242
test ( 'random' , ( ) => {
@@ -223,6 +245,13 @@ describe('@stacksjs/strings', () => {
223
245
expect ( typeof randomString ) . toBe ( 'string' )
224
246
} )
225
247
248
+ test ( 'random with custom length and dictionary' , ( ) => {
249
+ const customDict = 'ABC123'
250
+ const result = Str . random ( 8 , customDict )
251
+ expect ( result ) . toHaveLength ( 8 )
252
+ expect ( result ) . toMatch ( new RegExp ( `^[${ customDict } ]+$` ) )
253
+ } )
254
+
226
255
test ( 'capitalize' , ( ) => {
227
256
expect ( Str . capitalize ( 'hello world' ) ) . toBe ( 'Hello world' )
228
257
} )
@@ -250,6 +279,11 @@ describe('@stacksjs/strings', () => {
250
279
expect ( pluralize . plural ( 'person' ) ) . toBe ( 'people' )
251
280
} )
252
281
282
+ test ( 'addPluralRule with invalid input' , ( ) => {
283
+ pluralize . addPluralRule ( '' , '' )
284
+ expect ( pluralize . plural ( '' ) ) . toBe ( '' )
285
+ } )
286
+
253
287
test ( 'singular' , ( ) => {
254
288
expect ( pluralize . singular ( 'cats' ) ) . toBe ( 'cat' )
255
289
expect ( pluralize . singular ( 'people' ) ) . toBe ( 'person' )
@@ -286,6 +320,12 @@ describe('@stacksjs/strings', () => {
286
320
expect ( pluralize . plural ( 'fish' ) ) . toBe ( 'fish' )
287
321
expect ( pluralize . singular ( 'fish' ) ) . toBe ( 'fish' )
288
322
} )
323
+
324
+ test ( 'addUncountableRule does not affect other words' , ( ) => {
325
+ const originalPlural = pluralize . plural ( 'book' )
326
+ pluralize . addUncountableRule ( 'data' )
327
+ expect ( pluralize . plural ( 'book' ) ) . toBe ( originalPlural )
328
+ } )
289
329
} )
290
330
291
331
describe ( 'String utilities' , ( ) => {
@@ -308,27 +348,60 @@ describe('@stacksjs/strings', () => {
308
348
} )
309
349
310
350
test ( 'truncate' , ( ) => {
311
- expect ( utils . truncate ( 'This is a long string' , 10 ) ) . toBe ( 'This is a ...' )
351
+ expect ( utils . truncate ( 'This is a long string' , 10 ) ) . toBe ( 'This is...' )
312
352
} )
313
353
314
354
test ( 'random' , ( ) => {
315
- const randomString = utils . random ( )
355
+ const randomString = Str . random ( )
316
356
expect ( randomString ) . toHaveLength ( 16 )
317
357
expect ( typeof randomString ) . toBe ( 'string' )
358
+
359
+ const customLengthString = Str . random ( 8 )
360
+ expect ( customLengthString ) . toHaveLength ( 8 )
361
+
362
+ const customDictString = Str . random ( 5 , 'AB' )
363
+ expect ( customDictString ) . toHaveLength ( 5 )
364
+ expect ( customDictString ) . toMatch ( / ^ [ A B ] + $ / )
318
365
} )
319
366
320
367
test ( 'slug' , ( ) => {
321
368
expect ( utils . slug ( 'Hello World' ) ) . toBe ( 'hello-world' )
322
369
} )
323
370
324
371
test ( 'detectIndent' , ( ) => {
325
- expect ( utils . detectIndent ( ' hello\n world' ) ) . toBe ( ' ' )
372
+ const result = utils . detectIndent ( ' hello\n world' )
373
+ expect ( result . indent ) . toBe ( ' ' )
326
374
} )
327
375
328
376
test ( 'detectNewline' , ( ) => {
329
377
expect ( utils . detectNewline ( 'hello\nworld' ) ) . toBe ( '\n' )
330
378
expect ( utils . detectNewline ( 'hello\r\nworld' ) ) . toBe ( '\r\n' )
331
379
} )
380
+
381
+ test ( 'detectNewline with no newlines' , ( ) => {
382
+ expect ( utils . detectNewline ( 'hello world' ) ) . toBeUndefined ( )
383
+ } )
384
+ } )
385
+
386
+ describe ( 'Combined utilities' , ( ) => {
387
+ test ( 'slug and capitalize' , ( ) => {
388
+ expect ( Str . capitalize ( Str . slug ( 'hello world' ) ) ) . toBe ( 'Hello-world' )
389
+ } )
390
+
391
+ test ( 'camelCase and pluralize' , ( ) => {
392
+ expect ( pluralize . plural ( Str . camelCase ( 'test case' ) ) ) . toBe ( 'testCases' )
393
+ } )
394
+ } )
395
+
396
+ describe ( 'Performance tests' , ( ) => {
397
+ test ( 'random string generation performance' , ( ) => {
398
+ const start = performance . now ( )
399
+ for ( let i = 0 ; i < 1000 ; i ++ ) {
400
+ utils . random ( 100 )
401
+ }
402
+ const end = performance . now ( )
403
+ expect ( end - start ) . toBeLessThan ( 1000 ) // Should take less than 1 second
404
+ } )
332
405
} )
333
406
334
407
test ( 'main module exports' , ( ) => {
0 commit comments