globalpayments-api 3.10.13 → 3.10.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/CHANGELOG.md +11 -1
  2. package/lib/src/Builders/RequestBuilder/GpApi/GpApiAuthorizationRequestBuilder.js +21 -0
  3. package/lib/src/Builders/RequestBuilder/GpApi/GpApiAuthorizationRequestBuilder.js.map +1 -1
  4. package/lib/src/Builders/RequestBuilder/GpApi/GpApiSessionInfo.d.ts +11 -2
  5. package/lib/src/Builders/RequestBuilder/GpApi/GpApiSessionInfo.js +44 -5
  6. package/lib/src/Builders/RequestBuilder/GpApi/GpApiSessionInfo.js.map +1 -1
  7. package/lib/src/Entities/GpApi/PorticoTokenConfig.d.ts +25 -0
  8. package/lib/src/Entities/GpApi/PorticoTokenConfig.js +30 -0
  9. package/lib/src/Entities/GpApi/PorticoTokenConfig.js.map +1 -0
  10. package/lib/src/Entities/GpApi/index.d.ts +1 -0
  11. package/lib/src/Entities/GpApi/index.js +1 -0
  12. package/lib/src/Entities/GpApi/index.js.map +1 -1
  13. package/lib/src/Entities/Transaction.d.ts +2 -0
  14. package/lib/src/Entities/Transaction.js +2 -0
  15. package/lib/src/Entities/Transaction.js.map +1 -1
  16. package/lib/src/Entities/TransactionSummary.d.ts +1 -0
  17. package/lib/src/Entities/TransactionSummary.js +1 -0
  18. package/lib/src/Entities/TransactionSummary.js.map +1 -1
  19. package/lib/src/Entities/UPA/ExtraChargeType.d.ts +8 -0
  20. package/lib/src/Entities/UPA/ExtraChargeType.js +13 -0
  21. package/lib/src/Entities/UPA/ExtraChargeType.js.map +1 -0
  22. package/lib/src/Entities/UPA/Lodging.d.ts +11 -0
  23. package/lib/src/Entities/UPA/Lodging.js +15 -0
  24. package/lib/src/Entities/UPA/Lodging.js.map +1 -0
  25. package/lib/src/Entities/UPA/POSData.d.ts +6 -0
  26. package/lib/src/Entities/UPA/POSData.js +11 -0
  27. package/lib/src/Entities/UPA/POSData.js.map +1 -0
  28. package/lib/src/Gateways/GpApiConnector.d.ts +0 -6
  29. package/lib/src/Gateways/GpApiConnector.js +22 -43
  30. package/lib/src/Gateways/GpApiConnector.js.map +1 -1
  31. package/lib/src/Gateways/PorticoConnector.js +4 -6
  32. package/lib/src/Gateways/PorticoConnector.js.map +1 -1
  33. package/lib/src/Mapping/GpApiMapping.js +7 -0
  34. package/lib/src/Mapping/GpApiMapping.js.map +1 -1
  35. package/lib/src/ServiceConfigs/Gateways/GpApiConfig.d.ts +6 -0
  36. package/lib/src/ServiceConfigs/Gateways/GpApiConfig.js +25 -2
  37. package/lib/src/ServiceConfigs/Gateways/GpApiConfig.js.map +1 -1
  38. package/lib/src/Services/GpApiServices.js +4 -1
  39. package/lib/src/Services/GpApiServices.js.map +1 -1
  40. package/lib/src/Terminals/Builders/TerminalAuthBuilder.d.ts +1 -1
  41. package/lib/src/Terminals/Builders/TerminalAuthBuilder.js +11 -18
  42. package/lib/src/Terminals/Builders/TerminalAuthBuilder.js.map +1 -1
  43. package/lib/src/Terminals/Builders/TerminalManageBuilder.d.ts +1 -0
  44. package/lib/src/Terminals/Builders/TerminalManageBuilder.js +4 -0
  45. package/lib/src/Terminals/Builders/TerminalManageBuilder.js.map +1 -1
  46. package/lib/src/Terminals/Builders/TerminalReportBuilder.d.ts +15 -0
  47. package/lib/src/Terminals/Builders/TerminalReportBuilder.js +49 -0
  48. package/lib/src/Terminals/Builders/TerminalReportBuilder.js.map +1 -0
  49. package/lib/src/Terminals/UPA/Entities/UpaModels.d.ts +62 -0
  50. package/lib/src/Terminals/UPA/Entities/UpaModels.js +28 -0
  51. package/lib/src/Terminals/UPA/Entities/UpaModels.js.map +1 -0
  52. package/lib/src/Terminals/UPA/Entities/UpaSearchCriteria.d.ts +5 -0
  53. package/lib/src/Terminals/UPA/Entities/UpaSearchCriteria.js +10 -0
  54. package/lib/src/Terminals/UPA/Entities/UpaSearchCriteria.js.map +1 -0
  55. package/lib/src/Terminals/UPA/Reponses/BatchList.d.ts +16 -0
  56. package/lib/src/Terminals/UPA/Reponses/BatchList.js +82 -0
  57. package/lib/src/Terminals/UPA/Reponses/BatchList.js.map +1 -0
  58. package/lib/src/Terminals/UPA/Reponses/BatchReportResponse.d.ts +55 -0
  59. package/lib/src/Terminals/UPA/Reponses/BatchReportResponse.js +213 -0
  60. package/lib/src/Terminals/UPA/Reponses/BatchReportResponse.js.map +1 -0
  61. package/lib/src/Terminals/UPA/Reponses/OpenTabDetailsResponse.d.ts +25 -0
  62. package/lib/src/Terminals/UPA/Reponses/OpenTabDetailsResponse.js +109 -0
  63. package/lib/src/Terminals/UPA/Reponses/OpenTabDetailsResponse.js.map +1 -0
  64. package/lib/src/Terminals/UPA/Reponses/SafReportResponse.d.ts +36 -0
  65. package/lib/src/Terminals/UPA/Reponses/SafReportResponse.js +181 -0
  66. package/lib/src/Terminals/UPA/Reponses/SafReportResponse.js.map +1 -0
  67. package/lib/src/Terminals/UPA/Reponses/TransactionResponse.js +9 -2
  68. package/lib/src/Terminals/UPA/Reponses/TransactionResponse.js.map +1 -1
  69. package/lib/src/Terminals/UPA/Reponses/UpaEODResponse.d.ts +21 -0
  70. package/lib/src/Terminals/UPA/Reponses/UpaEODResponse.js +106 -0
  71. package/lib/src/Terminals/UPA/Reponses/UpaEODResponse.js.map +1 -0
  72. package/lib/src/Terminals/UPA/Reponses/UpaGiftCardResponse.d.ts +41 -0
  73. package/lib/src/Terminals/UPA/Reponses/UpaGiftCardResponse.js +93 -0
  74. package/lib/src/Terminals/UPA/Reponses/UpaGiftCardResponse.js.map +1 -0
  75. package/lib/src/Terminals/UPA/Reponses/UpaSAFResponse.d.ts +35 -0
  76. package/lib/src/Terminals/UPA/Reponses/UpaSAFResponse.js +194 -0
  77. package/lib/src/Terminals/UPA/Reponses/UpaSAFResponse.js.map +1 -0
  78. package/lib/src/Terminals/UPA/Reponses/UpaSignatureResponse.d.ts +18 -0
  79. package/lib/src/Terminals/UPA/Reponses/UpaSignatureResponse.js +94 -0
  80. package/lib/src/Terminals/UPA/Reponses/UpaSignatureResponse.js.map +1 -0
  81. package/lib/src/Terminals/UPA/UpaController.js +4 -1
  82. package/lib/src/Terminals/UPA/UpaController.js.map +1 -1
  83. package/lib/src/Utils/SdkVersion.d.ts +1 -0
  84. package/lib/src/Utils/SdkVersion.js +48 -0
  85. package/lib/src/Utils/SdkVersion.js.map +1 -0
  86. package/lib/src/Utils/index.d.ts +1 -0
  87. package/lib/src/Utils/index.js +1 -0
  88. package/lib/src/Utils/index.js.map +1 -1
  89. package/lib/test/Integration/Gateways/CI/gpapi/GpApiTransactionsTests.test.js +69 -0
  90. package/lib/test/Integration/Gateways/CI/gpapi/GpApiTransactionsTests.test.js.map +1 -0
  91. package/lib/test/Integration/Gateways/CI/portico/PorticoCreditTests.test.js +111 -0
  92. package/lib/test/Integration/Gateways/CI/portico/PorticoCreditTests.test.js.map +1 -0
  93. package/lib/test/Integration/Gateways/CI/upa_mitc/UpaFunctionalityTests.test.js +84 -0
  94. package/lib/test/Integration/Gateways/CI/upa_mitc/UpaFunctionalityTests.test.js.map +1 -0
  95. package/lib/test/Integration/Gateways/GpApiConnector/AccessTokenPorticoCredentials.test.d.ts +1 -0
  96. package/lib/test/Integration/Gateways/GpApiConnector/AccessTokenPorticoCredentials.test.js +175 -0
  97. package/lib/test/Integration/Gateways/GpApiConnector/AccessTokenPorticoCredentials.test.js.map +1 -0
  98. package/lib/test/Integration/Gateways/GpApiConnector/GpApiCreateTokenWithPorticoCredentialTests.test.d.ts +1 -0
  99. package/lib/test/Integration/Gateways/GpApiConnector/GpApiCreateTokenWithPorticoCredentialTests.test.js +205 -0
  100. package/lib/test/Integration/Gateways/GpApiConnector/GpApiCreateTokenWithPorticoCredentialTests.test.js.map +1 -0
  101. package/lib/test/Integration/Gateways/GpApiConnector/VisaAft.test.d.ts +1 -0
  102. package/lib/test/Integration/Gateways/GpApiConnector/VisaAft.test.js +168 -0
  103. package/lib/test/Integration/Gateways/GpApiConnector/VisaAft.test.js.map +1 -0
  104. package/lib/test/Integration/Gateways/PorticoConnector/GlobalTransactionId.test.d.ts +1 -0
  105. package/lib/test/Integration/Gateways/PorticoConnector/GlobalTransactionId.test.js +243 -0
  106. package/lib/test/Integration/Gateways/PorticoConnector/GlobalTransactionId.test.js.map +1 -0
  107. package/lib/test/Unit/Builders/AuthorizationBuilder/SupplementaryData.test.d.ts +1 -0
  108. package/lib/test/Unit/Builders/AuthorizationBuilder/SupplementaryData.test.js +147 -0
  109. package/lib/test/Unit/Builders/AuthorizationBuilder/SupplementaryData.test.js.map +1 -0
  110. package/lib/test/Unit/Terminals/UPA/UpaStory1Methods.test.d.ts +1 -0
  111. package/lib/test/Unit/Terminals/UPA/UpaStory1Methods.test.js +250 -0
  112. package/lib/test/Unit/Terminals/UPA/UpaStory1Methods.test.js.map +1 -0
  113. package/lib/test/Unit/Terminals/UPA/UpaStory2Methods.test.d.ts +1 -0
  114. package/lib/test/Unit/Terminals/UPA/UpaStory2Methods.test.js +1277 -0
  115. package/lib/test/Unit/Terminals/UPA/UpaStory2Methods.test.js.map +1 -0
  116. package/lib/test/Unit/Terminals/UPA/UpaStory3_4Methods.test.d.ts +1 -0
  117. package/lib/test/Unit/Terminals/UPA/UpaStory3_4Methods.test.js +411 -0
  118. package/lib/test/Unit/Terminals/UPA/UpaStory3_4Methods.test.js.map +1 -0
  119. package/lib/test/Utils/CiTestingHarness.d.ts +21 -0
  120. package/lib/test/Utils/CiTestingHarness.js +65 -7
  121. package/lib/test/Utils/CiTestingHarness.js.map +1 -1
  122. package/package.json +1 -1
  123. package/lib/test/Integration/Gateways/CI/GpApiCreditCardNotPresentTests.test.js +0 -90
  124. package/lib/test/Integration/Gateways/CI/GpApiCreditCardNotPresentTests.test.js.map +0 -1
  125. package/lib/test/Integration/Gateways/CI/PorticoCreditTests.test.js +0 -63
  126. package/lib/test/Integration/Gateways/CI/PorticoCreditTests.test.js.map +0 -1
  127. package/lib/test/Integration/Gateways/CI/UpaMicTests.test.js +0 -52
  128. package/lib/test/Integration/Gateways/CI/UpaMicTests.test.js.map +0 -1
  129. /package/lib/test/Integration/Gateways/CI/{GpApiCreditCardNotPresentTests.test.d.ts → gpapi/GpApiTransactionsTests.test.d.ts} +0 -0
  130. /package/lib/test/Integration/Gateways/CI/{PorticoCreditTests.test.d.ts → portico/PorticoCreditTests.test.d.ts} +0 -0
  131. /package/lib/test/Integration/Gateways/CI/{UpaMicTests.test.d.ts → upa_mitc/UpaFunctionalityTests.test.d.ts} +0 -0
