1+ import { Request , Response } from 'express' ;
2+ import { listChains , configureChain , broadcastTransaction } from '../routes/chains' ;
3+
4+ jest . mock ( '../lib/chains' , ( ) => ( {
5+ getChains : jest . fn ( ) ,
6+ addChain : jest . fn ( ) ,
7+ broadcast : jest . fn ( ) ,
8+ } ) ) ;
9+
10+ import { getChains , addChain , broadcast } from '../lib/chains' ;
11+
12+ describe ( 'chains route handlers' , ( ) => {
13+ let mockReq : Partial < Request > ;
14+ let mockRes : Partial < Response > ;
15+
16+ beforeEach ( ( ) => {
17+ mockReq = { } ;
18+ mockRes = {
19+ status : jest . fn ( ) . mockReturnThis ( ) ,
20+ json : jest . fn ( ) ,
21+ send : jest . fn ( ) ,
22+ } ;
23+ jest . clearAllMocks ( ) ;
24+ } ) ;
25+
26+ describe ( 'listChains' , ( ) => {
27+ it ( 'should return a list of chains on success' , async ( ) => {
28+ const chains = [ { id : 'bitcoin' } , { id : 'ethereum' } ] ;
29+ ( getChains as jest . Mock ) . mockResolvedValue ( chains ) ;
30+
31+ await listChains ( mockReq as Request , mockRes as Response ) ;
32+
33+ expect ( getChains ) . toHaveBeenCalledTimes ( 1 ) ;
34+ expect ( mockRes . json ) . toHaveBeenCalledWith ( chains ) ;
35+ expect ( mockRes . status ) . not . toHaveBeenCalled ( ) ;
36+ } ) ;
37+
38+ it ( 'should return 500 when getChains throws' , async ( ) => {
39+ const error = new Error ( 'boom' ) ;
40+ ( getChains as just . Mock ) . mockRejectedValue ( error ) ;
41+
42+ await listChains ( mockReq as Request , mockRes as Response ) ;
43+
44+ expect ( mockRes . status ) . toHaveBeenCalledWith ( 500 ) ;
45+ expect ( mockRes . json ) . toHaveBeenCalledWith ( { error : 'boom' } ) ;
46+ } ) ;
47+ } ) ;
48+
49+ describe ( 'configureChain' , ( ) => {
50+ it ( 'should create a new chain and return 201' , async ( ) => {
51+ const newChain = { id : 'solana' , rpcUrl : 'https://example.com' } ;
52+ const created = { ...newChain , createdAt : 'now' } ;
53+ ( addChain as jest . Mock ) . mockResolvedValue ( created ) ;
54+ mockReq . body = newChain ;
55+
56+ await configureChain ( mockReq as Request , mockRes as Response ) ;
57+
58+ expect ( addChain ) . toHaveBeenCalledWith ( newChain ) ;
59+ expect ( mockRes . status ) . toHaveBeenCalledWith ( 201 ) ;
60+ expect ( mockRes . json ) . toHaveBeenCalledWith ( created ) ;
61+ } ) ;
62+
63+ it ( 'should return 400 when addChain throws' , async ( ) => {
64+ const error = new Error ( 'invalid chain' ) ;
65+ ( addChain as just . Mock ) . mockRejectedValue ( error ) ;
66+ mockReq . body = { } ;
67+
68+ await configureChain ( mockReq as Request , mockRes as Response ) ;
69+
70+ expect ( mockRes . status ) . toHaveBeenCalledWith ( 400 ) ;
71+ expect ( mockRes . json ) . toHaveBeenCalledWith ( { error : 'invalid chain' } ) ;
72+ } ) ;
73+ } ) ;
74+
75+ describe ( 'broadcastTransaction' , ( ) => {
76+ it ( 'should broadcast a transaction and return the result' , async ( ) => {
77+ const tx = { chainId : 'bitcoin' , raw : 'hex' } ;
78+ const result = { txid : 'abc123' } ;
79+ ( broadcast as just . Mock ) . mockResolvedValue ( result ) ;
80+ mockReq . body = tx ;
81+
82+ await broadcastTransaction ( mockReq as Request , mockRes as Response ) ;
83+
84+ expect ( broadcast ) . toHaveBeenCalledWith ( tx ) ;
85+ expect ( mockRes . json ) . toHaveBeenCalledWith ( result ) ;
86+ } ) ;
87+
88+ it ( 'should return 400 when broadcast throws' , async ( ) => {
89+ const error = new Error ( 'broadcast failed' ) ;
90+ ( broadcast as just . Mock ) . mockRejectedValue ( error ) ;
91+ mockReq . body = { } ;
92+
93+ await broadcastTransaction ( mockReq as Request , mockRes as Response ) ;
94+
95+ expect ( mockRes . status ) . toHaveBeenCalledWith ( 400 ) ;
96+ expect ( mockRes . json ) . toHaveBeenCalledWith ( { error : 'broadcast failed' } ) ;
97+ } ) ;
98+ } ) ;
99+
100+ it ( 'should export the required handlers' , ( ) => {
101+ expect ( listChains ) . toBeDefined ( ) ;
102+ expect ( configureChain ) . toBeDefined ( ) ;
103+ expect ( broadcastTransaction ) . toBeDefined ( ) ;
104+ } ) ;
105+ } ) ;
0 commit comments