Skip to content

Commit

Permalink
feat: add should.ContainValue condition
Browse files Browse the repository at this point in the history
  • Loading branch information
omissis committed Aug 11, 2022
1 parent fe147bd commit ab29b23
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ if a file:
- [x] content matches value
- [x] content matches regex
- [ ] content matches template
- [ ] content contains a value
- [ ] is gitignored
- [ ] is gitcrypted

Expand Down
59 changes: 59 additions & 0 deletions internal/arch/file/should/contain_value.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package should

import (
"bytes"
"fmt"
"goarkitect/internal/arch/rule"
"os"
"path/filepath"
)

func ContainValue(value []byte, opts ...Option) *containValueExpression {
expr := &containValueExpression{
value: value,
}

for _, opt := range opts {
opt.apply(&expr.options)
}

return expr
}

type containValueExpression struct {
baseExpression

value []byte
}

func (e containValueExpression) Evaluate(rb rule.Builder) []rule.Violation {
return e.evaluate(rb, e.doEvaluate, e.getViolation)
}

func (e containValueExpression) doEvaluate(rb rule.Builder, filePath string) bool {
data, err := os.ReadFile(filePath)
if err != nil {
rb.AddError(err)

return true
}

if e.options.ignoreCase {
data = bytes.ToLower(data)
e.value = bytes.ToLower(e.value)
}

return !bytes.Contains(data, e.value)
}

func (e containValueExpression) getViolation(filePath string) rule.Violation {
format := "file '%s' does not contain the value '%s'"

if e.options.negated {
format = "file '%s' does contain the value '%s'"
}

return rule.NewViolation(
fmt.Sprintf(format, filepath.Base(filePath), e.value),
)
}
63 changes: 63 additions & 0 deletions internal/arch/file/should/contain_value_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package should_test

import (
"goarkitect/internal/arch/file"
"goarkitect/internal/arch/file/should"
"goarkitect/internal/arch/rule"
"os"
"path/filepath"
"testing"

"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
)

func Test_ContainValue(t *testing.T) {
basePath, err := os.Getwd()
if err != nil {
t.Fatal(err)
}

testCases := []struct {
desc string
ruleBuilder *file.RuleBuilder
value string
options []should.Option
want []rule.Violation
}{
{
desc: "file 'foobar.txt' contains the value 'bar'",
ruleBuilder: file.One(filepath.Join(basePath, "test/foobar.txt")),
value: "bar",
want: nil,
},
{
desc: "file 'foobar.txt' contains the value 'bar', ignoring case",
ruleBuilder: file.One(filepath.Join(basePath, "test/foobar.txt")),
value: "BAR",
options: []should.Option{
should.IgnoreCase{},
},
want: nil,
},
{
desc: "file 'foobar.txt' does not contain the value 'something else'",
ruleBuilder: file.One(filepath.Join(basePath, "test/foobar.txt")),
value: "something else",
want: []rule.Violation{
rule.NewViolation("file 'foobar.txt' does not contain the value 'something else'"),
},
},
}

for _, tC := range testCases {
t.Run(tC.desc, func(t *testing.T) {
hcm := should.ContainValue([]byte(tC.value), tC.options...)
got := hcm.Evaluate(tC.ruleBuilder)

if !cmp.Equal(got, tC.want, cmp.AllowUnexported(rule.Violation{}), cmpopts.EquateEmpty()) {
t.Errorf("want = %+v, got = %+v", tC.want, got)
}
})
}
}

0 comments on commit ab29b23

Please # to comment.