review
This commit is contained in:
parent
6ffc0d2c99
commit
6153017b62
22 changed files with 835 additions and 100 deletions
|
|
@ -34,6 +34,7 @@ type Question struct {
|
|||
Text string
|
||||
Type string
|
||||
Options []string
|
||||
CodeSnippet string
|
||||
ReferenceAnswer string
|
||||
Deprecated bool
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ type IParticipantService interface {
|
|||
type IInvitationService interface {
|
||||
List(context.Context, uint) ([]model.Invitation, error)
|
||||
Create(context.Context, uint, uint) (model.Invitation, error)
|
||||
Review(context.Context, uint, uint) (model.Interview, error)
|
||||
GetInterview(context.Context, string) (model.Interview, error)
|
||||
Accept(context.Context, string) (model.Interview, error)
|
||||
SaveAnswer(context.Context, string, uint, string) error
|
||||
|
|
@ -181,6 +182,7 @@ func (s *QuestionService) Update(ctx context.Context, id uint, value model.Quest
|
|||
|
||||
func validateQuestion(value model.Question) (model.Question, error) {
|
||||
value.Text = strings.TrimSpace(value.Text)
|
||||
value.CodeSnippet = strings.TrimSpace(value.CodeSnippet)
|
||||
value.ReferenceAnswer = strings.TrimSpace(value.ReferenceAnswer)
|
||||
switch value.Type {
|
||||
case "open", "multiple_choice", "radio", "code_review":
|
||||
|
|
@ -203,11 +205,17 @@ func validateQuestion(value model.Question) (model.Question, error) {
|
|||
if (value.Type == "open" || value.Type == "code_review") && value.ReferenceAnswer == "" {
|
||||
return model.Question{}, fmt.Errorf("%w: a reference answer is required", ErrInvalidQuestion)
|
||||
}
|
||||
if value.Type == "code_review" && value.CodeSnippet == "" {
|
||||
return model.Question{}, fmt.Errorf("%w: a code snippet is required", ErrInvalidQuestion)
|
||||
}
|
||||
if value.Type == "open" || value.Type == "code_review" {
|
||||
value.Options = nil
|
||||
} else {
|
||||
value.ReferenceAnswer = ""
|
||||
}
|
||||
if value.Type != "code_review" {
|
||||
value.CodeSnippet = ""
|
||||
}
|
||||
return value, nil
|
||||
}
|
||||
|
||||
|
|
@ -376,6 +384,19 @@ func (s *InvitationService) Create(ctx context.Context, jobID, participantID uin
|
|||
})
|
||||
}
|
||||
|
||||
func (s *InvitationService) Review(ctx context.Context, jobID, invitationID uint) (model.Interview, error) {
|
||||
invitations, err := s.store.ListInvitations(ctx, jobID)
|
||||
if err != nil {
|
||||
return model.Interview{}, err
|
||||
}
|
||||
for _, invitation := range invitations {
|
||||
if invitation.ID == invitationID {
|
||||
return s.store.GetInterview(ctx, invitation.Token)
|
||||
}
|
||||
}
|
||||
return model.Interview{}, repository.ErrNotFound
|
||||
}
|
||||
|
||||
func (s *InvitationService) GetInterview(ctx context.Context, token string) (model.Interview, error) {
|
||||
interview, err := s.store.GetInterview(ctx, token)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/danyel/go-guess/backend/internal/database/repository"
|
||||
"github.com/danyel/go-guess/backend/internal/service/model"
|
||||
)
|
||||
|
||||
|
|
@ -17,8 +18,9 @@ type fakeStore struct {
|
|||
|
||||
type invitationStore struct {
|
||||
*fakeStore
|
||||
interview model.Interview
|
||||
saved bool
|
||||
interview model.Interview
|
||||
invitations []model.Invitation
|
||||
saved bool
|
||||
}
|
||||
|
||||
func (f *invitationStore) CreateInvitation(_ context.Context, value model.Invitation) (model.Invitation, error) {
|
||||
|
|
@ -32,6 +34,9 @@ func (f *invitationStore) SaveAnswer(context.Context, string, uint, string) erro
|
|||
f.saved = true
|
||||
return nil
|
||||
}
|
||||
func (f *invitationStore) ListInvitations(context.Context, uint) ([]model.Invitation, error) {
|
||||
return f.invitations, nil
|
||||
}
|
||||
|
||||
func (f *fakeStore) FindUserByEmail(context.Context, string) (model.User, error) {
|
||||
return model.User{}, errors.New("unused")
|
||||
|
|
@ -179,4 +184,26 @@ func TestQuestionReferenceAnswerValidation(t *testing.T) {
|
|||
if question.ReferenceAnswer != "" || question.Options[0] != "One" {
|
||||
t.Fatalf("unexpected normalized question: %#v", question)
|
||||
}
|
||||
|
||||
if _, err := service.Create(context.Background(), model.Question{
|
||||
Text: "Review this change", Type: "code_review", ReferenceAnswer: "Spot the race",
|
||||
}); !errors.Is(err, ErrInvalidQuestion) {
|
||||
t.Fatalf("expected missing code snippet error, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInvitationReviewIsScopedToJob(t *testing.T) {
|
||||
store := &invitationStore{
|
||||
fakeStore: &fakeStore{},
|
||||
invitations: []model.Invitation{{ID: 3, JobID: 8, Token: "opaque-token"}},
|
||||
interview: model.Interview{Invitation: model.Invitation{ID: 3, JobID: 8}},
|
||||
}
|
||||
service := NewInvitationService(store, "")
|
||||
review, err := service.Review(context.Background(), 8, 3)
|
||||
if err != nil || review.Invitation.ID != 3 {
|
||||
t.Fatalf("expected invitation review, got %#v, %v", review, err)
|
||||
}
|
||||
if _, err := service.Review(context.Background(), 8, 4); !errors.Is(err, repository.ErrNotFound) {
|
||||
t.Fatalf("expected missing invitation error, got %v", err)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue