Skip to content

Commit 4510a9a

Browse files
add test for createFlags
1 parent b97be28 commit 4510a9a

File tree

6 files changed

+590
-33
lines changed

6 files changed

+590
-33
lines changed

dao/inmemory_impl_mock.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ func (m *InMemoryMockDao) GetFlags(ctx context.Context) ([]model.FeatureFlag, da
3333

3434
// GetFlagByID return a flag by its ID
3535
func (m *InMemoryMockDao) GetFlagByID(ctx context.Context, id string) (model.FeatureFlag, daoErr.DaoError) {
36+
if ctx.Value("error") != nil {
37+
if err, ok := ctx.Value("error").(daoErr.DaoErrorCode); ok {
38+
return model.FeatureFlag{}, daoErr.NewDaoError(err, fmt.Errorf("error on get flag by id"))
39+
}
40+
return model.FeatureFlag{}, daoErr.NewDaoError(daoErr.UnknownError, fmt.Errorf("error on get flag by id"))
41+
}
3642
for _, flag := range m.flags {
3743
if flag.ID == id {
3844
return flag, nil
@@ -43,6 +49,12 @@ func (m *InMemoryMockDao) GetFlagByID(ctx context.Context, id string) (model.Fea
4349

4450
// GetFlagByName return a flag by its name
4551
func (m *InMemoryMockDao) GetFlagByName(ctx context.Context, name string) (model.FeatureFlag, daoErr.DaoError) {
52+
if ctx.Value("error") != nil {
53+
if err, ok := ctx.Value("error").(daoErr.DaoErrorCode); ok {
54+
return model.FeatureFlag{}, daoErr.NewDaoError(err, fmt.Errorf("error on get flag by name"))
55+
}
56+
return model.FeatureFlag{}, daoErr.NewDaoError(daoErr.UnknownError, fmt.Errorf("error on get flag by name"))
57+
}
4658
for _, flag := range m.flags {
4759
if flag.Name == name {
4860
return flag, nil
@@ -53,6 +65,13 @@ func (m *InMemoryMockDao) GetFlagByName(ctx context.Context, name string) (model
5365

5466
// CreateFlag create a new flag, return the id of the flag
5567
func (m *InMemoryMockDao) CreateFlag(ctx context.Context, flag model.FeatureFlag) (string, daoErr.DaoError) {
68+
if ctx.Value("error_create") != nil {
69+
if err, ok := ctx.Value("error_create").(daoErr.DaoErrorCode); ok {
70+
return "", daoErr.NewDaoError(err, fmt.Errorf("error creating flag"))
71+
}
72+
return "", daoErr.NewDaoError(daoErr.UnknownError, fmt.Errorf("error creating flag"))
73+
}
74+
5675
m.flags = append(m.flags, flag)
5776
return flag.ID, nil
5877
}

handler/flags.go

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"errors"
66
"fmt"
77
daoErr "github.com/go-feature-flag/app-api/dao/err"
8+
"github.com/go-feature-flag/app-api/util"
89
"github.com/labstack/echo/v4"
910
"net/http"
1011
"time"
@@ -15,14 +16,25 @@ import (
1516
"github.com/lib/pq"
1617
)
1718

19+
type FlagAPIHandlerOptions struct {
20+
Clock util.Clock
21+
}
22+
1823
type FlagAPIHandler struct {
19-
dao dao.Flags
24+
dao dao.Flags
25+
options *FlagAPIHandlerOptions
2026
}
2127

2228
// NewFlagAPIHandler creates a new instance of the FlagAPIHandler handler
2329
// It is a controller class to handle the feature flag configuration logic
24-
func NewFlagAPIHandler(dao dao.Flags) FlagAPIHandler {
25-
return FlagAPIHandler{dao: dao}
30+
func NewFlagAPIHandler(dao dao.Flags, options *FlagAPIHandlerOptions) FlagAPIHandler {
31+
if options == nil {
32+
options = &FlagAPIHandlerOptions{}
33+
}
34+
if options.Clock == nil {
35+
options.Clock = util.DefaultClock{}
36+
}
37+
return FlagAPIHandler{dao: dao, options: options}
2638
}
2739

2840
// GetAllFeatureFlags is returning the list of all the flags
@@ -87,8 +99,8 @@ func (f FlagAPIHandler) CreateNewFlag(c echo.Context) error {
8799
if flag.ID == "" {
88100
flag.ID = uuid.NewString()
89101
}
90-
flag.CreatedDate = time.Now()
91-
flag.LastUpdatedDate = time.Now()
102+
flag.CreatedDate = f.options.Clock.Now()
103+
flag.LastUpdatedDate = f.options.Clock.Now()
92104
// TODO: remove this line and extract the information from the token
93105
flag.LastModifiedBy = "toto"
94106

@@ -105,6 +117,9 @@ func (f FlagAPIHandler) CreateNewFlag(c echo.Context) error {
105117

106118
id, err := f.dao.CreateFlag(c.Request().Context(), flag)
107119
if err != nil {
120+
if err.Code() == daoErr.ConversionError {
121+
return c.JSON(model.NewHTTPError(http.StatusBadRequest, err))
122+
}
108123
return c.JSON(model.NewHTTPError(http.StatusInternalServerError, err))
109124
}
110125
flag.ID = id
@@ -123,8 +138,17 @@ func validateFlag(flag model.FeatureFlag) (int, error) {
123138
return status, err
124139
}
125140

126-
if flag.VariationType == "" {
141+
switch flag.VariationType {
142+
case model.FlagTypeBoolean,
143+
model.FlagTypeDouble,
144+
model.FlagTypeInteger,
145+
model.FlagTypeString,
146+
model.FlagTypeJSON:
147+
break
148+
case "":
127149
return http.StatusBadRequest, errors.New("flag type is required")
150+
default:
151+
return http.StatusBadRequest, fmt.Errorf("flag type %s not supported", flag.VariationType)
128152
}
129153

130154
for _, rule := range flag.GetRules() {
@@ -137,10 +161,15 @@ func validateFlag(flag model.FeatureFlag) (int, error) {
137161
}
138162

139163
func validateRule(rule *model.Rule, isDefault bool) (int, error) {
140-
if rule == nil ||
141-
(rule.ProgressiveRollout == nil &&
142-
rule.Percentages == nil &&
143-
(rule.VariationResult == nil || *rule.VariationResult == "")) {
164+
if rule == nil || *rule == (model.Rule{}) {
165+
if isDefault {
166+
return http.StatusBadRequest, errors.New("flag default rule is required")
167+
}
168+
return http.StatusBadRequest, errors.New("targeting rule is nil")
169+
}
170+
if rule.ProgressiveRollout == nil &&
171+
rule.Percentages == nil &&
172+
(rule.VariationResult == nil || *rule.VariationResult == "") {
144173
err := fmt.Errorf("invalid rule %s", rule.Name)
145174
if isDefault {
146175
err = errors.New("flag default rule is invalid")
@@ -150,7 +179,7 @@ func validateRule(rule *model.Rule, isDefault bool) (int, error) {
150179

151180
if !isDefault {
152181
if rule.Query == "" {
153-
return http.StatusBadRequest, errors.New("rule query is required")
182+
return http.StatusBadRequest, errors.New("query is required for targeting rules")
154183
}
155184
}
156185
return http.StatusOK, nil
@@ -263,7 +292,7 @@ func (f FlagAPIHandler) UpdateFeatureFlagStatus(c echo.Context) error {
263292
func (f FlagAPIHandler) handleDaoError(c echo.Context, err daoErr.DaoError) error {
264293
switch err.Code() {
265294
case daoErr.NotFound:
266-
return c.JSON(model.NewHTTPError(http.StatusNotFound, fmt.Errorf("flag with id %s not found", c.Param("id"))))
295+
return c.JSON(model.NewHTTPError(http.StatusNotFound, fmt.Errorf("flag not found")))
267296
case daoErr.InvalidUUID:
268297
return c.JSON(model.NewHTTPError(http.StatusBadRequest, fmt.Errorf("invalid UUID format")))
269298
default:

0 commit comments

Comments
 (0)