Skip to content

Commit 673d42a

Browse files
committed
Add utils func FetchAndCheckSuccess
1 parent 01ae26e commit 673d42a

File tree

3 files changed

+57
-0
lines changed

3 files changed

+57
-0
lines changed

changes/20250414111304.feature

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
:sparkles: Add an API utils function to wrap API calls and check success

utils/api/api.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,23 @@ func CheckAPICallSuccess(ctx context.Context, errorContext string, resp *_http.R
5858
}
5959
return
6060
}
61+
62+
// FetchAndCheckSuccess is a wrapper for making an API call and then checking success with `CheckAPICallSuccess`
63+
// errorContext corresponds to the description of what led to the error if error there is e.g. `Failed adding a user`.
64+
// apiCallFunc corresponds to a generic function that will be called to make the API call
65+
func FetchAndCheckSuccess[T any](ctx context.Context, errorContext string, apiCallFunc func(ctx context.Context) (T, *_http.Response, error)) (result T, err error) {
66+
if err = parallelisation.DetermineContextError(ctx); err != nil {
67+
return
68+
}
69+
70+
result, resp, apiErr := apiCallFunc(ctx)
71+
if resp != nil && resp.Body != nil {
72+
_ = resp.Body.Close()
73+
}
74+
75+
if err = CheckAPICallSuccess(ctx, errorContext, resp, apiErr); err != nil {
76+
return
77+
}
78+
79+
return
80+
}

utils/api/api_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,3 +75,39 @@ func TestCheckAPICallSuccess(t *testing.T) {
7575
assert.NoError(t, err)
7676
})
7777
}
78+
79+
func TestFetchAndCheckSuccess(t *testing.T) {
80+
t.Run("context cancelled", func(t *testing.T) {
81+
errMessage := "context cancelled"
82+
parentCtx := context.Background()
83+
ctx, cancelCtx := context.WithCancel(parentCtx)
84+
cancelCtx()
85+
_, actualErr := FetchAndCheckSuccess(ctx, errMessage,
86+
func(ctx context.Context) (*struct{}, *_http.Response, error) {
87+
return nil, &_http.Response{Body: io.NopCloser(bytes.NewReader(nil))}, errors.New(errMessage)
88+
})
89+
assert.True(t, commonerrors.Any(actualErr, commonerrors.ErrCancelled))
90+
})
91+
92+
t.Run("api call not successful", func(t *testing.T) {
93+
errMessage := "client error"
94+
parentCtx := context.Background()
95+
_, actualErr := FetchAndCheckSuccess(parentCtx, errMessage,
96+
func(ctx context.Context) (*struct{}, *_http.Response, error) {
97+
resp := _http.Response{StatusCode: 400, Body: io.NopCloser(bytes.NewReader([]byte("{\"message\": \"client error\",\"requestId\": \"761761721\"}")))}
98+
return nil, &resp, errors.New(errMessage)
99+
})
100+
expectedErr := "client error (400): API call error [request-id: 761761721] client error; client error"
101+
assert.Equal(t, actualErr.Error(), expectedErr)
102+
})
103+
104+
t.Run("no context error, api call successful", func(t *testing.T) {
105+
errMessage := "no error"
106+
parentCtx := context.Background()
107+
_, err := FetchAndCheckSuccess(parentCtx, errMessage,
108+
func(ctx context.Context) (*struct{}, *_http.Response, error) {
109+
return nil, &_http.Response{StatusCode: 200}, errors.New(errMessage)
110+
})
111+
assert.NoError(t, err)
112+
})
113+
}

0 commit comments

Comments
 (0)