123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320 |
- package httpexpect
- import (
- "net/http"
- "regexp"
- "strings"
- "time"
- )
- // String provides methods to inspect attached string value
- // (Go representation of JSON string).
- type String struct {
- chain chain
- value string
- }
- // NewString returns a new String given a reporter used to report failures
- // and value to be inspected.
- //
- // reporter should not be nil.
- //
- // Example:
- // str := NewString(t, "Hello")
- func NewString(reporter Reporter, value string) *String {
- return &String{makeChain(reporter), value}
- }
- // Raw returns underlying value attached to String.
- // This is the value originally passed to NewString.
- //
- // Example:
- // str := NewString(t, "Hello")
- // assert.Equal(t, "Hello", str.Raw())
- func (s *String) Raw() string {
- return s.value
- }
- // Path is similar to Value.Path.
- func (s *String) Path(path string) *Value {
- return getPath(&s.chain, s.value, path)
- }
- // Schema is similar to Value.Schema.
- func (s *String) Schema(schema interface{}) *String {
- checkSchema(&s.chain, s.value, schema)
- return s
- }
- // Length returns a new Number object that may be used to inspect string length.
- //
- // Example:
- // str := NewString(t, "Hello")
- // str.Length().Equal(5)
- func (s *String) Length() *Number {
- return &Number{s.chain, float64(len(s.value))}
- }
- // DateTime parses date/time from string an returns a new DateTime object.
- //
- // If layout is given, DateTime() uses time.Parse() with given layout.
- // Otherwise, it uses http.ParseTime(). If pasing error occurred,
- // DateTime reports failure and returns empty (but non-nil) object.
- //
- // Example:
- // str := NewString(t, "Tue, 15 Nov 1994 08:12:31 GMT")
- // str.DateTime().Lt(time.Now())
- //
- // str := NewString(t, "15 Nov 94 08:12 GMT")
- // str.DateTime(time.RFC822).Lt(time.Now())
- func (s *String) DateTime(layout ...string) *DateTime {
- if s.chain.failed() {
- return &DateTime{s.chain, time.Unix(0, 0)}
- }
- var (
- t time.Time
- err error
- )
- if len(layout) != 0 {
- t, err = time.Parse(layout[0], s.value)
- } else {
- t, err = http.ParseTime(s.value)
- }
- if err != nil {
- s.chain.fail(err.Error())
- return &DateTime{s.chain, time.Unix(0, 0)}
- }
- return &DateTime{s.chain, t}
- }
- // Empty succeeds if string is empty.
- //
- // Example:
- // str := NewString(t, "")
- // str.Empty()
- func (s *String) Empty() *String {
- return s.Equal("")
- }
- // NotEmpty succeeds if string is non-empty.
- //
- // Example:
- // str := NewString(t, "Hello")
- // str.NotEmpty()
- func (s *String) NotEmpty() *String {
- return s.NotEqual("")
- }
- // Equal succeeds if string is equal to another str.
- //
- // Example:
- // str := NewString(t, "Hello")
- // str.Equal("Hello")
- func (s *String) Equal(value string) *String {
- if !(s.value == value) {
- s.chain.fail("\nexpected string equal to:\n %q\n\nbut got:\n %q",
- value, s.value)
- }
- return s
- }
- // NotEqual succeeds if string is not equal to another str.
- //
- // Example:
- // str := NewString(t, "Hello")
- // str.NotEqual("Goodbye")
- func (s *String) NotEqual(value string) *String {
- if !(s.value != value) {
- s.chain.fail("\nexpected string not equal to:\n %q", value)
- }
- return s
- }
- // EqualFold succeeds if string is equal to another string under Unicode case-folding
- // (case-insensitive match).
- //
- // Example:
- // str := NewString(t, "Hello")
- // str.EqualFold("hELLo")
- func (s *String) EqualFold(value string) *String {
- if !strings.EqualFold(s.value, value) {
- s.chain.fail(
- "\nexpected string equal to (case-insensitive):\n %q\n\nbut got:\n %q",
- value, s.value)
- }
- return s
- }
- // NotEqualFold succeeds if string is not equal to another string under Unicode
- // case-folding (case-insensitive match).
- //
- // Example:
- // str := NewString(t, "Hello")
- // str.NotEqualFold("gOODBYe")
- func (s *String) NotEqualFold(value string) *String {
- if strings.EqualFold(s.value, value) {
- s.chain.fail(
- "\nexpected string not equal to (case-insensitive):\n %q\n\nbut got:\n %q",
- value, s.value)
- }
- return s
- }
- // Contains succeeds if string contains given substr.
- //
- // Example:
- // str := NewString(t, "Hello")
- // str.Contains("ell")
- func (s *String) Contains(value string) *String {
- if !strings.Contains(s.value, value) {
- s.chain.fail(
- "\nexpected string containing substring:\n %q\n\nbut got:\n %q",
- value, s.value)
- }
- return s
- }
- // NotContains succeeds if string doesn't contain given substr.
- //
- // Example:
- // str := NewString(t, "Hello")
- // str.NotContains("bye")
- func (s *String) NotContains(value string) *String {
- if strings.Contains(s.value, value) {
- s.chain.fail(
- "\nexpected string not containing substring:\n %q\n\nbut got:\n %q",
- value, s.value)
- }
- return s
- }
- // ContainsFold succeeds if string contains given substring under Unicode case-folding
- // (case-insensitive match).
- //
- // Example:
- // str := NewString(t, "Hello")
- // str.ContainsFold("ELL")
- func (s *String) ContainsFold(value string) *String {
- if !strings.Contains(strings.ToLower(s.value), strings.ToLower(value)) {
- s.chain.fail(
- "\nexpected string containing substring (case-insensitive):\n %q"+
- "\n\nbut got:\n %q", value, s.value)
- }
- return s
- }
- // NotContainsFold succeeds if string doesn't contain given substring under Unicode
- // case-folding (case-insensitive match).
- //
- // Example:
- // str := NewString(t, "Hello")
- // str.NotContainsFold("BYE")
- func (s *String) NotContainsFold(value string) *String {
- if strings.Contains(strings.ToLower(s.value), strings.ToLower(value)) {
- s.chain.fail(
- "\nexpected string not containing substring (case-insensitive):\n %q"+
- "\n\nbut got:\n %q", value, s.value)
- }
- return s
- }
- // Match matches the string with given regexp and returns a new Match object
- // with found submatches.
- //
- // If regexp is invalid or string doesn't match regexp, Match fails and returns
- // empty (but non-nil) object. regexp.Compile is used to construct regexp, and
- // Regexp.FindStringSubmatch is used to construct matches.
- //
- // Example:
- // s := NewString(t, "http://example.com/users/john")
- // m := s.Match(`http://(?P<host>.+)/users/(?P<user>.+)`)
- //
- // 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 (s *String) Match(re string) *Match {
- r, err := regexp.Compile(re)
- if err != nil {
- s.chain.fail(err.Error())
- return makeMatch(s.chain, nil, nil)
- }
- m := r.FindStringSubmatch(s.value)
- if m == nil {
- s.chain.fail("\nexpected string matching regexp:\n `%s`\n\nbut got:\n %q",
- re, s.value)
- return makeMatch(s.chain, nil, nil)
- }
- return makeMatch(s.chain, m, r.SubexpNames())
- }
- // MatchAll find all matches in string for given regexp and returns a list
- // of found matches.
- //
- // If regexp is invalid or string doesn't match regexp, MatchAll fails and
- // returns empty (but non-nil) slice. regexp.Compile is used to construct
- // regexp, and Regexp.FindAllStringSubmatch is used to find matches.
- //
- // Example:
- // s := NewString(t,
- // "http://example.com/users/john http://example.com/users/bob")
- //
- // m := s.MatchAll(`http://(?P<host>\S+)/users/(?P<user>\S+)`)
- //
- // m[0].Name("user").Equal("john")
- // m[1].Name("user").Equal("bob")
- func (s *String) MatchAll(re string) []Match {
- r, err := regexp.Compile(re)
- if err != nil {
- s.chain.fail(err.Error())
- return []Match{}
- }
- matches := r.FindAllStringSubmatch(s.value, -1)
- if matches == nil {
- s.chain.fail("\nexpected string matching regexp:\n `%s`\n\nbut got:\n %q",
- re, s.value)
- return []Match{}
- }
- ret := []Match{}
- for _, m := range matches {
- ret = append(ret, *makeMatch(
- s.chain,
- m,
- r.SubexpNames()))
- }
- return ret
- }
- // NotMatch succeeds if the string doesn't match to given regexp.
- //
- // regexp.Compile is used to construct regexp, and Regexp.MatchString
- // is used to perform match.
- //
- // Example:
- // s := NewString(t, "a")
- // s.NotMatch(`[^a]`)
- func (s *String) NotMatch(re string) *String {
- r, err := regexp.Compile(re)
- if err != nil {
- s.chain.fail(err.Error())
- return s
- }
- if r.MatchString(s.value) {
- s.chain.fail("\nexpected string not matching regexp:\n `%s`\n\nbut got:\n %q",
- re, s.value)
- return s
- }
- return s
- }
|