198 lines
5.2 KiB
Go
198 lines
5.2 KiB
Go
package httpexpect
|
|
|
|
import (
|
|
"reflect"
|
|
)
|
|
|
|
// Match provides methods to inspect attached regexp match results.
|
|
type Match struct {
|
|
chain chain
|
|
submatches []string
|
|
names map[string]int
|
|
}
|
|
|
|
// NewMatch returns a new Match object given a reporter used to report
|
|
// failures and submatches to be inspected.
|
|
//
|
|
// reporter should not be nil. submatches and names may be nil.
|
|
//
|
|
// Example:
|
|
// s := "http://example.com/users/john"
|
|
// r := regexp.MustCompile(`http://(?P<host>.+)/users/(?P<user>.+)`)
|
|
// m := NewMatch(reporter, r.FindStringSubmatch(s), r.SubexpNames())
|
|
//
|
|
// m.NotEmpty()
|
|
// m.Length().Equal(3)
|
|
//
|
|
// m.Index(0).Equal("http://example.com/users/john")
|
|
// m.Index(1).Equal("example.com")
|
|
// m.Index(2).Equal("john")
|
|
//
|
|
// m.Name("host").Equal("example.com")
|
|
// m.Name("user").Equal("john")
|
|
func NewMatch(reporter Reporter, submatches []string, names []string) *Match {
|
|
return makeMatch(makeChain(reporter), submatches, names)
|
|
}
|
|
|
|
func makeMatch(chain chain, submatches []string, names []string) *Match {
|
|
if submatches == nil {
|
|
submatches = []string{}
|
|
}
|
|
namemap := map[string]int{}
|
|
for n, name := range names {
|
|
if name != "" {
|
|
namemap[name] = n
|
|
}
|
|
}
|
|
return &Match{chain, submatches, namemap}
|
|
}
|
|
|
|
// Raw returns underlying submatches attached to Match.
|
|
// This is the value originally passed to NewMatch.
|
|
//
|
|
// Example:
|
|
// m := NewMatch(t, submatches, names)
|
|
// assert.Equal(t, submatches, m.Raw())
|
|
func (m *Match) Raw() []string {
|
|
return m.submatches
|
|
}
|
|
|
|
// Length returns a new Number object that may be used to inspect
|
|
// number of submatches.
|
|
//
|
|
// Example:
|
|
// m := NewMatch(t, submatches, names)
|
|
// m.Length().Equal(len(submatches))
|
|
func (m *Match) Length() *Number {
|
|
return &Number{m.chain, float64(len(m.submatches))}
|
|
}
|
|
|
|
// Index returns a new String object that may be used to inspect submatch
|
|
// with given index.
|
|
//
|
|
// Note that submatch with index 0 contains the whole match. If index is out
|
|
// of bounds, Index reports failure and returns empty (but non-nil) value.
|
|
//
|
|
// Example:
|
|
// s := "http://example.com/users/john"
|
|
//
|
|
// r := regexp.MustCompile(`http://(.+)/users/(.+)`)
|
|
// m := NewMatch(t, r.FindStringSubmatch(s), nil)
|
|
//
|
|
// m.Index(0).Equal("http://example.com/users/john")
|
|
// m.Index(1).Equal("example.com")
|
|
// m.Index(2).Equal("john")
|
|
func (m *Match) Index(index int) *String {
|
|
if index < 0 || index >= len(m.submatches) {
|
|
m.chain.fail(
|
|
"\nsubmatch index out of bounds:\n index %d\n\n bounds [%d; %d)",
|
|
index,
|
|
0,
|
|
len(m.submatches))
|
|
return &String{m.chain, ""}
|
|
}
|
|
return &String{m.chain, m.submatches[index]}
|
|
}
|
|
|
|
// Name returns a new String object that may be used to inspect submatch
|
|
// with given name.
|
|
//
|
|
// If there is no submatch with given name, Name reports failure and returns
|
|
// empty (but non-nil) value.
|
|
//
|
|
// Example:
|
|
// s := "http://example.com/users/john"
|
|
//
|
|
// r := regexp.MustCompile(`http://(?P<host>.+)/users/(?P<user>.+)`)
|
|
// m := NewMatch(t, r.FindStringSubmatch(s), r.SubexpNames())
|
|
//
|
|
// m.Name("host").Equal("example.com")
|
|
// m.Name("user").Equal("john")
|
|
func (m *Match) Name(name string) *String {
|
|
index, ok := m.names[name]
|
|
if !ok {
|
|
m.chain.fail(
|
|
"\nsubmatch name not found:\n %q\n\navailable names:\n%s",
|
|
name,
|
|
dumpValue(m.names))
|
|
return &String{m.chain, ""}
|
|
}
|
|
return m.Index(index)
|
|
}
|
|
|
|
// Empty succeeds if submatches array is empty.
|
|
//
|
|
// Example:
|
|
// m := NewMatch(t, submatches, names)
|
|
// m.Empty()
|
|
func (m *Match) Empty() *Match {
|
|
if len(m.submatches) != 0 {
|
|
m.chain.fail("\nexpected zero submatches, but got:\n %s",
|
|
dumpValue(m.submatches))
|
|
}
|
|
return m
|
|
}
|
|
|
|
// NotEmpty succeeds if submatches array is non-empty.
|
|
//
|
|
// Example:
|
|
// m := NewMatch(t, submatches, names)
|
|
// m.NotEmpty()
|
|
func (m *Match) NotEmpty() *Match {
|
|
if len(m.submatches) == 0 {
|
|
m.chain.fail("expected non-zero submatches")
|
|
}
|
|
return m
|
|
}
|
|
|
|
// Values succeeds if submatches array, starting from index 1, is equal to
|
|
// given array.
|
|
//
|
|
// Note that submatch with index 0 contains the whole match and is not
|
|
// included into this check.
|
|
//
|
|
// Example:
|
|
// s := "http://example.com/users/john"
|
|
// r := regexp.MustCompile(`http://(.+)/users/(.+)`)
|
|
// m := NewMatch(t, r.FindStringSubmatch(s), nil)
|
|
// m.Values("example.com", "john")
|
|
func (m *Match) Values(values ...string) *Match {
|
|
if values == nil {
|
|
values = []string{}
|
|
}
|
|
if !reflect.DeepEqual(values, m.getValues()) {
|
|
m.chain.fail("\nexpected submatches equal to:\n%s\n\nbut got:\n%s",
|
|
dumpValue(values),
|
|
dumpValue(m.getValues()))
|
|
}
|
|
return m
|
|
}
|
|
|
|
// NotValues succeeds if submatches array, starting from index 1, is not
|
|
// equal to given array.
|
|
//
|
|
// Note that submatch with index 0 contains the whole match and is not
|
|
// included into this check.
|
|
//
|
|
// Example:
|
|
// s := "http://example.com/users/john"
|
|
// r := regexp.MustCompile(`http://(.+)/users/(.+)`)
|
|
// m := NewMatch(t, r.FindStringSubmatch(s), nil)
|
|
// m.NotValues("example.com", "bob")
|
|
func (m *Match) NotValues(values ...string) *Match {
|
|
if values == nil {
|
|
values = []string{}
|
|
}
|
|
if reflect.DeepEqual(values, m.getValues()) {
|
|
m.chain.fail("\nexpected submatches not equal to:\n%s",
|
|
dumpValue(values))
|
|
}
|
|
return m
|
|
}
|
|
|
|
func (m *Match) getValues() []string {
|
|
if len(m.submatches) > 1 {
|
|
return m.submatches[1:]
|
|
}
|
|
return []string{}
|
|
}
|