@@ -12,7 +12,7 @@ import {
1212 ProcessState ,
1313 RegisterWebHookRequest ,
1414 WebHook ,
15- WebHookEventType
15+ WebHookEventType ,
1616} from './domain' ;
1717import { HttpClient } from './http' ;
1818
@@ -341,6 +341,153 @@ describe('Client', () => {
341341 expect ( result ) . toBe ( undefined ) ;
342342 } ) ;
343343
344+ // JWT Authentication Tests
345+ describe ( 'Client with JWT Authentication' , ( ) => {
346+ let client : Client ;
347+ let mockHttpClient : HttpClient ;
348+ const jwtToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ' ;
349+
350+ beforeEach ( ( ) => {
351+ mockHttpClient = {
352+ get : jest . fn ( ) ,
353+ post : jest . fn ( ) ,
354+ put : jest . fn ( ) ,
355+ patch : jest . fn ( ) ,
356+ delete : jest . fn ( ) ,
357+ } as unknown as HttpClient ;
358+
359+ client = new Client ( '' , jwtToken , mockHttpClient ) ;
360+ } ) ;
361+
362+ it ( 'creates client with JWT authentication' , ( ) => {
363+ expect ( client ) . toBeDefined ( ) ;
364+ } ) ;
365+
366+ it ( 'sends a message with JWT authentication' , async ( ) => {
367+ const message : Message = {
368+ message : 'Hello' ,
369+ phoneNumbers : [ '+1234567890' ] ,
370+ } ;
371+ const expectedState : MessageState = {
372+ id : '123' ,
373+ state : ProcessState . Pending ,
374+ recipients : [
375+ {
376+ phoneNumber : '+1234567890' ,
377+ state : ProcessState . Pending ,
378+ }
379+ ]
380+ } ;
381+
382+ ( mockHttpClient . post as jest . Mock ) . mockResolvedValue ( expectedState ) ;
383+
384+ const result = await client . send ( message ) ;
385+
386+ expect ( mockHttpClient . post ) . toHaveBeenCalledWith (
387+ `${ BASE_URL } /message` ,
388+ message ,
389+ {
390+ "Content-Type" : "application/json" ,
391+ "User-Agent" : "android-sms-gateway/3.0 (client; js)" ,
392+ Authorization : `Bearer ${ jwtToken } ` ,
393+ } ,
394+ ) ;
395+ expect ( result ) . toBe ( expectedState ) ;
396+ } ) ;
397+
398+ it ( 'gets the state of a message with JWT authentication' , async ( ) => {
399+ const messageId = '123' ;
400+ const expectedState : MessageState = {
401+ id : '123' ,
402+ state : ProcessState . Pending ,
403+ recipients : [
404+ {
405+ phoneNumber : '+1234567890' ,
406+ state : ProcessState . Pending ,
407+ }
408+ ]
409+ } ;
410+
411+ ( mockHttpClient . get as jest . Mock ) . mockResolvedValue ( expectedState ) ;
412+
413+ const result = await client . getState ( messageId ) ;
414+
415+ expect ( mockHttpClient . get ) . toHaveBeenCalledWith (
416+ `${ BASE_URL } /message/${ messageId } ` ,
417+ {
418+ "User-Agent" : "android-sms-gateway/3.0 (client; js)" ,
419+ Authorization : `Bearer ${ jwtToken } ` ,
420+ } ,
421+ ) ;
422+ expect ( result ) . toBe ( expectedState ) ;
423+ } ) ;
424+
425+ it ( 'throws error when JWT token is missing' , ( ) => {
426+ expect ( ( ) => {
427+ new Client ( '' , '' , mockHttpClient ) ;
428+ } ) . toThrow ( 'Token is required for JWT authentication' ) ;
429+ } ) ;
430+ } ) ;
431+
432+ // Backward Compatibility Tests
433+ describe ( 'Client Backward Compatibility' , ( ) => {
434+ let client : Client ;
435+ let mockHttpClient : HttpClient ;
436+
437+ beforeEach ( ( ) => {
438+ mockHttpClient = {
439+ get : jest . fn ( ) ,
440+ post : jest . fn ( ) ,
441+ put : jest . fn ( ) ,
442+ patch : jest . fn ( ) ,
443+ delete : jest . fn ( ) ,
444+ } as unknown as HttpClient ;
445+ client = new Client ( 'login' , 'password' , mockHttpClient ) ;
446+ } ) ;
447+
448+ it ( 'creates client with Basic Auth using legacy constructor' , ( ) => {
449+ expect ( client ) . toBeDefined ( ) ;
450+ } ) ;
451+
452+ it ( 'sends a message with Basic Auth using legacy constructor' , async ( ) => {
453+ const message : Message = {
454+ message : 'Hello' ,
455+ phoneNumbers : [ '+1234567890' ] ,
456+ } ;
457+ const expectedState : MessageState = {
458+ id : '123' ,
459+ state : ProcessState . Pending ,
460+ recipients : [
461+ {
462+ phoneNumber : '+1234567890' ,
463+ state : ProcessState . Pending ,
464+ }
465+ ]
466+ } ;
467+
468+ ( mockHttpClient . post as jest . Mock ) . mockResolvedValue ( expectedState ) ;
469+
470+ const result = await client . send ( message ) ;
471+
472+ expect ( mockHttpClient . post ) . toHaveBeenCalledWith (
473+ `${ BASE_URL } /message` ,
474+ message ,
475+ {
476+ "Content-Type" : "application/json" ,
477+ "User-Agent" : "android-sms-gateway/3.0 (client; js)" ,
478+ Authorization : expect . stringMatching ( / ^ B a s i c / ) ,
479+ } ,
480+ ) ;
481+ expect ( result ) . toBe ( expectedState ) ;
482+ } ) ;
483+
484+ it ( 'throws error when password is missing in legacy constructor' , ( ) => {
485+ expect ( ( ) => {
486+ new Client ( 'login' , '' , mockHttpClient ) ;
487+ } ) . toThrow ( 'Password is required when using Basic Auth with login' ) ;
488+ } ) ;
489+ } ) ;
490+
344491 it ( 'patches settings' , async ( ) => {
345492 const settings : Partial < DeviceSettings > = {
346493 messages : { limitValue : 200 } ,
0 commit comments