@@ -0,0 +1,1277 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ /**
4
+ * Unit tests for UPA Story 2 methods:
5
+ * balance(), reverse(), deletePreAuth(), startCardTransaction(), reboot()
6
+ *
7
+ * Balance – UpaEbtTests.cs:EbtFoodstampBalanceInquiry, EbtCashBenefitsBalanceInquiry, EbtBalance
8
+ * Reverse – UpaCreditTests.cs:CreditSale_WhenReversedByTerminalRefNumber_ShouldReturnSuccess
9
+ * DeletePreAuth – UpaCreditTests.cs:DeletePreAuth / UpaMicTests.cs:CreditDeletePreAuth
10
+ * StartCardTransaction – UpaAdminTests.cs (4 test cases)
11
+ * Reboot – UpaAdminTests.cs:Reboot / UpaMicTests.cs:Reboot
12
+ */
13
+ const src_1 = require("../../../../src");
14
+ const Logging_1 = require("../../../../src/Utils/Logging");
15
+ const DeviceService_1 = require("../../../../src/Services/DeviceService");
16
+ const Enums_1 = require("../../../../src/Terminals/Enums");
17
+ const TransactionResponse_1 = require("../../../../src/Terminals/UPA/Reponses/TransactionResponse");
18
+ const UpaGiftCardResponse_1 = require("../../../../src/Terminals/UPA/Reponses/UpaGiftCardResponse");
19
+ const AcquisitionType_1 = require("../../../../src/Entities/Enums/AcquisitionType");
20
+ const CardTypeFilter_1 = require("../../../../src/Entities/Enums/CardTypeFilter");
21
+ const ProcessIndicator_1 = require("../../../../src/Entities/UPA/ProcessIndicator");
22
+ const UpaParam_1 = require("../../../../src/Entities/UPA/UpaParam");
23
+ const UpaTransactionData_1 = require("../../../../src/Entities/UPA/UpaTransactionData");
24
+ const Enums_2 = require("../../../../src/Entities/Enums");
25
+ const useLiveMic = process.env.UPA_LIVE === "true";
26
+ const gpApiAppId = process.env.GP_API_APP_ID;
27
+ const gpApiAppKey = process.env.GP_API_APP_KEY;
28
+ const hasLiveGpApiCredentials = !!gpApiAppId && !!gpApiAppKey;
29
+ const describeUpaStory2 = useLiveMic && !hasLiveGpApiCredentials ? describe.skip : describe;
30
+ const liveOnlyStory2 = useLiveMic ? test : test.skip;
31
+ jest.setTimeout(240000);
32
+ /* eslint-disable indent */
33
+ function expectLiveSuccess(response, expectedCommand) {
34
+ const expectedCommands = Array.isArray(expectedCommand)
35
+ ? expectedCommand
36
+ : [expectedCommand];
37
+ expect(expectedCommands).toContain(response.command);
38
+ expect(response.status).toBe("Success");
39
+ expect(response.deviceResponseCode).toBe("00");
40
+ }
41
+ function formatLiveFailure(response, operation) {
42
+ const deviceCode = response.deviceResponseCode ?? "";
43
+ const hostCode = response.responseCode ?? "";
44
+ return `${operation} prerequisite failed in live MIC: device ${deviceCode} ${response.deviceResponseMessage ?? ""}; host ${hostCode} ${response.responseText ?? ""}`.trim();
45
+ }
46
+ function isKnownLiveSaleBlocker(response) {
47
+ const pinVerificationError = response.deviceResponseCode === "HOST001" &&
48
+ response.responseCode === "86" &&
49
+ response.responseText === "CANT VERIFY PIN";
50
+ const timeoutError = response.deviceResponseCode === "APP002" &&
51
+ response.deviceResponseMessage === "TIMEOUT";
52
+ return pinVerificationError || timeoutError;
53
+ }
54
+ function isKnownLiveBalanceBlocker(response) {
55
+ const pinVerificationError = response.deviceResponseCode === "HOST001" &&
56
+ response.responseCode === "86" &&
57
+ response.responseText === "CANT VERIFY PIN";
58
+ const hostCommunicationError = response.deviceResponseCode === "HOST002" &&
59
+ response.deviceResponseMessage === "HOST COMMUNICATIONS ERROR";
60
+ const userCancelledError = response.deviceResponseCode === "APP001" &&
61
+ response.deviceResponseMessage === "TRANSACTION CANCELLED BY USER";
62
+ const timeoutError = response.deviceResponseCode === "APP002" &&
63
+ response.deviceResponseMessage === "TIMEOUT";
64
+ return (pinVerificationError ||
65
+ hostCommunicationError ||
66
+ userCancelledError ||
67
+ timeoutError);
68
+ }
69
+ function isKnownLiveBusyBlocker(response) {
70
+ return (response.command === "SendCommand" &&
71
+ response.deviceResponseCode === "32" &&
72
+ response.deviceResponseMessage === "BUSY");
73
+ }
74
+ function isKnownLiveStartCardTransactionBlocker(response) {
75
+ const documentedErrorCodes = [
76
+ "CARD002",
77
+ "CARD003",
78
+ "CARD004",
79
+ "CARD006",
80
+ "CARD007",
81
+ "CARD009",
82
+ "CARD011",
83
+ "CARD018",
84
+ "APP001",
85
+ "APP002",
86
+ "APP013",
87
+ "ERR013",
88
+ ];
89
+ return (!!response.deviceResponseCode &&
90
+ documentedErrorCodes.includes(response.deviceResponseCode));
91
+ }
92
+ function isKnownLiveGiftCardBlocker(response) {
93
+ return (response.deviceResponseCode === "GIFT001" &&
94
+ response.deviceResponseMessage === "NOT A VALID GIFT CARD");
95
+ }
96
+ function isKnownLiveReverseAutoFallbackBlocker(response) {
97
+ return (response.command === "Reversal" &&
98
+ response.deviceResponseCode === "ERR013" &&
99
+ response.deviceResponseMessage === "[tranNo]-MISSING MANDATORY FIELD");
100
+ }
101
+ function isKnownLiveTransportTimeout(error) {
102
+ return (error instanceof Error &&
103
+ (error.message === "Socket timeout occurred." ||
104
+ error.message.includes("ECONNRESET") ||
105
+ error.message.includes("socket hang up")));
106
+ }
107
+ function expectParsedStartCardTransactionResponse(response) {
108
+ expect(response.command).toBe("StartCardTransaction");
109
+ expect(response.status).toBe("Success");
110
+ expect(response.deviceResponseCode).toBe("00");
111
+ if (response.acquisitionType) {
112
+ expect(response.acquisitionType).toMatch(/^(INSERT|CONTACT|CONTACTLESS|SWIPE|MANUAL|SCAN|TAP)$/);
113
+ }
114
+ if (response.luhnCheckPassed) {
115
+ expect(response.luhnCheckPassed).toMatch(/^[YN]$/);
116
+ }
117
+ if (response.fallback) {
118
+ expect(response.fallback).toMatch(/^[01]$/);
119
+ }
120
+ if (response.avsFlag) {
121
+ expect(response.avsFlag).toMatch(/^[01]$/);
122
+ }
123
+ if (response.cardSecurityPromptFlag) {
124
+ expect(response.cardSecurityPromptFlag).toMatch(/^[01]$/);
125
+ }
126
+ if (response.cashBackFlag) {
127
+ expect(response.cashBackFlag).toMatch(/^[01]$/);
128
+ }
129
+ if (response.surchargeFlag) {
130
+ expect(response.surchargeFlag).toMatch(/^[01]$/);
131
+ }
132
+ if (response.dccEligible) {
133
+ expect(response.dccEligible).toMatch(/^[01]$/);
134
+ }
135
+ }
136
+ function delay(ms) {
137
+ return new Promise((resolve) => setTimeout(resolve, ms));
138
+ }
139
+ async function expectLiveDeletePreAuthFailure(action, operation) {
140
+ try {
141
+ const response = await action();
142
+ expect(response).not.toBeNull();
143
+ expect(response).toBeInstanceOf(TransactionResponse_1.TransactionResponse);
144
+ if (isKnownLiveBusyBlocker(response)) {
145
+ console.warn(formatLiveFailure(response, operation));
146
+ return;
147
+ }
148
+ expect(response.status !== "Success" ||
149
+ response.deviceResponseCode !== "00" ||
150
+ (!!response.responseCode && response.responseCode !== "00")).toBe(true);
151
+ }
152
+ catch (error) {
153
+ if (isKnownLiveTransportTimeout(error)) {
154
+ console.warn(`${operation} timed out while waiting on the device or gateway.`);
155
+ return;
156
+ }
157
+ expect(error).toBeInstanceOf(Error);
158
+ expect(error.message).toBeTruthy();
159
+ }
160
+ }
161
+ function expectLiveBalanceResponseFields(response) {
162
+ expect(["BalanceInquiry", "SendCommand"]).toContain(response.command);
163
+ expect(response.status).toBe("Success");
164
+ expect(response.deviceResponseCode).toBe("00");
165
+ expect(response.responseCode).toBe("00");
166
+ expect(response.responseText).toBeTruthy();
167
+ if (response.referenceNumber) {
168
+ expect(response.referenceNumber).toMatch(/^[A-Z0-9]+$/i);
169
+ }
170
+ expect(response.availableBalance).not.toBeUndefined();
171
+ if (response.transactionType) {
172
+ expect(response.transactionType).toContain("BALANCE");
173
+ }
174
+ if (response.maskedCardNumber) {
175
+ expect(response.maskedCardNumber).toMatch(/\*{2,}|X{2,}/);
176
+ }
177
+ if (response.entryMethod) {
178
+ expect(response.entryMethod).toMatch(/^(MANUAL|SWIPE|INSERT|TAP|SCAN|NONE)$/);
179
+ }
180
+ if (response.expirationDate) {
181
+ expect(response.expirationDate).toMatch(/^\d{2}\/\d{2}$/);
182
+ }
183
+ if (response.pinVerified) {
184
+ expect(response.pinVerified).toMatch(/^[01]$/);
185
+ }
186
+ if (response.fallback) {
187
+ expect(response.fallback).toMatch(/^[01]$/);
188
+ }
189
+ }
190
+ async function expectLiveBalanceFailure(action, operation) {
191
+ try {
192
+ const response = await action();
193
+ expect(response).not.toBeNull();
194
+ expect(response).toBeInstanceOf(TransactionResponse_1.TransactionResponse);
195
+ if (isKnownLiveBusyBlocker(response)) {
196
+ console.warn(formatLiveFailure(response, operation));
197
+ return;
198
+ }
199
+ expect(response.status !== "Success" ||
200
+ response.deviceResponseCode !== "00" ||
201
+ (!!response.responseCode && response.responseCode !== "00")).toBe(true);
202
+ }
203
+ catch (error) {
204
+ if (isKnownLiveTransportTimeout(error)) {
205
+ console.warn(`${operation} timed out while waiting on the device or gateway.`);
206
+ return;
207
+ }
208
+ expect(error).toBeInstanceOf(Error);
209
+ expect(error.message).toBeTruthy();
210
+ }
211
+ }
212
+ async function reverseLiveSaleWithRetry(device, terminalRefNumber, amount, maxAttempts = 3) {
213
+ let response;
214
+ for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
215
+ const builder = device.reverse().withEcrId(12);
216
+ if (terminalRefNumber) {
217
+ builder.withTerminalRefNumber(terminalRefNumber);
218
+ }
219
+ if (amount !== undefined) {
220
+ builder.withAmount(amount);
221
+ }
222
+ response = await builder.execute();
223
+ if (!isKnownLiveBusyBlocker(response) || attempt === maxAttempts) {
224
+ return response;
225
+ }
226
+ await delay(10000);
227
+ }
228
+ return response;
229
+ }
230
+ function expectLiveReverseResponseFields(response) {
231
+ expect(response.command).toBe("Reversal");
232
+ expect(response.status).toBe("Success");
233
+ expect(response.deviceResponseCode).toBe("00");
234
+ expect(response.responseCode).toBe("00");
235
+ expect(response.responseText).toBeTruthy();
236
+ expect(response.terminalRefNumber).toBeTruthy();
237
+ if (response.referenceNumber) {
238
+ expect(response.referenceNumber).toMatch(/^[A-Z0-9]+$/i);
239
+ }
240
+ if (response.transactionType) {
241
+ expect(response.transactionType).toContain("REVERSAL");
242
+ }
243
+ if (response.maskedCardNumber) {
244
+ expect(response.maskedCardNumber).toMatch(/\*{2,}|X{2,}/);
245
+ }
246
+ if (response.entryMethod) {
247
+ expect(response.entryMethod).toMatch(/^(MANUAL|SWIPE|INSERT|TAP|SCAN|NONE)$/);
248
+ }
249
+ if (response.expirationDate) {
250
+ expect(response.expirationDate).toMatch(/^\d{2}\/\d{2}$/);
251
+ }
252
+ }
253
+ async function expectLiveReverseFailure(action, operation) {
254
+ try {
255
+ const response = await action();
256
+ expect(response).not.toBeNull();
257
+ expect(response).toBeInstanceOf(TransactionResponse_1.TransactionResponse);
258
+ if (isKnownLiveBusyBlocker(response)) {
259
+ console.warn(formatLiveFailure(response, operation));
260
+ return;
261
+ }
262
+ expect(response.status !== "Success" ||
263
+ response.deviceResponseCode !== "00" ||
264
+ (!!response.responseCode && response.responseCode !== "00")).toBe(true);
265
+ }
266
+ catch (error) {
267
+ if (isKnownLiveTransportTimeout(error)) {
268
+ console.warn(`${operation} timed out while waiting on the device or gateway.`);
269
+ return;
270
+ }
271
+ expect(error).toBeInstanceOf(Error);
272
+ expect(error.message).toBeTruthy();
273
+ }
274
+ }
275
+ async function deletePreAuthWithRetry(device, transactionId, amount, maxAttempts = 3) {
276
+ let response;
277
+ for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
278
+ response = await device
279
+ .deletePreAuth()
280
+ .withEcrId(13)
281
+ .withTransactionId(transactionId)
282
+ .withAmount(amount)
283
+ .execute();
284
+ if (!isKnownLiveBusyBlocker(response) || attempt === maxAttempts) {
285
+ return response;
286
+ }
287
+ await delay(10000);
288
+ }
289
+ return response;
290
+ }
291
+ async function createLiveSale(device) {
292
+ const response = await device
293
+ .sale(1.0)
294
+ .withGratuity(0)
295
+ .withEcrId(13)
296
+ .withClerkId(123)
297
+ .execute();
298
+ expect(response).toBeInstanceOf(TransactionResponse_1.TransactionResponse);
299
+ if (response.deviceResponseCode === "00") {
300
+ expect(["COMPLETE", "INITIATED"]).toContain(response.deviceResponseText);
301
+ expect(response.terminalRefNumber).toBeTruthy();
302
+ }
303
+ return response;
304
+ }
305
+ async function createLiveDebitSale(device) {
306
+ const response = await device
307
+ .sale(1.0)
308
+ .withPaymentMethodType(src_1.PaymentMethodType.Debit)
309
+ .withCashBack(0)
310
+ .withEcrId(13)
311
+ .withClerkId(123)
312
+ .execute();
313
+ expect(response).toBeInstanceOf(TransactionResponse_1.TransactionResponse);
314
+ if (response.deviceResponseCode === "00") {
315
+ expect(["COMPLETE", "INITIATED"]).toContain(response.deviceResponseText);
316
+ expect(response.terminalRefNumber).toBeTruthy();
317
+ }
318
+ return response;
319
+ }
320
+ async function createLivePreAuth(device) {
321
+ const response = await device
322
+ .authorize(1.0)
323
+ .withEcrId(13)
324
+ .withClerkId(123)
325
+ .execute();
326
+ expect(response).toBeInstanceOf(TransactionResponse_1.TransactionResponse);
327
+ if (response.deviceResponseCode !== "00") {
328
+ throw new Error(formatLiveFailure(response, "PreAuth"));
329
+ }
330
+ expect(["COMPLETE", "INITIATED"]).toContain(response.deviceResponseText);
331
+ expect(response.transactionId).toBeTruthy();
332
+ return response;
333
+ }
334
+ async function executeLiveStartCardTransaction(device, param, indicator, transData, operation) {
335
+ let response;
336
+ try {
337
+ response = await device.startCardTransaction(param, indicator, transData);
338
+ }
339
+ catch (error) {
340
+ if (isKnownLiveTransportTimeout(error)) {
341
+ console.warn(`${operation} timed out while waiting on the device or gateway.`);
342
+ return undefined;
343
+ }
344
+ throw error;
345
+ }
346
+ expect(response).not.toBeNull();
347
+ expect(response).toBeInstanceOf(UpaGiftCardResponse_1.UpaGiftCardResponse);
348
+ if (isKnownLiveGiftCardBlocker(response) ||
349
+ isKnownLiveStartCardTransactionBlocker(response)) {
350
+ console.warn(formatLiveFailure(response, operation));
351
+ return undefined;
352
+ }
353
+ expectLiveSuccess(response, "StartCardTransaction");
354
+ expectParsedStartCardTransactionResponse(response);
355
+ return response;
356
+ }
357
+ /* eslint-enable indent */
358
+ // ===========================================================================
359
+ // Test infrastructure helpers
360
+ // ===========================================================================
361
+ function buildConfig(gpApiOverrides = {}) {
362
+ const config = new src_1.ConnectionConfig();
363
+ config.deviceType = src_1.DeviceType.UPA_DEVICE;
364
+ config.connectionMode = Enums_1.ConnectionModes.MEET_IN_THE_CLOUD;
365
+ config.requestIdProvider = { getRequestId: () => 9999 };
366
+ const logger = new Logging_1.SampleRequestLogger(new Logging_1.Logger("logs"));
367
+ config.requestLogger = logger;
368
+ if (useLiveMic && !hasLiveGpApiCredentials) {
369
+ throw new Error("Set GP_API_APP_ID and GP_API_APP_KEY to run live UPA Story 2 tests.");
370
+ }
371
+ const gpApiConfig = new src_1.GpApiConfig();
372
+ gpApiConfig.appId = gpApiAppId ?? "UNIT_TEST_APP_ID";
373
+ gpApiConfig.appKey = gpApiAppKey ?? "UNIT_TEST_APP_KEY";
374
+ gpApiConfig.environment = src_1.Environment.Test;
375
+ gpApiConfig.channel = src_1.Channel.CardPresent;
376
+ gpApiConfig.country = "US";
377
+ gpApiConfig.deviceCurrency = "USD";
378
+ gpApiConfig.requestLogger = logger;
379
+ if (useLiveMic) {
380
+ gpApiConfig.accessTokenInfo = new src_1.AccessTokenInfo();
381
+ }
382
+ else {
383
+ gpApiConfig.accessTokenInfo = {
384
+ transactionProcessingAccountName: "test",
385
+ accessToken: "UNIT_TEST_FAKE_TOKEN",
386
+ };
387
+ }
388
+ Object.assign(gpApiConfig, gpApiOverrides);
389
+ config.gatewayConfig = gpApiConfig;
390
+ return config;
391
+ }
392
+ // ===========================================================================
393
+ // balance()
394
+ // References:
395
+ // UpaEbtTests.cs – EbtFoodstampBalanceInquiry, EbtCashBenefitsBalanceInquiry, EbtBalance
396
+ // Assert.AreEqual("00", response.ResponseCode / DeviceResponseCode)
397
+ // Assert.AreEqual("Success", response.DeviceResponseText)
398
+ // ===========================================================================
399
+ describeUpaStory2("UPA Story 2 – balance()", () => {
400
+ let device;
401
+ beforeEach(() => {
402
+ device = DeviceService_1.DeviceService.create(buildConfig());
403
+ device.ecrId = "13";
404
+ });
405
+ /**
406
+ * Mirrors UpaEbtTests.cs – EbtFoodstampBalanceInquiry
407
+ * var response = _device.Balance().WithEcrId(13)
408
+ * .WithPaymentMethodType(PaymentMethodType.EBT)
409
+ * .WithCurrency(CurrencyType.FOODSTAMPS).Execute();
410
+ * Assert.AreEqual("00", response.ResponseCode);
411
+ */
412
+ test("[UpaEbtTests] balance() with EBT Foodstamp returns deviceResponseCode == '00'", async () => {
413
+ const response = await device
414
+ .balance()
415
+ .withEcrId(13)
416
+ .withPaymentMethodType(src_1.PaymentMethodType.EBT)
417
+ .execute();
418
+ expect(response).not.toBeNull();
419
+ expect(response).toBeInstanceOf(TransactionResponse_1.TransactionResponse);
420
+ if (useLiveMic) {
421
+ if (isKnownLiveBalanceBlocker(response)) {
422
+ console.warn(formatLiveFailure(response, "BalanceInquiry Foodstamp"));
423
+ return;
424
+ }
425
+ if (isKnownLiveBusyBlocker(response)) {
426
+ console.warn(formatLiveFailure(response, "BalanceInquiry Foodstamp"));
427
+ return;
428
+ }
429
+ expectLiveSuccess(response, ["BalanceInquiry", "SendCommand"]);
430
+ return;
431
+ }
432
+ expect(response.deviceResponseCode).toBe("00");
433
+ });
434
+ /**
435
+ * Mirrors UpaEbtTests.cs – EbtBalance
436
+ * Assert.AreEqual("Success", response.DeviceResponseText);
437
+ * Assert.AreEqual("00", response.DeviceResponseCode);
438
+ */
439
+ test("[UpaEbtTests] balance() with EBT returns status Success and deviceResponseCode '00'", async () => {
440
+ const response = await device
441
+ .balance()
442
+ .withEcrId(13)
443
+ .withPaymentMethodType(src_1.PaymentMethodType.EBT)
444
+ .execute();
445
+ expect(response).not.toBeNull();
446
+ if (useLiveMic) {
447
+ if (isKnownLiveBalanceBlocker(response)) {
448
+ console.warn(formatLiveFailure(response, "BalanceInquiry EBT"));
449
+ return;
450
+ }
451
+ if (isKnownLiveBusyBlocker(response)) {
452
+ console.warn(formatLiveFailure(response, "BalanceInquiry EBT"));
453
+ return;
454
+ }
455
+ expectLiveSuccess(response, ["BalanceInquiry", "SendCommand"]);
456
+ return;
457
+ }
458
+ expect(response.status).toBe("Success");
459
+ expect(response.deviceResponseText).toBe("Success");
460
+ expect(response.deviceResponseCode).toBe("00");
461
+ });
462
+ liveOnlyStory2("[LivePositive] balance() with MC card returns success", async () => {
463
+ const response = await device
464
+ .balance()
465
+ .withEcrId(13)
466
+ .withPaymentMethodType(src_1.PaymentMethodType.Credit)
467
+ .execute();
468
+ expect(response).not.toBeNull();
469
+ expect(response).toBeInstanceOf(TransactionResponse_1.TransactionResponse);
470
+ if (isKnownLiveBalanceBlocker(response)) {
471
+ console.warn(formatLiveFailure(response, "BalanceInquiry Mastercard"));
472
+ return;
473
+ }
474
+ if (isKnownLiveBusyBlocker(response)) {
475
+ console.warn(formatLiveFailure(response, "BalanceInquiry Mastercard"));
476
+ return;
477
+ }
478
+ expectLiveSuccess(response, ["BalanceInquiry", "SendCommand"]);
479
+ expectLiveBalanceResponseFields(response);
480
+ expect(response.cardGroup).toBe("CREDIT");
481
+ expect(response.cardType).toMatch(/^(MASTERCARD|MasterCard|MC)$/i);
482
+ });
483
+ liveOnlyStory2("[LivePositive] balance() returns documented response fields on success", async () => {
484
+ const response = await device
485
+ .balance()
486
+ .withEcrId(13)
487
+ .withPaymentMethodType(src_1.PaymentMethodType.Credit)
488
+ .execute();
489
+ expect(response).not.toBeNull();
490
+ expect(response).toBeInstanceOf(TransactionResponse_1.TransactionResponse);
491
+ if (isKnownLiveBalanceBlocker(response)) {
492
+ console.warn(formatLiveFailure(response, "BalanceInquiry response fields"));
493
+ return;
494
+ }
495
+ if (isKnownLiveBusyBlocker(response)) {
496
+ console.warn(formatLiveFailure(response, "BalanceInquiry response fields"));
497
+ return;
498
+ }
499
+ expectLiveSuccess(response, ["BalanceInquiry", "SendCommand"]);
500
+ expectLiveBalanceResponseFields(response);
501
+ expect(response.cardType).toBeTruthy();
502
+ expect(response.cardGroup).toBeTruthy();
503
+ expect(response.cardHolderName).toBeTruthy();
504
+ });
505
+ liveOnlyStory2("[LivePositive] balance() with EBT populates ebtType and cardGroup", async () => {
506
+ const response = await device
507
+ .balance()
508
+ .withEcrId(13)
509
+ .withPaymentMethodType(src_1.PaymentMethodType.EBT)
510
+ .execute();
511
+ expect(response).not.toBeNull();
512
+ expect(response).toBeInstanceOf(TransactionResponse_1.TransactionResponse);
513
+ expect(["BalanceInquiry", "SendCommand"]).toContain(response.command);
514
+ if (isKnownLiveBusyBlocker(response)) {
515
+ console.warn(formatLiveFailure(response, "BalanceInquiry EBT field validation"));
516
+ return;
517
+ }
518
+ if (isKnownLiveBalanceBlocker(response)) {
519
+ expect(response.cardGroup).toBeTruthy();
520
+ expect(response.ebtType).toBeTruthy();
521
+ expect(response.cardType).toBeTruthy();
522
+ return;
523
+ }
524
+ expectLiveSuccess(response, ["BalanceInquiry", "SendCommand"]);
525
+ expectLiveBalanceResponseFields(response);
526
+ if (response.cardGroup !== "EBT" || !response.ebtType) {
527
+ console.warn("BalanceInquiry EBT field validation requires an actual EBT-presented card; the current live run returned a non-EBT successful balance response.");
528
+ return;
529
+ }
530
+ expect(response.cardGroup).toBe("EBT");
531
+ expect(response.ebtType).toBeTruthy();
532
+ expect(response.cardType).toBeTruthy();
533
+ });
534
+ liveOnlyStory2("[LiveNegative] balance() with invalid target device surfaces device error", async () => {
535
+ const unavailableDevice = DeviceService_1.DeviceService.create(buildConfig());
536
+ unavailableDevice.ecrId = "99999999";
537
+ await expectLiveBalanceFailure(() => unavailableDevice
538
+ .balance()
539
+ .withEcrId(99999999)
540
+ .withPaymentMethodType(src_1.PaymentMethodType.Credit)
541
+ .execute(), "BalanceInquiry invalid target device");
542
+ });
543
+ liveOnlyStory2("[LiveSetup] balance() invalid clerk number documents current terminal behavior", async () => {
544
+ const response = await device
545
+ .balance()
546
+ .withEcrId(13)
547
+ .withClerkId(99999999)
548
+ .withPaymentMethodType(src_1.PaymentMethodType.Credit)
549
+ .execute();
550
+ expect(response).not.toBeNull();
551
+ expect(response).toBeInstanceOf(TransactionResponse_1.TransactionResponse);
552
+ if (isKnownLiveBusyBlocker(response)) {
553
+ console.warn(formatLiveFailure(response, "BalanceInquiry invalid clerk"));
554
+ return;
555
+ }
556
+ if (response.status !== "Success" ||
557
+ response.deviceResponseCode !== "00" ||
558
+ (!!response.responseCode && response.responseCode !== "00")) {
559
+ expect(response.deviceResponseCode).not.toBe("00");
560
+ return;
561
+ }
562
+ console.warn("BalanceInquiry invalid clerk number was accepted by the current terminal configuration.");
563
+ });
564
+ liveOnlyStory2("[LiveSetup] balance() host error omits availableBalance and documents current reference behavior", async () => {
565
+ const response = await device
566
+ .balance()
567
+ .withEcrId(13)
568
+ .withPaymentMethodType(src_1.PaymentMethodType.EBT)
569
+ .execute();
570
+ expect(response).not.toBeNull();
571
+ expect(response).toBeInstanceOf(TransactionResponse_1.TransactionResponse);
572
+ if (isKnownLiveBusyBlocker(response)) {
573
+ console.warn(formatLiveFailure(response, "BalanceInquiry host error"));
574
+ return;
575
+ }
576
+ if (response.deviceResponseCode === "HOST001") {
577
+ expect(response.availableBalance).toBeUndefined();
578
+ return;
579
+ }
580
+ if (response.deviceResponseCode === "APP002") {
581
+ console.warn(formatLiveFailure(response, "BalanceInquiry host error"));
582
+ return;
583
+ }
584
+ console.warn("BalanceInquiry host error scenario was not reproduced in the current live run.");
585
+ });
586
+ test.skip("[EnvDependent] balance() forced transaction timeout requires controlled network or device conditions", () => { });
587
+ test.skip("[CardDependent] balance() EBT not supported for presented card requires a deterministic non-EBT card routing scenario", () => { });
588
+ test.skip("[PhysicalDevice] balance() with low battery requires a device-level APP013 precondition", () => { });
589
+ });
590
+ // ===========================================================================
591
+ // reverse()
592
+ // References:
593
+ // UpaCreditTests.cs – CreditSale_WhenReversedByTerminalRefNumber_ShouldReturnSuccess
594
+ // Assert.AreEqual("00", reverseResponse.DeviceResponseCode);
595
+ // ===========================================================================
596
+ describeUpaStory2("UPA Story 2 – reverse()", () => {
597
+ let device;
598
+ beforeEach(() => {
599
+ device = DeviceService_1.DeviceService.create(buildConfig());
600
+ device.ecrId = "13";
601
+ });
602
+ /**
603
+ * Mirrors UpaCreditTests.cs – CreditSale_WhenReversedByTerminalRefNumber_ShouldReturnSuccess
604
+ * Assert.IsNotNull(reverseResponse);
605
+ * Assert.AreEqual("00", reverseResponse.DeviceResponseCode);
606
+ */
607
+ test("[.] reverse() with TerminalRefNumber returns deviceResponseCode == '00'", async () => {
608
+ let response;
609
+ if (useLiveMic) {
610
+ try {
611
+ const saleResponse = await createLiveSale(device);
612
+ if (saleResponse.deviceResponseCode !== "00") {
613
+ if (isKnownLiveSaleBlocker(saleResponse)) {
614
+ console.warn(formatLiveFailure(saleResponse, "Sale"));
615
+ return;
616
+ }
617
+ throw new Error(formatLiveFailure(saleResponse, "Sale"));
618
+ }
619
+ response = await reverseLiveSaleWithRetry(device, saleResponse.terminalRefNumber);
620
+ }
621
+ catch (error) {
622
+ if (isKnownLiveTransportTimeout(error)) {
623
+ console.warn("Reverse live MIC prerequisite timed out while waiting on the device or gateway.");
624
+ return;
625
+ }
626
+ throw error;
627
+ }
628
+ }
629
+ else {
630
+ response = await device
631
+ .reverse()
632
+ .withTerminalRefNumber("0001234567890123")
633
+ .withEcrId(12)
634
+ .execute();
635
+ }
636
+ expect(response).not.toBeNull();
637
+ expect(response).toBeInstanceOf(TransactionResponse_1.TransactionResponse);
638
+ if (useLiveMic) {
639
+ if (isKnownLiveBusyBlocker(response)) {
640
+ console.warn(formatLiveFailure(response, "Reversal"));
641
+ return;
642
+ }
643
+ expectLiveSuccess(response, ["Reversal", "SendCommand"]);
644
+ return;
645
+ }
646
+ expect(response.deviceResponseCode).toBe("00");
647
+ expect(response.status).toBe("Success");
648
+ });
649
+ // The documented no-tranNo auto-reversal behavior is SI-only. In the current
650
+ // MITC setup this test records the live terminal limitation instead of claiming
651
+ // full spec compliance for the SI fallback path.
652
+ liveOnlyStory2("[LiveSetup] reverse() without tranNo documents current MITC behavior", async () => {
653
+ try {
654
+ const saleResponse = await createLiveSale(device);
655
+ if (saleResponse.deviceResponseCode !== "00") {
656
+ if (isKnownLiveSaleBlocker(saleResponse)) {
657
+ console.warn(formatLiveFailure(saleResponse, "Sale"));
658
+ return;
659
+ }
660
+ throw new Error(formatLiveFailure(saleResponse, "Sale"));
661
+ }
662
+ const response = await reverseLiveSaleWithRetry(device);
663
+ if (isKnownLiveBusyBlocker(response)) {
664
+ console.warn(formatLiveFailure(response, "Reversal auto previous financial transaction"));
665
+ return;
666
+ }
667
+ if (isKnownLiveReverseAutoFallbackBlocker(response)) {
668
+ console.warn("Reverse auto previous financial transaction is not supported in the current MITC configuration; the terminal requires tranNo.");
669
+ return;
670
+ }
671
+ expectLiveSuccess(response, ["Reversal", "SendCommand"]);
672
+ }
673
+ catch (error) {
674
+ if (isKnownLiveTransportTimeout(error)) {
675
+ console.warn("Reverse auto previous financial transaction timed out while waiting on the device or gateway.");
676
+ return;
677
+ }
678
+ throw error;
679
+ }
680
+ });
681
+ liveOnlyStory2("[LivePositive] reverse() returns documented response fields on success", async () => {
682
+ try {
683
+ const saleResponse = await createLiveSale(device);
684
+ if (saleResponse.deviceResponseCode !== "00") {
685
+ if (isKnownLiveSaleBlocker(saleResponse)) {
686
+ console.warn(formatLiveFailure(saleResponse, "Sale"));
687
+ return;
688
+ }
689
+ throw new Error(formatLiveFailure(saleResponse, "Sale"));
690
+ }
691
+ const response = await reverseLiveSaleWithRetry(device, saleResponse.terminalRefNumber);
692
+ if (isKnownLiveBusyBlocker(response)) {
693
+ console.warn(formatLiveFailure(response, "Reversal response field verification"));
694
+ return;
695
+ }
696
+ expectLiveSuccess(response, ["Reversal", "SendCommand"]);
697
+ expectLiveReverseResponseFields(response);
698
+ }
699
+ catch (error) {
700
+ if (isKnownLiveTransportTimeout(error)) {
701
+ console.warn("Reverse response field verification timed out while waiting on the device or gateway.");
702
+ return;
703
+ }
704
+ throw error;
705
+ }
706
+ });
707
+ liveOnlyStory2("[LiveNegative] reverse() already reversed transaction returns failure", async () => {
708
+ try {
709
+ const saleResponse = await createLiveSale(device);
710
+ if (saleResponse.deviceResponseCode !== "00") {
711
+ if (isKnownLiveSaleBlocker(saleResponse)) {
712
+ console.warn(formatLiveFailure(saleResponse, "Sale"));
713
+ return;
714
+ }
715
+ throw new Error(formatLiveFailure(saleResponse, "Sale"));
716
+ }
717
+ const firstReverseResponse = await reverseLiveSaleWithRetry(device, saleResponse.terminalRefNumber);
718
+ if (isKnownLiveBusyBlocker(firstReverseResponse)) {
719
+ console.warn(formatLiveFailure(firstReverseResponse, "Initial reversal"));
720
+ return;
721
+ }
722
+ expectLiveSuccess(firstReverseResponse, ["Reversal", "SendCommand"]);
723
+ await expectLiveReverseFailure(() => reverseLiveSaleWithRetry(device, saleResponse.terminalRefNumber, undefined, 1), "Reversal already reversed transaction");
724
+ }
725
+ catch (error) {
726
+ if (isKnownLiveTransportTimeout(error)) {
727
+ console.warn("Reverse already reversed transaction timed out while waiting on the device or gateway.");
728
+ return;
729
+ }
730
+ throw error;
731
+ }
732
+ });
733
+ liveOnlyStory2("[LiveNegative] reverse() with invalid authorizedAmount returns failure", async () => {
734
+ try {
735
+ const saleResponse = await createLiveSale(device);
736
+ if (saleResponse.deviceResponseCode !== "00") {
737
+ if (isKnownLiveSaleBlocker(saleResponse)) {
738
+ console.warn(formatLiveFailure(saleResponse, "Sale"));
739
+ return;
740
+ }
741
+ throw new Error(formatLiveFailure(saleResponse, "Sale"));
742
+ }
743
+ await expectLiveReverseFailure(() => reverseLiveSaleWithRetry(device, saleResponse.terminalRefNumber, 99.99, 1), "Reversal invalid authorizedAmount");
744
+ }
745
+ catch (error) {
746
+ if (isKnownLiveTransportTimeout(error)) {
747
+ console.warn("Reverse invalid authorizedAmount timed out while waiting on the device or gateway.");
748
+ return;
749
+ }
750
+ throw error;
751
+ }
752
+ });
753
+ liveOnlyStory2("[LivePositive] reverse() debit transaction returns success", async () => {
754
+ try {
755
+ const saleResponse = await createLiveDebitSale(device);
756
+ if (saleResponse.deviceResponseCode !== "00") {
757
+ if (isKnownLiveSaleBlocker(saleResponse)) {
758
+ console.warn(formatLiveFailure(saleResponse, "Debit Sale"));
759
+ return;
760
+ }
761
+ throw new Error(formatLiveFailure(saleResponse, "Debit Sale"));
762
+ }
763
+ const response = await reverseLiveSaleWithRetry(device, saleResponse.terminalRefNumber);
764
+ if (isKnownLiveBusyBlocker(response)) {
765
+ console.warn(formatLiveFailure(response, "Debit Reversal"));
766
+ return;
767
+ }
768
+ expectLiveSuccess(response, ["Reversal", "SendCommand"]);
769
+ expectLiveReverseResponseFields(response);
770
+ if (response.transactionType) {
771
+ expect(response.transactionType.toUpperCase()).toContain("DEBIT");
772
+ }
773
+ }
774
+ catch (error) {
775
+ if (isKnownLiveTransportTimeout(error)) {
776
+ console.warn("Reverse debit transaction timed out while waiting on the device or gateway.");
777
+ return;
778
+ }
779
+ throw error;
780
+ }
781
+ });
782
+ liveOnlyStory2("[LiveNegative] reverse() with invalid target device returns failure", async () => {
783
+ const unavailableDevice = DeviceService_1.DeviceService.create(buildConfig());
784
+ unavailableDevice.ecrId = "99999999";
785
+ await expectLiveReverseFailure(() => unavailableDevice
786
+ .reverse()
787
+ .withEcrId(99999999)
788
+ .withTerminalRefNumber("0001")
789
+ .execute(), "Reversal invalid target device");
790
+ });
791
+ // The following cases are intentionally left as skipped placeholders because
792
+ // they require SI-only reversal fallback behavior or physical device states
793
+ // that are not reproducible from the current MITC automation setup.
794
+ test.skip("[SIOnly] reverse() after non-financial transaction with no previous financial transaction returns TRAN001", () => { });
795
+ test.skip("[SIOnly] reverse() without tranNo on an already voided transaction returns VOID002", () => { });
796
+ test.skip("[MITCLimit] reverse() not accepted in current state returns a deterministic device error", () => { });
797
+ test.skip("[EnvDependent] reverse() forced timeout scenario requires controlled network or device conditions", () => { });
798
+ test.skip("[PhysicalDevice] reverse() on a not-activated device requires a separately provisioned terminal state", () => { });
799
+ test.skip("[PhysicalDevice] reverse() with low battery requires a device-level battery precondition", () => { });
800
+ });
801
+ // ===========================================================================
802
+ // deletePreAuth()
803
+ // References:
804
+ // UpaCreditTests.cs – DeletePreAuth (TCP)
805
+ // Assert.AreEqual("Success", response.DeviceResponseText);
806
+ // Assert.AreEqual("00", response.DeviceResponseCode);
807
+ // UpaMicTests.cs – CreditDeletePreAuth (MIC — Declined on real device)
808
+ // ===========================================================================
809
+ describeUpaStory2("UPA Story 2 – deletePreAuth()", () => {
810
+ let device;
811
+ beforeEach(() => {
812
+ device = DeviceService_1.DeviceService.create(buildConfig());
813
+ device.ecrId = "13";
814
+ });
815
+ /**
816
+ * Mirrors UpaCreditTests.cs – DeletePreAuth
817
+ * Assert.IsNotNull(response);
818
+ * Assert.AreEqual("Success", response.DeviceResponseText);
819
+ * Assert.AreEqual("00", response.DeviceResponseCode);
820
+ */
821
+ test("[UpaCreditTests] deletePreAuth() with transactionId and amount returns Success", async () => {
822
+ let response;
823
+ if (useLiveMic) {
824
+ try {
825
+ const preAuthResponse = await createLivePreAuth(device);
826
+ response = await deletePreAuthWithRetry(device, preAuthResponse.transactionId, 1.0);
827
+ }
828
+ catch (error) {
829
+ if (isKnownLiveTransportTimeout(error)) {
830
+ console.warn("DeletePreAuth live MIC prerequisite timed out while waiting on the device or gateway.");
831
+ return;
832
+ }
833
+ throw error;
834
+ }
835
+ }
836
+ else {
837
+ response = await device
838
+ .deletePreAuth()
839
+ .withEcrId(13)
840
+ .withTransactionId("200071138640")
841
+ .withAmount(1.0)
842
+ .execute();
843
+ }
844
+ expect(response).not.toBeNull();
845
+ expect(response).toBeInstanceOf(TransactionResponse_1.TransactionResponse);
846
+ if (useLiveMic) {
847
+ if (isKnownLiveBusyBlocker(response)) {
848
+ console.warn(formatLiveFailure(response, "DeletePreAuth"));
849
+ return;
850
+ }
851
+ expectLiveSuccess(response, ["DeletePreAuth", "SendCommand"]);
852
+ return;
853
+ }
854
+ expect(response.status).toBe("Success");
855
+ expect(response.deviceResponseText).toBe("Success");
856
+ expect(response.deviceResponseCode).toBe("00");
857
+ });
858
+ liveOnlyStory2("[LiveNegative] deletePreAuth() with unknown reference number returns failure", async () => {
859
+ await expectLiveDeletePreAuthFailure(() => device
860
+ .deletePreAuth()
861
+ .withEcrId(13)
862
+ .withTransactionId("999999999999")
863
+ .withAmount(1.0)
864
+ .execute(), "DeletePreAuth unknown reference number");
865
+ });
866
+ liveOnlyStory2("[LiveNegative] deletePreAuth() without reference number returns failure", async () => {
867
+ await expectLiveDeletePreAuthFailure(() => device
868
+ .deletePreAuth()
869
+ .withEcrId(13)
870
+ .withAmount(1.0)
871
+ .execute(), "DeletePreAuth missing mandatory reference number");
872
+ });
873
+ liveOnlyStory2("[LiveNegative] deletePreAuth() with invalid target device surfaces device error", async () => {
874
+ const unavailableDevice = DeviceService_1.DeviceService.create(buildConfig());
875
+ unavailableDevice.ecrId = "99999999";
876
+ await expectLiveDeletePreAuthFailure(() => unavailableDevice
877
+ .deletePreAuth()
878
+ .withEcrId(99999999)
879
+ .withTransactionId("200015214831")
880
+ .withAmount(1.0)
881
+ .execute(), "DeletePreAuth device error");
882
+ });
883
+ });
884
+ // ===========================================================================
885
+ // startCardTransaction()
886
+ // References:
887
+ // UpaAdminTests.cs – StartCardTransaction_AllCardAcquisitionTypes
888
+ // Assert.AreEqual("Success", response.Status);
889
+ // Assert.AreEqual("00", response.DeviceResponseCode);
890
+ // ===========================================================================
891
+ describeUpaStory2("UPA Story 2 – startCardTransaction()", () => {
892
+ let device;
893
+ beforeEach(() => {
894
+ device = DeviceService_1.DeviceService.create(buildConfig());
895
+ device.ecrId = "13";
896
+ });
897
+ /**
898
+ * Mirrors UpaAdminTests.cs – StartCardTransaction_AllCardAcquisitionTypes
899
+ * Assert.IsNotNull(response);
900
+ * Assert.AreEqual("Success", response.Status);
901
+ test("[UpaAdminTests] startCardTransaction() all acquisition types returns Success", async () => {
902
+ */
903
+ test("[UpaAdminTests] startCardTransaction() all acquisition types returns Success", async () => {
904
+ const param = new UpaParam_1.UpaParam();
905
+ param.acquisitionTypes = [
906
+ AcquisitionType_1.AcquisitionType.Contact,
907
+ AcquisitionType_1.AcquisitionType.Contactless,
908
+ AcquisitionType_1.AcquisitionType.Swipe,
909
+ AcquisitionType_1.AcquisitionType.Manual,
910
+ ];
911
+ param.header = "Sale Transaction";
912
+ param.displayTotalAmount = "Yes";
913
+ param.promptForManual = false;
914
+ param.brandIcon1 = 1;
915
+ param.brandIcon2 = 1;
916
+ param.timeout = 100;
917
+ const indicator = new ProcessIndicator_1.ProcessingIndicator();
918
+ indicator.QuickChip = "Y";
919
+ indicator.CheckLuhn = "N";
920
+ indicator.SecurityCode = "Y";
921
+ indicator.CardTypeFilter = [
922
+ CardTypeFilter_1.CardTypeFilter.VISA,
923
+ CardTypeFilter_1.CardTypeFilter.MC,
924
+ CardTypeFilter_1.CardTypeFilter.AMEX,
925
+ CardTypeFilter_1.CardTypeFilter.DISCOVER,
926
+ ];
927
+ const transData = new UpaTransactionData_1.UpaTransactionData();
928
+ transData.totalAmount = 5.0;
929
+ transData.cashBackAmount = 0.0;
930
+ transData.tranDate = new Date();
931
+ transData.tranTime = new Date();
932
+ transData.transType = Enums_2.TransactionType.Sale;
933
+ let response;
934
+ try {
935
+ response = await device.startCardTransaction(param, indicator, transData);
936
+ }
937
+ catch (error) {
938
+ if (useLiveMic && isKnownLiveTransportTimeout(error)) {
939
+ console.warn("StartCardTransaction all acquisition types timed out while waiting on the device or gateway.");
940
+ return;
941
+ }
942
+ throw error;
943
+ }
944
+ expect(response).not.toBeNull();
945
+ expect(response).toBeInstanceOf(UpaGiftCardResponse_1.UpaGiftCardResponse);
946
+ if (useLiveMic) {
947
+ if (isKnownLiveStartCardTransactionBlocker(response)) {
948
+ console.warn(formatLiveFailure(response, "StartCardTransaction all acquisition types"));
949
+ return;
950
+ }
951
+ expectLiveSuccess(response, "StartCardTransaction");
952
+ expectParsedStartCardTransactionResponse(response);
953
+ return;
954
+ }
955
+ expect(response.status).toBe("Success");
956
+ expect(response.deviceResponseCode).toBe("00");
957
+ });
958
+ /**
959
+ * Mirrors UpaAdminTests.cs – StartCardTransaction (basic, swipe only)
960
+ * Assert.IsNotNull(response);
961
+ * Assert.AreEqual("Success", response.Status);
962
+ */
963
+ test("[UpaAdminTests] startCardTransaction() swipe with GIFT filter returns Success", async () => {
964
+ const param = new UpaParam_1.UpaParam();
965
+ param.timeout = 60;
966
+ param.acquisitionTypes = [AcquisitionType_1.AcquisitionType.Swipe];
967
+ param.header = "Header";
968
+ param.displayTotalAmount = "Y";
969
+ param.promptForManual = true;
970
+ param.brandIcon1 = 4;
971
+ param.brandIcon2 = 3;
972
+ const indicator = new ProcessIndicator_1.ProcessingIndicator();
973
+ indicator.QuickChip = "Y";
974
+ indicator.CheckLuhn = "Y";
975
+ indicator.SecurityCode = "Y";
976
+ indicator.CardTypeFilter = [CardTypeFilter_1.CardTypeFilter.GIFT];
977
+ const transData = new UpaTransactionData_1.UpaTransactionData();
978
+ transData.totalAmount = 11.2;
979
+ transData.cashBackAmount = 2.5;
980
+ transData.tranDate = new Date();
981
+ transData.tranTime = new Date();
982
+ transData.transType = Enums_2.TransactionType.Sale;
983
+ let response;
984
+ try {
985
+ response = await device.startCardTransaction(param, indicator, transData);
986
+ }
987
+ catch (error) {
988
+ if (useLiveMic && isKnownLiveTransportTimeout(error)) {
989
+ console.warn("StartCardTransaction swipe with GIFT filter timed out while waiting on the device or gateway.");
990
+ return;
991
+ }
992
+ throw error;
993
+ }
994
+ expect(response).not.toBeNull();
995
+ if (useLiveMic) {
996
+ if (isKnownLiveGiftCardBlocker(response) ||
997
+ isKnownLiveStartCardTransactionBlocker(response)) {
998
+ console.warn(formatLiveFailure(response, "StartCardTransaction swipe with GIFT filter"));
999
+ return;
1000
+ }
1001
+ expectLiveSuccess(response, "StartCardTransaction");
1002
+ expectParsedStartCardTransactionResponse(response);
1003
+ return;
1004
+ }
1005
+ expect(response.status).toBe("Success");
1006
+ });
1007
+ test("[SdkValidation] startCardTransaction() without acquisitionTypes throws ArgumentError", async () => {
1008
+ const param = new UpaParam_1.UpaParam();
1009
+ param.timeout = 90;
1010
+ param.header = "Missing acquisition types";
1011
+ param.displayTotalAmount = "Yes";
1012
+ const indicator = new ProcessIndicator_1.ProcessingIndicator();
1013
+ indicator.QuickChip = "Y";
1014
+ const transData = new UpaTransactionData_1.UpaTransactionData();
1015
+ transData.totalAmount = 1.0;
1016
+ transData.cashBackAmount = 0.0;
1017
+ transData.tranDate = new Date();
1018
+ transData.tranTime = new Date();
1019
+ transData.transType = Enums_2.TransactionType.Sale;
1020
+ await expect(device.startCardTransaction(param, indicator, transData)).rejects.toMatchObject({
1021
+ name: src_1.ArgumentError.name,
1022
+ message: "acquisitionTypes is required for startCardTransaction",
1023
+ });
1024
+ });
1025
+ test.each([[-1], [Number.NaN], ["invalid"]])("[SdkValidation] startCardTransaction() with invalid totalAmount %p throws ArgumentError", async (invalidTotalAmount) => {
1026
+ const param = new UpaParam_1.UpaParam();
1027
+ param.timeout = 90;
1028
+ param.acquisitionTypes = [AcquisitionType_1.AcquisitionType.Manual];
1029
+ param.header = "Invalid amount";
1030
+ param.displayTotalAmount = "Yes";
1031
+ const indicator = new ProcessIndicator_1.ProcessingIndicator();
1032
+ indicator.QuickChip = "Y";
1033
+ const transData = new UpaTransactionData_1.UpaTransactionData();
1034
+ transData.totalAmount = invalidTotalAmount;
1035
+ transData.cashBackAmount = 0.0;
1036
+ transData.tranDate = new Date();
1037
+ transData.tranTime = new Date();
1038
+ transData.transType = Enums_2.TransactionType.Sale;
1039
+ await expect(device.startCardTransaction(param, indicator, transData)).rejects.toMatchObject({
1040
+ name: src_1.ArgumentError.name,
1041
+ message: "totalAmount must be a non-negative number for startCardTransaction",
1042
+ });
1043
+ });
1044
+ test("[SdkValidation] startCardTransaction() with invalid cardTypeFilter throws ArgumentError", async () => {
1045
+ const param = new UpaParam_1.UpaParam();
1046
+ param.timeout = 90;
1047
+ param.acquisitionTypes = [AcquisitionType_1.AcquisitionType.Manual];
1048
+ param.header = "Invalid card type filter";
1049
+ param.displayTotalAmount = "Yes";
1050
+ const indicator = new ProcessIndicator_1.ProcessingIndicator();
1051
+ indicator.QuickChip = "Y";
1052
+ indicator.CardTypeFilter = ["XYZ"];
1053
+ const transData = new UpaTransactionData_1.UpaTransactionData();
1054
+ transData.totalAmount = 1.0;
1055
+ transData.cashBackAmount = 0.0;
1056
+ transData.tranDate = new Date();
1057
+ transData.tranTime = new Date();
1058
+ transData.transType = Enums_2.TransactionType.Sale;
1059
+ await expect(device.startCardTransaction(param, indicator, transData)).rejects.toMatchObject({
1060
+ name: src_1.ArgumentError.name,
1061
+ message: "cardTypeFilter must contain only supported card types for startCardTransaction",
1062
+ });
1063
+ });
1064
+ liveOnlyStory2("[LiveSetup] startCardTransaction() manual mode with MC filter returns manual entry data", async () => {
1065
+ const param = new UpaParam_1.UpaParam();
1066
+ param.timeout = 90;
1067
+ param.acquisitionTypes = [AcquisitionType_1.AcquisitionType.Manual];
1068
+ param.header = "Manual MC Sale";
1069
+ param.displayTotalAmount = "Yes";
1070
+ param.promptForManual = true;
1071
+ const indicator = new ProcessIndicator_1.ProcessingIndicator();
1072
+ indicator.QuickChip = "Y";
1073
+ indicator.CheckLuhn = "Y";
1074
+ indicator.SecurityCode = "Y";
1075
+ indicator.CardTypeFilter = [CardTypeFilter_1.CardTypeFilter.MC];
1076
+ const transData = new UpaTransactionData_1.UpaTransactionData();
1077
+ transData.totalAmount = 1.0;
1078
+ transData.cashBackAmount = 0.0;
1079
+ transData.tranDate = new Date();
1080
+ transData.tranTime = new Date();
1081
+ transData.transType = Enums_2.TransactionType.Sale;
1082
+ const response = await executeLiveStartCardTransaction(device, param, indicator, transData, "StartCardTransaction manual MC");
1083
+ if (!response) {
1084
+ return;
1085
+ }
1086
+ expect(response.acquisitionType.toUpperCase()).toBe("MANUAL");
1087
+ if (response.cardBrandShortName) {
1088
+ expect(response.cardBrandShortName.toUpperCase()).toBe("MC");
1089
+ }
1090
+ if (response.cardBrand) {
1091
+ expect(response.cardBrand.toUpperCase()).toContain("MASTER");
1092
+ }
1093
+ expect(response.expiryDate).toBeTruthy();
1094
+ expect(response.cvv).toBeTruthy();
1095
+ });
1096
+ liveOnlyStory2("[LiveSetup] startCardTransaction() accepts infinite timeout card entry", async () => {
1097
+ const param = new UpaParam_1.UpaParam();
1098
+ param.timeout = 0;
1099
+ param.acquisitionTypes = [AcquisitionType_1.AcquisitionType.Contact, AcquisitionType_1.AcquisitionType.Swipe];
1100
+ param.header = "Infinite Timeout";
1101
+ param.displayTotalAmount = "Yes";
1102
+ const indicator = new ProcessIndicator_1.ProcessingIndicator();
1103
+ indicator.QuickChip = "Y";
1104
+ indicator.CheckLuhn = "Y";
1105
+ const transData = new UpaTransactionData_1.UpaTransactionData();
1106
+ transData.totalAmount = 1.0;
1107
+ transData.cashBackAmount = 0.0;
1108
+ transData.tranDate = new Date();
1109
+ transData.tranTime = new Date();
1110
+ transData.transType = Enums_2.TransactionType.Sale;
1111
+ const response = await executeLiveStartCardTransaction(device, param, indicator, transData, "StartCardTransaction infinite timeout");
1112
+ if (!response) {
1113
+ return;
1114
+ }
1115
+ expect(response.acquisitionType).toBeTruthy();
1116
+ });
1117
+ liveOnlyStory2("[LiveSetup] startCardTransaction() manual VISA flow returns AVS-capable response data", async () => {
1118
+ const param = new UpaParam_1.UpaParam();
1119
+ param.timeout = 90;
1120
+ param.acquisitionTypes = [AcquisitionType_1.AcquisitionType.Manual];
1121
+ param.header = "Manual VISA Sale";
1122
+ param.displayTotalAmount = "Yes";
1123
+ param.promptForManual = true;
1124
+ const indicator = new ProcessIndicator_1.ProcessingIndicator();
1125
+ indicator.QuickChip = "Y";
1126
+ indicator.CheckLuhn = "Y";
1127
+ indicator.SecurityCode = "Y";
1128
+ indicator.CardTypeFilter = [CardTypeFilter_1.CardTypeFilter.VISA];
1129
+ const transData = new UpaTransactionData_1.UpaTransactionData();
1130
+ transData.totalAmount = 1.0;
1131
+ transData.cashBackAmount = 0.0;
1132
+ transData.tranDate = new Date();
1133
+ transData.tranTime = new Date();
1134
+ transData.transType = Enums_2.TransactionType.Sale;
1135
+ const response = await executeLiveStartCardTransaction(device, param, indicator, transData, "StartCardTransaction manual VISA");
1136
+ if (!response) {
1137
+ return;
1138
+ }
1139
+ expect(response.acquisitionType.toUpperCase()).toBe("MANUAL");
1140
+ if (response.cardBrandShortName) {
1141
+ expect(response.cardBrandShortName.toUpperCase()).toBe("VI");
1142
+ }
1143
+ if (response.cardBrand) {
1144
+ expect(response.cardBrand.toUpperCase()).toContain("VISA");
1145
+ }
1146
+ if (response.avsFlag) {
1147
+ expect(response.avsFlag).toBe("1");
1148
+ }
1149
+ else {
1150
+ console.warn("StartCardTransaction manual VISA did not return AVSFlag on the current device configuration.");
1151
+ }
1152
+ });
1153
+ liveOnlyStory2("[LiveSetup] startCardTransaction() manual AMEX refund flow returns refund card-entry data", async () => {
1154
+ const param = new UpaParam_1.UpaParam();
1155
+ param.timeout = 90;
1156
+ param.acquisitionTypes = [AcquisitionType_1.AcquisitionType.Manual];
1157
+ param.header = "Manual AMEX Refund";
1158
+ param.displayTotalAmount = "Yes";
1159
+ param.promptForManual = true;
1160
+ const indicator = new ProcessIndicator_1.ProcessingIndicator();
1161
+ indicator.QuickChip = "Y";
1162
+ indicator.CheckLuhn = "Y";
1163
+ indicator.SecurityCode = "Y";
1164
+ indicator.CardTypeFilter = [CardTypeFilter_1.CardTypeFilter.AMEX];
1165
+ const transData = new UpaTransactionData_1.UpaTransactionData();
1166
+ transData.totalAmount = 1.0;
1167
+ transData.cashBackAmount = 0.0;
1168
+ transData.tranDate = new Date();
1169
+ transData.tranTime = new Date();
1170
+ transData.transType = Enums_2.TransactionType.Refund;
1171
+ const response = await executeLiveStartCardTransaction(device, param, indicator, transData, "StartCardTransaction manual AMEX refund");
1172
+ if (!response) {
1173
+ return;
1174
+ }
1175
+ expect(response.acquisitionType.toUpperCase()).toBe("MANUAL");
1176
+ if (response.cardBrandShortName &&
1177
+ !["AX", "AMEX"].includes(response.cardBrandShortName.toUpperCase())) {
1178
+ console.warn("StartCardTransaction AMEX refund validation requires an actual AMEX-presented card; the current live run returned a different brand.");
1179
+ return;
1180
+ }
1181
+ if (response.cardBrand &&
1182
+ !response.cardBrand.toUpperCase().includes("AMEX") &&
1183
+ !response.cardBrand.toUpperCase().includes("AMERICAN EXPRESS")) {
1184
+ console.warn("StartCardTransaction AMEX refund validation requires an actual AMEX-presented card; the current live run returned a different brand.");
1185
+ return;
1186
+ }
1187
+ expect(response.expiryDate).toBeTruthy();
1188
+ expect(response.cvv).toBeTruthy();
1189
+ });
1190
+ liveOnlyStory2("[LiveSetup] startCardTransaction() scan mode returns scanned data", async () => {
1191
+ const param = new UpaParam_1.UpaParam();
1192
+ param.timeout = 90;
1193
+ param.acquisitionTypes = [AcquisitionType_1.AcquisitionType.Scan];
1194
+ param.header = "Scan Sale";
1195
+ param.displayTotalAmount = "Yes";
1196
+ const indicator = new ProcessIndicator_1.ProcessingIndicator();
1197
+ indicator.QuickChip = "Y";
1198
+ const transData = new UpaTransactionData_1.UpaTransactionData();
1199
+ transData.totalAmount = 1.0;
1200
+ transData.cashBackAmount = 0.0;
1201
+ transData.tranDate = new Date();
1202
+ transData.tranTime = new Date();
1203
+ transData.transType = Enums_2.TransactionType.Sale;
1204
+ const response = await executeLiveStartCardTransaction(device, param, indicator, transData, "StartCardTransaction scan mode");
1205
+ if (!response) {
1206
+ return;
1207
+ }
1208
+ expect(response.acquisitionType.toUpperCase()).toBe("SCAN");
1209
+ expect(response.scannedData).toBeTruthy();
1210
+ });
1211
+ });
1212
+ // ===========================================================================
1213
+ // reboot()
1214
+ // References:
1215
+ // UpaAdminTests.cs – Reboot: Assert.AreEqual("Success", response.Status)
1216
+ // UpaMicTests.cs – Reboot: Assert.AreEqual("00", response.DeviceResponseCode)
1217
+ // Assert.AreEqual("COMPLETE", response.DeviceResponseText)
1218
+ // (unit test uses mock returning "Success" / "00")
1219
+ // ===========================================================================
1220
+ describeUpaStory2("UPA Story 2 – reboot()", () => {
1221
+ let device;
1222
+ beforeEach(() => {
1223
+ device = DeviceService_1.DeviceService.create(buildConfig());
1224
+ device.ecrId = "13";
1225
+ });
1226
+ /**
1227
+ * Mirrors UpaAdminTests.cs – Reboot + UpaMicTests.cs – Reboot
1228
+ * Assert.IsNotNull(response);
1229
+ * Assert.AreEqual("Success", response.Status);
1230
+ * Assert.AreEqual("00", response.DeviceResponseCode);
1231
+ */
1232
+ test("[UpaAdminTests][UpaMicTests] reboot() returns Success and does not throw", async () => {
1233
+ const response = await device.reboot();
1234
+ expect(response).not.toBeNull();
1235
+ expect(response).toBeInstanceOf(TransactionResponse_1.TransactionResponse);
1236
+ if (useLiveMic) {
1237
+ expectLiveSuccess(response, "Reboot");
1238
+ return;
1239
+ }
1240
+ expect(response.status).toBe("Success");
1241
+ expect(response.deviceResponseCode).toBe("00");
1242
+ });
1243
+ liveOnlyStory2("[LiveSetup] reboot() on inactive or unresponsive terminal documents current routing behavior", async () => {
1244
+ const unavailableDevice = DeviceService_1.DeviceService.create(buildConfig());
1245
+ unavailableDevice.ecrId = "99999999";
1246
+ try {
1247
+ const response = await unavailableDevice.reboot();
1248
+ expect(response).not.toBeNull();
1249
+ expect(response).toBeInstanceOf(TransactionResponse_1.TransactionResponse);
1250
+ if (isKnownLiveBusyBlocker(response)) {
1251
+ console.warn(formatLiveFailure(response, "Reboot inactive or unresponsive terminal"));
1252
+ return;
1253
+ }
1254
+ if (response.status !== "Success" ||
1255
+ response.deviceResponseCode !== "00" ||
1256
+ (!!response.responseCode && response.responseCode !== "00")) {
1257
+ expect(response.deviceResponseCode).not.toBe("00");
1258
+ return;
1259
+ }
1260
+ console.warn("Reboot inactive or unresponsive terminal scenario was accepted by the current terminal routing configuration.");
1261
+ }
1262
+ catch (error) {
1263
+ if (isKnownLiveTransportTimeout(error)) {
1264
+ console.warn("Reboot inactive or unresponsive terminal timed out while waiting on the device or gateway.");
1265
+ return;
1266
+ }
1267
+ expect(error).toBeInstanceOf(Error);
1268
+ expect(error.message).toBeTruthy();
1269
+ }
1270
+ });
1271
+ test("[Negative] reboot() surfaces network or communication failure", async () => {
1272
+ const communicationFailureDevice = DeviceService_1.DeviceService.create(buildConfig({ serviceUrl: "http://127.0.0.1:1" }), "reboot-communication-failure");
1273
+ communicationFailureDevice.ecrId = "13";
1274
+ await expect(communicationFailureDevice.reboot()).rejects.toBeInstanceOf(Error);
1275
+ });
1276
+ });
1277
+ //# sourceMappingURL=UpaStory2Methods.test.js.map