Skip to content

Commit

Permalink
add language annotation in code block and empty string assertion
Browse files Browse the repository at this point in the history
  • Loading branch information
chonla committed Jun 7, 2020
1 parent e45d78f commit 797289c
Show file tree
Hide file tree
Showing 7 changed files with 186 additions and 3 deletions.
11 changes: 11 additions & 0 deletions assertable/matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"regexp"
"strings"
"reflect"

"github.com/fatih/color"
)
Expand Down Expand Up @@ -124,6 +125,16 @@ func (m *Matcher) Match(a *Assertable) (bool, error) {
return true, nil
}
return false, fmt.Errorf("expect %s to be boolean and false, but it does not", red(m.key))
case "should be empty":
if reflect.DeepEqual(val, []string{""}) {
return true, nil
}
return false, fmt.Errorf("expect %s to be empty string, but it does not", red(m.key))
case "should not be empty":
if !reflect.DeepEqual(val, []string{""}) {
return true, nil
}
return false, fmt.Errorf("expect %s to be empty string, but it does not", red(m.key))
}
}
if ok {
Expand Down
124 changes: 124 additions & 0 deletions assertable/matcher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -646,3 +646,127 @@ func TestBuiltInShouldBeFalseOnNonBooleanValue(t *testing.T) {
})
}
}

func TestBuiltInShouldBeEmpty(t *testing.T) {
jsonString := "{ \"data\": \"ok\", \"list\": [0, 1, 2], \"item\": \"\" }"

response := &response.Response{
Proto: "http",
Status: "200 OK",
StatusCode: 200,
Header: map[string][]string{
"content-type": []string{
"application/json; charset=utf-8",
},
},
Body: jsonString,
}

assertable := NewAssertable(response)

cases := []struct {
name string
input string
}{
{
name: "star",
input: "*should be empty*",
},
{
name: "underscore",
input: "_should be empty_",
},
}

negativeCases := []struct {
name string
input string
}{
{
name: "star",
input: "*should not be empty*",
},
{
name: "underscore",
input: "_should not be empty_",
},
}

for _, v := range cases {
t.Run(v.name, func(t *testing.T) {
m := NewMatcher("data.item", v.input, nil)
r, _ := m.Match(assertable)
assert.True(t, r)
})
}

for _, v := range negativeCases {
t.Run(v.name, func(t *testing.T) {
m := NewMatcher("data.item", v.input, nil)
r, _ := m.Match(assertable)
assert.False(t, r)
})
}
}

func TestBuiltInShouldNotBeEmpty(t *testing.T) {
jsonString := "{ \"data\": \"ok\", \"list\": [0, 1, 2], \"item\": \"element\" }"

response := &response.Response{
Proto: "http",
Status: "200 OK",
StatusCode: 200,
Header: map[string][]string{
"content-type": []string{
"application/json; charset=utf-8",
},
},
Body: jsonString,
}

assertable := NewAssertable(response)

cases := []struct {
name string
input string
}{
{
name: "star",
input: "*should not be empty*",
},
{
name: "underscore",
input: "_should not be empty_",
},
}

negativeCases := []struct {
name string
input string
}{
{
name: "star",
input: "*should be empty*",
},
{
name: "underscore",
input: "_should be empty_",
},
}

for _, v := range cases {
t.Run(v.name, func(t *testing.T) {
m := NewMatcher("data.item", v.input, nil)
r, _ := m.Match(assertable)
assert.True(t, r)
})
}

for _, v := range negativeCases {
t.Run(v.name, func(t *testing.T) {
m := NewMatcher("data.item", v.input, nil)
r, _ := m.Match(assertable)
assert.False(t, r)
})
}
}
19 changes: 18 additions & 1 deletion guide/Actions.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Action is a request sent to RESTful API application. Use `##` to define an actio

## Request Body

Some action may need to send a body to the server, like `POST`. Use ~```~ to declare the request body.
Some action may need to send a body to the server, like `POST`. Use code block, ~```~ or `~~~`, to declare the request body. Code block with language annotated is acceptable.

## Request Headers

Expand Down Expand Up @@ -43,6 +43,23 @@ Authorization: Bearer some-token
}
```

## Example Code Block with Annotated Language

~~~
## POST /todos
| Header | Value |
| - | - |
| Content-Type | application/json |
| Authorization | Bearer some-token |
```json
{
"title": "Buy milk"
}
```
~~~

## File Upload Example

~~~
Expand Down
2 changes: 2 additions & 0 deletions guide/Assertions.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ Cotton provide some predefined expectation to help assertion. The following expe
| `*should not be null*` | The asserted variable should not be null. |
| `*should be true*` | The asserted variable should be boolean with value TRUE. |
| `*should be false*` | The asserted variable should be boolean with value FALSE. |
| `*should be empty*` | The asserted variable should be empty string. This is a shortcut version of regular expression `//`. |
| `*should not be empty*` | The asserted variable should not be empty string. This is a shortcut version of regular expression `/.+/`. |

Underscores can also be used instead of stars, e.g.: `_should exist_`

Expand Down
2 changes: 1 addition & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
)

// VERSION of cotton
const VERSION = "0.3.8"
const VERSION = "0.4.0"

// Vars are injected variables from command line
type Vars []string
Expand Down
10 changes: 9 additions & 1 deletion markdown/element.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,16 @@ func tryBullet(data []string) (ElementInterface, bool) {

func tryCodeBlock(data []string) (ElementInterface, bool) {
body := strings.Join(data, "\n")
re := regexp.MustCompile("^(?s)```\\n(.*)\\n```")
re := regexp.MustCompile("^(?s)```[^\\n]*\\n(.*)\\n```")
m := re.FindStringSubmatch(body)
if len(m) == 0 {
// Alternate code block
re = regexp.MustCompile("^(?s)~~~[^\\n]*\\n(.*)\\n~~~")
m = re.FindStringSubmatch(body)
if len(m) == 0 {
}
}

if len(m) > 1 {
return &SimpleElement{
BaseElement: &BaseElement{
Expand Down
21 changes: 21 additions & 0 deletions markdown/element_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ func TestNewElementWithKnownElements(t *testing.T) {
[]string{"* Bullet 1 with [Anchor Text](Anchor Link)"},
[]string{"* [Anchor Text](Anchor Link)"},
[]string{"```", "text in code block", "another text", "```"},
[]string{"~~~", "text in code block", "another text", "~~~"},
[]string{"```json", "text in code block", "another text", "```"},
[]string{"~~~json", "text in code block", "another text", "~~~"},
}
expected := []ElementInterface{
&SimpleElement{
Expand Down Expand Up @@ -93,6 +96,24 @@ func TestNewElementWithKnownElements(t *testing.T) {
},
Text: "text in code block\nanother text",
},
&SimpleElement{
BaseElement: &BaseElement{
Type: "Code",
},
Text: "text in code block\nanother text",
},
&SimpleElement{
BaseElement: &BaseElement{
Type: "Code",
},
Text: "text in code block\nanother text",
},
&SimpleElement{
BaseElement: &BaseElement{
Type: "Code",
},
Text: "text in code block\nanother text",
},
}

for i := 0; i < len(data); i++ {
Expand Down

0 comments on commit 797289c

Please sign in to comment.