diff --git a/.mockery.yaml b/.mockery.yaml index a0cc9cce..9a8153db 100644 --- a/.mockery.yaml +++ b/.mockery.yaml @@ -10,3 +10,6 @@ packages: github.com/ministryofjustice/opg-data-lpa-store/internal/event: github.com/ministryofjustice/opg-data-lpa-store/internal/objectstore: github.com/ministryofjustice/opg-data-lpa-store/internal/shared: + github.com/ministryofjustice/opg-data-lpa-store/lambda/create: + github.com/ministryofjustice/opg-data-lpa-store/lambda/get: + github.com/ministryofjustice/opg-data-lpa-store/lambda/getlist: diff --git a/lambda/create/main.go b/lambda/create/main.go index f9967604..ce8c17dd 100644 --- a/lambda/create/main.go +++ b/lambda/create/main.go @@ -49,9 +49,12 @@ type Lambda struct { store Store verifier Verifier logger Logger + now func() time.Time } func (l *Lambda) HandleEvent(ctx context.Context, req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) { + uid := req.PathParameters["uid"] + _, err := l.verifier.VerifyHeader(req) if err != nil { l.logger.Info("Unable to verify JWT from header") @@ -60,9 +63,6 @@ func (l *Lambda) HandleEvent(ctx context.Context, req events.APIGatewayProxyRequ l.logger.Debug("Successfully parsed JWT from event header") - var input shared.LpaInit - uid := req.PathParameters["uid"] - response := events.APIGatewayProxyResponse{ StatusCode: 500, Body: "{\"code\":\"INTERNAL_SERVER_ERROR\",\"detail\":\"Internal server error\"}", @@ -82,8 +82,8 @@ func (l *Lambda) HandleEvent(ctx context.Context, req events.APIGatewayProxyRequ return problem.Respond() } - err = json.Unmarshal([]byte(req.Body), &input) - if err != nil { + var input shared.LpaInit + if err := json.Unmarshal([]byte(req.Body), &input); err != nil { l.logger.Error("error unmarshalling request", slog.Any("err", err)) return shared.ProblemInternalServerError.Respond() } @@ -91,7 +91,7 @@ func (l *Lambda) HandleEvent(ctx context.Context, req events.APIGatewayProxyRequ // validation if errs := Validate(input); len(errs) > 0 { if input.Channel == shared.ChannelPaper { - l.logger.Info("encountered validation errors in lpa", slog.Any("uid", uid)) + l.logger.Info("encountered validation errors in lpa", slog.String("uid", uid)) } else { problem := shared.ProblemInvalidRequest problem.Errors = errs @@ -100,10 +100,12 @@ func (l *Lambda) HandleEvent(ctx context.Context, req events.APIGatewayProxyRequ } } - data := shared.Lpa{LpaInit: input} - data.Uid = uid - data.Status = shared.LpaStatusInProgress - data.UpdatedAt = time.Now() + data := shared.Lpa{ + LpaInit: input, + Uid: uid, + Status: shared.LpaStatusInProgress, + UpdatedAt: l.now(), + } if data.Channel == shared.ChannelPaper && len(input.RestrictionsAndConditionsImages) > 0 { data.RestrictionsAndConditionsImages = make([]shared.File, len(input.RestrictionsAndConditionsImages)) @@ -111,7 +113,6 @@ func (l *Lambda) HandleEvent(ctx context.Context, req events.APIGatewayProxyRequ path := fmt.Sprintf("%s/scans/rc_%d_%s", data.Uid, i, image.Filename) data.RestrictionsAndConditionsImages[i], err = l.staticLpaStorage.UploadFile(ctx, image, path) - if err != nil { l.logger.Error("error saving restrictions and conditions image", slog.Any("err", err)) return shared.ProblemInternalServerError.Respond() @@ -120,7 +121,7 @@ func (l *Lambda) HandleEvent(ctx context.Context, req events.APIGatewayProxyRequ } // save - if err = l.store.Put(ctx, data); err != nil { + if err := l.store.Put(ctx, data); err != nil { l.logger.Error("error saving LPA", slog.Any("err", err)) return shared.ProblemInternalServerError.Respond() } @@ -128,18 +129,16 @@ func (l *Lambda) HandleEvent(ctx context.Context, req events.APIGatewayProxyRequ // save to static storage as JSON objectKey := fmt.Sprintf("%s/donor-executed-lpa.json", data.Uid) - if err = l.staticLpaStorage.Put(ctx, objectKey, data); err != nil { + if err := l.staticLpaStorage.Put(ctx, objectKey, data); err != nil { l.logger.Error("error saving static record", slog.Any("err", err)) return shared.ProblemInternalServerError.Respond() } // send lpa-updated event - err = l.eventClient.SendLpaUpdated(ctx, event.LpaUpdated{ + if err := l.eventClient.SendLpaUpdated(ctx, event.LpaUpdated{ Uid: uid, ChangeType: "CREATE", - }) - - if err != nil { + }); err != nil { l.logger.Error("unexpected error occurred", slog.Any("err", err)) } @@ -179,6 +178,7 @@ func main() { ), verifier: shared.NewJWTVerifier(cfg, logger), logger: logger, + now: time.Now, } lambda.Start(l.HandleEvent) diff --git a/lambda/create/main_test.go b/lambda/create/main_test.go new file mode 100644 index 00000000..78c7a653 --- /dev/null +++ b/lambda/create/main_test.go @@ -0,0 +1,459 @@ +package main + +import ( + "context" + "encoding/json" + "errors" + "log/slog" + "testing" + "time" + + "github.com/aws/aws-lambda-go/events" + "github.com/ministryofjustice/opg-data-lpa-store/internal/event" + "github.com/ministryofjustice/opg-data-lpa-store/internal/shared" + "github.com/stretchr/testify/assert" + mock "github.com/stretchr/testify/mock" +) + +var ( + ctx = context.WithValue(context.Background(), (*string)(nil), "testing") + expectedError = errors.New("err") + testNow = time.Date(2024, time.January, 2, 12, 13, 14, 15, time.UTC) + testNowFn = func() time.Time { return testNow } + validLpaInit = shared.LpaInit{ + LpaType: shared.LpaTypePropertyAndAffairs, + Channel: shared.ChannelOnline, + Donor: shared.Donor{ + Person: shared.Person{ + UID: "a06daa09-750d-4e02-9877-0ea782491014", + FirstNames: "donor-firstname", + LastName: "donor-lastname", + Address: shared.Address{ + Line1: "donor-line1", + Country: "GB", + }, + }, + DateOfBirth: makeDate("2020-01-02"), + Email: "donor-email", + ContactLanguagePreference: shared.LangEn, + }, + Attorneys: []shared.Attorney{{ + Person: shared.Person{ + UID: "c442a9a2-9d14-48ca-9cfa-d30d591b0d68", + FirstNames: "attorney-firstname", + LastName: "attorney-lastname", + Address: shared.Address{ + Line1: "attorney-line1", + Country: "GB", + }, + }, + DateOfBirth: makeDate("2020-02-03"), + ContactLanguagePreference: shared.LangEn, + Status: shared.AttorneyStatusActive, + Channel: shared.ChannelPaper, + }}, + CertificateProvider: shared.CertificateProvider{ + Person: shared.Person{ + UID: "e9751c0a-0504-4ec6-942e-b85fddbbd178", + FirstNames: "certificate-provider-firstname", + LastName: "certificate-provider-lastname", + Address: shared.Address{ + Line1: "certificate-provider-line1", + Country: "GB", + }, + }, + Channel: shared.ChannelOnline, + Email: "certificate-provider-email", + Phone: "0777777777", + ContactLanguagePreference: shared.LangEn, + }, + WhenTheLpaCanBeUsed: shared.CanUseWhenHasCapacity, + SignedAt: testNow, + } +) + +func makeDate(s string) shared.Date { + d := &shared.Date{} + _ = d.UnmarshalText([]byte(s)) + return *d +} + +func TestLambdaHandleEvent(t *testing.T) { + for _, channel := range []shared.Channel{shared.ChannelOnline, shared.ChannelPaper} { + t.Run(string(channel), func(t *testing.T) { + lpaInit := validLpaInit + lpaInit.Channel = channel + body, _ := json.Marshal(lpaInit) + + lpa := shared.Lpa{ + Uid: "my-uid", + Status: shared.LpaStatusInProgress, + UpdatedAt: testNow, + LpaInit: lpaInit, + } + + req := events.APIGatewayProxyRequest{ + PathParameters: map[string]string{"uid": "my-uid"}, + Body: string(body), + } + + verifier := newMockVerifier(t) + verifier.EXPECT(). + VerifyHeader(req). + Return(nil, nil) + + logger := newMockLogger(t) + logger.EXPECT(). + Debug("Successfully parsed JWT from event header") + + store := newMockStore(t) + store.EXPECT(). + Get(ctx, "my-uid"). + Return(shared.Lpa{}, nil) + store.EXPECT(). + Put(ctx, lpa). + Return(nil) + + staticLpaStorage := newMockS3Client(t) + staticLpaStorage.EXPECT(). + Put(ctx, "my-uid/donor-executed-lpa.json", lpa). + Return(nil) + + eventClient := newMockEventClient(t) + eventClient.EXPECT(). + SendLpaUpdated(ctx, event.LpaUpdated{ + Uid: "my-uid", + ChangeType: "CREATE", + }). + Return(nil) + + lambda := &Lambda{ + verifier: verifier, + logger: logger, + store: store, + staticLpaStorage: staticLpaStorage, + eventClient: eventClient, + now: testNowFn, + } + + resp, err := lambda.HandleEvent(ctx, req) + assert.Nil(t, err) + assert.Equal(t, events.APIGatewayProxyResponse{ + StatusCode: 201, + Body: "{}", + }, resp) + }) + } +} + +func TestLambdaHandleEventWhenPaperSubmissionContainsImages(t *testing.T) { + lpaInit := validLpaInit + lpaInit.Channel = shared.ChannelPaper + lpaInit.RestrictionsAndConditionsImages = []shared.FileUpload{{ + Filename: "restriction.jpg", + Data: "some-base64", + }} + body, _ := json.Marshal(lpaInit) + + lpa := shared.Lpa{ + Uid: "my-uid", + Status: shared.LpaStatusInProgress, + UpdatedAt: testNow, + LpaInit: lpaInit, + } + lpa.RestrictionsAndConditionsImages = []shared.File{{Path: "a", Hash: "b"}} + + req := events.APIGatewayProxyRequest{ + PathParameters: map[string]string{"uid": "my-uid"}, + Body: string(body), + } + + verifier := newMockVerifier(t) + verifier.EXPECT(). + VerifyHeader(req). + Return(nil, nil) + + logger := newMockLogger(t) + logger.EXPECT(). + Debug("Successfully parsed JWT from event header") + + store := newMockStore(t) + store.EXPECT(). + Get(ctx, "my-uid"). + Return(shared.Lpa{}, nil) + store.EXPECT(). + Put(ctx, lpa). + Return(nil) + + staticLpaStorage := newMockS3Client(t) + staticLpaStorage.EXPECT(). + Put(ctx, "my-uid/donor-executed-lpa.json", lpa). + Return(nil) + staticLpaStorage.EXPECT(). + UploadFile(ctx, shared.FileUpload{Filename: "restriction.jpg", Data: "some-base64"}, "my-uid/scans/rc_0_restriction.jpg"). + Return(shared.File{Path: "a", Hash: "b"}, nil) + + eventClient := newMockEventClient(t) + eventClient.EXPECT(). + SendLpaUpdated(ctx, event.LpaUpdated{ + Uid: "my-uid", + ChangeType: "CREATE", + }). + Return(nil) + + lambda := &Lambda{ + verifier: verifier, + logger: logger, + store: store, + staticLpaStorage: staticLpaStorage, + eventClient: eventClient, + now: testNowFn, + } + + resp, err := lambda.HandleEvent(ctx, req) + assert.Nil(t, err) + assert.Equal(t, events.APIGatewayProxyResponse{ + StatusCode: 201, + Body: "{}", + }, resp) +} + +func TestLambdaHandleEventWhenPaperSubmissionHasValidationErrors(t *testing.T) { + lpaInit := validLpaInit + lpaInit.Channel = shared.ChannelPaper + lpaInit.WhenTheLpaCanBeUsed = shared.CanUseUnset + body, _ := json.Marshal(lpaInit) + + lpa := shared.Lpa{ + Uid: "my-uid", + Status: shared.LpaStatusInProgress, + UpdatedAt: testNow, + LpaInit: lpaInit, + } + + req := events.APIGatewayProxyRequest{ + PathParameters: map[string]string{"uid": "my-uid"}, + Body: string(body), + } + + verifier := newMockVerifier(t) + verifier.EXPECT(). + VerifyHeader(req). + Return(nil, nil) + + logger := newMockLogger(t) + logger.EXPECT(). + Debug("Successfully parsed JWT from event header") + logger.EXPECT(). + Info("encountered validation errors in lpa", slog.String("uid", "my-uid")) + + store := newMockStore(t) + store.EXPECT(). + Get(ctx, "my-uid"). + Return(shared.Lpa{}, nil) + store.EXPECT(). + Put(ctx, lpa). + Return(nil) + + staticLpaStorage := newMockS3Client(t) + staticLpaStorage.EXPECT(). + Put(ctx, "my-uid/donor-executed-lpa.json", lpa). + Return(nil) + + eventClient := newMockEventClient(t) + eventClient.EXPECT(). + SendLpaUpdated(ctx, event.LpaUpdated{ + Uid: "my-uid", + ChangeType: "CREATE", + }). + Return(nil) + + lambda := &Lambda{ + verifier: verifier, + logger: logger, + store: store, + staticLpaStorage: staticLpaStorage, + eventClient: eventClient, + now: testNowFn, + } + + resp, err := lambda.HandleEvent(ctx, req) + assert.Nil(t, err) + assert.Equal(t, events.APIGatewayProxyResponse{ + StatusCode: 201, + Body: "{}", + }, resp) +} + +func TestLambdaHandleEventWhenUnauthorised(t *testing.T) { + req := events.APIGatewayProxyRequest{ + PathParameters: map[string]string{"uid": "my-uid"}, + Body: "{}", + } + + verifier := newMockVerifier(t) + verifier.EXPECT(). + VerifyHeader(req). + Return(nil, expectedError) + + logger := newMockLogger(t) + logger.EXPECT(). + Info("Unable to verify JWT from header") + + lambda := &Lambda{ + verifier: verifier, + logger: logger, + now: testNowFn, + } + + resp, err := lambda.HandleEvent(ctx, req) + assert.Nil(t, err) + assert.Equal(t, events.APIGatewayProxyResponse{ + StatusCode: 401, + Body: `{"code":"UNAUTHORISED","detail":"Invalid JWT"}`, + }, resp) +} + +func TestLambdaHandleEventWhenLpaAlreadyExists(t *testing.T) { + req := events.APIGatewayProxyRequest{ + PathParameters: map[string]string{"uid": "my-uid"}, + Body: "{}", + } + + verifier := newMockVerifier(t) + verifier.EXPECT(). + VerifyHeader(req). + Return(nil, nil) + + logger := newMockLogger(t) + logger.EXPECT(). + Debug("Successfully parsed JWT from event header") + + store := newMockStore(t) + store.EXPECT(). + Get(ctx, "my-uid"). + Return(shared.Lpa{Uid: "my-uid"}, nil) + + lambda := &Lambda{ + verifier: verifier, + logger: logger, + store: store, + now: testNowFn, + } + + resp, err := lambda.HandleEvent(ctx, req) + assert.Nil(t, err) + assert.Equal(t, events.APIGatewayProxyResponse{ + StatusCode: 400, + Body: `{"code":"INVALID_REQUEST","detail":"LPA with UID already exists"}`, + }, resp) +} + +func TestLambdaHandleEventWhenUploadFileErrors(t *testing.T) { + lpaInit := validLpaInit + lpaInit.Channel = shared.ChannelPaper + lpaInit.RestrictionsAndConditionsImages = []shared.FileUpload{{ + Filename: "restriction.jpg", + Data: "some-base64", + }} + body, _ := json.Marshal(lpaInit) + + req := events.APIGatewayProxyRequest{ + PathParameters: map[string]string{"uid": "my-uid"}, + Body: string(body), + } + + verifier := newMockVerifier(t) + verifier.EXPECT(). + VerifyHeader(req). + Return(nil, nil) + + logger := newMockLogger(t) + logger.EXPECT(). + Debug("Successfully parsed JWT from event header") + logger.EXPECT(). + Error("error saving restrictions and conditions image", slog.Any("err", expectedError)) + + store := newMockStore(t) + store.EXPECT(). + Get(ctx, "my-uid"). + Return(shared.Lpa{}, nil) + + staticLpaStorage := newMockS3Client(t) + staticLpaStorage.EXPECT(). + UploadFile(ctx, shared.FileUpload{Filename: "restriction.jpg", Data: "some-base64"}, "my-uid/scans/rc_0_restriction.jpg"). + Return(shared.File{}, expectedError) + + lambda := &Lambda{ + verifier: verifier, + logger: logger, + store: store, + staticLpaStorage: staticLpaStorage, + now: testNowFn, + } + + resp, err := lambda.HandleEvent(ctx, req) + assert.Nil(t, err) + assert.Equal(t, events.APIGatewayProxyResponse{ + StatusCode: 500, + Body: `{"code":"INTERNAL_SERVER_ERROR","detail":"Internal server error"}`, + }, resp) +} + +func TestLambdaHandleEventWhenSendLpaUpdatedErrors(t *testing.T) { + lpaInit := validLpaInit + body, _ := json.Marshal(lpaInit) + + req := events.APIGatewayProxyRequest{ + PathParameters: map[string]string{"uid": "my-uid"}, + Body: string(body), + } + + verifier := newMockVerifier(t) + verifier.EXPECT(). + VerifyHeader(req). + Return(nil, nil) + + logger := newMockLogger(t) + logger.EXPECT(). + Debug("Successfully parsed JWT from event header") + logger.EXPECT(). + Error("unexpected error occurred", slog.Any("err", expectedError)) + + store := newMockStore(t) + store.EXPECT(). + Get(ctx, "my-uid"). + Return(shared.Lpa{}, nil) + store.EXPECT(). + Put(ctx, mock.Anything). + Return(nil) + + staticLpaStorage := newMockS3Client(t) + staticLpaStorage.EXPECT(). + Put(ctx, "my-uid/donor-executed-lpa.json", mock.Anything). + Return(nil) + + eventClient := newMockEventClient(t) + eventClient.EXPECT(). + SendLpaUpdated(ctx, event.LpaUpdated{ + Uid: "my-uid", + ChangeType: "CREATE", + }). + Return(expectedError) + + lambda := &Lambda{ + verifier: verifier, + logger: logger, + store: store, + staticLpaStorage: staticLpaStorage, + eventClient: eventClient, + now: testNowFn, + } + + resp, err := lambda.HandleEvent(ctx, req) + assert.Nil(t, err) + assert.Equal(t, events.APIGatewayProxyResponse{ + StatusCode: 201, + Body: "{}", + }, resp) +} diff --git a/lambda/create/mock_EventClient_test.go b/lambda/create/mock_EventClient_test.go new file mode 100644 index 00000000..62d69c0a --- /dev/null +++ b/lambda/create/mock_EventClient_test.go @@ -0,0 +1,84 @@ +// Code generated by mockery v2.42.2. DO NOT EDIT. + +package main + +import ( + context "context" + + event "github.com/ministryofjustice/opg-data-lpa-store/internal/event" + mock "github.com/stretchr/testify/mock" +) + +// mockEventClient is an autogenerated mock type for the EventClient type +type mockEventClient struct { + mock.Mock +} + +type mockEventClient_Expecter struct { + mock *mock.Mock +} + +func (_m *mockEventClient) EXPECT() *mockEventClient_Expecter { + return &mockEventClient_Expecter{mock: &_m.Mock} +} + +// SendLpaUpdated provides a mock function with given fields: ctx, _a1 +func (_m *mockEventClient) SendLpaUpdated(ctx context.Context, _a1 event.LpaUpdated) error { + ret := _m.Called(ctx, _a1) + + if len(ret) == 0 { + panic("no return value specified for SendLpaUpdated") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, event.LpaUpdated) error); ok { + r0 = rf(ctx, _a1) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// mockEventClient_SendLpaUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendLpaUpdated' +type mockEventClient_SendLpaUpdated_Call struct { + *mock.Call +} + +// SendLpaUpdated is a helper method to define mock.On call +// - ctx context.Context +// - _a1 event.LpaUpdated +func (_e *mockEventClient_Expecter) SendLpaUpdated(ctx interface{}, _a1 interface{}) *mockEventClient_SendLpaUpdated_Call { + return &mockEventClient_SendLpaUpdated_Call{Call: _e.mock.On("SendLpaUpdated", ctx, _a1)} +} + +func (_c *mockEventClient_SendLpaUpdated_Call) Run(run func(ctx context.Context, _a1 event.LpaUpdated)) *mockEventClient_SendLpaUpdated_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(event.LpaUpdated)) + }) + return _c +} + +func (_c *mockEventClient_SendLpaUpdated_Call) Return(_a0 error) *mockEventClient_SendLpaUpdated_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockEventClient_SendLpaUpdated_Call) RunAndReturn(run func(context.Context, event.LpaUpdated) error) *mockEventClient_SendLpaUpdated_Call { + _c.Call.Return(run) + return _c +} + +// newMockEventClient creates a new instance of mockEventClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func newMockEventClient(t interface { + mock.TestingT + Cleanup(func()) +}) *mockEventClient { + mock := &mockEventClient{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/lambda/create/mock_Logger_test.go b/lambda/create/mock_Logger_test.go new file mode 100644 index 00000000..9c2a803a --- /dev/null +++ b/lambda/create/mock_Logger_test.go @@ -0,0 +1,164 @@ +// Code generated by mockery v2.42.2. DO NOT EDIT. + +package main + +import mock "github.com/stretchr/testify/mock" + +// mockLogger is an autogenerated mock type for the Logger type +type mockLogger struct { + mock.Mock +} + +type mockLogger_Expecter struct { + mock *mock.Mock +} + +func (_m *mockLogger) EXPECT() *mockLogger_Expecter { + return &mockLogger_Expecter{mock: &_m.Mock} +} + +// Debug provides a mock function with given fields: _a0, _a1 +func (_m *mockLogger) Debug(_a0 string, _a1 ...interface{}) { + var _ca []interface{} + _ca = append(_ca, _a0) + _ca = append(_ca, _a1...) + _m.Called(_ca...) +} + +// mockLogger_Debug_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Debug' +type mockLogger_Debug_Call struct { + *mock.Call +} + +// Debug is a helper method to define mock.On call +// - _a0 string +// - _a1 ...interface{} +func (_e *mockLogger_Expecter) Debug(_a0 interface{}, _a1 ...interface{}) *mockLogger_Debug_Call { + return &mockLogger_Debug_Call{Call: _e.mock.On("Debug", + append([]interface{}{_a0}, _a1...)...)} +} + +func (_c *mockLogger_Debug_Call) Run(run func(_a0 string, _a1 ...interface{})) *mockLogger_Debug_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]interface{}, len(args)-1) + for i, a := range args[1:] { + if a != nil { + variadicArgs[i] = a.(interface{}) + } + } + run(args[0].(string), variadicArgs...) + }) + return _c +} + +func (_c *mockLogger_Debug_Call) Return() *mockLogger_Debug_Call { + _c.Call.Return() + return _c +} + +func (_c *mockLogger_Debug_Call) RunAndReturn(run func(string, ...interface{})) *mockLogger_Debug_Call { + _c.Call.Return(run) + return _c +} + +// Error provides a mock function with given fields: _a0, _a1 +func (_m *mockLogger) Error(_a0 string, _a1 ...interface{}) { + var _ca []interface{} + _ca = append(_ca, _a0) + _ca = append(_ca, _a1...) + _m.Called(_ca...) +} + +// mockLogger_Error_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Error' +type mockLogger_Error_Call struct { + *mock.Call +} + +// Error is a helper method to define mock.On call +// - _a0 string +// - _a1 ...interface{} +func (_e *mockLogger_Expecter) Error(_a0 interface{}, _a1 ...interface{}) *mockLogger_Error_Call { + return &mockLogger_Error_Call{Call: _e.mock.On("Error", + append([]interface{}{_a0}, _a1...)...)} +} + +func (_c *mockLogger_Error_Call) Run(run func(_a0 string, _a1 ...interface{})) *mockLogger_Error_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]interface{}, len(args)-1) + for i, a := range args[1:] { + if a != nil { + variadicArgs[i] = a.(interface{}) + } + } + run(args[0].(string), variadicArgs...) + }) + return _c +} + +func (_c *mockLogger_Error_Call) Return() *mockLogger_Error_Call { + _c.Call.Return() + return _c +} + +func (_c *mockLogger_Error_Call) RunAndReturn(run func(string, ...interface{})) *mockLogger_Error_Call { + _c.Call.Return(run) + return _c +} + +// Info provides a mock function with given fields: _a0, _a1 +func (_m *mockLogger) Info(_a0 string, _a1 ...interface{}) { + var _ca []interface{} + _ca = append(_ca, _a0) + _ca = append(_ca, _a1...) + _m.Called(_ca...) +} + +// mockLogger_Info_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Info' +type mockLogger_Info_Call struct { + *mock.Call +} + +// Info is a helper method to define mock.On call +// - _a0 string +// - _a1 ...interface{} +func (_e *mockLogger_Expecter) Info(_a0 interface{}, _a1 ...interface{}) *mockLogger_Info_Call { + return &mockLogger_Info_Call{Call: _e.mock.On("Info", + append([]interface{}{_a0}, _a1...)...)} +} + +func (_c *mockLogger_Info_Call) Run(run func(_a0 string, _a1 ...interface{})) *mockLogger_Info_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]interface{}, len(args)-1) + for i, a := range args[1:] { + if a != nil { + variadicArgs[i] = a.(interface{}) + } + } + run(args[0].(string), variadicArgs...) + }) + return _c +} + +func (_c *mockLogger_Info_Call) Return() *mockLogger_Info_Call { + _c.Call.Return() + return _c +} + +func (_c *mockLogger_Info_Call) RunAndReturn(run func(string, ...interface{})) *mockLogger_Info_Call { + _c.Call.Return(run) + return _c +} + +// newMockLogger creates a new instance of mockLogger. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func newMockLogger(t interface { + mock.TestingT + Cleanup(func()) +}) *mockLogger { + mock := &mockLogger{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/lambda/create/mock_S3Client_test.go b/lambda/create/mock_S3Client_test.go new file mode 100644 index 00000000..8b141ee2 --- /dev/null +++ b/lambda/create/mock_S3Client_test.go @@ -0,0 +1,143 @@ +// Code generated by mockery v2.42.2. DO NOT EDIT. + +package main + +import ( + context "context" + + shared "github.com/ministryofjustice/opg-data-lpa-store/internal/shared" + mock "github.com/stretchr/testify/mock" +) + +// mockS3Client is an autogenerated mock type for the S3Client type +type mockS3Client struct { + mock.Mock +} + +type mockS3Client_Expecter struct { + mock *mock.Mock +} + +func (_m *mockS3Client) EXPECT() *mockS3Client_Expecter { + return &mockS3Client_Expecter{mock: &_m.Mock} +} + +// Put provides a mock function with given fields: ctx, objectKey, obj +func (_m *mockS3Client) Put(ctx context.Context, objectKey string, obj interface{}) error { + ret := _m.Called(ctx, objectKey, obj) + + if len(ret) == 0 { + panic("no return value specified for Put") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, string, interface{}) error); ok { + r0 = rf(ctx, objectKey, obj) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// mockS3Client_Put_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Put' +type mockS3Client_Put_Call struct { + *mock.Call +} + +// Put is a helper method to define mock.On call +// - ctx context.Context +// - objectKey string +// - obj interface{} +func (_e *mockS3Client_Expecter) Put(ctx interface{}, objectKey interface{}, obj interface{}) *mockS3Client_Put_Call { + return &mockS3Client_Put_Call{Call: _e.mock.On("Put", ctx, objectKey, obj)} +} + +func (_c *mockS3Client_Put_Call) Run(run func(ctx context.Context, objectKey string, obj interface{})) *mockS3Client_Put_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(string), args[2].(interface{})) + }) + return _c +} + +func (_c *mockS3Client_Put_Call) Return(_a0 error) *mockS3Client_Put_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockS3Client_Put_Call) RunAndReturn(run func(context.Context, string, interface{}) error) *mockS3Client_Put_Call { + _c.Call.Return(run) + return _c +} + +// UploadFile provides a mock function with given fields: ctx, file, path +func (_m *mockS3Client) UploadFile(ctx context.Context, file shared.FileUpload, path string) (shared.File, error) { + ret := _m.Called(ctx, file, path) + + if len(ret) == 0 { + panic("no return value specified for UploadFile") + } + + var r0 shared.File + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, shared.FileUpload, string) (shared.File, error)); ok { + return rf(ctx, file, path) + } + if rf, ok := ret.Get(0).(func(context.Context, shared.FileUpload, string) shared.File); ok { + r0 = rf(ctx, file, path) + } else { + r0 = ret.Get(0).(shared.File) + } + + if rf, ok := ret.Get(1).(func(context.Context, shared.FileUpload, string) error); ok { + r1 = rf(ctx, file, path) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// mockS3Client_UploadFile_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UploadFile' +type mockS3Client_UploadFile_Call struct { + *mock.Call +} + +// UploadFile is a helper method to define mock.On call +// - ctx context.Context +// - file shared.FileUpload +// - path string +func (_e *mockS3Client_Expecter) UploadFile(ctx interface{}, file interface{}, path interface{}) *mockS3Client_UploadFile_Call { + return &mockS3Client_UploadFile_Call{Call: _e.mock.On("UploadFile", ctx, file, path)} +} + +func (_c *mockS3Client_UploadFile_Call) Run(run func(ctx context.Context, file shared.FileUpload, path string)) *mockS3Client_UploadFile_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(shared.FileUpload), args[2].(string)) + }) + return _c +} + +func (_c *mockS3Client_UploadFile_Call) Return(_a0 shared.File, _a1 error) *mockS3Client_UploadFile_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *mockS3Client_UploadFile_Call) RunAndReturn(run func(context.Context, shared.FileUpload, string) (shared.File, error)) *mockS3Client_UploadFile_Call { + _c.Call.Return(run) + return _c +} + +// newMockS3Client creates a new instance of mockS3Client. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func newMockS3Client(t interface { + mock.TestingT + Cleanup(func()) +}) *mockS3Client { + mock := &mockS3Client{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/lambda/create/mock_Store_test.go b/lambda/create/mock_Store_test.go new file mode 100644 index 00000000..fc6c8e4f --- /dev/null +++ b/lambda/create/mock_Store_test.go @@ -0,0 +1,141 @@ +// Code generated by mockery v2.42.2. DO NOT EDIT. + +package main + +import ( + context "context" + + shared "github.com/ministryofjustice/opg-data-lpa-store/internal/shared" + mock "github.com/stretchr/testify/mock" +) + +// mockStore is an autogenerated mock type for the Store type +type mockStore struct { + mock.Mock +} + +type mockStore_Expecter struct { + mock *mock.Mock +} + +func (_m *mockStore) EXPECT() *mockStore_Expecter { + return &mockStore_Expecter{mock: &_m.Mock} +} + +// Get provides a mock function with given fields: ctx, uid +func (_m *mockStore) Get(ctx context.Context, uid string) (shared.Lpa, error) { + ret := _m.Called(ctx, uid) + + if len(ret) == 0 { + panic("no return value specified for Get") + } + + var r0 shared.Lpa + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string) (shared.Lpa, error)); ok { + return rf(ctx, uid) + } + if rf, ok := ret.Get(0).(func(context.Context, string) shared.Lpa); ok { + r0 = rf(ctx, uid) + } else { + r0 = ret.Get(0).(shared.Lpa) + } + + if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { + r1 = rf(ctx, uid) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// mockStore_Get_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Get' +type mockStore_Get_Call struct { + *mock.Call +} + +// Get is a helper method to define mock.On call +// - ctx context.Context +// - uid string +func (_e *mockStore_Expecter) Get(ctx interface{}, uid interface{}) *mockStore_Get_Call { + return &mockStore_Get_Call{Call: _e.mock.On("Get", ctx, uid)} +} + +func (_c *mockStore_Get_Call) Run(run func(ctx context.Context, uid string)) *mockStore_Get_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(string)) + }) + return _c +} + +func (_c *mockStore_Get_Call) Return(_a0 shared.Lpa, _a1 error) *mockStore_Get_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *mockStore_Get_Call) RunAndReturn(run func(context.Context, string) (shared.Lpa, error)) *mockStore_Get_Call { + _c.Call.Return(run) + return _c +} + +// Put provides a mock function with given fields: ctx, data +func (_m *mockStore) Put(ctx context.Context, data interface{}) error { + ret := _m.Called(ctx, data) + + if len(ret) == 0 { + panic("no return value specified for Put") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, interface{}) error); ok { + r0 = rf(ctx, data) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// mockStore_Put_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Put' +type mockStore_Put_Call struct { + *mock.Call +} + +// Put is a helper method to define mock.On call +// - ctx context.Context +// - data interface{} +func (_e *mockStore_Expecter) Put(ctx interface{}, data interface{}) *mockStore_Put_Call { + return &mockStore_Put_Call{Call: _e.mock.On("Put", ctx, data)} +} + +func (_c *mockStore_Put_Call) Run(run func(ctx context.Context, data interface{})) *mockStore_Put_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(interface{})) + }) + return _c +} + +func (_c *mockStore_Put_Call) Return(_a0 error) *mockStore_Put_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockStore_Put_Call) RunAndReturn(run func(context.Context, interface{}) error) *mockStore_Put_Call { + _c.Call.Return(run) + return _c +} + +// newMockStore creates a new instance of mockStore. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func newMockStore(t interface { + mock.TestingT + Cleanup(func()) +}) *mockStore { + mock := &mockStore{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/lambda/create/mock_Verifier_test.go b/lambda/create/mock_Verifier_test.go new file mode 100644 index 00000000..d225a22f --- /dev/null +++ b/lambda/create/mock_Verifier_test.go @@ -0,0 +1,95 @@ +// Code generated by mockery v2.42.2. DO NOT EDIT. + +package main + +import ( + events "github.com/aws/aws-lambda-go/events" + mock "github.com/stretchr/testify/mock" + + shared "github.com/ministryofjustice/opg-data-lpa-store/internal/shared" +) + +// mockVerifier is an autogenerated mock type for the Verifier type +type mockVerifier struct { + mock.Mock +} + +type mockVerifier_Expecter struct { + mock *mock.Mock +} + +func (_m *mockVerifier) EXPECT() *mockVerifier_Expecter { + return &mockVerifier_Expecter{mock: &_m.Mock} +} + +// VerifyHeader provides a mock function with given fields: _a0 +func (_m *mockVerifier) VerifyHeader(_a0 events.APIGatewayProxyRequest) (*shared.LpaStoreClaims, error) { + ret := _m.Called(_a0) + + if len(ret) == 0 { + panic("no return value specified for VerifyHeader") + } + + var r0 *shared.LpaStoreClaims + var r1 error + if rf, ok := ret.Get(0).(func(events.APIGatewayProxyRequest) (*shared.LpaStoreClaims, error)); ok { + return rf(_a0) + } + if rf, ok := ret.Get(0).(func(events.APIGatewayProxyRequest) *shared.LpaStoreClaims); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*shared.LpaStoreClaims) + } + } + + if rf, ok := ret.Get(1).(func(events.APIGatewayProxyRequest) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// mockVerifier_VerifyHeader_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'VerifyHeader' +type mockVerifier_VerifyHeader_Call struct { + *mock.Call +} + +// VerifyHeader is a helper method to define mock.On call +// - _a0 events.APIGatewayProxyRequest +func (_e *mockVerifier_Expecter) VerifyHeader(_a0 interface{}) *mockVerifier_VerifyHeader_Call { + return &mockVerifier_VerifyHeader_Call{Call: _e.mock.On("VerifyHeader", _a0)} +} + +func (_c *mockVerifier_VerifyHeader_Call) Run(run func(_a0 events.APIGatewayProxyRequest)) *mockVerifier_VerifyHeader_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(events.APIGatewayProxyRequest)) + }) + return _c +} + +func (_c *mockVerifier_VerifyHeader_Call) Return(_a0 *shared.LpaStoreClaims, _a1 error) *mockVerifier_VerifyHeader_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *mockVerifier_VerifyHeader_Call) RunAndReturn(run func(events.APIGatewayProxyRequest) (*shared.LpaStoreClaims, error)) *mockVerifier_VerifyHeader_Call { + _c.Call.Return(run) + return _c +} + +// newMockVerifier creates a new instance of mockVerifier. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func newMockVerifier(t interface { + mock.TestingT + Cleanup(func()) +}) *mockVerifier { + mock := &mockVerifier{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/lambda/get/main.go b/lambda/get/main.go index f70019f6..18fa8056 100644 --- a/lambda/get/main.go +++ b/lambda/get/main.go @@ -50,6 +50,10 @@ func (l *Lambda) HandleEvent(ctx context.Context, event events.APIGatewayProxyRe } lpa, err := l.store.Get(ctx, event.PathParameters["uid"]) + if err != nil { + l.logger.Error("error fetching LPA", slog.Any("err", err)) + return shared.ProblemInternalServerError.Respond() + } // If item can't be found in DynamoDB then it returns empty object hence 404 error returned if // empty object returned @@ -58,13 +62,7 @@ func (l *Lambda) HandleEvent(ctx context.Context, event events.APIGatewayProxyRe return shared.ProblemNotFoundRequest.Respond() } - if err != nil { - l.logger.Error("error fetching LPA", slog.Any("err", err)) - return shared.ProblemInternalServerError.Respond() - } - body, err := json.Marshal(lpa) - if err != nil { l.logger.Error("error marshalling LPA", slog.Any("err", err)) return shared.ProblemInternalServerError.Respond() diff --git a/lambda/get/main_test.go b/lambda/get/main_test.go new file mode 100644 index 00000000..5d2b9b8c --- /dev/null +++ b/lambda/get/main_test.go @@ -0,0 +1,151 @@ +package main + +import ( + "context" + "encoding/json" + "errors" + "log/slog" + "testing" + + "github.com/aws/aws-lambda-go/events" + "github.com/ministryofjustice/opg-data-lpa-store/internal/shared" + "github.com/stretchr/testify/assert" +) + +var ( + ctx = context.WithValue(context.Background(), (*string)(nil), "testing") + expectedError = errors.New("err") +) + +func TestLambdaHandleEvent(t *testing.T) { + req := events.APIGatewayProxyRequest{ + PathParameters: map[string]string{"uid": "my-uid"}, + } + + lpa := shared.Lpa{Uid: "my-uid"} + body, _ := json.Marshal(lpa) + + verifier := newMockVerifier(t) + verifier.EXPECT(). + VerifyHeader(req). + Return(nil, nil) + + logger := newMockLogger(t) + logger.EXPECT(). + Debug("Successfully parsed JWT from event header") + + store := newMockStore(t) + store.EXPECT(). + Get(ctx, "my-uid"). + Return(lpa, nil) + + lambda := &Lambda{ + verifier: verifier, + logger: logger, + store: store, + } + + resp, err := lambda.HandleEvent(ctx, req) + assert.Nil(t, err) + assert.Equal(t, events.APIGatewayProxyResponse{ + StatusCode: 200, + Body: string(body), + }, resp) +} + +func TestLambdaHandleEventWhenUnauthorised(t *testing.T) { + req := events.APIGatewayProxyRequest{ + PathParameters: map[string]string{"uid": "my-uid"}, + } + + verifier := newMockVerifier(t) + verifier.EXPECT(). + VerifyHeader(req). + Return(nil, expectedError) + + logger := newMockLogger(t) + logger.EXPECT(). + Info("Unable to verify JWT from header") + + lambda := &Lambda{ + verifier: verifier, + logger: logger, + } + + resp, err := lambda.HandleEvent(ctx, req) + assert.Nil(t, err) + assert.Equal(t, events.APIGatewayProxyResponse{ + StatusCode: 401, + Body: `{"code":"UNAUTHORISED","detail":"Invalid JWT"}`, + }, resp) +} + +func TestLambdaHandleEventWhenNotFound(t *testing.T) { + req := events.APIGatewayProxyRequest{ + PathParameters: map[string]string{"uid": "my-uid"}, + } + + verifier := newMockVerifier(t) + verifier.EXPECT(). + VerifyHeader(req). + Return(nil, nil) + + logger := newMockLogger(t) + logger.EXPECT(). + Debug("Successfully parsed JWT from event header") + logger.EXPECT(). + Debug("Uid not found") + + store := newMockStore(t) + store.EXPECT(). + Get(ctx, "my-uid"). + Return(shared.Lpa{}, nil) + + lambda := &Lambda{ + verifier: verifier, + logger: logger, + store: store, + } + + resp, err := lambda.HandleEvent(ctx, req) + assert.Nil(t, err) + assert.Equal(t, events.APIGatewayProxyResponse{ + StatusCode: 404, + Body: `{"code":"NOT_FOUND","detail":"Record not found"}`, + }, resp) +} + +func TestLambdaHandleEventWhenStoreErrors(t *testing.T) { + req := events.APIGatewayProxyRequest{ + PathParameters: map[string]string{"uid": "my-uid"}, + } + + verifier := newMockVerifier(t) + verifier.EXPECT(). + VerifyHeader(req). + Return(nil, nil) + + logger := newMockLogger(t) + logger.EXPECT(). + Debug("Successfully parsed JWT from event header") + logger.EXPECT(). + Error("error fetching LPA", slog.Any("err", expectedError)) + + store := newMockStore(t) + store.EXPECT(). + Get(ctx, "my-uid"). + Return(shared.Lpa{}, expectedError) + + lambda := &Lambda{ + verifier: verifier, + logger: logger, + store: store, + } + + resp, err := lambda.HandleEvent(ctx, req) + assert.Nil(t, err) + assert.Equal(t, events.APIGatewayProxyResponse{ + StatusCode: 500, + Body: `{"code":"INTERNAL_SERVER_ERROR","detail":"Internal server error"}`, + }, resp) +} diff --git a/lambda/get/mock_Logger_test.go b/lambda/get/mock_Logger_test.go new file mode 100644 index 00000000..9c2a803a --- /dev/null +++ b/lambda/get/mock_Logger_test.go @@ -0,0 +1,164 @@ +// Code generated by mockery v2.42.2. DO NOT EDIT. + +package main + +import mock "github.com/stretchr/testify/mock" + +// mockLogger is an autogenerated mock type for the Logger type +type mockLogger struct { + mock.Mock +} + +type mockLogger_Expecter struct { + mock *mock.Mock +} + +func (_m *mockLogger) EXPECT() *mockLogger_Expecter { + return &mockLogger_Expecter{mock: &_m.Mock} +} + +// Debug provides a mock function with given fields: _a0, _a1 +func (_m *mockLogger) Debug(_a0 string, _a1 ...interface{}) { + var _ca []interface{} + _ca = append(_ca, _a0) + _ca = append(_ca, _a1...) + _m.Called(_ca...) +} + +// mockLogger_Debug_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Debug' +type mockLogger_Debug_Call struct { + *mock.Call +} + +// Debug is a helper method to define mock.On call +// - _a0 string +// - _a1 ...interface{} +func (_e *mockLogger_Expecter) Debug(_a0 interface{}, _a1 ...interface{}) *mockLogger_Debug_Call { + return &mockLogger_Debug_Call{Call: _e.mock.On("Debug", + append([]interface{}{_a0}, _a1...)...)} +} + +func (_c *mockLogger_Debug_Call) Run(run func(_a0 string, _a1 ...interface{})) *mockLogger_Debug_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]interface{}, len(args)-1) + for i, a := range args[1:] { + if a != nil { + variadicArgs[i] = a.(interface{}) + } + } + run(args[0].(string), variadicArgs...) + }) + return _c +} + +func (_c *mockLogger_Debug_Call) Return() *mockLogger_Debug_Call { + _c.Call.Return() + return _c +} + +func (_c *mockLogger_Debug_Call) RunAndReturn(run func(string, ...interface{})) *mockLogger_Debug_Call { + _c.Call.Return(run) + return _c +} + +// Error provides a mock function with given fields: _a0, _a1 +func (_m *mockLogger) Error(_a0 string, _a1 ...interface{}) { + var _ca []interface{} + _ca = append(_ca, _a0) + _ca = append(_ca, _a1...) + _m.Called(_ca...) +} + +// mockLogger_Error_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Error' +type mockLogger_Error_Call struct { + *mock.Call +} + +// Error is a helper method to define mock.On call +// - _a0 string +// - _a1 ...interface{} +func (_e *mockLogger_Expecter) Error(_a0 interface{}, _a1 ...interface{}) *mockLogger_Error_Call { + return &mockLogger_Error_Call{Call: _e.mock.On("Error", + append([]interface{}{_a0}, _a1...)...)} +} + +func (_c *mockLogger_Error_Call) Run(run func(_a0 string, _a1 ...interface{})) *mockLogger_Error_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]interface{}, len(args)-1) + for i, a := range args[1:] { + if a != nil { + variadicArgs[i] = a.(interface{}) + } + } + run(args[0].(string), variadicArgs...) + }) + return _c +} + +func (_c *mockLogger_Error_Call) Return() *mockLogger_Error_Call { + _c.Call.Return() + return _c +} + +func (_c *mockLogger_Error_Call) RunAndReturn(run func(string, ...interface{})) *mockLogger_Error_Call { + _c.Call.Return(run) + return _c +} + +// Info provides a mock function with given fields: _a0, _a1 +func (_m *mockLogger) Info(_a0 string, _a1 ...interface{}) { + var _ca []interface{} + _ca = append(_ca, _a0) + _ca = append(_ca, _a1...) + _m.Called(_ca...) +} + +// mockLogger_Info_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Info' +type mockLogger_Info_Call struct { + *mock.Call +} + +// Info is a helper method to define mock.On call +// - _a0 string +// - _a1 ...interface{} +func (_e *mockLogger_Expecter) Info(_a0 interface{}, _a1 ...interface{}) *mockLogger_Info_Call { + return &mockLogger_Info_Call{Call: _e.mock.On("Info", + append([]interface{}{_a0}, _a1...)...)} +} + +func (_c *mockLogger_Info_Call) Run(run func(_a0 string, _a1 ...interface{})) *mockLogger_Info_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]interface{}, len(args)-1) + for i, a := range args[1:] { + if a != nil { + variadicArgs[i] = a.(interface{}) + } + } + run(args[0].(string), variadicArgs...) + }) + return _c +} + +func (_c *mockLogger_Info_Call) Return() *mockLogger_Info_Call { + _c.Call.Return() + return _c +} + +func (_c *mockLogger_Info_Call) RunAndReturn(run func(string, ...interface{})) *mockLogger_Info_Call { + _c.Call.Return(run) + return _c +} + +// newMockLogger creates a new instance of mockLogger. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func newMockLogger(t interface { + mock.TestingT + Cleanup(func()) +}) *mockLogger { + mock := &mockLogger{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/lambda/get/mock_Store_test.go b/lambda/get/mock_Store_test.go new file mode 100644 index 00000000..e45d72a1 --- /dev/null +++ b/lambda/get/mock_Store_test.go @@ -0,0 +1,94 @@ +// Code generated by mockery v2.42.2. DO NOT EDIT. + +package main + +import ( + context "context" + + shared "github.com/ministryofjustice/opg-data-lpa-store/internal/shared" + mock "github.com/stretchr/testify/mock" +) + +// mockStore is an autogenerated mock type for the Store type +type mockStore struct { + mock.Mock +} + +type mockStore_Expecter struct { + mock *mock.Mock +} + +func (_m *mockStore) EXPECT() *mockStore_Expecter { + return &mockStore_Expecter{mock: &_m.Mock} +} + +// Get provides a mock function with given fields: ctx, uid +func (_m *mockStore) Get(ctx context.Context, uid string) (shared.Lpa, error) { + ret := _m.Called(ctx, uid) + + if len(ret) == 0 { + panic("no return value specified for Get") + } + + var r0 shared.Lpa + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string) (shared.Lpa, error)); ok { + return rf(ctx, uid) + } + if rf, ok := ret.Get(0).(func(context.Context, string) shared.Lpa); ok { + r0 = rf(ctx, uid) + } else { + r0 = ret.Get(0).(shared.Lpa) + } + + if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { + r1 = rf(ctx, uid) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// mockStore_Get_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Get' +type mockStore_Get_Call struct { + *mock.Call +} + +// Get is a helper method to define mock.On call +// - ctx context.Context +// - uid string +func (_e *mockStore_Expecter) Get(ctx interface{}, uid interface{}) *mockStore_Get_Call { + return &mockStore_Get_Call{Call: _e.mock.On("Get", ctx, uid)} +} + +func (_c *mockStore_Get_Call) Run(run func(ctx context.Context, uid string)) *mockStore_Get_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(string)) + }) + return _c +} + +func (_c *mockStore_Get_Call) Return(_a0 shared.Lpa, _a1 error) *mockStore_Get_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *mockStore_Get_Call) RunAndReturn(run func(context.Context, string) (shared.Lpa, error)) *mockStore_Get_Call { + _c.Call.Return(run) + return _c +} + +// newMockStore creates a new instance of mockStore. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func newMockStore(t interface { + mock.TestingT + Cleanup(func()) +}) *mockStore { + mock := &mockStore{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/lambda/get/mock_Verifier_test.go b/lambda/get/mock_Verifier_test.go new file mode 100644 index 00000000..d225a22f --- /dev/null +++ b/lambda/get/mock_Verifier_test.go @@ -0,0 +1,95 @@ +// Code generated by mockery v2.42.2. DO NOT EDIT. + +package main + +import ( + events "github.com/aws/aws-lambda-go/events" + mock "github.com/stretchr/testify/mock" + + shared "github.com/ministryofjustice/opg-data-lpa-store/internal/shared" +) + +// mockVerifier is an autogenerated mock type for the Verifier type +type mockVerifier struct { + mock.Mock +} + +type mockVerifier_Expecter struct { + mock *mock.Mock +} + +func (_m *mockVerifier) EXPECT() *mockVerifier_Expecter { + return &mockVerifier_Expecter{mock: &_m.Mock} +} + +// VerifyHeader provides a mock function with given fields: _a0 +func (_m *mockVerifier) VerifyHeader(_a0 events.APIGatewayProxyRequest) (*shared.LpaStoreClaims, error) { + ret := _m.Called(_a0) + + if len(ret) == 0 { + panic("no return value specified for VerifyHeader") + } + + var r0 *shared.LpaStoreClaims + var r1 error + if rf, ok := ret.Get(0).(func(events.APIGatewayProxyRequest) (*shared.LpaStoreClaims, error)); ok { + return rf(_a0) + } + if rf, ok := ret.Get(0).(func(events.APIGatewayProxyRequest) *shared.LpaStoreClaims); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*shared.LpaStoreClaims) + } + } + + if rf, ok := ret.Get(1).(func(events.APIGatewayProxyRequest) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// mockVerifier_VerifyHeader_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'VerifyHeader' +type mockVerifier_VerifyHeader_Call struct { + *mock.Call +} + +// VerifyHeader is a helper method to define mock.On call +// - _a0 events.APIGatewayProxyRequest +func (_e *mockVerifier_Expecter) VerifyHeader(_a0 interface{}) *mockVerifier_VerifyHeader_Call { + return &mockVerifier_VerifyHeader_Call{Call: _e.mock.On("VerifyHeader", _a0)} +} + +func (_c *mockVerifier_VerifyHeader_Call) Run(run func(_a0 events.APIGatewayProxyRequest)) *mockVerifier_VerifyHeader_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(events.APIGatewayProxyRequest)) + }) + return _c +} + +func (_c *mockVerifier_VerifyHeader_Call) Return(_a0 *shared.LpaStoreClaims, _a1 error) *mockVerifier_VerifyHeader_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *mockVerifier_VerifyHeader_Call) RunAndReturn(run func(events.APIGatewayProxyRequest) (*shared.LpaStoreClaims, error)) *mockVerifier_VerifyHeader_Call { + _c.Call.Return(run) + return _c +} + +// newMockVerifier creates a new instance of mockVerifier. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func newMockVerifier(t interface { + mock.TestingT + Cleanup(func()) +}) *mockVerifier { + mock := &mockVerifier{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/lambda/getlist/main_test.go b/lambda/getlist/main_test.go new file mode 100644 index 00000000..675cae4c --- /dev/null +++ b/lambda/getlist/main_test.go @@ -0,0 +1,146 @@ +package main + +import ( + "context" + "encoding/json" + "errors" + "log/slog" + "testing" + + "github.com/aws/aws-lambda-go/events" + "github.com/ministryofjustice/opg-data-lpa-store/internal/shared" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" +) + +var ( + ctx = context.WithValue(context.Background(), "for", "testing") + expectedError = errors.New("expect") +) + +func TestLambdaHandleEvent(t *testing.T) { + req := events.APIGatewayProxyRequest{ + Body: `{"uids":["my-uid","another-uid"]}`, + } + + lpas := []shared.Lpa{{Uid: "my-uid"}, {Uid: "another-uid"}} + body, _ := json.Marshal(lpasResponse{Lpas: lpas}) + + verifier := newMockVerifier(t) + verifier.EXPECT(). + VerifyHeader(req). + Return(nil, nil) + + logger := newMockLogger(t) + logger.EXPECT(). + Debug("Successfully parsed JWT from event header") + + store := newMockStore(t) + store.EXPECT(). + GetList(ctx, []string{"my-uid", "another-uid"}). + Return(lpas, nil) + + lambda := &Lambda{ + verifier: verifier, + logger: logger, + store: store, + } + + resp, err := lambda.HandleEvent(ctx, req) + assert.Nil(t, err) + assert.Equal(t, events.APIGatewayProxyResponse{ + StatusCode: 200, + Body: string(body), + }, resp) +} + +func TestLambdaHandleEventWhenUnauthorised(t *testing.T) { + req := events.APIGatewayProxyRequest{ + Body: `{"uids":["my-uid","another-uid"]}`, + } + + verifier := newMockVerifier(t) + verifier.EXPECT(). + VerifyHeader(req). + Return(nil, errors.New("hey")) + + logger := newMockLogger(t) + logger.EXPECT(). + Info("Unable to verify JWT from header") + + lambda := &Lambda{ + verifier: verifier, + logger: logger, + } + + resp, err := lambda.HandleEvent(ctx, req) + assert.Nil(t, err) + assert.Equal(t, events.APIGatewayProxyResponse{ + StatusCode: 401, + Body: `{"code":"UNAUTHORISED","detail":"Invalid JWT"}`, + }, resp) +} + +func TestLambdaHandleEventWhenBadRequest(t *testing.T) { + req := events.APIGatewayProxyRequest{ + Body: `{`, + } + + verifier := newMockVerifier(t) + verifier.EXPECT(). + VerifyHeader(req). + Return(nil, nil) + + logger := newMockLogger(t) + logger.EXPECT(). + Debug("Successfully parsed JWT from event header") + logger.EXPECT(). + Error("error unmarshalling request", mock.Anything) + + lambda := &Lambda{ + verifier: verifier, + logger: logger, + } + + resp, err := lambda.HandleEvent(ctx, req) + assert.Nil(t, err) + assert.Equal(t, events.APIGatewayProxyResponse{ + StatusCode: 500, + Body: `{"code":"INTERNAL_SERVER_ERROR","detail":"Internal server error"}`, + }, resp) +} + +func TestLambdaHandleEventWhenStoreErrors(t *testing.T) { + req := events.APIGatewayProxyRequest{ + Body: `{"uids":["my-uid","another-uid"]}`, + } + + verifier := newMockVerifier(t) + verifier.EXPECT(). + VerifyHeader(req). + Return(nil, nil) + + logger := newMockLogger(t) + logger.EXPECT(). + Debug("Successfully parsed JWT from event header") + logger.EXPECT(). + Error("error fetching LPAs", slog.Any("err", expectedError)) + + store := newMockStore(t) + store.EXPECT(). + GetList(ctx, []string{"my-uid", "another-uid"}). + Return(nil, expectedError) + + lambda := &Lambda{ + verifier: verifier, + logger: logger, + store: store, + } + + resp, err := lambda.HandleEvent(ctx, req) + assert.Nil(t, err) + assert.Equal(t, events.APIGatewayProxyResponse{ + StatusCode: 500, + Body: `{"code":"INTERNAL_SERVER_ERROR","detail":"Internal server error"}`, + }, resp) +} diff --git a/lambda/getlist/mock_Logger_test.go b/lambda/getlist/mock_Logger_test.go new file mode 100644 index 00000000..9c2a803a --- /dev/null +++ b/lambda/getlist/mock_Logger_test.go @@ -0,0 +1,164 @@ +// Code generated by mockery v2.42.2. DO NOT EDIT. + +package main + +import mock "github.com/stretchr/testify/mock" + +// mockLogger is an autogenerated mock type for the Logger type +type mockLogger struct { + mock.Mock +} + +type mockLogger_Expecter struct { + mock *mock.Mock +} + +func (_m *mockLogger) EXPECT() *mockLogger_Expecter { + return &mockLogger_Expecter{mock: &_m.Mock} +} + +// Debug provides a mock function with given fields: _a0, _a1 +func (_m *mockLogger) Debug(_a0 string, _a1 ...interface{}) { + var _ca []interface{} + _ca = append(_ca, _a0) + _ca = append(_ca, _a1...) + _m.Called(_ca...) +} + +// mockLogger_Debug_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Debug' +type mockLogger_Debug_Call struct { + *mock.Call +} + +// Debug is a helper method to define mock.On call +// - _a0 string +// - _a1 ...interface{} +func (_e *mockLogger_Expecter) Debug(_a0 interface{}, _a1 ...interface{}) *mockLogger_Debug_Call { + return &mockLogger_Debug_Call{Call: _e.mock.On("Debug", + append([]interface{}{_a0}, _a1...)...)} +} + +func (_c *mockLogger_Debug_Call) Run(run func(_a0 string, _a1 ...interface{})) *mockLogger_Debug_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]interface{}, len(args)-1) + for i, a := range args[1:] { + if a != nil { + variadicArgs[i] = a.(interface{}) + } + } + run(args[0].(string), variadicArgs...) + }) + return _c +} + +func (_c *mockLogger_Debug_Call) Return() *mockLogger_Debug_Call { + _c.Call.Return() + return _c +} + +func (_c *mockLogger_Debug_Call) RunAndReturn(run func(string, ...interface{})) *mockLogger_Debug_Call { + _c.Call.Return(run) + return _c +} + +// Error provides a mock function with given fields: _a0, _a1 +func (_m *mockLogger) Error(_a0 string, _a1 ...interface{}) { + var _ca []interface{} + _ca = append(_ca, _a0) + _ca = append(_ca, _a1...) + _m.Called(_ca...) +} + +// mockLogger_Error_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Error' +type mockLogger_Error_Call struct { + *mock.Call +} + +// Error is a helper method to define mock.On call +// - _a0 string +// - _a1 ...interface{} +func (_e *mockLogger_Expecter) Error(_a0 interface{}, _a1 ...interface{}) *mockLogger_Error_Call { + return &mockLogger_Error_Call{Call: _e.mock.On("Error", + append([]interface{}{_a0}, _a1...)...)} +} + +func (_c *mockLogger_Error_Call) Run(run func(_a0 string, _a1 ...interface{})) *mockLogger_Error_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]interface{}, len(args)-1) + for i, a := range args[1:] { + if a != nil { + variadicArgs[i] = a.(interface{}) + } + } + run(args[0].(string), variadicArgs...) + }) + return _c +} + +func (_c *mockLogger_Error_Call) Return() *mockLogger_Error_Call { + _c.Call.Return() + return _c +} + +func (_c *mockLogger_Error_Call) RunAndReturn(run func(string, ...interface{})) *mockLogger_Error_Call { + _c.Call.Return(run) + return _c +} + +// Info provides a mock function with given fields: _a0, _a1 +func (_m *mockLogger) Info(_a0 string, _a1 ...interface{}) { + var _ca []interface{} + _ca = append(_ca, _a0) + _ca = append(_ca, _a1...) + _m.Called(_ca...) +} + +// mockLogger_Info_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Info' +type mockLogger_Info_Call struct { + *mock.Call +} + +// Info is a helper method to define mock.On call +// - _a0 string +// - _a1 ...interface{} +func (_e *mockLogger_Expecter) Info(_a0 interface{}, _a1 ...interface{}) *mockLogger_Info_Call { + return &mockLogger_Info_Call{Call: _e.mock.On("Info", + append([]interface{}{_a0}, _a1...)...)} +} + +func (_c *mockLogger_Info_Call) Run(run func(_a0 string, _a1 ...interface{})) *mockLogger_Info_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]interface{}, len(args)-1) + for i, a := range args[1:] { + if a != nil { + variadicArgs[i] = a.(interface{}) + } + } + run(args[0].(string), variadicArgs...) + }) + return _c +} + +func (_c *mockLogger_Info_Call) Return() *mockLogger_Info_Call { + _c.Call.Return() + return _c +} + +func (_c *mockLogger_Info_Call) RunAndReturn(run func(string, ...interface{})) *mockLogger_Info_Call { + _c.Call.Return(run) + return _c +} + +// newMockLogger creates a new instance of mockLogger. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func newMockLogger(t interface { + mock.TestingT + Cleanup(func()) +}) *mockLogger { + mock := &mockLogger{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/lambda/getlist/mock_Store_test.go b/lambda/getlist/mock_Store_test.go new file mode 100644 index 00000000..ac8bac38 --- /dev/null +++ b/lambda/getlist/mock_Store_test.go @@ -0,0 +1,96 @@ +// Code generated by mockery v2.42.2. DO NOT EDIT. + +package main + +import ( + context "context" + + shared "github.com/ministryofjustice/opg-data-lpa-store/internal/shared" + mock "github.com/stretchr/testify/mock" +) + +// mockStore is an autogenerated mock type for the Store type +type mockStore struct { + mock.Mock +} + +type mockStore_Expecter struct { + mock *mock.Mock +} + +func (_m *mockStore) EXPECT() *mockStore_Expecter { + return &mockStore_Expecter{mock: &_m.Mock} +} + +// GetList provides a mock function with given fields: ctx, uids +func (_m *mockStore) GetList(ctx context.Context, uids []string) ([]shared.Lpa, error) { + ret := _m.Called(ctx, uids) + + if len(ret) == 0 { + panic("no return value specified for GetList") + } + + var r0 []shared.Lpa + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, []string) ([]shared.Lpa, error)); ok { + return rf(ctx, uids) + } + if rf, ok := ret.Get(0).(func(context.Context, []string) []shared.Lpa); ok { + r0 = rf(ctx, uids) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]shared.Lpa) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, []string) error); ok { + r1 = rf(ctx, uids) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// mockStore_GetList_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetList' +type mockStore_GetList_Call struct { + *mock.Call +} + +// GetList is a helper method to define mock.On call +// - ctx context.Context +// - uids []string +func (_e *mockStore_Expecter) GetList(ctx interface{}, uids interface{}) *mockStore_GetList_Call { + return &mockStore_GetList_Call{Call: _e.mock.On("GetList", ctx, uids)} +} + +func (_c *mockStore_GetList_Call) Run(run func(ctx context.Context, uids []string)) *mockStore_GetList_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].([]string)) + }) + return _c +} + +func (_c *mockStore_GetList_Call) Return(_a0 []shared.Lpa, _a1 error) *mockStore_GetList_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *mockStore_GetList_Call) RunAndReturn(run func(context.Context, []string) ([]shared.Lpa, error)) *mockStore_GetList_Call { + _c.Call.Return(run) + return _c +} + +// newMockStore creates a new instance of mockStore. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func newMockStore(t interface { + mock.TestingT + Cleanup(func()) +}) *mockStore { + mock := &mockStore{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/lambda/getlist/mock_Verifier_test.go b/lambda/getlist/mock_Verifier_test.go new file mode 100644 index 00000000..d225a22f --- /dev/null +++ b/lambda/getlist/mock_Verifier_test.go @@ -0,0 +1,95 @@ +// Code generated by mockery v2.42.2. DO NOT EDIT. + +package main + +import ( + events "github.com/aws/aws-lambda-go/events" + mock "github.com/stretchr/testify/mock" + + shared "github.com/ministryofjustice/opg-data-lpa-store/internal/shared" +) + +// mockVerifier is an autogenerated mock type for the Verifier type +type mockVerifier struct { + mock.Mock +} + +type mockVerifier_Expecter struct { + mock *mock.Mock +} + +func (_m *mockVerifier) EXPECT() *mockVerifier_Expecter { + return &mockVerifier_Expecter{mock: &_m.Mock} +} + +// VerifyHeader provides a mock function with given fields: _a0 +func (_m *mockVerifier) VerifyHeader(_a0 events.APIGatewayProxyRequest) (*shared.LpaStoreClaims, error) { + ret := _m.Called(_a0) + + if len(ret) == 0 { + panic("no return value specified for VerifyHeader") + } + + var r0 *shared.LpaStoreClaims + var r1 error + if rf, ok := ret.Get(0).(func(events.APIGatewayProxyRequest) (*shared.LpaStoreClaims, error)); ok { + return rf(_a0) + } + if rf, ok := ret.Get(0).(func(events.APIGatewayProxyRequest) *shared.LpaStoreClaims); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*shared.LpaStoreClaims) + } + } + + if rf, ok := ret.Get(1).(func(events.APIGatewayProxyRequest) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// mockVerifier_VerifyHeader_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'VerifyHeader' +type mockVerifier_VerifyHeader_Call struct { + *mock.Call +} + +// VerifyHeader is a helper method to define mock.On call +// - _a0 events.APIGatewayProxyRequest +func (_e *mockVerifier_Expecter) VerifyHeader(_a0 interface{}) *mockVerifier_VerifyHeader_Call { + return &mockVerifier_VerifyHeader_Call{Call: _e.mock.On("VerifyHeader", _a0)} +} + +func (_c *mockVerifier_VerifyHeader_Call) Run(run func(_a0 events.APIGatewayProxyRequest)) *mockVerifier_VerifyHeader_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(events.APIGatewayProxyRequest)) + }) + return _c +} + +func (_c *mockVerifier_VerifyHeader_Call) Return(_a0 *shared.LpaStoreClaims, _a1 error) *mockVerifier_VerifyHeader_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *mockVerifier_VerifyHeader_Call) RunAndReturn(run func(events.APIGatewayProxyRequest) (*shared.LpaStoreClaims, error)) *mockVerifier_VerifyHeader_Call { + _c.Call.Return(run) + return _c +} + +// newMockVerifier creates a new instance of mockVerifier. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func newMockVerifier(t interface { + mock.TestingT + Cleanup(func()) +}) *mockVerifier { + mock := &mockVerifier{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +}