-
-
Notifications
You must be signed in to change notification settings - Fork 39
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added new operation 4xx response rule
Checks for at least a single request error defined for each operation. Had to update the burgershop spec, as it fell out of favor. added a silly 4xx code for fun. Signed-off-by: Dave Shanley <dave@quobix.com>
- Loading branch information
1 parent
c3171be
commit a0e8553
Showing
12 changed files
with
201 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
// Copyright 2020-2021 Dave Shanley / Quobix | ||
// SPDX-License-Identifier: MIT | ||
|
||
package openapi | ||
|
||
import ( | ||
"fmt" | ||
"github.com/daveshanley/vacuum/model" | ||
"github.com/daveshanley/vacuum/utils" | ||
"gopkg.in/yaml.v3" | ||
"strconv" | ||
) | ||
|
||
// Operation4xResponse is a rule that checks if an operation returns a 4xx (user error) code. | ||
type Operation4xResponse struct { | ||
} | ||
|
||
// GetSchema returns a model.RuleFunctionSchema defining the schema of the SuccessResponse rule. | ||
func (or Operation4xResponse) GetSchema() model.RuleFunctionSchema { | ||
return model.RuleFunctionSchema{Name: "operation_4xx_response"} | ||
} | ||
|
||
// RunRule will execute the Operation4xResponse rule, based on supplied context and a supplied []*yaml.Node slice. | ||
func (or Operation4xResponse) RunRule(nodes []*yaml.Node, context model.RuleFunctionContext) []model.RuleFunctionResult { | ||
|
||
if len(nodes) <= 0 { | ||
return nil | ||
} | ||
|
||
var results []model.RuleFunctionResult | ||
|
||
if context.Index.GetPathsNode() == nil { | ||
return results | ||
} | ||
ops := context.Index.GetPathsNode().Content | ||
|
||
var opPath, opMethod string | ||
for i, op := range ops { | ||
if i%2 == 0 { | ||
opPath = op.Value | ||
continue | ||
} | ||
for m, method := range op.Content { | ||
if m%2 == 0 { | ||
opMethod = method.Value | ||
continue | ||
} | ||
basePath := fmt.Sprintf("$.paths.%s.%s", opPath, opMethod) | ||
_, responsesNode := utils.FindKeyNode("responses", method.Content) | ||
|
||
if responsesNode != nil { | ||
seen := false | ||
for k, response := range responsesNode.Content { | ||
if k%2 != 0 { | ||
continue | ||
} | ||
responseCode, _ := strconv.Atoi(response.Value) | ||
if responseCode >= 400 && responseCode <= 499 { | ||
seen = true | ||
} | ||
} | ||
if !seen { | ||
results = append(results, model.RuleFunctionResult{ | ||
Message: "Operation must define at least one 4xx error response", | ||
StartNode: method, | ||
EndNode: utils.FindLastChildNode(method), | ||
Path: basePath, | ||
Rule: context.Rule, | ||
}) | ||
} | ||
} | ||
} | ||
} | ||
return results | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
package openapi | ||
|
||
import ( | ||
"github.com/daveshanley/vacuum/model" | ||
"github.com/daveshanley/vacuum/utils" | ||
"github.com/stretchr/testify/assert" | ||
"gopkg.in/yaml.v3" | ||
"io/ioutil" | ||
"testing" | ||
) | ||
|
||
func TestOperation4xResponse_GetSchema(t *testing.T) { | ||
def := Operation4xResponse{} | ||
assert.Equal(t, "operation_4xx_response", def.GetSchema().Name) | ||
} | ||
|
||
func TestOperation4xResponse_RunRule(t *testing.T) { | ||
def := Operation4xResponse{} | ||
res := def.RunRule(nil, model.RuleFunctionContext{}) | ||
assert.Len(t, res, 0) | ||
} | ||
|
||
func TestOperation4xResponse_RunRule_Success(t *testing.T) { | ||
|
||
sampleYaml, _ := ioutil.ReadFile("../../model/test_files/burgershop.openapi.yaml") | ||
|
||
var rootNode yaml.Node | ||
yaml.Unmarshal(sampleYaml, &rootNode) | ||
nodes, _ := utils.FindNodes(sampleYaml, "$") | ||
rule := buildOpenApiTestRuleAction(GetAllOperationsJSONPath(), "xor", "responses", nil) | ||
ctx := buildOpenApiTestContext(model.CastToRuleAction(rule.Then), nil) | ||
ctx.Index = model.NewSpecIndex(&rootNode) | ||
|
||
def := Operation4xResponse{} | ||
res := def.RunRule(nodes, ctx) | ||
|
||
assert.Len(t, res, 0) | ||
} | ||
|
||
func TestOperation4xResponse_RunRule_ExitEarly(t *testing.T) { | ||
|
||
sampleYaml := []byte("hi: there") | ||
|
||
var rootNode yaml.Node | ||
yaml.Unmarshal(sampleYaml, &rootNode) | ||
nodes, _ := utils.FindNodes(sampleYaml, "$") | ||
rule := buildOpenApiTestRuleAction(GetAllOperationsJSONPath(), "xor", "responses", nil) | ||
ctx := buildOpenApiTestContext(model.CastToRuleAction(rule.Then), nil) | ||
ctx.Index = model.NewSpecIndex(&rootNode) | ||
|
||
def := Operation4xResponse{} | ||
res := def.RunRule(nodes, ctx) | ||
|
||
assert.Len(t, res, 0) | ||
} | ||
|
||
func TestOperation4xResponse_RunRule_Fail(t *testing.T) { | ||
|
||
sampleYaml, _ := ioutil.ReadFile("../../model/test_files/stripe.yaml") | ||
|
||
var rootNode yaml.Node | ||
yaml.Unmarshal(sampleYaml, &rootNode) | ||
nodes, _ := utils.FindNodes(sampleYaml, "$") | ||
rule := buildOpenApiTestRuleAction(GetAllOperationsJSONPath(), "xor", "responses", nil) | ||
ctx := buildOpenApiTestContext(model.CastToRuleAction(rule.Then), nil) | ||
ctx.Index = model.NewSpecIndex(&rootNode) | ||
|
||
def := Operation4xResponse{} | ||
res := def.RunRule(nodes, ctx) | ||
|
||
assert.Len(t, res, 402) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters