generated from VLADIMIR/template
112 lines
3.8 KiB
Go
112 lines
3.8 KiB
Go
package app
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"testing"
|
|
|
|
"evening_detective_server/internal/modules/file_storage"
|
|
"evening_detective_server/internal/repos"
|
|
"evening_detective_server/internal/services/game_print_service"
|
|
"evening_detective_server/internal/services/scenarios_service"
|
|
"evening_detective_server/internal/services/team_service"
|
|
"evening_detective_server/proto"
|
|
|
|
"google.golang.org/grpc"
|
|
"google.golang.org/grpc/codes"
|
|
"google.golang.org/grpc/status"
|
|
)
|
|
|
|
type printGameStub struct{}
|
|
|
|
func (printGameStub) GetGameByID(context.Context, int) (*repos.Game, error) {
|
|
return &repos.Game{ID: 1, Name: "Дело №1", Format: "offline"}, nil
|
|
}
|
|
|
|
func (printGameStub) GetFullScenarioByID(context.Context, int) (*scenarios_service.Scenario, error) {
|
|
return &scenarios_service.Scenario{}, nil
|
|
}
|
|
|
|
func (printGameStub) GetActiveTeamsByGameID(context.Context, int) ([]*repos.Team, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
func TestDownloadGamePrintMaterialsHeaders(t *testing.T) {
|
|
for _, role := range []string{"organizer", "author", "admin"} {
|
|
t.Run(role, func(t *testing.T) {
|
|
stub := printGameStub{}
|
|
s := &server{gamePrintService: game_print_service.NewGamePrintService(stub, stub, stub, nil, nil, "")}
|
|
stream := &mockServerTransportStream{}
|
|
ctx := grpc.NewContextWithServerTransportStream(ctxWithClaims(role), stream)
|
|
body, err := s.DownloadGamePrintMaterials(ctx, &proto.GetGameReq{ID: 1})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if body.ContentType != "application/zip" || !bytes.HasPrefix(body.Data, []byte("PK")) {
|
|
t.Fatal("invalid ZIP response")
|
|
}
|
|
for key, want := range map[string]string{
|
|
"content-disposition": "attachment; filename=game-1-print-materials.zip",
|
|
"cache-control": "no-store",
|
|
"x-content-type-options": "nosniff",
|
|
} {
|
|
values := stream.header.Get(key)
|
|
if len(values) != 1 || values[0] != want {
|
|
t.Errorf("%s = %v, want %s", key, values, want)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDownloadGamePrintMaterialsAccess(t *testing.T) {
|
|
for _, tc := range []struct {
|
|
name string
|
|
ctx context.Context
|
|
request *proto.GetGameReq
|
|
want codes.Code
|
|
}{
|
|
{"anonymous", context.Background(), &proto.GetGameReq{ID: 1}, codes.Unauthenticated},
|
|
{"player", ctxWithClaims("user"), &proto.GetGameReq{ID: 1}, codes.PermissionDenied},
|
|
{"developer", ctxWithClaims("developer"), &proto.GetGameReq{ID: 1}, codes.PermissionDenied},
|
|
{"organizer invalid ID", ctxWithClaims("organizer"), &proto.GetGameReq{}, codes.InvalidArgument},
|
|
{"author invalid ID", ctxWithClaims("author"), &proto.GetGameReq{ID: -1}, codes.InvalidArgument},
|
|
{"admin nil request", ctxWithClaims("admin"), nil, codes.InvalidArgument},
|
|
} {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
_, err := (&server{}).DownloadGamePrintMaterials(tc.ctx, tc.request)
|
|
if status.Code(err) != tc.want {
|
|
t.Fatalf("code = %v, want %v", status.Code(err), tc.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGamePrintErrorMapping(t *testing.T) {
|
|
for _, tc := range []struct {
|
|
err error
|
|
want codes.Code
|
|
}{
|
|
{team_service.ErrGameNotFound, codes.NotFound},
|
|
{scenarios_service.ErrScenarioNotFound, codes.NotFound},
|
|
{game_print_service.ErrPackageTooLarge, codes.ResourceExhausted},
|
|
{game_print_service.ErrInvalidPrintText, codes.FailedPrecondition},
|
|
{file_storage.ErrFileNotFound, codes.FailedPrecondition},
|
|
{context.Canceled, codes.Canceled},
|
|
{context.DeadlineExceeded, codes.DeadlineExceeded},
|
|
{errors.New("private storage detail"), codes.Internal},
|
|
} {
|
|
t.Run(tc.err.Error(), func(t *testing.T) {
|
|
err := gamePrintError(fmt.Errorf("wrapped: %w", tc.err))
|
|
if status.Code(err) != tc.want {
|
|
t.Fatalf("code = %v, want %v", status.Code(err), tc.want)
|
|
}
|
|
if tc.want == codes.Internal && status.Convert(err).Message() != "не удалось подготовить материалы для печати" {
|
|
t.Fatal("private error exposed")
|
|
}
|
|
})
|
|
}
|
|
}
|