Skip to content

Commit

Permalink
Merge pull request #27 from go-spectest/import-subproject
Browse files Browse the repository at this point in the history
Import subproject
  • Loading branch information
nao1215 authored Oct 7, 2023
2 parents 109b419 + c2590b7 commit 7b9164a
Show file tree
Hide file tree
Showing 26 changed files with 2,563 additions and 9 deletions.
4 changes: 2 additions & 2 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@ linters:
- goconst
- gocritic
- goimports
- gomnd
#- gomnd
- gosec
- ifshort
- misspell
- nakedret
- noctx
- nolintlint
#- nolintlint
#- paralleltest
- prealloc
- rowserrcheck
Expand Down
30 changes: 30 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Changelog

## [0.0.2, Unreleased] - 2023-XX-XX

### Added
- GitHub Actions
- Unit Test for Linux/macOS/windows, reviewdog, golangci-lint
- Dependabot and patch/minor version auto update.
- Import side project; jsonpath, jsonschema, plantuml, css-selector
- aws package is not imported. It's broken.
- `APITest.CustomReportName()`
- Output sequence diagram with custom name instead of hash.
- Add help target to Makefile.

### Fixed
- Refactoring
- Refactoring for internal code. For example, meta information is now stored in a struct instead of a map.

### Changed
- Rename 'Http' to 'HTTP'. So, some function names are changed.
- `Http` -> `HTTP`
- `HttpHandler` -> `HTTPHandler`
- deprecated method in io/ioutil.

- Export difflib.
- I exported difflib as an external package (diff) because it is an independent package. Additionally, I made the diff package compatible with Windows. Specifically, it now displays differences in color even when indicating diffs in a Windows environment.

