@@ -5,30 +5,31 @@ import { syncRefund, syncRes, syncResEventNotification, syncResEventNotification
55import Client from "../client" ;
66import TerminalCloudAPI from "../services/terminalCloudAPI" ;
77import { terminal } from "../typings" ;
8+ import { EnvironmentEnum } from "../config" ;
89
910let client : Client ;
1011let terminalCloudAPI : TerminalCloudAPI ;
1112let scope : nock . Scope ;
1213
1314beforeEach ( ( ) : void => {
14- if ( ! nock . isActive ( ) ) {
15- nock . activate ( ) ;
16- }
17- client = createClient ( process . env . ADYEN_TERMINAL_APIKEY ) ;
15+ if ( ! nock . isActive ( ) ) {
16+ nock . activate ( ) ;
17+ }
18+ client = createClient ( process . env . ADYEN_TERMINAL_APIKEY ) ;
1819
19- terminalCloudAPI = new TerminalCloudAPI ( client ) ;
20- scope = nock ( `${ client . config . terminalApiCloudEndpoint } ` ) ;
20+ terminalCloudAPI = new TerminalCloudAPI ( client ) ;
21+ scope = nock ( `${ client . config . terminalApiCloudEndpoint } ` ) ;
2122} ) ;
2223
2324afterEach ( ( ) : void => {
24- nock . cleanAll ( ) ;
25+ nock . cleanAll ( ) ;
2526} ) ;
2627
2728describe ( "Terminal Cloud API" , ( ) : void => {
28- test ( "should make an async payment request" , async ( ) : Promise < void > => {
29- scope . post ( "/async" ) . reply ( 200 , asyncRes ) ;
29+ test ( "should make an async payment request" , async ( ) : Promise < void > => {
30+ scope . post ( "/async" ) . reply ( 200 , asyncRes ) ;
3031
31- const terminalAPIPaymentRequest = createTerminalAPIPaymentRequest ( ) ;
32+ const terminalAPIPaymentRequest = createTerminalAPIPaymentRequest ( ) ;
3233
3334 const requestResponse = await terminalCloudAPI . async ( terminalAPIPaymentRequest ) ;
3435
@@ -54,88 +55,152 @@ describe("Terminal Cloud API", (): void => {
5455 test ( "should make a sync payment request" , async ( ) : Promise < void > => {
5556 scope . post ( "/sync" ) . reply ( 200 , syncRes ) ;
5657
57- const terminalAPIPaymentRequest = createTerminalAPIPaymentRequest ( ) ;
58- const terminalAPIResponse : terminal . TerminalApiResponse = await terminalCloudAPI . sync ( terminalAPIPaymentRequest ) ;
58+ const terminalAPIPaymentRequest = createTerminalAPIPaymentRequest ( ) ;
59+ const terminalAPIResponse : terminal . TerminalApiResponse = await terminalCloudAPI . sync ( terminalAPIPaymentRequest ) ;
5960
60- expect ( terminalAPIResponse . SaleToPOIResponse ?. PaymentResponse ) . toBeDefined ( ) ;
61- expect ( terminalAPIResponse . SaleToPOIResponse ?. MessageHeader ) . toBeDefined ( ) ;
62- } ) ;
61+ expect ( terminalAPIResponse . SaleToPOIResponse ?. PaymentResponse ) . toBeDefined ( ) ;
62+ expect ( terminalAPIResponse . SaleToPOIResponse ?. MessageHeader ) . toBeDefined ( ) ;
63+ } ) ;
6364
64- test ( "should make a sync payment request with additional attributes" , async ( ) : Promise < void > => {
65- scope . post ( "/sync" ) . reply ( 200 , syncTerminalPaymentResponse ) ;
65+ test ( "should make a sync payment request with additional attributes" , async ( ) : Promise < void > => {
66+ scope . post ( "/sync" ) . reply ( 200 , syncTerminalPaymentResponse ) ;
6667
67- const terminalAPIPaymentRequest = createTerminalAPIPaymentRequest ( ) ;
68+ const terminalAPIPaymentRequest = createTerminalAPIPaymentRequest ( ) ;
6869
69- await expect ( async ( ) => {
70- const terminalAPIResponse = await terminalCloudAPI . sync ( terminalAPIPaymentRequest ) ;
71- expect ( terminalAPIResponse . SaleToPOIResponse ?. PaymentResponse ) . toBeDefined ( ) ;
72- expect ( terminalAPIResponse . SaleToPOIResponse ?. MessageHeader ) . toBeDefined ( ) ;
73- } ) . not . toThrow ( ) ;
70+ await expect ( async ( ) => {
71+ const terminalAPIResponse = await terminalCloudAPI . sync ( terminalAPIPaymentRequest ) ;
72+ expect ( terminalAPIResponse . SaleToPOIResponse ?. PaymentResponse ) . toBeDefined ( ) ;
73+ expect ( terminalAPIResponse . SaleToPOIResponse ?. MessageHeader ) . toBeDefined ( ) ;
74+ } ) . not . toThrow ( ) ;
7475
75- } ) ;
76+ } ) ;
7677
77- test ( "should return event notification Reject" , async ( ) : Promise < void > => {
78+ test ( "should return event notification Reject" , async ( ) : Promise < void > => {
7879
79- const terminalAPIPaymentRequest = createTerminalAPIPaymentRequest ( ) ;
80- scope . post ( "/sync" ) . reply ( 200 , syncResEventNotification ) ;
80+ const terminalAPIPaymentRequest = createTerminalAPIPaymentRequest ( ) ;
81+ scope . post ( "/sync" ) . reply ( 200 , syncResEventNotification ) ;
8182
82- const terminalAPIResponse = await terminalCloudAPI . sync ( terminalAPIPaymentRequest ) ;
83+ const terminalAPIResponse = await terminalCloudAPI . sync ( terminalAPIPaymentRequest ) ;
8384
84- expect ( terminalAPIResponse . SaleToPOIRequest ?. EventNotification ) . toBeDefined ( ) ;
85- expect ( terminalAPIResponse . SaleToPOIRequest ?. EventNotification ?. EventToNotify ) . toBe ( "Reject" ) ;
85+ expect ( terminalAPIResponse . SaleToPOIRequest ?. EventNotification ) . toBeDefined ( ) ;
86+ expect ( terminalAPIResponse . SaleToPOIRequest ?. EventNotification ?. EventToNotify ) . toBe ( "Reject" ) ;
8687
87- } ) ;
88+ } ) ;
8889
89- test ( "should return event notification Shutdown with additional attributes" , async ( ) : Promise < void > => {
90+ test ( "should return event notification Shutdown with additional attributes" , async ( ) : Promise < void > => {
9091
91- const terminalAPIPaymentRequest = createTerminalAPIPaymentRequest ( ) ;
92- scope . post ( "/sync" ) . reply ( 200 , syncResEventNotificationWithAdditionalAttributes ) ;
93-
94- await expect ( async ( ) => {
95- const terminalAPIResponse = await terminalCloudAPI . sync ( terminalAPIPaymentRequest ) ;
96- expect ( terminalAPIResponse . SaleToPOIRequest ?. EventNotification ) . toBeDefined ( ) ;
97- expect ( terminalAPIResponse . SaleToPOIRequest ?. EventNotification ?. EventToNotify ) . toBe ( "Shutdown" ) ;
98- expect ( terminalAPIResponse . SaleToPOIRequest ?. MessageHeader ) . toBeDefined ( ) ;
99- } ) . not . toThrow ( ) ;
100- } ) ;
92+ const terminalAPIPaymentRequest = createTerminalAPIPaymentRequest ( ) ;
93+ scope . post ( "/sync" ) . reply ( 200 , syncResEventNotificationWithAdditionalAttributes ) ;
10194
102- test ( "should return event notification with unknown enum" , async ( ) : Promise < void > => {
95+ await expect ( async ( ) => {
96+ const terminalAPIResponse = await terminalCloudAPI . sync ( terminalAPIPaymentRequest ) ;
97+ expect ( terminalAPIResponse . SaleToPOIRequest ?. EventNotification ) . toBeDefined ( ) ;
98+ expect ( terminalAPIResponse . SaleToPOIRequest ?. EventNotification ?. EventToNotify ) . toBe ( "Shutdown" ) ;
99+ expect ( terminalAPIResponse . SaleToPOIRequest ?. MessageHeader ) . toBeDefined ( ) ;
100+ } ) . not . toThrow ( ) ;
101+ } ) ;
103102
104- const terminalAPIPaymentRequest = createTerminalAPIPaymentRequest ( ) ;
105- scope . post ( "/sync" ) . reply ( 200 , syncResEventNotificationWithUnknownEnum ) ;
103+ test ( "should return event notification with unknown enum" , async ( ) : Promise < void > => {
106104
107- await expect ( async ( ) => {
108- const terminalAPIResponse = await terminalCloudAPI . sync ( terminalAPIPaymentRequest ) ;
109- expect ( terminalAPIResponse . SaleToPOIRequest ?. EventNotification ) . toBeDefined ( ) ;
110- // EventToNotify is unknown, so it holds whatever value is found in the payload
111- expect ( terminalAPIResponse . SaleToPOIRequest ?. EventNotification ?. EventToNotify ) . toBe ( "this is unknown" ) ;
105+ const terminalAPIPaymentRequest = createTerminalAPIPaymentRequest ( ) ;
106+ scope . post ( "/sync" ) . reply ( 200 , syncResEventNotificationWithUnknownEnum ) ;
112107
113- } ) . not . toThrow ( ) ;
114- } ) ;
108+ await expect ( async ( ) => {
109+ const terminalAPIResponse = await terminalCloudAPI . sync ( terminalAPIPaymentRequest ) ;
110+ expect ( terminalAPIResponse . SaleToPOIRequest ?. EventNotification ) . toBeDefined ( ) ;
111+ // EventToNotify is unknown, so it holds whatever value is found in the payload
112+ expect ( terminalAPIResponse . SaleToPOIRequest ?. EventNotification ?. EventToNotify ) . toBe ( "this is unknown" ) ;
115113
116- test ( "should make an async refund request" , async ( ) : Promise < void > => {
117- scope . post ( "/sync" ) . reply ( 200 , syncRes ) ;
114+ } ) . not . toThrow ( ) ;
115+ } ) ;
118116
119- const terminalAPIPaymentRequest = createTerminalAPIPaymentRequest ( ) ;
120- const terminalAPIResponse : terminal . TerminalApiResponse = await terminalCloudAPI . sync ( terminalAPIPaymentRequest ) ;
117+ test ( "should make an async refund request" , async ( ) : Promise < void > => {
118+ scope . post ( "/ sync" ) . reply ( 200 , syncRes ) ;
121119
122- const pOITransactionId = terminalAPIResponse . SaleToPOIResponse ! . PaymentResponse ! . POIData ! . POITransactionID ;
123- expect ( pOITransactionId ) . toBeTruthy ( ) ;
120+ const terminalAPIPaymentRequest = createTerminalAPIPaymentRequest ( ) ;
121+ const terminalAPIResponse : terminal . TerminalApiResponse = await terminalCloudAPI . sync ( terminalAPIPaymentRequest ) ;
124122
125- scope . post ( "/sync" ) . reply ( 200 , syncRefund ) ;
123+ const pOITransactionId = terminalAPIResponse . SaleToPOIResponse ! . PaymentResponse ! . POIData ! . POITransactionID ;
124+ expect ( pOITransactionId ) . toBeTruthy ( ) ;
126125
127- const terminalAPIRefundRequest = createTerminalAPIRefundRequest ( pOITransactionId ) ;
128- const id = Math . floor ( Math . random ( ) * Math . floor ( 10000000 ) ) . toString ( ) ;
129- terminalAPIRefundRequest . SaleToPOIRequest . MessageHeader . ServiceID = id ;
130- const saleToAcquirerData : terminal . SaleToAcquirerData = new terminal . SaleToAcquirerData ( ) ;
131- saleToAcquirerData . currency = "EUR" ;
132- terminalAPIRefundRequest . SaleToPOIRequest . ReversalRequest ! . SaleData ! . SaleToAcquirerData = saleToAcquirerData ;
133- const terminalAPIRefundResponse = await terminalCloudAPI . sync ( terminalAPIRefundRequest ) ;
126+ scope . post ( "/sync" ) . reply ( 200 , syncRefund ) ;
134127
135- expect ( terminalAPIRefundResponse . SaleToPOIResponse ?. ReversalResponse ?. Response . Result ) . toBe ( "Success" ) ;
136- } , 20000 ) ;
137- } ) ;
128+ const terminalAPIRefundRequest = createTerminalAPIRefundRequest ( pOITransactionId ) ;
129+ const id = Math . floor ( Math . random ( ) * Math . floor ( 10000000 ) ) . toString ( ) ;
130+ terminalAPIRefundRequest . SaleToPOIRequest . MessageHeader . ServiceID = id ;
131+ const saleToAcquirerData : terminal . SaleToAcquirerData = new terminal . SaleToAcquirerData ( ) ;
132+ saleToAcquirerData . currency = "EUR" ;
133+ terminalAPIRefundRequest . SaleToPOIRequest . ReversalRequest ! . SaleData ! . SaleToAcquirerData = saleToAcquirerData ;
134+ const terminalAPIRefundResponse = await terminalCloudAPI . sync ( terminalAPIRefundRequest ) ;
135+
136+ expect ( terminalAPIRefundResponse . SaleToPOIResponse ?. ReversalResponse ?. Response . Result ) . toBe ( "Success" ) ;
137+ } , 20000 ) ;
138+
139+ test ( "async should handle 308" , async ( ) : Promise < void > => {
138140
141+ const terminalApiHost = "https://terminal-api-test.adyen.com" ;
142+
143+ const client = new Client ( { apiKey : "YOUR_API_KEY" , environment : EnvironmentEnum . TEST } ) ;
144+ const terminalCloudAPI = new TerminalCloudAPI ( client ) ;
145+
146+ const terminalAPIPaymentRequest = createTerminalAPIPaymentRequest ( ) ;
147+ // custom value to trigger mock 308 response
148+ terminalAPIPaymentRequest . SaleToPOIRequest . MessageHeader . SaleID = "response-with-redirect" ;
149+
150+ // Mock first request: returns a 308 redirect with Location header
151+ nock ( terminalApiHost )
152+ . post ( "/async" , ( body ) => {
153+ return body ?. SaleToPOIRequest ?. MessageHeader ?. SaleID === "response-with-redirect" ;
154+ } )
155+ . reply ( 308 , "" , { Location : `${ terminalApiHost } /async?redirect=false` } ) ;
156+
157+ // Mock follow-up request: returns successful response 'ok'
158+ nock ( terminalApiHost )
159+ . post ( "/async?redirect=false" )
160+ . reply ( 200 , "ok" ) ;
161+
162+ const terminalAPIResponse = await terminalCloudAPI . async ( terminalAPIPaymentRequest ) ;
163+
164+ expect ( terminalAPIResponse ) . toEqual ( "ok" ) ;
165+ } ) ;
166+
167+ test ( "sync should validate 308 location header" , async ( ) : Promise < void > => {
168+ const terminalApiHost = "https://terminal-api-test.adyen.com" ;
169+
170+ const client = new Client ( { apiKey : "YOUR_API_KEY" , environment : EnvironmentEnum . TEST } ) ;
171+ const terminalCloudAPI = new TerminalCloudAPI ( client ) ;
172+
173+ const terminalAPIPaymentRequest = createTerminalAPIPaymentRequest ( ) ;
174+ // custom value to trigger mock 308 response
175+ terminalAPIPaymentRequest . SaleToPOIRequest . MessageHeader . SaleID = "response-with-redirect" ;
176+
177+ // Mock first request: returns a 308 redirect with invalid Location header
178+ nock ( terminalApiHost )
179+ . post ( "/sync" , ( body ) => {
180+ return body ?. SaleToPOIRequest ?. MessageHeader ?. SaleID === "response-with-redirect" ;
181+ } )
182+ . reply ( 308 , "" , { Location : "https://example.org/sync?redirect=false" } ) ;
183+
184+ // Mock follow-up request: returns successful response
185+ nock ( terminalApiHost )
186+ . post ( "/sync?redirect=false" )
187+ . reply ( 200 , {
188+ SaleToPOIResponse : {
189+ PaymentResponse : { Response : "Authorised" } ,
190+ MessageHeader : { SaleID : "001-308" } ,
191+ } ,
192+ } ) ;
193+
194+ try {
195+ await terminalCloudAPI . sync ( terminalAPIPaymentRequest ) ;
196+ fail ( "No exception was thrown" ) ;
197+ } catch ( e ) {
198+ expect ( e ) . toBeInstanceOf ( Error ) ;
199+ }
200+
201+ } ) ;
202+
203+ } ) ;
139204
140205export const syncTerminalPaymentResponse = {
141206 "SaleToPOIResponse" : {
0 commit comments