@@ -13,6 +13,7 @@ import {
1313 type ListResultPromise ,
1414 mapParamsToDto ,
1515 mapQueryToParams ,
16+ getMessageForError ,
1617} from "../src/api-client" ;
1718import { getInternalInstance } from "../src/util" ;
1819import { delay , mountData , mockEndpoint } from "./test-utils" ;
@@ -73,6 +74,125 @@ describe("error handling", () => {
7374 } ) ;
7475} ) ;
7576
77+ describe ( "getMessageForError" , ( ) => {
78+ test ( "returns string error as-is" , ( ) => {
79+ expect ( getMessageForError ( "Custom error message" ) ) . toBe (
80+ "Custom error message" ,
81+ ) ;
82+ } ) ;
83+
84+ test ( "returns standard Error message" , ( ) => {
85+ expect ( getMessageForError ( new Error ( "Error occurred" ) ) ) . toBe (
86+ "Error occurred" ,
87+ ) ;
88+ } ) ;
89+
90+ test ( "returns message from standard Coalesce API response" , ( ) => {
91+ const axiosError = new AxiosError ( "Request failed" ) ;
92+ axiosError . response = {
93+ data : { wasSuccessful : false , message : "Validation failed" } ,
94+ status : 400 ,
95+ statusText : "Bad Request" ,
96+ headers : { } ,
97+ config : { } as any ,
98+ } ;
99+
100+ expect ( getMessageForError ( axiosError ) ) . toBe ( "Validation failed" ) ;
101+ } ) ;
102+
103+ test ( "returns 'Unknown Error' when Coalesce response has empty message" , ( ) => {
104+ const axiosError = new AxiosError ( "Request failed" ) ;
105+ axiosError . response = {
106+ data : { wasSuccessful : false , message : "" } ,
107+ status : 400 ,
108+ statusText : "Bad Request" ,
109+ headers : { } ,
110+ config : { } as any ,
111+ } ;
112+
113+ expect ( getMessageForError ( axiosError ) ) . toBe ( "Unknown Error" ) ;
114+ } ) ;
115+
116+ test ( "returns detail from application/problem+json response" , ( ) => {
117+ const axiosError = new AxiosError ( "Request failed" ) ;
118+ axiosError . response = {
119+ data : {
120+ type : "https://example.com/probs/out-of-credit" ,
121+ title : "You do not have enough credit." ,
122+ detail : "Your current balance is 30, but that costs 50." ,
123+ status : 403 ,
124+ } ,
125+ status : 403 ,
126+ statusText : "Forbidden" ,
127+ headers : { "content-type" : "application/problem+json; charset=utf-8" } ,
128+ config : { } as any ,
129+ } ;
130+
131+ expect ( getMessageForError ( axiosError ) ) . toBe (
132+ "Your current balance is 30, but that costs 50." ,
133+ ) ;
134+ } ) ;
135+
136+ test ( "returns title from application/problem+json when detail is missing" , ( ) => {
137+ const axiosError = new AxiosError ( "Request failed" ) ;
138+ axiosError . response = {
139+ data : {
140+ type : "https://example.com/probs/forbidden" ,
141+ title : "Access denied" ,
142+ status : 403 ,
143+ } ,
144+ status : 403 ,
145+ statusText : "Forbidden" ,
146+ headers : { "content-type" : "application/problem+json" } ,
147+ config : { } as any ,
148+ } ;
149+
150+ expect ( getMessageForError ( axiosError ) ) . toBe ( "Access denied" ) ;
151+ } ) ;
152+
153+ test ( "returns axios message with status text appended" , ( ) => {
154+ const axiosError = new AxiosError ( "Request failed with status code 403" ) ;
155+ axiosError . response = {
156+ data : { } ,
157+ status : 403 ,
158+ statusText : "Forbidden" ,
159+ headers : { } ,
160+ config : { } as any ,
161+ } ;
162+
163+ expect ( getMessageForError ( axiosError ) ) . toBe (
164+ "Request failed with status code 403 (Forbidden)" ,
165+ ) ;
166+ } ) ;
167+
168+ test ( "does not append status text if already in message" , ( ) => {
169+ const axiosError = new AxiosError ( "Request failed: Forbidden" ) ;
170+ axiosError . response = {
171+ data : { } ,
172+ status : 403 ,
173+ statusText : "Forbidden" ,
174+ headers : { } ,
175+ config : { } as any ,
176+ } ;
177+
178+ expect ( getMessageForError ( axiosError ) ) . toBe ( "Request failed: Forbidden" ) ;
179+ } ) ;
180+
181+ test ( "returns generic message for axios error without response" , ( ) => {
182+ const axiosError = new AxiosError ( "Network Error" ) ;
183+ // No response set
184+ expect ( getMessageForError ( axiosError ) ) . toBe ( "Network Error" ) ;
185+ } ) ;
186+
187+ test ( "returns 'An unknown error occurred' for null" , ( ) => {
188+ expect ( getMessageForError ( null ) ) . toBe ( "An unknown error occurred" ) ;
189+ } ) ;
190+
191+ test ( "returns 'An unknown error occurred' for undefined" , ( ) => {
192+ expect ( getMessageForError ( undefined ) ) . toBe ( "An unknown error occurred" ) ;
193+ } ) ;
194+ } ) ;
195+
76196describe ( "$useSimultaneousRequestCaching" , ( ) => {
77197 test ( "uses proper cache key for standard method" , async ( ) => {
78198 const mock = ( AxiosClient . defaults . adapter = vitest
@@ -1551,15 +1671,19 @@ describe("ModelApiClient", () => {
15511671 } ) ;
15521672
15531673 test ( "refResponse is ignored for file-returning methods" , async ( ) => {
1554- const mock = ( AxiosClient . defaults . adapter = vitest . fn ( ) . mockResolvedValue ( < AxiosResponse < any > > {
1555- data : new Blob ( ) ,
1556- status : 200 ,
1557- } ) ) ;
1674+ const mock = ( AxiosClient . defaults . adapter = vitest
1675+ . fn ( )
1676+ . mockResolvedValue ( < AxiosResponse < any > > {
1677+ data : new Blob ( ) ,
1678+ status : 200 ,
1679+ } ) ) ;
15581680
15591681 const client = new ComplexModelApiClient ( ) ;
1560-
1682+
15611683 // Create a caller with refResponse enabled for a file-returning method
1562- const caller = client . $makeCaller ( "item" , ( c ) => c . downloadAttachment ( 1 ) ) . useRefResponse ( ) ;
1684+ const caller = client
1685+ . $makeCaller ( "item" , ( c ) => c . downloadAttachment ( 1 ) )
1686+ . useRefResponse ( ) ;
15631687
15641688 await caller ( ) ;
15651689
0 commit comments