### Removed
- `APITest.Meta()` method.
- The precise information of the meta (map[string]interface{}) was not being exposed to users. Consequently, users found it challenging to effectively utilize APITest.Meta(). Instead of providing an alternative method, APITest.Meta() was removed.
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,14 @@ go get -u github.com/go-spectest/spectest
| [Ginkgo](https://github.com/go-spectest/spectest/tree/master/examples/ginkgo) | Ginkgo BDD test framework|

### Companion libraries (Side projects)

In the original apitest repository, side projects were managed in separate repositories. However, in spectest, these side projects are managed within the same repository. However, the difflib, which operates independently from spectest, and the malfunctioning aws package, are managed in separate repositories.

| Library | Comment |
| ----------------------------------------------------------------------- | -----------------------------------------------|
| [JSON Path](https://github.com/go-spectest/jsonpath) | JSON Path assertion addons |
| [JOSN Schema](https://github.com/go-spectest/jsonschema) | JSON Schema assertion addons |
| [CSS Selectors](https://github.com/go-spectest/css-selector) | CSS selector assertion addons |
| [PlantUML](https://github.com/go-spectest/plantuml) | Export sequence diagrams as plantUML |
| [JSON Path](https://github.com/go-spectest/spectest/jsonpath) | JSON Path assertion addons |
| [JOSN Schema](https://github.com/go-spectest/spectest/jsonschema) | JSON Schema assertion addons |
| [CSS Selectors](https://github.com/go-spectest/spectest/css-selector) | CSS selector assertion addons |
| [PlantUML](https://github.com/go-spectest/spectest/plantuml) | Export sequence diagrams as plantUML |
| [DynamoDB](https://github.com/go-spectest/aws) | Add DynamoDB interactions to sequence diagrams |

### Credits
Expand Down Expand Up @@ -82,7 +83,7 @@ func TestApi(t *testing.T) {

#### JSONPath

For asserting on parts of the response body JSONPath may be used. A separate module must be installed which provides these assertions - `go get -u github.com/go-spectest/jsonpath`. This is packaged separately to keep this library dependency free.
For asserting on parts of the response body JSONPath may be used. A separate module must be installed which provides these assertions - `go get -u github.com/go-spectest/spectest/jsonpath`. This is packaged separately to keep this library dependency free.

Given the response is `{"a": 12345, "b": [{"key": "c", "value": "result"}]}`

Expand Down
136 changes: 136 additions & 0 deletions css-selector/selector.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
// Package selector provides a set of functions for css selector based assertions
package selector

import (
"bytes"
"fmt"
"io"
"net/http"
"strings"

"github.com/PuerkitoBio/goquery"
)

type selectionMatcher func(i int, selection *goquery.Selection) bool

// DataTestID returns a css selector for a data-test-id attribute
func DataTestID(value string) string {
return fmt.Sprintf(`[data-test-id="%s"]`, value)
}

// FirstTextValue returns a function that asserts the first element matching the selection has the expected text value
func FirstTextValue(selection string, expectedTextValue string) func(*http.Response, *http.Request) error { //nolint
return newAssertSelection(selection, func(i int, selection *goquery.Selection) bool {
if i == 0 {
if selection.Text() == expectedTextValue {
return true
}
}
return false
})
}

// NthTextValue returns a function that asserts the nth element matching the selection has the expected text value
func NthTextValue(n int, selection string, expectedTextValue string) func(*http.Response, *http.Request) error { //nolint
return newAssertSelection(selection, func(i int, selection *goquery.Selection) bool {
if i == n {
if selection.Text() == expectedTextValue {
return true
}
}
return false
})
}

// ContainsTextValue returns a function that asserts the first element matching the selection contains the expected text value
func ContainsTextValue(selection string, expectedTextValue string) func(*http.Response, *http.Request) error { //nolint
return newAssertSelection(selection, func(i int, selection *goquery.Selection) bool {
return strings.Contains(selection.Text(), expectedTextValue)
})
}

// Selection returns
func Selection(selection string, selectionFunc func(*goquery.Selection) error) func(*http.Response, *http.Request) error {
return func(response *http.Response, request *http.Request) error {
doc, err := goquery.NewDocumentFromReader(response.Body)
if err != nil {
return err
}
return selectionFunc(doc.Find(selection))
}
}

// Exists returns a function that asserts the selection exists
func Exists(selections ...string) func(*http.Response, *http.Request) error {
return expectExists(true, selections...)
}

// NotExists returns a function that asserts the selection does not exist
func NotExists(selections ...string) func(*http.Response, *http.Request) error {
return expectExists(false, selections...)
}

// TextExists returns a function that asserts the document contains the expected text
func TextExists(text string) func(*http.Response, *http.Request) error {
return func(response *http.Response, request *http.Request) error {
bodyBytes, err := io.ReadAll(response.Body)
if err != nil {
return err
}

if !strings.Contains(string(bodyBytes), text) {
return fmt.Errorf("document did not contain '%v'", text)
}

return nil
}
}

func expectExists(exists bool, selections ...string) func(*http.Response, *http.Request) error {
return func(response *http.Response, request *http.Request) error {
bodyBytes, err := io.ReadAll(response.Body)
if err != nil {
return err
}

for _, selection := range selections {
doc, err := goquery.NewDocumentFromReader(bytes.NewReader(bodyBytes))
if err != nil {
return err
}

var found bool
doc.Find(selection).Each(func(i int, selection *goquery.Selection) {
found = true
})

if found != exists {
return fmt.Errorf("expected found='%v' for selector '%s'", exists, selection)
}
}

return nil
}
}

func newAssertSelection(selection string, matcher selectionMatcher) func(*http.Response, *http.Request) error {
return func(response *http.Response, request *http.Request) error {
doc, err := goquery.NewDocumentFromReader(response.Body)
if err != nil {
return err
}

var found bool
doc.Find(selection).Each(func(i int, selection *goquery.Selection) {
if matcher(i, selection) {
found = true
}
})

if !found {
return fmt.Errorf("did not find expected value for selector '%s'", selection)
}

return nil
}
}
Loading

0 comments on commit 7b9164a

Please sign in to comment.