diff --git a/README.md b/README.md index c83bdb5..bc3ccf6 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![gdutils](https://github.com/pawelWritesCode/gdutils/workflows/gdutils/badge.svg)](https://github.com/pawelWritesCode/gdutils/actions) [![Go Reference](https://pkg.go.dev/badge/github.com/pawelWritesCode/gdutils.svg)](https://pkg.go.dev/github.com/pawelWritesCode/gdutils) ![Coverage](https://img.shields.io/badge/Coverage-65.2%25-brightgreen) +[![gdutils](https://github.com/pawelWritesCode/gdutils/workflows/gdutils/badge.svg)](https://github.com/pawelWritesCode/gdutils/actions) [![Go Reference](https://pkg.go.dev/badge/github.com/pawelWritesCode/gdutils.svg)](https://pkg.go.dev/github.com/pawelWritesCode/gdutils) ![Coverage](https://img.shields.io/badge/Coverage-65.7%25-brightgreen) # GDUTILS @@ -41,73 +41,73 @@ if err := ac.AssertNodeIsType(format.JSON, "$.gifs", types.Array); err != nil { ### Available methods: -| NAME | DESCRIPTION | -|----------------------------------------|:----------------------------------------------------------------------------------------:| -| | | -| **Sending HTTP(s) requests:** | | -| | | -| RequestSendWithBodyAndHeaders | Sends HTTP(s) request with provided body and headers. | -| RequestPrepare | Prepare HTTP(s) request | -| RequestSetHeaders | Sets provided headers for previously prepared request | -| RequestSetForm | Sets provided form for previously prepared request | -| RequestSetCookies | Sets provided cookies for previously prepared request | -| RequestSetBody | Sets body for previously prepared request | -| RequestSend | Sends previously prepared HTTP(s) request | -| | | -| **Random data generation:** | | -| | | -| GenerateRandomInt | Generates random integer from provided range and save it under provided cache key | -| GenerateFloat64 | Generates random float from provided range and save it under provided cache key | -| GeneratorRandomRunes | Creates generator for random strings from provided charset in provided range | -| GeneratorRandomSentence | Creates generator for random sentence from provided charset in provided range | -| GetTimeAndTravel | Accepts time object and move in time by given time interval | -| GenerateTimeAndTravel | Creates current time object and move in time by given time interval | -| | | -| **Preserving data:** | | -| | | -| SaveNode | Saves from last response body JSON node under given cacheKey key | -| SaveHeader | Saves into cache given header value | -| Save | Saves into cache arbitrary passed value | -| | | -| **Debugging:** | | -| | | -| DebugPrintResponseBody | Prints last response from request | -| DebugStart | Starts debugging mode | -| DebugStop | Stops debugging mode | -| | | -| **Flow control:** | | -| | | -| Wait | Stops test execution for provided amount of time | -| | | -| **Assertions:** | | -| | | -| AssertResponseHeaderExists | Checks whether last HTTP(s) response has given header | -| AssertResponseHeaderNotExists | Checks whether last HTTP(s) response doesn't have given header | -| AssertResponseHeaderValueIs | Checks whether last HTTP(s) response has given header with provided value | -| AssertStatusCodeIs | Checks last HTTP(s) response status code | -| AssertStatusCodeIsNot | Checks if last HTTP(s) response status code is not of provided value | -| AssertResponseFormatIs | Checks whether last HTTP(s) response body has given data format | -| AssertResponseFormatIsNot | Checks whether last HTTP(s) response body doesn't have given data format | -| AssertNodeExists | Checks whether last response body contains given key | -| AssertNodeNotExists | Checks whether last response body doesn't contain given key | -| AssertNodesExist | Checks whether last HTTP(s) response body JSON has given nodes | -| AssertNodeIsTypeAndValue | Compares json node value from expression to expected by user | -| AssertNodeIsTypeAndHasOneOfValues | Compares node value from expression to expected by user set of values | -| AsserNodeContainsSubString | Checks whether node value from expression contains given substring | -| AsserNodeNotContainsSubString | Checks whether node value from expression doesn't contain given substring | -| AssertNodeIsType | Checks whether node from last HTTP(s) response body is of provided type | -| AssertNodeIsNotType | Checks whether node from last HTTP(s) response body is not of provided type | -| AssertNodeMatchesRegExp | Checks whether last HTTP(s) response body JSON node matches regExp | -| AssertNodeNotMatchesRegExp | Checks whether last HTTP(s) response body JSON node doesn't match regExp | -| AssertNodeSliceLengthIs | checks whether given key is slice and has given length | -| AssertNodeSliceLengthIsNot | checks whether given key is slice and doesn't have given length | -| AssertResponseMatchesSchemaByReference | Validates last HTTP(s) response body against provided in reference JSON schema | -| AssertResponseMatchesSchemaByString | Validates last HTTP(s) response body against provided JSON schema | -| AssertNodeMatchesSchemaByString | Validates last HTTP(s) response body JSON node against provided JSON schema | -| AssertNodeMatchesSchemaByReference | Validates last HTTP(s) response body JSON node against provided in reference JSON schema | -| AssertTimeBetweenRequestAndResponseIs | Asserts that last HTTP(s) request-response time is <= than expected | -| AssertResponseCookieExists | Checks whether last HTTP(s) response has given cookie | -| AssertResponseCookieNotExists | Checks whether last HTTP(s) response doesn't have given cookie | -| AssertResponseCookieValueIs | Checks whether last HTTP(s) response has given cookie of given value | -| AssertResponseCookieValueMatchesRegExp | Checks whether last HTTP(s) response has given cookie matching provided regExp | +| NAME | DESCRIPTION | +|-------------------------------------------|:----------------------------------------------------------------------------------------:| +| | | +| **Sending HTTP(s) requests:** | | +| | | +| RequestSendWithBodyAndHeaders | Sends HTTP(s) request with provided body and headers. | +| RequestPrepare | Prepare HTTP(s) request | +| RequestSetHeaders | Sets provided headers for previously prepared request | +| RequestSetForm | Sets provided form for previously prepared request | +| RequestSetCookies | Sets provided cookies for previously prepared request | +| RequestSetBody | Sets body for previously prepared request | +| RequestSend | Sends previously prepared HTTP(s) request | +| | | +| **Random data generation:** | | +| | | +| GenerateRandomInt | Generates random integer from provided range and save it under provided cache key | +| GenerateFloat64 | Generates random float from provided range and save it under provided cache key | +| GeneratorRandomRunes | Creates generator for random strings from provided charset in provided range | +| GeneratorRandomSentence | Creates generator for random sentence from provided charset in provided range | +| GetTimeAndTravel | Accepts time object and move in time by given time interval | +| GenerateTimeAndTravel | Creates current time object and move in time by given time interval | +| | | +| **Preserving data:** | | +| | | +| SaveNode | Saves from last response body JSON node under given cacheKey key | +| SaveHeader | Saves into cache given header value | +| Save | Saves into cache arbitrary passed value | +| | | +| **Debugging:** | | +| | | +| DebugPrintResponseBody | Prints last response from request | +| DebugStart | Starts debugging mode | +| DebugStop | Stops debugging mode | +| | | +| **Flow control:** | | +| | | +| Wait | Stops test execution for provided amount of time | +| | | +| **Assertions:** | | +| | | +| AssertResponseHeaderExists | Checks whether last HTTP(s) response has given header | +| AssertResponseHeaderNotExists | Checks whether last HTTP(s) response doesn't have given header | +| AssertResponseHeaderValueIs | Checks whether last HTTP(s) response has given header with provided value | +| AssertStatusCodeIs | Checks last HTTP(s) response status code | +| AssertStatusCodeIsNot | Checks if last HTTP(s) response status code is not of provided value | +| AssertResponseFormatIs | Checks whether last HTTP(s) response body has given data format | +| AssertResponseFormatIsNot | Checks whether last HTTP(s) response body doesn't have given data format | +| AssertNodeExists | Checks whether last response body contains given key | +| AssertNodeNotExists | Checks whether last response body doesn't contain given key | +| AssertNodesExist | Checks whether last HTTP(s) response body JSON has given nodes | +| AssertNodeIsTypeAndValue | Compares json node value from expression to expected by user | +| AssertNodeIsTypeAndHasOneOfValues | Compares node value from expression to expected by user set of values | +| AssertNodeContainsSubString | Checks whether node value from expression contains given substring | +| AssertNodeNotContainsSubString | Checks whether node value from expression doesn't contain given substring | +| AssertNodeIsType | Checks whether node from last HTTP(s) response body is of provided type | +| AssertNodeIsNotType | Checks whether node from last HTTP(s) response body is not of provided type | +| AssertNodeMatchesRegExp | Checks whether last HTTP(s) response body JSON node matches regExp | +| AssertNodeNotMatchesRegExp | Checks whether last HTTP(s) response body JSON node doesn't match regExp | +| AssertNodeSliceLengthIs | checks whether given key is slice and has given length | +| AssertNodeSliceLengthIsNot | checks whether given key is slice and doesn't have given length | +| AssertResponseMatchesSchemaByReference | Validates last HTTP(s) response body against provided in reference JSON schema | +| AssertResponseMatchesSchemaByString | Validates last HTTP(s) response body against provided JSON schema | +| AssertNodeMatchesSchemaByString | Validates last HTTP(s) response body JSON node against provided JSON schema | +| AssertNodeMatchesSchemaByReference | Validates last HTTP(s) response body JSON node against provided in reference JSON schema | +| AssertTimeBetweenRequestAndResponseIs | Asserts that last HTTP(s) request-response time is <= than expected | +| AssertResponseCookieExists | Checks whether last HTTP(s) response has given cookie | +| AssertResponseCookieNotExists | Checks whether last HTTP(s) response doesn't have given cookie | +| AssertResponseCookieValueIs | Checks whether last HTTP(s) response has given cookie of given value | +| AssertResponseCookieValueMatchesRegExp | Checks whether last HTTP(s) response has given cookie matching provided regExp | | AssertResponseCookieValueNotMatchesRegExp | Checks whether last HTTP(s) response has given cookie is not matching provided regExp | diff --git a/steps.go b/steps.go index db1e46c..83c21dc 100644 --- a/steps.go +++ b/steps.go @@ -488,7 +488,7 @@ func (apiCtx *APIContext) AssertStatusCodeIsNot(code int) error { return nil } - return fmt.Errorf("expected status code is other than %d, but is %d", code, lastResponse.StatusCode) + return fmt.Errorf("expected status code different than %d, but got %d", code, lastResponse.StatusCode) } // AssertResponseFormatIs checks whether last response body has given data format. @@ -596,7 +596,7 @@ func (apiCtx *APIContext) AssertNodeExists(dataFormat format.DataFormat, exprTem apiCtx.Debugger.Print(fmt.Sprintf("last response body:\n\n%s", body)) } - return fmt.Errorf("node '%s', err: %w", expr, err) + return fmt.Errorf("node '%s' could not be found within last response body, reason: %w", expr, err) } return nil @@ -722,7 +722,7 @@ func (apiCtx *APIContext) AssertNodeIsNotType(dataFormat format.DataFormat, expr return nil } - return fmt.Errorf("node %s is '%s', but expected not to be", expr, inType) + return fmt.Errorf("node '%s' has type '%s', but expected not to be", expr, inType) } recognizedDataType := apiCtx.TypeMappers.GO.Map(iNodeVal) @@ -730,7 +730,7 @@ func (apiCtx *APIContext) AssertNodeIsNotType(dataFormat format.DataFormat, expr return nil } - return fmt.Errorf("node %s is '%s', but expected not to be", expr, inType) + return fmt.Errorf("node '%s' has type '%s', but expected not to be", expr, inType) case format.YAML: iNodeVal, err = apiCtx.PathFinders.YAML.Find(expr, body) if err != nil { @@ -747,7 +747,7 @@ func (apiCtx *APIContext) AssertNodeIsNotType(dataFormat format.DataFormat, expr return nil } - return fmt.Errorf("node %s is '%s', but expected not to be", expr, inType) + return fmt.Errorf("node '%s' has type '%s', but expected not to be", expr, inType) } recognizedDataType := apiCtx.TypeMappers.GO.Map(iNodeVal) @@ -755,7 +755,7 @@ func (apiCtx *APIContext) AssertNodeIsNotType(dataFormat format.DataFormat, expr return nil } - return fmt.Errorf("node %s is '%s', but expected not to be", expr, inType) + return fmt.Errorf("node '%s' has type '%s', but expected not to be", expr, inType) case format.XML: return fmt.Errorf("this method does not support data in format: %s", format.XML) default: @@ -827,18 +827,23 @@ func (apiCtx *APIContext) AssertNodeIsTypeAndHasOneOfValues(dataFormat format.Da } valuesSlice := strings.Split(values, ",") - for _, value := range valuesSlice { - if err = assertNodeTypeAndValue(expr, dataType, iValue, strings.TrimSpace(value)); err == nil { + valuesSliceTrimmed := make([]string, 0, len(valuesSlice)) + for _, v := range valuesSlice { + valuesSliceTrimmed = append(valuesSliceTrimmed, strings.TrimSpace(v)) + } + + for _, value := range valuesSliceTrimmed { + if err = assertNodeTypeAndValue(expr, dataType, iValue, value); err == nil { return nil } } - return fmt.Errorf("node '%s' doesn't contain any of: %#v", expr, valuesSlice) + return fmt.Errorf("node '%s' doesn't contain any of: %#v", expr, valuesSliceTrimmed) } // AsserNodeContainsSubString checks whether value of last HTTP response node, obtained using exprTemplate // is string type and contains given substring -func (apiCtx *APIContext) AsserNodeContainsSubString(dataFormat format.DataFormat, exprTemplate string, subTemplate string) error { +func (apiCtx *APIContext) AssertNodeContainsSubString(dataFormat format.DataFormat, exprTemplate string, subTemplate string) error { expr, err := apiCtx.TemplateEngine.Replace(exprTemplate, apiCtx.Cache.All()) if err != nil { return fmt.Errorf("template engine has problem with 'expr' template, err: %w", err) @@ -873,7 +878,7 @@ func (apiCtx *APIContext) AsserNodeContainsSubString(dataFormat format.DataForma } if !strings.Contains(valueString, sub) { - return fmt.Errorf("node string value doesn't contain any occurence of '%s'", sub) + return fmt.Errorf("node '%s' string value doesn't contain any occurrence of '%s'", expr, sub) } return nil @@ -881,7 +886,7 @@ func (apiCtx *APIContext) AsserNodeContainsSubString(dataFormat format.DataForma // AsserNodeNotContainsSubString checks whether value of last HTTP response node, obtained using exprTemplate // is string type and doesn't contain given substring -func (apiCtx *APIContext) AsserNodeNotContainsSubString(dataFormat format.DataFormat, exprTemplate string, subTemplate string) error { +func (apiCtx *APIContext) AssertNodeNotContainsSubString(dataFormat format.DataFormat, exprTemplate string, subTemplate string) error { expr, err := apiCtx.TemplateEngine.Replace(exprTemplate, apiCtx.Cache.All()) if err != nil { return fmt.Errorf("template engine has problem with 'expr' template, err: %w", err) @@ -916,7 +921,7 @@ func (apiCtx *APIContext) AsserNodeNotContainsSubString(dataFormat format.DataFo } if strings.Contains(valueString, sub) { - return fmt.Errorf("node value contain some '%s', but expected not to", sub) + return fmt.Errorf("node '%s' string value contain some '%s', but expected not to", expr, sub) } return nil @@ -947,7 +952,7 @@ func (apiCtx *APIContext) AssertNodeSliceLengthIs(dataFormat format.DataFormat, v := reflect.ValueOf(iValue) if v.Kind() == reflect.Slice { if v.Len() != length { - return fmt.Errorf("%s slice has length: %d, expected: %d", expr, v.Len(), length) + return fmt.Errorf("node '%s' contains slice(array) which has length: %d, but expected: %d", expr, v.Len(), length) } return nil @@ -988,7 +993,7 @@ func (apiCtx *APIContext) AssertNodeSliceLengthIsNot(dataFormat format.DataForma return nil } - return fmt.Errorf("%s slice has length: %d, expected not to have: %d", expr, v.Len(), length) + return fmt.Errorf("node '%s' contains slice(array) which has length: %d, but expected not to have it", expr, v.Len()) } if apiCtx.Debugger.IsOn() { @@ -1035,7 +1040,7 @@ func (apiCtx *APIContext) AssertNodeMatchesRegExp(dataFormat format.DataFormat, } if !matched { - return fmt.Errorf("%s does not contain any: %s", string(jsonValue), regExpString) + return fmt.Errorf("node '%s' does not match regExp: '%s'", expr, regExpString) } return nil @@ -1081,7 +1086,7 @@ func (apiCtx *APIContext) AssertNodeNotMatchesRegExp(dataFormat format.DataForma return nil } - return fmt.Errorf("%s contains some: %s", string(jsonValue), regExpString) + return fmt.Errorf("node '%s' matches regExp: '%s', but expected not to", expr, regExpString) } // AssertResponseHeaderExists checks whether last HTTP response has given header. @@ -1111,7 +1116,7 @@ func (apiCtx *APIContext) AssertResponseHeaderExists(name string) error { apiCtx.Debugger.Print(fmt.Sprintf("last HTTP(s) response headers: %#v", lastResp.Header)) } - return fmt.Errorf("could not find header %s in last HTTP response", name) + return fmt.Errorf("could not find header '%s' in last HTTP response", name) } // AssertResponseHeaderNotExists checks whether last HTTP response does not have given header. @@ -1137,7 +1142,7 @@ func (apiCtx *APIContext) AssertResponseHeaderNotExists(name string) error { return nil } - return fmt.Errorf("last response has header %s", name) + return fmt.Errorf("last HTTP(s) response has header '%s', but expected not to", name) } // AssertResponseHeaderValueIs checks whether last HTTP response has given header with provided valueTemplate. @@ -1172,7 +1177,7 @@ func (apiCtx *APIContext) AssertResponseHeaderValueIs(name, valueTemplate string return nil } - return fmt.Errorf("%s header exists but, expected value: %s, is not equal to actual: %s", name, value, header) + return fmt.Errorf("last HTTP(s) response contains header '%s', but it's expected value: '%s', is not equal to actual value: '%s'", name, value, header) } // AssertResponseMatchesSchemaByReference validates last response body against schema as provided in referenceTemplate. @@ -1694,7 +1699,7 @@ func (apiCtx *APIContext) getNode(body []byte, expr string, dataFormat format.Da recognizedDataType = apiCtx.TypeMappers.GO.Map(iValue) if recognizedDataType != dataType { - return nil, fmt.Errorf("expected node '%s' to be '%s', but is detected as '%s' in terms of JSON and '%s' in terms of Go", + return nil, fmt.Errorf("expected node '%s' to be '%s', but node value is detected as '%s' in terms of JSON and '%s' in terms of Go", expr, dataType, tmpRecognizedDataType, recognizedDataType) } } @@ -1718,7 +1723,7 @@ func (apiCtx *APIContext) getNode(body []byte, expr string, dataFormat format.Da recognizedDataType = apiCtx.TypeMappers.GO.Map(iValue) if recognizedDataType != dataType { - return nil, fmt.Errorf("expected node '%s' to be '%s', but is detected as '%s' in terms of YAML and '%s' in terms of Go", + return nil, fmt.Errorf("expected node '%s' to be '%s', but node value is detected as '%s' in terms of YAML and '%s' in terms of Go", expr, dataType, tmpRecognizedDataType, recognizedDataType) } } @@ -1753,22 +1758,22 @@ func checkBool(nodeValue any, expectedValue, expr string) error { if !ok { strVal, ok := nodeValue.(string) if !ok { - return fmt.Errorf("expected %s to be %s, got %v", expr, "bool", nodeValue) + return fmt.Errorf("expected '%s' to be '%s', got '%v'", expr, "bool", nodeValue) } boolVal, err = strconv.ParseBool(strVal) if err != nil { - return fmt.Errorf("expected %s to be %s, got %v", expr, "bool", nodeValue) + return fmt.Errorf("expected '%s' to be '%s', got '%v'", expr, "bool", nodeValue) } } boolNodeValue, err := strconv.ParseBool(expectedValue) if err != nil { - return fmt.Errorf("replaced node %s value %s could not be converted to bool", expr, expectedValue) + return fmt.Errorf("node '%s' value '%s' could not be converted to bool", expr, expectedValue) } if boolVal != boolNodeValue { - return fmt.Errorf("node %s bool value %t is not equal to expected bool value %t", expr, boolVal, boolNodeValue) + return fmt.Errorf("node '%s' has bool value '%t', but expected '%t'", expr, boolVal, boolNodeValue) } return nil @@ -1779,11 +1784,11 @@ func checkBool(nodeValue any, expectedValue, expr string) error { func checkString(nodeValue any, expectedValue, expr string) error { strVal, ok := nodeValue.(string) if !ok { - return fmt.Errorf("expected %s to be %s, got %v", expr, "string", nodeValue) + return fmt.Errorf("expected '%s' to be '%s', got '%v'", expr, "string", nodeValue) } if strVal != expectedValue { - return fmt.Errorf("node %s string value: %s is not equal to expected string value: %s", expr, strVal, expectedValue) + return fmt.Errorf("node '%s' has string value: '%s', but expected: '%s'", expr, strVal, expectedValue) } return nil @@ -1794,13 +1799,13 @@ func checkString(nodeValue any, expectedValue, expr string) error { func checkInt(nodeValue any, expectedValue, expr string) error { intNodeValue, err := strconv.Atoi(expectedValue) if err != nil { - return fmt.Errorf("replaced node %s value %s could not be converted to int", expr, expectedValue) + return fmt.Errorf("node '%s' value '%s' could not be converted to int", expr, expectedValue) } if strVal, ok := nodeValue.(string); ok { if intVal, errAtoi := strconv.Atoi(strVal); errAtoi == nil { if intVal != intNodeValue { - return fmt.Errorf("node %s int value: %d is not equal to expected int value: %d", expr, intVal, intNodeValue) + return fmt.Errorf("node '%s' has int value: '%d', but expected: '%d'", expr, intVal, intNodeValue) } return nil @@ -1819,7 +1824,7 @@ func checkInt(nodeValue any, expectedValue, expr string) error { intVal := int(floatVal) if intVal != intNodeValue { - return fmt.Errorf("node %s int value: %d is not equal to expected int value: %d", expr, intVal, intNodeValue) + return fmt.Errorf("node '%s' has int value: '%d', but expected: '%d'", expr, intVal, intNodeValue) } return nil @@ -1830,13 +1835,13 @@ func checkInt(nodeValue any, expectedValue, expr string) error { func checkFloat(nodeValue any, expectedValue, expr string) error { floatNodeValue, err := strconv.ParseFloat(expectedValue, 64) if err != nil { - return fmt.Errorf("replaced node %s value %s could not be converted to float64", expr, expectedValue) + return fmt.Errorf("node '%s' value '%s' could not be converted to float64", expr, expectedValue) } if strVal, ok := nodeValue.(string); ok { if floatVal, errParseFloat := strconv.ParseFloat(strVal, 64); errParseFloat == nil { if floatVal != floatNodeValue { - return fmt.Errorf("node %s float value: %f is not equal to expected int value: %f", expr, floatVal, floatNodeValue) + return fmt.Errorf("node '%s' has float value: '%f', but expected: '%f'", expr, floatVal, floatNodeValue) } return nil @@ -1845,11 +1850,11 @@ func checkFloat(nodeValue any, expectedValue, expr string) error { floatVal, ok := nodeValue.(float64) if !ok { - return fmt.Errorf("expected %s to be %s, got %v", expr, "float", nodeValue) + return fmt.Errorf("expected '%s' to be '%s', got '%v'", expr, "float", nodeValue) } if floatVal != floatNodeValue { - return fmt.Errorf("node %s float value %f is not equal to expected float value %f", expr, floatVal, floatNodeValue) + return fmt.Errorf("node '%s' has float value: '%f', but expected '%f'", expr, floatVal, floatNodeValue) } return nil diff --git a/steps_test.go b/steps_test.go index b67938a..5f04874 100644 --- a/steps_test.go +++ b/steps_test.go @@ -6,6 +6,7 @@ import ( "fmt" "io" "io/ioutil" + "log" "net/http" "strconv" "strings" @@ -85,10 +86,6 @@ func createXMLRespBody() io.ReadCloser { return ioutil.NopCloser(bytes.NewBufferString(bigXML)) } -type mockedHTTPContext struct { - mock.Mock -} - type mockedJSONValidator struct { mock.Mock } @@ -129,24 +126,6 @@ func (m *mockedJSONValidator) Validate(document, schemaPath string) error { return args.Error(0) } -func (m *mockedHTTPContext) GetHTTPClient() *http.Client { - args := m.Called() - - return args.Get(0).(*http.Client) -} - -func (m *mockedHTTPContext) GetLastResponse() (*http.Response, error) { - args := m.Called() - - return args.Get(0).(*http.Response), args.Error(1) -} - -func (m *mockedHTTPContext) GetLastResponseBody() ([]byte, error) { - args := m.Called() - - return args.Get(0).([]byte), args.Error(1) -} - func (m *mockedJsonPathFinder) Find(expr string, jsonBytes []byte) (any, error) { args := m.Called(expr, jsonBytes) @@ -483,6 +462,20 @@ func TestState_AssertStatusCodeIs(t *testing.T) { } } +func ExampleAPIContext_AssertStatusCodeIs() { + apiCtx := NewDefaultAPIContext(false, "") + + // instead of sending real HTTP(s) request with apiCtx.RequestSend + // we simply mock last HTTP(s) request's response + apiCtx.Cache.Save(httpcache.LastHTTPResponseCacheKey, &http.Response{StatusCode: 201}) + + err := apiCtx.AssertStatusCodeIs(200) + fmt.Println(err) + + // Output: + // expected status code 200, but got 201 +} + func TestAPIContext_AssertStatusCodeIsNot(t *testing.T) { type fields struct { cache map[string]any @@ -520,6 +513,20 @@ func TestAPIContext_AssertStatusCodeIsNot(t *testing.T) { } } +func ExampleAPIContext_AssertStatusCodeIsNot() { + apiCtx := NewDefaultAPIContext(false, "") + + // instead of sending real HTTP(s) request with apiCtx.RequestSend + // we simply mock last HTTP(s) request's response + apiCtx.Cache.Save(httpcache.LastHTTPResponseCacheKey, &http.Response{StatusCode: 200}) + + err := apiCtx.AssertStatusCodeIsNot(200) + fmt.Println(err) + + // Output: + // expected status code different than 200, but got 200 +} + func TestState_AssertResponseFormatIs(t *testing.T) { yaml := ` --- @@ -581,6 +588,20 @@ user: } } +func ExampleAPIContext_AssertResponseFormatIs() { + apiCtx := NewDefaultAPIContext(false, "") + + // instead of sending real HTTP(s) request with apiCtx.RequestSend + // we simply mock last HTTP(s) request's response + apiCtx.Cache.Save(httpcache.LastHTTPResponseCacheKey, &http.Response{Body: io.NopCloser(strings.NewReader("abc"))}) + + err := apiCtx.AssertResponseFormatIs(format.JSON) + fmt.Println(err) + + // Output: + // response body doesn't have format JSON +} + func TestAPIContext_AssertResponseFormatIsNot(t *testing.T) { yaml := ` --- @@ -641,6 +662,20 @@ user: } } +func ExampleAPIContext_AssertResponseFormatIsNot() { + apiCtx := NewDefaultAPIContext(false, "") + + // instead of sending real HTTP(s) request with apiCtx.RequestSend + // we simply mock last HTTP(s) request's response + apiCtx.Cache.Save(httpcache.LastHTTPResponseCacheKey, &http.Response{Body: io.NopCloser(strings.NewReader("{}"))}) + + err := apiCtx.AssertResponseFormatIsNot(format.JSON) + fmt.Println(err) + + // Output: + // response body has format JSON +} + func TestState_GenerateRandomInt(t *testing.T) { s := NewDefaultAPIContext(false, "") for i := 0; i < 100; i++ { @@ -664,6 +699,48 @@ func TestState_GenerateRandomInt(t *testing.T) { } } +func ExampleAPIContext_GenerateRandomInt() { + apiCtx := NewDefaultAPIContext(false, "") + + if err := apiCtx.GenerateRandomInt(2, 2, "MYINT"); err != nil { + log.Fatal(err) + + return + } + + myInt, err := apiCtx.Cache.GetSaved("MYINT") + if err != nil { + log.Fatal(err) + + return + } + + fmt.Println(myInt) + // Output: + // 2 +} + +func ExampleAPIContext_GenerateFloat64() { + apiCtx := NewDefaultAPIContext(false, "") + + if err := apiCtx.GenerateFloat64(0, 0, "MYFLOAT"); err != nil { + log.Fatal(err) + + return + } + + myFloat, err := apiCtx.Cache.GetSaved("MYFLOAT") + if err != nil { + log.Fatal(err) + + return + } + + fmt.Println(myFloat) + // Output: + // 0 +} + func TestState_GeneratorRandomRunes(t *testing.T) { s := NewDefaultAPIContext(false, "") @@ -716,6 +793,29 @@ func TestState_GeneratorRandomRunes(t *testing.T) { } } +func ExampleAPIContext_GeneratorRandomRunes() { + apiCtx := NewDefaultAPIContext(false, "") + + generateA := apiCtx.GeneratorRandomRunes("A") + err := generateA(2, 2, "TWO_A") + if err != nil { + log.Fatal(err) + + return + } + + myA, err := apiCtx.Cache.GetSaved("TWO_A") + if err != nil { + log.Fatal(err) + + return + } + + fmt.Println(myA) + // Output: + // AA +} + func TestState_GeneratorRandomSentence_ASCII(t *testing.T) { s := NewDefaultAPIContext(false, "") sentenceGen := s.GeneratorRandomSentence("ab", 1, 1) @@ -744,6 +844,29 @@ func TestState_GeneratorRandomSentence_ASCII(t *testing.T) { } } +func ExampleAPIContext_GeneratorRandomSentence() { + apiCtx := NewDefaultAPIContext(false, "") + + generateA := apiCtx.GeneratorRandomSentence("A", 2, 2) + err := generateA(2, 2, "TWO_WORDS_A") + if err != nil { + log.Fatal(err) + + return + } + + myA, err := apiCtx.Cache.GetSaved("TWO_WORDS_A") + if err != nil { + log.Fatal(err) + + return + } + + fmt.Println(myA) + // Output: + // AA AA +} + func TestState_GeneratorRandomSentence_Unicode(t *testing.T) { s := NewDefaultAPIContext(false, "") sentenceGen := s.GeneratorRandomSentence("🤡🤖🧟🏋🥇", 1, 1) @@ -980,6 +1103,20 @@ users: } } +func ExampleAPIContext_AssertNodeExists() { + apiCtx := NewDefaultAPIContext(false, "") + + // instead of sending real HTTP(s) request with apiCtx.RequestSend + // we simply mock last HTTP(s) request's response + apiCtx.Cache.Save(httpcache.LastHTTPResponseCacheKey, &http.Response{Body: io.NopCloser(strings.NewReader("{}"))}) + + err := apiCtx.AssertNodeExists(format.JSON, "user") + fmt.Println(err) + + // Output: + // node 'user' could not be found within last response body, reason: could not find node using provided expression: 'user', err: could not find node, using expression user +} + func TestAPIContext_AssertNodeNotExists(t *testing.T) { json := `{ "users": [ @@ -1107,6 +1244,20 @@ users: } } +func ExampleAPIContext_AssertNodeNotExists() { + apiCtx := NewDefaultAPIContext(false, "") + + // instead of sending real HTTP(s) request with apiCtx.RequestSend + // we simply mock last HTTP(s) request's response + apiCtx.Cache.Save(httpcache.LastHTTPResponseCacheKey, &http.Response{Body: io.NopCloser(strings.NewReader(`{"user": "abc"}`))}) + + err := apiCtx.AssertNodeNotExists(format.JSON, "user") + fmt.Println(err) + + // Output: + // JSON node 'user' exists +} + func TestState_AssertNodesExist(t *testing.T) { json := `{ "users": [ @@ -1254,6 +1405,21 @@ users: } } +func ExampleAPIContext_AssertNodesExist() { + apiCtx := NewDefaultAPIContext(false, "") + + // instead of sending real HTTP(s) request with apiCtx.RequestSend + // we simply mock last HTTP(s) request's response + apiCtx.Cache.Save(httpcache.LastHTTPResponseCacheKey, &http.Response{Body: io.NopCloser(strings.NewReader(`{"user":"abc"}`))}) + + err := apiCtx.AssertNodesExist(format.JSON, "user, address, roles") + fmt.Println(err) + + // Output: + // node 'address', err: could not find node using provided expression: 'address', err: could not find node, using expression address + //node 'roles', err: could not find node using provided expression: 'roles', err: could not find node, using expression roles +} + func TestAPIContext_AssertNodeIsNotType(t *testing.T) { type fields struct { saved map[string]any @@ -1566,6 +1732,20 @@ func TestAPIContext_AssertNodeIsNotType(t *testing.T) { } } +func ExampleAPIContext_AssertNodeIsNotType() { + apiCtx := NewDefaultAPIContext(false, "") + + // instead of sending real HTTP(s) request with apiCtx.RequestSend + // we simply mock last HTTP(s) request's response + apiCtx.Cache.Save(httpcache.LastHTTPResponseCacheKey, &http.Response{Body: io.NopCloser(strings.NewReader(`{"user":"abc"}`))}) + + err := apiCtx.AssertNodeIsNotType(format.JSON, "user", types.String) + fmt.Println(err) + + // Output: + // node 'user' has type 'string', but expected not to be +} + func TestState_AssertNodeIsType(t *testing.T) { type fields struct { saved map[string]any @@ -1878,6 +2058,20 @@ func TestState_AssertNodeIsType(t *testing.T) { } } +func ExampleAPIContext_AssertNodeIsType() { + apiCtx := NewDefaultAPIContext(false, "") + + // instead of sending real HTTP(s) request with apiCtx.RequestSend + // we simply mock last HTTP(s) request's response + apiCtx.Cache.Save(httpcache.LastHTTPResponseCacheKey, &http.Response{Body: io.NopCloser(strings.NewReader(`{"user":"abc"}`))}) + + err := apiCtx.AssertNodeIsType(format.JSON, "user", types.Number) + fmt.Println(err) + + // Output: + // expected node 'user' to be 'number', but node value is detected as 'string' in terms of JSON and 'string' in terms of Go +} + func TestState_AssertNodeSliceLengthIs(t *testing.T) { json := `{ "count": 2, @@ -1994,6 +2188,20 @@ data: } } +func ExampleAPIContext_AssertNodeSliceLengthIs() { + apiCtx := NewDefaultAPIContext(false, "") + + // instead of sending real HTTP(s) request with apiCtx.RequestSend + // we simply mock last HTTP(s) request's response + apiCtx.Cache.Save(httpcache.LastHTTPResponseCacheKey, &http.Response{Body: io.NopCloser(strings.NewReader(`{"user":[]}`))}) + + err := apiCtx.AssertNodeSliceLengthIs(format.JSON, "user", 1) + fmt.Println(err) + + // Output: + // node 'user' contains slice(array) which has length: 0, but expected: 1 +} + func TestAPIContext_AssertNodeSliceLengthIsNot(t *testing.T) { json := `{ "count": 2, @@ -2110,6 +2318,20 @@ data: } } +func ExampleAPIContext_AssertNodeSliceLengthIsNot() { + apiCtx := NewDefaultAPIContext(false, "") + + // instead of sending real HTTP(s) request with apiCtx.RequestSend + // we simply mock last HTTP(s) request's response + apiCtx.Cache.Save(httpcache.LastHTTPResponseCacheKey, &http.Response{Body: io.NopCloser(strings.NewReader(`{"user":[]}`))}) + + err := apiCtx.AssertNodeSliceLengthIsNot(format.JSON, "user", 0) + fmt.Println(err) + + // Output: + // node 'user' contains slice(array) which has length: 0, but expected not to have it +} + // TODO: Add YAML cases func TestState_AssertNodeIsTypeAndValue(t *testing.T) { type fields struct { @@ -2628,6 +2850,20 @@ func TestAPIContext_AssertNodeIsTypeAndValue(t *testing.T) { } } +func ExampleAPIContext_AssertNodeIsTypeAndValue() { + apiCtx := NewDefaultAPIContext(false, "") + + // instead of sending real HTTP(s) request with apiCtx.RequestSend + // we simply mock last HTTP(s) request's response + apiCtx.Cache.Save(httpcache.LastHTTPResponseCacheKey, &http.Response{Body: io.NopCloser(strings.NewReader(`{"user": "abc"}`))}) + + err := apiCtx.AssertNodeIsTypeAndValue(format.JSON, "user", types.String, "def") + fmt.Println(err) + + // Output: + // node 'user' has string value: 'abc', but expected: 'def' +} + func TestAPIContext_AssertNodeIsTypeAndHasOneOfValues(t *testing.T) { type fields struct { lastResponse *http.Response @@ -3128,6 +3364,20 @@ func TestAPIContext_AssertNodeIsTypeAndHasOneOfValues(t *testing.T) { } } +func ExampleAPIContext_AssertNodeIsTypeAndHasOneOfValues() { + apiCtx := NewDefaultAPIContext(false, "") + + // instead of sending real HTTP(s) request with apiCtx.RequestSend + // we simply mock last HTTP(s) request's response + apiCtx.Cache.Save(httpcache.LastHTTPResponseCacheKey, &http.Response{Body: io.NopCloser(strings.NewReader(`{"user": "abc"}`))}) + + err := apiCtx.AssertNodeIsTypeAndHasOneOfValues(format.JSON, "user", types.String, "def, ghi") + fmt.Println(err) + + // Output: + // node 'user' doesn't contain any of: []string{"def", "ghi"} +} + func TestAPIContext_AsserNodeContainsSubString(t *testing.T) { type fields struct { lastResponse *http.Response @@ -3407,13 +3657,27 @@ func TestAPIContext_AsserNodeContainsSubString(t *testing.T) { apiCtx.Cache.Save(key, val) } - if err := apiCtx.AsserNodeContainsSubString(tt.args.dataFormat, tt.args.exprTemplate, tt.args.sub); (err != nil) != tt.wantErr { + if err := apiCtx.AssertNodeContainsSubString(tt.args.dataFormat, tt.args.exprTemplate, tt.args.sub); (err != nil) != tt.wantErr { t.Errorf("AsserNodeContainsSubString() error = %v, wantErr %v", err, tt.wantErr) } }) } } +func ExampleAPIContext_AssertNodeContainsSubString() { + apiCtx := NewDefaultAPIContext(false, "") + + // instead of sending real HTTP(s) request with apiCtx.RequestSend + // we simply mock last HTTP(s) request's response + apiCtx.Cache.Save(httpcache.LastHTTPResponseCacheKey, &http.Response{Body: io.NopCloser(strings.NewReader(`{"user": "abc"}`))}) + + err := apiCtx.AssertNodeContainsSubString(format.JSON, "user", "abcd") + fmt.Println(err) + + // Output: + // node 'user' string value doesn't contain any occurrence of 'abcd' +} + func TestAPIContext_AsserNodeNotContainsSubString(t *testing.T) { type fields struct { lastResponse *http.Response @@ -3694,13 +3958,27 @@ func TestAPIContext_AsserNodeNotContainsSubString(t *testing.T) { apiCtx.Cache.Save(key, val) } - if err := apiCtx.AsserNodeNotContainsSubString(tt.args.dataFormat, tt.args.exprTemplate, tt.args.sub); (err != nil) != tt.wantErr { + if err := apiCtx.AssertNodeNotContainsSubString(tt.args.dataFormat, tt.args.exprTemplate, tt.args.sub); (err != nil) != tt.wantErr { t.Errorf("AsserNodeNotContainsSubString() error = %v, wantErr %v", err, tt.wantErr) } }) } } +func ExampleAPIContext_AssertNodeNotContainsSubString() { + apiCtx := NewDefaultAPIContext(false, "") + + // instead of sending real HTTP(s) request with apiCtx.RequestSend + // we simply mock last HTTP(s) request's response + apiCtx.Cache.Save(httpcache.LastHTTPResponseCacheKey, &http.Response{Body: io.NopCloser(strings.NewReader(`{"user": "abc"}`))}) + + err := apiCtx.AssertNodeNotContainsSubString(format.JSON, "user", "a") + fmt.Println(err) + + // Output: + // node 'user' string value contain some 'a', but expected not to +} + func TestState_AssertNodeMatchesRegExp(t *testing.T) { mTemplateEngine := new(mockedTemplateEngine) mJsonPathResolver := new(mockedJsonPathFinder) @@ -3850,6 +4128,20 @@ name: abcdef`, } } +func ExampleAPIContext_AssertNodeMatchesRegExp() { + apiCtx := NewDefaultAPIContext(false, "") + + // instead of sending real HTTP(s) request with apiCtx.RequestSend + // we simply mock last HTTP(s) request's response + apiCtx.Cache.Save(httpcache.LastHTTPResponseCacheKey, &http.Response{Body: io.NopCloser(strings.NewReader(`{"user": "abc"}`))}) + + err := apiCtx.AssertNodeMatchesRegExp(format.JSON, "user", `ac.*`) + fmt.Println(err) + + // Output: + // node 'user' does not match regExp: 'ac.*' +} + func TestAPIContext_AssertNodeNotMatchesRegExp(t *testing.T) { mTemplateEngine := new(mockedTemplateEngine) mJsonPathResolver := new(mockedJsonPathFinder) @@ -3998,6 +4290,20 @@ name: abcdef`, } } +func ExampleAPIContext_AssertNodeNotMatchesRegExp() { + apiCtx := NewDefaultAPIContext(false, "") + + // instead of sending real HTTP(s) request with apiCtx.RequestSend + // we simply mock last HTTP(s) request's response + apiCtx.Cache.Save(httpcache.LastHTTPResponseCacheKey, &http.Response{Body: io.NopCloser(strings.NewReader(`{"user": "abc"}`))}) + + err := apiCtx.AssertNodeNotMatchesRegExp(format.JSON, "user", `ab.*`) + fmt.Println(err) + + // Output: + // node 'user' matches regExp: 'ab.*', but expected not to +} + func TestState_AssertResponseHeaderExists(t *testing.T) { type fields struct { cache map[string]any @@ -4043,6 +4349,20 @@ func TestState_AssertResponseHeaderExists(t *testing.T) { } } +func ExampleAPIContext_AssertResponseHeaderExists() { + apiCtx := NewDefaultAPIContext(false, "") + + // instead of sending real HTTP(s) request with apiCtx.RequestSend + // we simply mock last HTTP(s) request's response + apiCtx.Cache.Save(httpcache.LastHTTPResponseCacheKey, &http.Response{Header: map[string][]string{"Content-Type": {"application/json"}}}) + + err := apiCtx.AssertResponseHeaderExists("Content-Length") + fmt.Println(err) + + // Output: + // could not find header 'Content-Length' in last HTTP response +} + func TestAPIContext_AssertResponseHeaderNotExists(t *testing.T) { type fields struct { cache map[string]any @@ -4087,6 +4407,20 @@ func TestAPIContext_AssertResponseHeaderNotExists(t *testing.T) { } } +func ExampleAPIContext_AssertResponseHeaderNotExists() { + apiCtx := NewDefaultAPIContext(false, "") + + // instead of sending real HTTP(s) request with apiCtx.RequestSend + // we simply mock last HTTP(s) request's response + apiCtx.Cache.Save(httpcache.LastHTTPResponseCacheKey, &http.Response{Header: map[string][]string{"Content-Type": {"application/json"}}}) + + err := apiCtx.AssertResponseHeaderNotExists("content-type") + fmt.Println(err) + + // Output: + // last HTTP(s) response has header 'content-type', but expected not to +} + func TestState_AssertResponseHeaderValueIs(t *testing.T) { type fields struct { cache map[string]any @@ -4150,6 +4484,20 @@ func TestState_AssertResponseHeaderValueIs(t *testing.T) { } } +func ExampleAPIContext_AssertResponseHeaderValueIs() { + apiCtx := NewDefaultAPIContext(false, "") + + // instead of sending real HTTP(s) request with apiCtx.RequestSend + // we simply mock last HTTP(s) request's response + apiCtx.Cache.Save(httpcache.LastHTTPResponseCacheKey, &http.Response{Header: map[string][]string{"Content-Type": {"application/json"}}}) + + err := apiCtx.AssertResponseHeaderValueIs("content-type", "application/json+ld") + fmt.Println(err) + + // Output: + // last HTTP(s) response contains header 'content-type', but it's expected value: 'application/json+ld', is not equal to actual value: 'application/json' +} + func TestState_AssertResponseMatchesSchemaByReference(t *testing.T) { type fields struct { resp *http.Response @@ -4750,6 +5098,23 @@ func TestState_Save(t *testing.T) { } } +func ExampleAPIContext_Save() { + apiCtx := NewDefaultAPIContext(false, "") + + apiCtx.Cache.Save("MY_KEY", "MY_VAL") + + val, err := apiCtx.Cache.GetSaved("MY_KEY") + if err != nil { + fmt.Println(err) + + return + } + + fmt.Println(val) + // Output: + // MY_VAL +} + func TestState_SaveNode(t *testing.T) { type fields struct { cache cache.Cache @@ -4891,6 +5256,32 @@ user: } } +func ExampleAPIContext_SaveNode() { + apiCtx := NewDefaultAPIContext(false, "") + + // instead of sending real HTTP(s) request with apiCtx.RequestSend + // we simply mock last HTTP(s) request's response + apiCtx.Cache.Save(httpcache.LastHTTPResponseCacheKey, &http.Response{Body: io.NopCloser(strings.NewReader(`{"user": "abc"}`))}) + + err := apiCtx.SaveNode(format.JSON, "user", "USER_NAME") + if err != nil { + fmt.Println(err) + + return + } + + val, err := apiCtx.Cache.GetSaved("USER_NAME") + if err != nil { + fmt.Println(err) + + return + } + + fmt.Println(val) + // Output: + // abc +} + func TestAPIContext_SaveHeader(t *testing.T) { type fields struct { resp *http.Response @@ -4941,3 +5332,29 @@ func TestAPIContext_SaveHeader(t *testing.T) { }) } } + +func ExampleAPIContext_SaveHeader() { + apiCtx := NewDefaultAPIContext(false, "") + + // instead of sending real HTTP(s) request with apiCtx.RequestSend + // we simply mock last HTTP(s) request's response + apiCtx.Cache.Save(httpcache.LastHTTPResponseCacheKey, &http.Response{Header: map[string][]string{"Content-Type": {"application/json"}}}) + + if err := apiCtx.SaveHeader("content-type", "CONTENT_TYPE_VALUE"); err != nil { + fmt.Println(err) + + return + } + + val, err := apiCtx.Cache.GetSaved("CONTENT_TYPE_VALUE") + if err != nil { + fmt.Println(err) + + return + } + + fmt.Println(val) + + // Output: + // application/json +}