Full Code of ozontech/cute for AI

master 9f4583b9e8d9 cached
72 files
255.0 KB
73.4k tokens
470 symbols
1 requests
Download .txt
Showing preview only (273K chars total). Download the full file or copy to clipboard to get everything.
Repository: ozontech/cute
Branch: master
Commit: 9f4583b9e8d9
Files: 72
Total size: 255.0 KB

Directory structure:
gitextract_fkbtdg57/

├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   └── feature_request.md
│   └── workflows/
│       └── main.yml
├── .gitignore
├── .golangci.yaml
├── LICENSE
├── Makefile
├── README.MD
├── allure.go
├── assert.go
├── assert_broken.go
├── assert_broken_test.go
├── assert_optional.go
├── assert_optional_test.go
├── assert_require.go
├── assert_require_test.go
├── assert_trace.go
├── asserts/
│   ├── headers/
│   │   ├── headers.go
│   │   └── headers_test.go
│   └── json/
│       ├── json.go
│       ├── json_test.go
│       └── util.go
├── builder.go
├── builder_allure.go
├── builder_asserts.go
├── builder_middleware.go
├── builder_option.go
├── builder_request.go
├── builder_retry.go
├── builder_table.go
├── builder_table_test.go
├── builder_test.go
├── cute.go
├── errors/
│   ├── broken.go
│   ├── error.go
│   ├── optional.go
│   ├── require.go
│   └── trace.go
├── examples/
│   ├── custom_asserts.go
│   ├── inside_step_test.go
│   ├── masked_data_test.go
│   ├── parallel_test.go
│   ├── single_test.go
│   ├── suite/
│   │   ├── common.go
│   │   ├── main_test.go
│   │   ├── one_step.go
│   │   ├── one_step_errors.go
│   │   ├── resources/
│   │   │   └── example_valid_request.json
│   │   ├── simple.go
│   │   └── two_steps.go
│   ├── table_test/
│   │   └── table_test.go
│   ├── two_step_test.go
│   └── upload_file_test.go
├── go.mod
├── go.sum
├── init.go
├── interface.go
├── internal/
│   └── utils/
│       ├── body.go
│       └── json.go
├── json_marshaler.go
├── jsonschema.go
├── jsonschema_test.go
├── logger.go
├── provider.go
├── request.go
├── request_test.go
├── result.go
├── result_test.go
├── roundtripper.go
├── step.go
├── test.go
└── test_test.go

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report \
about: Create a report to help us improve \
title: ' ' \
labels: ' ' \
assignees: ' ' 

---

**Describe the bug**
A clear and concise description of what the bug is.

**To Reproduce**
Steps to reproduce the behavior:
1. Used func: '...'
2. What you actually wanted to do: '...'
3. What has been expected: '...'
4. What you got actual: '....'
5. Error Log (if any): '...'
6. Allure-Report screenshot (if any): '...'

**Expected behavior**
A clear and concise description of what you expected to happen.

**Screenshots**
If applicable, add screenshots to help explain your problem.

**Additional context**
Add any other context about the problem here.

================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request \
about: Suggest an idea for this project \
title: '' \
labels: '' \
assignees: ''

---

**Is your feature request related to a problem? Please describe.** \
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

**Describe the solution you'd like** \
A clear and concise description of what you want to happen.

**Describe alternatives you've considered** \
A clear and concise description of any alternative solutions or features you've considered.

**Additional context** \
Add any other context or screenshots about the feature request here.

================================================
FILE: .github/workflows/main.yml
================================================
name: CI

on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]

jobs:
  build_and_test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Set up Go
        uses: actions/setup-go@v2
        with:
          go-version: 1.21

      - name: Build
        run: go build -v ./...

      - name: Test
        run: go test -v ./...

  golangci-lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Run golangci-lint
        # You may pin to the exact commit or the version.
        # uses: golangci/golangci-lint-action@5c56cd6c9dc07901af25baab6f2b0d9f3b7c3018
        uses: golangci/golangci-lint-action@v2.5.2
        # for settings see https://github.com/golangci/golangci-lint-action
        with:
          only-new-issues: true
          # golangci-lint command line arguments
          args: --timeout=5m0s

  examples:
    name: examples
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Run examples
        run: make examples
      - name: Archive code coverage results
        uses: actions/upload-artifact@v4
        with:
          name: allure-results
          path: ./examples/allure-results

================================================
FILE: .gitignore
================================================
.idea/
testdata/
allure-results/
bin/
vendor/

# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib

# Test binary, build with `go test -c`
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
*.out


================================================
FILE: .golangci.yaml
================================================
run:
  timeout: 10m
  issues-exit-code: 1
  tests: true
  skip-dirs:
    - bin
    - vendor
    - var
    - tmp
  skip-files:
    - \.pb\.go$
    - \.pb\.goclay\.go$

output:
  format: colored-line-number
  print-issued-lines: true
  print-linter-name: true

linters-settings:
  govet:
    check-shadowing: true
  dupl:
    threshold: 100
  goconst:
    min-len:         2
    min-occurrences: 2

linters:
  disable-all: true
  enable:
    - errcheck
    - goconst
    - goimports
    - gosec
    - govet
    - ineffassign
    - megacheck
    - revive
    - typecheck
    - unused # will be used insted of varcheck + deadcode + structcheck. More info https://github.com/golangci/golangci-lint/issues/1841
    - prealloc
    - wsl

issues:
  exclude-use-default: false
  exclude:
    # _ instead of err checks
    - G104
    # for "public interface + private struct implementation" cases only!
    - exported func .* returns unexported type .*, which can be annoying to use
    # can be removed in the development phase
    # - (comment on exported (method|function|type|const)|should have( a package)? comment|comment should be of the form)
    # not for the active development - can be removed in the stable phase
    - should have a package comment
    - don't use an underscore in package name
    # EXC0001 errcheck: Almost all programs ignore errors on these functions and in most cases it's ok
    - Error return value of .((os\.)?std(out|err)\..*|.*Close|.*Flush|os\.Remove(All)?|.*print(f|ln)?|os\.(Un)?Setenv). is not checked
    - should check returned error before deferring


================================================
FILE: LICENSE
================================================
                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "[]"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright [yyyy] [name of copyright owner]

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.


================================================
FILE: Makefile
================================================
export GO111MODULE=on
export GOSUMDB=off
LOCAL_BIN:=$(CURDIR)/bin

##################### GOLANG-CI RELATED CHECKS #####################
# Check global GOLANGCI-LINT
GOLANGCI_BIN:=$(LOCAL_BIN)/golangci-lint
GOLANGCI_TAG:=1.54.2

# Check local bin version
ifneq ($(wildcard $(GOLANGCI_BIN)),)
GOLANGCI_BIN_VERSION:=$(shell $(GOLANGCI_BIN) --version)
ifneq ($(GOLANGCI_BIN_VERSION),)
GOLANGCI_BIN_VERSION_SHORT:=$(shell echo "$(GOLANGCI_BIN_VERSION)" | sed -E 's/.* version (.*) built from .* on .*/\1/g')
else
GOLANGCI_BIN_VERSION_SHORT:=0
endif
ifneq "$(GOLANGCI_TAG)" "$(word 1, $(sort $(GOLANGCI_TAG) $(GOLANGCI_BIN_VERSION_SHORT)))"
GOLANGCI_BIN:=
endif
endif

# Check global bin version
ifneq (, $(shell which golangci-lint))
GOLANGCI_VERSION:=$(shell golangci-lint --version 2> /dev/null )
ifneq ($(GOLANGCI_VERSION),)
GOLANGCI_VERSION_SHORT:=$(shell echo "$(GOLANGCI_VERSION)"|sed -E 's/.* version (.*) built from .* on .*/\1/g')
else
GOLANGCI_VERSION_SHORT:=0
endif
ifeq "$(GOLANGCI_TAG)" "$(word 1, $(sort $(GOLANGCI_TAG) $(GOLANGCI_VERSION_SHORT)))"
GOLANGCI_BIN:=$(shell which golangci-lint)
endif
endif
##################### GOLANG-CI RELATED CHECKS #####################

.PHONY: install
install:
	go mod tidy && go mod download

# run full lint like in pipeline
.PHONY: lint
lint: install-lint
	$(GOLANGCI_BIN) run --config=.golangci.yaml ./... --new-from-rev=origin/master --build-tags=examples,allure_go,provider


.PHONY: install-lint
install-lint:
ifeq ($(wildcard $(GOLANGCI_BIN)),)
	$(info #Downloading golangci-lint v$(GOLANGCI_TAG))
	tmp=$$(mktemp -d) && cd $$tmp && pwd && go mod init temp && go get -d github.com/golangci/golangci-lint/cmd/golangci-lint@v$(GOLANGCI_TAG) && \
		go build -ldflags "-X 'main.version=$(GOLANGCI_TAG)' -X 'main.commit=test' -X 'main.date=test'" -o $(LOCAL_BIN)/golangci-lint github.com/golangci/golangci-lint/cmd/golangci-lint && \
		rm -rf $$tmp
GOLANGCI_BIN:=$(LOCAL_BIN)/golangci-lint
endif

.PHONY: cover
cover:
	go test -v -coverprofile=coverage.out ./...  && go tool cover -html=coverage.out

.PHONY: example
example:
	go test ./... -tags example

.PHONY: test
test:
	go test ./...


================================================
FILE: README.MD
================================================
<p align="center">
  <img src=".images/cute.png" alt="cute"/>
</p>

# CUTE — create your tests easily

HTTP and REST API testing for Go using Allure reports.

## Features

- Expressive and intuitive syntax.
- Built-in JSON support.
- Custom asserts.
- One step to BDD.
- Allure reports.

---

## Head of contents

- [Features](#features)
- [Workflow](#workflow)
- [Installation](#installation)
- [Requirements](#requirements)
- [Demo](#demo)
- [Test examples](#test-examples)
    - [Single test](#single-step-test)
    - [Multi-step test](#multi-step-test)
    - [Suite tests](#suite)
    - [Table tests](#table-tests)
- [Asserts](#asserts)
    - [Ready-made asserts](#ready-made-asserts)
        - [JSON asserts](#json-asserts)
        - [Headers asserts](#headers-asserts)
        - [JSON schema](#json-schema-validations)
    - [Custom asserts](#custom-asserts)
        - [Base](#base)
        - [T](#t)
        - [Errors](#assert-errors)
- [Global Environment Keys](#global-environment-keys)


## Workflow
1. Create a request and write assets.
2. Run tests.
3. Check Allure reports.

## Installation

```bash
  go get -u github.com/ozontech/cute
```

## Requirements

- Go 1.17+


## Demo

Run example.
```bash
  make example
```
To view detailed test reports, install Allure framework. It's optional.

[Learn more about Allure reports](https://github.com/allure-framework)

```bash
  brew install allure
```

Run Allure.

```bash
  allure serve ./examples/allure-results
```

## Test examples

See [**Examples**](examples) directory for featured examples.

### <h3><a href="examples/single_test.go">Single-step test</a></h3>

Allows implementing single-request tests. See full example in the [**Examples**](examples) directory.
To view an Allure report, use `testing.T` or `provider.T` from [allure-go](https://github.com/ozontech/allure-go/tree/master?tab=readme-ov-file).

```go
import (
    "context"
    "net/http"
    "path"
    "testing"
    "time"

    "github.com/ozontech/cute"
    "github.com/ozontech/cute/asserts/json"
)

func TestExample(t *testing.T) {
    cute.NewTestBuilder().
        Title("Title").
        Description("some_description").
        Create().
        RequestBuilder(
            cute.WithURI("https://jsonplaceholder.typicode.com/posts/1/comments"),
            cute.WithMethod(http.MethodGet),
        ).
        ExpectExecuteTimeout(10*time.Second).
        ExpectStatus(http.StatusOK).
        AssertBody(
            json.Equal("$[0].email", "Eliseo@gardner.biz"),
            json.Present("$[1].name"),
        ).
        ExecuteTest(context.Background(), t)
}
```
<details>
  <summary>Allure report</summary>

![img.png](.images/simple.png)

</details>


### <h3><a href="examples/two_step_test.go">Multi-step test</a></h3>

Allows implementing several requests within one test.

```go
import (
    "context"
    "fmt"
    "net/http"
    "testing"

    "github.com/ozontech/cute"
)
    
func Test_TwoSteps(t *testing.T) {
    responseCode := 0

    // First step
    cute.NewTestBuilder().
        Title("Test with two requests and parse body.").
        Tag("two_steps").
        Create().
        RequestBuilder(
            cute.WithURI("https://jsonplaceholder.typicode.com/posts/1/comments"),
            cute.WithMethod(http.MethodGet),
        ).
        ExpectStatus(http.StatusOK).
        NextTest().

        // Execute after first step and parse response code
        AfterTestExecute(func(response *http.Response, errors []error) error { 
            responseCode = response.StatusCode

            return nil
        }).

        // Second step
        Create().
        RequestBuilder(
            cute.WithURI("https://jsonplaceholder.typicode.com/posts/2/comments"),
            cute.WithMethod(http.MethodDelete),
        ).
        ExecuteTest(context.Background(), t)

        fmt.Println("Response code from first request", responseCode)
}
```
See full in the [**Examples**](examples/two_step_test.go) directory.

<details>
  <summary>Allure report</summary>

![multistep_test.png](.images/multistep_test.png)

</details>

### <h3><a href="examples/suite">Suite</a></h3>

Suite provides a structure for describing tests by organizing them into test suites. It's helpful if you have a large number of different tests and find it difficult to browse through them without using additional layer nesting levels of test calls.

[Learn more about suite with Allure reports](https://github.com/ozontech/allure-go#suite)


1. Declare a structure with `suite.Suite` and `*cute.HTTPTestMaker`.

```go
import (
    "github.com/ozontech/cute"
    "github.com/ozontech/allure-go/pkg/framework/provider"
    "github.com/ozontech/allure-go/pkg/framework/suite"
)

type ExampleSuite struct {
    suite.Suite
    host *url.URL

    testMaker *cute.HTTPTestMaker
}

func (i *ExampleSuite) BeforeAll(t provider.T) {
    // Prepare http test builder
    i.testMaker = cute.NewHTTPTestMaker()

    // Preparing host
    host, err := url.Parse("https://jsonplaceholder.typicode.com/")
    if err != nil {
        t.Fatalf("could not parse url, error %w", err)
    }

    i.host = host
}

```
2. Declare a test.

```go
import (
    "github.com/ozontech/allure-go/pkg/framework/suite"
)

func TestExampleTest(t *testing.T) {
    suite.RunSuite(t, new(ExampleSuite))
}
```

3. Describe tests.

```go
import (
    "github.com/ozontech/cute"
    "github.com/ozontech/cute/asserts/headers"
    "github.com/ozontech/cute/asserts/json"
)

func (i *ExampleSuite) TestExample_OneStep(t provider.T) {
    var (
        testBuilder = i.testMaker.NewTestBuilder()
    )
    
    u, _ := url.Parse(i.host.String())
    u.Path = path.Join(u.Path, "/posts/1/comments")
    
    testBuilder.
        Title("TestExample_OneStep").
        Tags("one_step", "some_local_tag", "json").
        Create().
        StepName("Example GET json request").
        RequestBuilder(
            cute.WithHeaders(map[string][]string{
                "some_header":       []string{"something"},
                "some_array_header": []string{"1", "2", "3", "some_thing"},
            }),
            cute.WithURL(u),
            cute.WithMethod(http.MethodGet),
        ).
        ExpectExecuteTimeout(10*time.Second).
        ExpectJSONSchemaFile("file://./resources/example_valid_request.json").
        ExpectStatus(http.StatusOK).
        AssertBody(
            json.Equal("$[0].email", "Eliseo@gardner.biz"),
            json.Present("$[1].name"),
            json.NotPresent("$[1].some_not_present"),
            json.GreaterThan("$", 3),
            json.Length("$", 5),
            json.LessThan("$", 100),
            json.NotEqual("$[3].name", "kekekekeke"),
        ).
        OptionalAssertBody(
            json.GreaterThan("$", 3),
            json.Length("$", 5),
            json.LessThan("$", 100),
        ).
        AssertHeaders(
            headers.Present("Content-Type"),
        ).
        ExecuteTest(context.Background(), t)
}
```
See full example in the [**Examples**](examples/suite) directory.

<details>
  <summary>Allure report</summary>

![one_step.png](.images/one_step.png)

</details>

## <h2><a href="examples/table_test/table_test.go">Table tests</a></h2>

You can create a table test in 2 ways. They'll have the same Allure reports.

### Builder table tests

```go
import (
    "context"
    "fmt"
    "net/http"
    "testing"

    "github.com/ozontech/cute"
)

func Test_Table_Array(t *testing.T) {
    tests := []*cute.Test{
        {
            Name:       "test_1",
            Middleware: nil,
            Request: &cute.Request{
                Builders: []cute.RequestBuilder{
                    cute.WithURI("https://jsonplaceholder.typicode.com/posts/1/comments"),
                    cute.WithMethod(http.MethodPost),
                },
            },
            Expect: &cute.Expect{
                Code: 200,
            },
        },
        {
            Name:       "test_2",
            Middleware: nil,
            Request: &cute.Request{
                Builders: []cute.RequestBuilder{
                    cute.WithURI("https://jsonplaceholder.typicode.com/posts/1/comments"),
                    cute.WithMethod(http.MethodGet),
                },
            },
            Expect: &cute.Expect{
                Code: 200,
                AssertBody: []cute.AssertBody{
                    json.Equal("$[0].email", "Eliseo@gardner.biz"),
                    json.Present("$[1].name"),
                    func(body []byte) error {
                        return errors.NewAssertError("example error", "example message", nil, nil)
                    },
                },
            },
        },
    }

    cute.NewTestBuilder().
        Title("Example table test").
        Tag("table_test").
        Description("Execute array tests").
        CreateTableTest().
        PutTests(tests...).
        ExecuteTest(context.Background(), t)
}
```

### Array tests

```go
func Test_Execute_Array(t *testing.T) {
    tests := []*cute.Test{
        {
            Name:       "test_1",
            Middleware: nil,
            Request: &cute.Request{
                Builders: []cute.RequestBuilder{
                    cute.WithURI("https://jsonplaceholder.typicode.com/posts/1/comments"),
                    cute.WithMethod(http.MethodPost),
                },
            },
            Expect: &cute.Expect{
                Code: 200,
            },
        },
        {
            Name:       "test_2",
            Middleware: nil,
            Request: &cute.Request{
                Builders: []cute.RequestBuilder{
                    cute.WithURI("https://jsonplaceholder.typicode.com/posts/1/comments"),
                    cute.WithMethod(http.MethodGet),
                },
            },
            Expect: &cute.Expect{
                Code: 200,
                AssertBody: []cute.AssertBody{
                    json.Equal("$[0].email", "Eliseo@gardner.biz"),
                    json.Present("$[1].name"),
                    func(body []byte) error {
                        return errors.NewAssertError("example error", "example message", nil, nil)
                    },
                },
            },
        },
    }

    for _, test := range tests {
        test.Execute(context.Background(), t)
    }
}
```

See full example in the [**Examples**](examples/table_test/table_test.go) directory.

<details>
  <summary>Allure report</summary>

Common report for all table tests:

![table_tests_execute_array.png](.images/table_tests_execute_array.png)

Main report:

![table_tests_execute_array_test_1.png](.images/table_tests_execute_array_test_1.png)

</details>

<h2><a href="asserts">Asserts</a></h2>

You can create your own asserts or use ready-made from the package asserts.

### Ready-made asserts

#### <h4><a href="asserts/json">JSON asserts</a></h4>


- `Equal` is a function to assert that a JSONPath expression matches the given value.
- `NotEqual` is a function to check that a JSONPath expression value isn't equal to the given value.
- `Length` is a function to assert that value is the expected length.
    - `GreaterThan` is a function to assert that value is greater than the given length.
    - `GreaterOrEqualThan` is a function to assert that value is greater or equal to the given length.
    - `LessThan` is a function to assert that value is less than the given length.
    - `LessOrEqualThan` is a function to assert that value is less or equal to the given length.
- `Present` is a function to assert that value is present. Value can be 0 or null.
- `NotEmpty` is a function to assert that value is present and not empty. Value can't be 0 or null.
- `NotPresent` is a function to assert that value isn't present.
- `Diff` is a function to compare two JSONs.
- `Contains` is a function to assert that a JSONPath expression extracts a value in an array.
- `EqualJSON` is a function to check that a JSON path expression value is equal to given JSON.
- `NotEqualJSON` is a function to check that a JSONPath expression value isn't equal to given JSON.
- `GetValueFromJSON` is a function for getting a value from a JSON.

[Learn more about expressions](https://goessner.net/articles/JsonPath/)

[Learn more about asserts implementation](https://github.com/ozontech/cute/blob/master/asserts/json/json.go)

#### <h4><a href="asserts/headers">Headers asserts</a></h4>

- `Present` is a function to assert that header is present.
- `NotPresent` is a function to assert that header isn't present.

[Learn more about asserts implementation](asserts/headers/headers.go)

#### <h4><a href="jsonschema.go">JSON schema validations</a></h4>

You can validate a JSON schema in 3 ways. Choose a way depending on JSON schema location.

- `ExpectJSONSchemaString(string)` is a function for validating a JSON schema from a string.
- `ExpectJSONSchemaByte([]byte)` is a function for validating a JSON schema from an array of bytes.
- `ExpectJSONSchemaFile(string)` is a function for validating a JSON schema from a file or remote resource.

<details>
  <summary>Allure report</summary>

![img.png](.images/json_schema.png)

</details>

### <h3><a href="assert.go">Custom asserts</a></h3>

You can implement [3 type of asserts](assert.go):

#### Base

Types for creating custom assertions.

```go
    type AssertBody func(body []byte) error
    type AssertHeaders func(headers http.Header) error
    type AssertResponse func(response *http.Response) error
```

Example:

```go
func customAssertBody() cute.AssertBody {
    return func(bytes []byte) error {
        if len(bytes) == 0 {
            return errors.New("response body is empty")
        }
        
        return nil
    }
}
```

#### T

Used for creating custom asserts via [Allure Actions](https://github.com/ozontech/allure-go#suite) and [testing.TB](https://pkg.go.dev/testing#TB).
You can:

- log information to Allure,
- log error on Allure yourself,
- return an error.

```go
    type AssertBodyT func(t cute.T, body []byte) error
    type AssertHeadersT func(t cute.T, headers http.Header) error
    type AssertResponseT func(t cute.T, response *http.Response) error
```

Example with T:

```go
func customAssertBodyT() cute.AssertBodyT {
    return func(t cute.T, bytes []byte) error {
        require.GreaterOrEqual(t, len(bytes), 100)
        return nil
    }
}
```

Example with creating steps:

```go
func customAssertBodySuite() cute.AssertBodyT {
    return func(t cute.T, bytes []byte) error {
        step := allure.NewSimpleStep("Custom assert step")
        defer func() {
            t.Step(step)
        }()

        if len(bytes) == 0 {
            step.Status = allure.Failed
            step.Attachment(allure.NewAttachment("Error", allure.Text, []byte("response body is empty")))

            return nil
        }

        return nil
    }
}

```

<details>
  <summary>Allure report</summary>

![custom_assert.png](.images/custom_assert.png)

</details>

#### <h4><a href="errors/error.go">Assert errors</a></h4>

You can use `errors.NewAssertError` method from [errors](errors/error.go) package.

Example:

```go
import (
    "github.com/ozontech/cute"
    "github.com/ozontech/cute/errors"
)

func customAssertBodyWithCustomError() cute.AssertBody {
    return func(bytes []byte) error {
        if len(bytes) == 0 {
            return errors.NewAssertError("customAssertBodyWithCustomError", "body must be not empty", "len is 0", "len more 0")
        }

        return nil
    }
}
```
To create a pretty-error in your custom assert, implement it with [interfaces](errors/error.go):

- Name.

```go
type WithNameError interface {
    GetName() string
    SetName(string)
}
```

- Parameters for Allure step.

```go
type WithFields interface {
    GetFields() map[string]interface{}
    PutFields(map[string]interface{})
}
```

<details>
  <summary>Allure report</summary>

![assert_error.png](.images/assert_error.png)

</details>

#### Optional assert

If assert returns an optional error, step fails but the test is successful.

You can use  `errors.NewOptionalError(error)` method from [errors](errors/error.go) package.

```go
import (
    "github.com/ozontech/cute"
    "github.com/ozontech/cute/errors"
)

func customAssertBodyWithCustomError() cute.AssertBody {
    return func(bytes []byte) error {
        if len(bytes) == 0 {
            return errors.NewOptionalError("body is empty")
        }

        return nil
    }
}
```

To create optional error, implement error with interface:

```go
type OptionalError interface {
    IsOptional() bool
    SetOptional(bool)
}
```

<details>
  <summary>Allure report</summary>

![optional_error.png](.images/optional_error.png)

</details>

## <h2><a href="https://github.com/ozontech/allure-go?tab=readme-ov-file#wrench-configure-your-environment">Global Environment Keys</a></h2>


| Key | Meaning                                                       | Default                 |
|---|---------------------------------------------------------------|-------------------------|
|`ALLURE_OUTPUT_PATH`| Path to output allure results.                                 | `.` (Folder with tests) |
|`ALLURE_OUTPUT_FOLDER`| Name of result folder.                                            | `/allure-results`       |
|`ALLURE_ISSUE_PATTERN`| Url pattepn to issue. Must contain `%s`.                   |                         |
|`ALLURE_TESTCASE_PATTERN`| URL pattern to TestCase. Must contain `%s`.               |                         |
|`ALLURE_LAUNCH_TAGS`| Default tags for all tests. Tags must be separated by commas. |                         |


================================================
FILE: allure.go
================================================
package cute

func (qt *cute) setAllureInformation(t allureProvider) {
	// Log main vars to allureProvider
	qt.setLabelsAllure(t)
	qt.setInfoAllure(t)
	qt.setLinksAllure(t)
}

func (qt *cute) setLinksAllure(t linksAllureProvider) {
	if qt.allureLinks.issue != "" {
		t.SetIssue(qt.allureLinks.issue)
	}

	if qt.allureLinks.testCase != "" {
		t.SetTestCase(qt.allureLinks.testCase)
	}

	if qt.allureLinks.link != nil {
		t.Link(qt.allureLinks.link)
	}

	if qt.allureLinks.tmsLink != "" {
		t.TmsLink(qt.allureLinks.tmsLink)
	}

	if len(qt.allureLinks.tmsLinks) > 0 {
		t.TmsLinks(qt.allureLinks.tmsLinks...)
	}
}

func (qt *cute) setLabelsAllure(t labelsAllureProvider) {
	if qt.allureLabels.id != "" {
		t.ID(qt.allureLabels.id)
	}

	if qt.allureLabels.suiteLabel != "" {
		t.AddSuiteLabel(qt.allureLabels.suiteLabel)
	}

	if qt.allureLabels.subSuite != "" {
		t.AddSubSuite(qt.allureLabels.subSuite)
	}

	if qt.allureLabels.parentSuite != "" {
		t.AddParentSuite(qt.allureLabels.parentSuite)
	}

	if qt.allureLabels.story != "" {
		t.Story(qt.allureLabels.story)
	}

	if qt.allureLabels.tag != "" {
		t.Tag(qt.allureLabels.tag)
	}

	if qt.allureLabels.allureID != "" {
		t.AllureID(qt.allureLabels.allureID)
	}

	if qt.allureLabels.severity != "" {
		t.Severity(qt.allureLabels.severity)
	}

	if qt.allureLabels.owner != "" {
		t.Owner(qt.allureLabels.owner)
	}

	if qt.allureLabels.lead != "" {
		t.Lead(qt.allureLabels.lead)
	}

	if qt.allureLabels.label != nil {
		t.Label(qt.allureLabels.label)
	}

	if len(qt.allureLabels.labels) != 0 {
		t.Labels(qt.allureLabels.labels...)
	}

	if qt.allureLabels.feature != "" {
		t.Feature(qt.allureLabels.feature)
	}

	if qt.allureLabels.epic != "" {
		t.Epic(qt.allureLabels.epic)
	}

	if len(qt.allureLabels.tags) != 0 {
		t.Tags(qt.allureLabels.tags...)
	}

	if qt.allureLabels.layer != "" {
		t.Layer(qt.allureLabels.layer)
	}
}

func (qt *cute) setInfoAllure(t infoAllureProvider) {
	if qt.allureInfo.title != "" {
		t.Title(qt.allureInfo.title)
	}

	if qt.allureInfo.description != "" {
		t.Description(qt.allureInfo.description)
	}

	if qt.allureInfo.stage != "" {
		t.Stage(qt.allureInfo.stage)
	}
}


================================================
FILE: assert.go
================================================
package cute

import (
	"net/http"
)

// This is type of asserts, for create some assert with using custom logic.

// AssertBody is type for create custom assertions for body
// Example asserts:
// - json.LengthGreaterThan
// - json.LengthGreaterOrEqualThan
// - json.LengthLessThan
// - json.LengthLessOrEqualThan
// - json.Present
// - json.NotEmpty
// - json.NotPresent
type AssertBody func(body []byte) error

// AssertHeaders is type for create custom assertions for headers
// Example asserts:
// - headers.Present
// - headers.NotPresent
type AssertHeaders func(headers http.Header) error

// AssertResponse is type for create custom assertions for response
type AssertResponse func(response *http.Response) error

// This is type for create custom assertions with using allure and testing.allureProvider

// AssertBodyT is type for create custom assertions for body with TB
// Check example in AssertBody
// TB is testing.T and it can be used for require ore assert from testify or another packages
type AssertBodyT func(t T, body []byte) error

// AssertHeadersT is type for create custom assertions for headers with TB
// Check example in AssertHeaders
// TB is testing.T and it can be used for require ore assert from testify or another packages
type AssertHeadersT func(t T, headers http.Header) error

// AssertResponseT is type for create custom assertions for response with TB
// Check example in AssertResponse
// TB is testing.T and it can be used for require ore assert from testify or another packages
type AssertResponseT func(t T, response *http.Response) error

func (it *Test) assertHeaders(t internalT, headers http.Header) []error {
	var (
		asserts = it.Expect.AssertHeaders
		assertT = it.Expect.AssertHeadersT
	)

	if len(asserts) == 0 && len(assertT) == 0 {
		return nil
	}

	return it.executeWithStep(t, "Assert headers", func(t T) []error {
		errs := make([]error, 0)
		// Execute assert only response
		for _, f := range asserts {
			err := f(headers)
			if err != nil {
				errs = append(errs, err)
			}
		}

		// Execute assert for response with TB
		for _, f := range assertT {
			err := f(t, headers)
			if err != nil {
				errs = append(errs, err)
			}
		}

		return errs
	})
}

func (it *Test) assertResponse(t internalT, resp *http.Response) []error {
	var (
		asserts = it.Expect.AssertResponse
		assertT = it.Expect.AssertResponseT
	)

	if len(asserts) == 0 && len(assertT) == 0 {
		return nil
	}

	return it.executeWithStep(t, "Assert response", func(t T) []error {
		errs := make([]error, 0)
		// Execute assert only response
		for _, f := range asserts {
			err := f(resp)
			if err != nil {
				errs = append(errs, err)
			}
		}

		// Execute assert for response with TB
		for _, f := range assertT {
			err := f(t, resp)
			if err != nil {
				errs = append(errs, err)
			}
		}

		return errs
	})
}

func (it *Test) assertBody(t internalT, body []byte) []error {
	var (
		asserts = it.Expect.AssertBody
		assertT = it.Expect.AssertBodyT
	)

	if len(asserts) == 0 && len(assertT) == 0 {
		return nil
	}

	return it.executeWithStep(t, "Assert body", func(t T) []error {
		errs := make([]error, 0)
		// Execute assert only response
		for _, f := range asserts {
			err := f(body)
			if err != nil {
				errs = append(errs, err)
			}
		}

		// Execute assert for response with TB
		for _, f := range assertT {
			err := f(t, body)
			if err != nil {
				errs = append(errs, err)
			}
		}

		return errs
	})
}


================================================
FILE: assert_broken.go
================================================
package cute

import (
	"net/http"

	"github.com/ozontech/cute/errors"
)

func brokenAssertHeaders(assert AssertHeaders) AssertHeaders {
	return func(headers http.Header) error {
		err := assert(headers)

		return wrapBrokenError(err)
	}
}

func brokenAssertBody(assert AssertBody) AssertBody {
	return func(body []byte) error {
		err := assert(body)

		return wrapBrokenError(err)
	}
}

func brokenAssertResponse(assert AssertResponse) AssertResponse {
	return func(resp *http.Response) error {
		err := assert(resp)

		return wrapBrokenError(err)
	}
}

func brokenAssertHeadersT(assert AssertHeadersT) AssertHeadersT {
	return func(t T, headers http.Header) error {
		err := assert(t, headers)

		return wrapBrokenError(err)
	}
}

func brokenAssertBodyT(assert AssertBodyT) AssertBodyT {
	return func(t T, body []byte) error {
		err := assert(t, body)

		return wrapBrokenError(err)
	}
}

func brokenAssertResponseT(assert AssertResponseT) AssertResponseT {
	return func(t T, resp *http.Response) error {
		err := assert(t, resp)

		return wrapBrokenError(err)
	}
}

func wrapBrokenError(err error) error {
	if err == nil {
		return nil
	}

	if tErr, ok := err.(errors.BrokenError); ok {
		tErr.SetBroken(true)

		return tErr.(error)
	}

	return errors.WrapBrokenError(err)
}


================================================
FILE: assert_broken_test.go
================================================
package cute

import (
	"errors"
	"net/http"
	"testing"

	cuteErrors "github.com/ozontech/cute/errors"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

func TestBrokenAssertResponse(t *testing.T) {
	v := &http.Response{}
	f := func(_ *http.Response) error {
		return errors.New("test error")
	}

	err := brokenAssertResponse(f)(v)

	if BrokenError, ok := err.(cuteErrors.BrokenError); assert.True(t, ok) {
		require.True(t, BrokenError.IsBroken())
	}
}

func TestBrokenAssertResponseT(t *testing.T) {
	v := &http.Response{}
	f := func(T, *http.Response) error {
		return errors.New("test error")
	}

	err := brokenAssertResponseT(f)(nil, v)

	if BrokenError, ok := err.(cuteErrors.BrokenError); assert.True(t, ok) {
		require.True(t, BrokenError.IsBroken())
	}
}

func TestBrokenAssertHeaders(t *testing.T) {
	h := http.Header{}
	f := func(_ http.Header) error {
		return errors.New("test error")
	}

	err := brokenAssertHeaders(f)(h)

	if BrokenError, ok := err.(cuteErrors.BrokenError); assert.True(t, ok) {
		require.True(t, BrokenError.IsBroken())
	}
}

func TestBrokenAssertHeadersT(t *testing.T) {
	h := http.Header{}
	f := func(T, http.Header) error {
		return errors.New("test error")
	}

	err := brokenAssertHeadersT(f)(nil, h)

	if BrokenError, ok := err.(cuteErrors.BrokenError); assert.True(t, ok) {
		require.True(t, BrokenError.IsBroken())
	}
}

func TestBrokenAssertBody(t *testing.T) {
	v := []byte{}
	f := func(_ []byte) error {
		return errors.New("test error")
	}

	err := brokenAssertBody(f)(v)

	if BrokenError, ok := err.(cuteErrors.BrokenError); assert.True(t, ok) {
		require.True(t, BrokenError.IsBroken())
	}
}

func TestBrokenAssertBodyT(t *testing.T) {
	v := []byte{}
	f := func(T, []byte) error {
		return errors.New("test error")
	}

	err := brokenAssertBodyT(f)(nil, v)

	if BrokenError, ok := err.(cuteErrors.BrokenError); assert.True(t, ok) {
		require.True(t, BrokenError.IsBroken())
	}
}

func TestWrapBrokenError(t *testing.T) {
	err := errors.New("test error")

	optError := wrapBrokenError(err)
	if BrokenError, ok := optError.(cuteErrors.BrokenError); assert.True(t, ok) {
		require.True(t, BrokenError.IsBroken())
	}
}


================================================
FILE: assert_optional.go
================================================
package cute

import (
	"net/http"

	"github.com/ozontech/cute/errors"
)

func optionalAssertHeaders(assert AssertHeaders) AssertHeaders {
	return func(headers http.Header) error {
		err := assert(headers)

		return wrapOptionalError(err)
	}
}

func optionalAssertBody(assert AssertBody) AssertBody {
	return func(body []byte) error {
		err := assert(body)

		return wrapOptionalError(err)
	}
}

func optionalAssertResponse(assert AssertResponse) AssertResponse {
	return func(resp *http.Response) error {
		err := assert(resp)

		return wrapOptionalError(err)
	}
}

func optionalAssertHeadersT(assert AssertHeadersT) AssertHeadersT {
	return func(t T, headers http.Header) error {
		err := assert(t, headers)

		return wrapOptionalError(err)
	}
}

func optionalAssertBodyT(assert AssertBodyT) AssertBodyT {
	return func(t T, body []byte) error {
		err := assert(t, body)

		return wrapOptionalError(err)
	}
}

func optionalAssertResponseT(assert AssertResponseT) AssertResponseT {
	return func(t T, resp *http.Response) error {
		err := assert(t, resp)

		return wrapOptionalError(err)
	}
}

func wrapOptionalError(err error) error {
	if err == nil {
		return nil
	}

	if tErr, ok := err.(errors.OptionalError); ok {
		tErr.SetOptional(true)

		return tErr.(error)
	}

	return errors.WrapOptionalError(err)
}


================================================
FILE: assert_optional_test.go
================================================
package cute

import (
	"errors"
	"net/http"
	"testing"

	cuteErrors "github.com/ozontech/cute/errors"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

func TestOptionalAssertResponse(t *testing.T) {
	v := &http.Response{}
	f := func(*http.Response) error {
		return errors.New("test error")
	}

	err := optionalAssertResponse(f)(v)

	if optionalError, ok := err.(cuteErrors.OptionalError); assert.True(t, ok) {
		require.True(t, optionalError.IsOptional())
	}
}

func TestOptionalAssertResponseT(t *testing.T) {
	v := &http.Response{}
	f := func(T, *http.Response) error {
		return errors.New("test error")
	}

	err := optionalAssertResponseT(f)(nil, v)

	if optionalError, ok := err.(cuteErrors.OptionalError); assert.True(t, ok) {
		require.True(t, optionalError.IsOptional())
	}
}

func TestOptionalAssertHeaders(t *testing.T) {
	h := http.Header{}
	f := func(http.Header) error {
		return errors.New("test error")
	}

	err := optionalAssertHeaders(f)(h)

	if optionalError, ok := err.(cuteErrors.OptionalError); assert.True(t, ok) {
		require.True(t, optionalError.IsOptional())
	}
}

func TestOptionalAssertHeadersT(t *testing.T) {
	h := http.Header{}
	f := func(T, http.Header) error {
		return errors.New("test error")
	}

	err := optionalAssertHeadersT(f)(nil, h)

	if optionalError, ok := err.(cuteErrors.OptionalError); assert.True(t, ok) {
		require.True(t, optionalError.IsOptional())
	}
}

func TestOptionalAssertBody(t *testing.T) {
	v := []byte{}
	f := func([]byte) error {
		return errors.New("test error")
	}

	err := optionalAssertBody(f)(v)

	if optionalError, ok := err.(cuteErrors.OptionalError); assert.True(t, ok) {
		require.True(t, optionalError.IsOptional())
	}
}

func TestOptionalAssertBodyT(t *testing.T) {
	v := []byte{}
	f := func(T, []byte) error {
		return errors.New("test error")
	}

	err := optionalAssertBodyT(f)(nil, v)

	if optionalError, ok := err.(cuteErrors.OptionalError); assert.True(t, ok) {
		require.True(t, optionalError.IsOptional())
	}
}

func TestWrapOptionalError(t *testing.T) {
	err := errors.New("test error")

	optError := wrapOptionalError(err)
	if optionalError, ok := optError.(cuteErrors.OptionalError); assert.True(t, ok) {
		require.True(t, optionalError.IsOptional())
	}
}


================================================
FILE: assert_require.go
================================================
package cute

import (
	"net/http"

	"github.com/ozontech/cute/errors"
)

func requireAssertHeaders(assert AssertHeaders) AssertHeaders {
	return func(headers http.Header) error {
		err := assert(headers)

		return wrapRequireError(err)
	}
}

func requireAssertBody(assert AssertBody) AssertBody {
	return func(body []byte) error {
		err := assert(body)

		return wrapRequireError(err)
	}
}

func requireAssertResponse(assert AssertResponse) AssertResponse {
	return func(resp *http.Response) error {
		err := assert(resp)

		return wrapRequireError(err)
	}
}

func requireAssertHeadersT(assert AssertHeadersT) AssertHeadersT {
	return func(t T, headers http.Header) error {
		err := assert(t, headers)

		return wrapRequireError(err)
	}
}

func requireAssertBodyT(assert AssertBodyT) AssertBodyT {
	return func(t T, body []byte) error {
		err := assert(t, body)

		return wrapRequireError(err)
	}
}

func requireAssertResponseT(assert AssertResponseT) AssertResponseT {
	return func(t T, resp *http.Response) error {
		err := assert(t, resp)

		return wrapRequireError(err)
	}
}

func wrapRequireError(err error) error {
	if err == nil {
		return nil
	}

	if tErr, ok := err.(errors.RequireError); ok {
		tErr.SetRequire(true)

		return tErr.(error)
	}

	return errors.WrapRequireError(err)
}


================================================
FILE: assert_require_test.go
================================================
package cute

import (
	"errors"
	"net/http"
	"testing"

	cuteErrors "github.com/ozontech/cute/errors"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

func TestRequireAssertResponse(t *testing.T) {
	v := &http.Response{}
	f := func(_ *http.Response) error {
		return errors.New("test error")
	}

	err := requireAssertResponse(f)(v)

	if RequireError, ok := err.(cuteErrors.RequireError); assert.True(t, ok) {
		require.True(t, RequireError.IsRequire())
	}
}

func TestRequireAssertResponseT(t *testing.T) {
	v := &http.Response{}
	f := func(T, *http.Response) error {
		return errors.New("test error")
	}

	err := requireAssertResponseT(f)(nil, v)

	if RequireError, ok := err.(cuteErrors.RequireError); assert.True(t, ok) {
		require.True(t, RequireError.IsRequire())
	}
}

func TestRequireAssertHeaders(t *testing.T) {
	h := http.Header{}
	f := func(http.Header) error {
		return errors.New("test error")
	}

	err := requireAssertHeaders(f)(h)

	if RequireError, ok := err.(cuteErrors.RequireError); assert.True(t, ok) {
		require.True(t, RequireError.IsRequire())
	}
}

func TestRequireAssertHeadersT(t *testing.T) {
	h := http.Header{}
	f := func(T, http.Header) error {
		return errors.New("test error")
	}

	err := requireAssertHeadersT(f)(nil, h)

	if RequireError, ok := err.(cuteErrors.RequireError); assert.True(t, ok) {
		require.True(t, RequireError.IsRequire())
	}
}

func TestRequireAssertBody(t *testing.T) {
	v := []byte{}
	f := func([]byte) error {
		return errors.New("test error")
	}

	err := requireAssertBody(f)(v)

	if RequireError, ok := err.(cuteErrors.RequireError); assert.True(t, ok) {
		require.True(t, RequireError.IsRequire())
	}
}

func TestRequireAssertBodyT(t *testing.T) {
	v := []byte{}
	f := func(T, []byte) error {
		return errors.New("test error")
	}

	err := requireAssertBodyT(f)(nil, v)

	if RequireError, ok := err.(cuteErrors.RequireError); assert.True(t, ok) {
		require.True(t, RequireError.IsRequire())
	}
}

func TestWrapRequireError(t *testing.T) {
	err := errors.New("test error")

	optError := wrapRequireError(err)
	if RequireError, ok := optError.(cuteErrors.RequireError); assert.True(t, ok) {
		require.True(t, RequireError.IsRequire())
	}
}


================================================
FILE: assert_trace.go
================================================
package cute

import (
	"fmt"
	"net/http"
	"runtime"

	"github.com/ozontech/cute/errors"
)

// assertHeadersWithTrace is a function to add trace inside assert headers error
func assertHeadersWithTrace(assert AssertHeaders, trace string) AssertHeaders {
	return func(headers http.Header) error {
		err := assert(headers)

		return wrapWithTrace(err, trace)
	}
}

// assertBodyWithTrace is a function to add trace inside assert body error
func assertBodyWithTrace(assert AssertBody, trace string) AssertBody {
	return func(body []byte) error {
		err := assert(body)

		return wrapWithTrace(err, trace)
	}
}

// assertResponseWithTrace is a function to add trace inside assert response error
func assertResponseWithTrace(assert AssertResponse, trace string) AssertResponse {
	return func(resp *http.Response) error {
		err := assert(resp)

		return wrapWithTrace(err, trace)
	}
}

// assertHeadersTWithTrace is a function to add trace inside assert headers error
func assertHeadersTWithTrace(assert AssertHeadersT, trace string) AssertHeadersT {
	return func(t T, headers http.Header) error {
		err := assert(t, headers)

		return wrapWithTrace(err, trace)
	}
}

// assertBodyTWithTrace is a function to add trace inside assert body error
func assertBodyTWithTrace(assert AssertBodyT, trace string) AssertBodyT {
	return func(t T, body []byte) error {
		err := assert(t, body)

		return wrapWithTrace(err, trace)
	}
}

// assertResponseTWithTrace is a function to add trace inside assert response error
func assertResponseTWithTrace(assert AssertResponseT, trace string) AssertResponseT {
	return func(t T, resp *http.Response) error {
		err := assert(t, resp)

		return wrapWithTrace(err, trace)
	}
}

// wrapWithTrace is a function to add trace inside error
func wrapWithTrace(err error, trace string) error {
	if err == nil {
		return nil
	}

	if tErr, ok := err.(errors.WithTrace); ok {
		tErr.SetTrace(trace)

		return tErr.(error)
	}

	return errors.WrapErrorWithTrace(err, trace)
}

func getTrace() string {
	pcs := make([]uintptr, 10)
	depth := runtime.Callers(3, pcs)

	if depth == 0 {
		fmt.Println("Couldn't get the stack information")
		return ""
	}

	callers := runtime.CallersFrames(pcs[:depth])
	caller, _ := callers.Next()

	return fmt.Sprintf("%s:%d", caller.File, caller.Line)
}


================================================
FILE: asserts/headers/headers.go
================================================
package headers

import (
	"fmt"
	"net/http"

	"github.com/ozontech/cute"
	"github.com/ozontech/cute/errors"
)

// Present is a function to asserts that header is present
func Present(key string) cute.AssertHeaders {
	return func(headers http.Header) error {
		if v := headers.Get(key); v == "" {
			return errors.NewAssertError("Present", fmt.Sprintf("header %s is not present", key), nil, nil)
		}

		return nil
	}
}

// NotPresent is a function to asserts that header is not present
func NotPresent(key string) cute.AssertHeaders {
	return func(headers http.Header) error {
		if v := headers.Values(key); len(v) > 0 {
			return errors.NewAssertError("NotPresent", fmt.Sprintf("header %s is present", key), nil, nil)
		}

		return nil
	}
}


================================================
FILE: asserts/headers/headers_test.go
================================================
package headers

import (
	"net/http"
	"testing"

	"github.com/stretchr/testify/require"
)

func TestPresent(t *testing.T) {
	headers := http.Header{
		"Content-Type": []string{"application/json"},
	}

	err := Present("Content-Type")(headers)
	require.NoError(t, err)
}

func TestPresentError(t *testing.T) {
	headers := http.Header{
		"Content-Type": []string{},
	}

	err := Present("not-present")(headers)
	require.Error(t, err)
}

func TestNotPresent(t *testing.T) {
	headers := http.Header{
		"Content-Type": []string{"", "application/json"},
	}

	err := NotPresent("Content-Type")(headers)
	require.Error(t, err)
}

func TestNotPresentError(t *testing.T) {
	headers := http.Header{
		"Content-Type": []string{},
	}

	err := NotPresent("not-present")(headers)
	require.NoError(t, err)
}


================================================
FILE: asserts/json/json.go
================================================
package json

import (
	"fmt"

	jd "github.com/josephburnett/jd/lib"
	"github.com/ohler55/ojg/jp"
	"github.com/ohler55/ojg/oj"
	"github.com/ozontech/cute"
	cuteErrors "github.com/ozontech/cute/errors"
)

// Diff is a function to compare two jsons
func Diff(original string) cute.AssertBody {
	return func(body []byte) error {
		originalJSON, err := jd.ReadJsonString(original)
		if err != nil {
			return fmt.Errorf("could not parse original json in Diff error: '%s'", err)
		}

		bodyJSON, err := jd.ReadJsonString(string(body))
		if err != nil {
			return fmt.Errorf("could not parse body json in Diff error: '%s'", err)
		}

		diff := originalJSON.Diff(bodyJSON).Render()
		if diff != "" {
			cErr := cuteErrors.NewEmptyAssertError("JSON Diff", "JSON is not the same")
			cErr.PutAttachment(&cuteErrors.Attachment{
				Name:     "JSON diff",
				MimeType: "text/plain",
				Content:  []byte(diff),
			})

			return cErr
		}

		return nil
	}
}

// Contains is a function to assert that a jsonpath expression extracts a value in an array
// About expression - https://goessner.net/articles/JsonPath/
func Contains(expression string, expect interface{}) cute.AssertBody {
	return func(body []byte) error {
		return contains(body, expression, expect)
	}
}

// Equal is a function to assert that a jsonpath expression matches the given value
// About expression - https://goessner.net/articles/JsonPath/
func Equal(expression string, expect interface{}) cute.AssertBody {
	return func(body []byte) error {
		return equal(body, expression, expect)
	}
}

// NotEqual is a function to check json path expression value is not equal to given value
// About expression - https://goessner.net/articles/JsonPath/
func NotEqual(expression string, expect interface{}) cute.AssertBody {
	return func(body []byte) error {
		return notEqual(body, expression, expect)
	}
}

// EqualJSON is a function to check json path expression value is equal to given json
// About expression - https://goessner.net/articles/JsonPath/
func EqualJSON(expression string, expect []byte) cute.AssertBody {
	return func(body []byte) error {
		return equalJSON(body, expression, expect)
	}
}

// NotEqualJSON is a function to check json path expression value is not equal to given json
// About expression - https://goessner.net/articles/JsonPath/
func NotEqualJSON(expression string, expect []byte) cute.AssertBody {
	return func(body []byte) error {
		return notEqualJSON(body, expression, expect)
	}
}

// Length is a function to asserts that value is the expected length
// About expression - https://goessner.net/articles/JsonPath/
func Length(expression string, expectLength int) cute.AssertBody {
	return func(body []byte) error {
		return length(body, expression, expectLength)
	}
}

// LengthGreaterThan is a function to asserts that value is greater than the given length
// About expression - https://goessner.net/articles/JsonPath/
func LengthGreaterThan(expression string, minimumLength int) cute.AssertBody {
	return func(body []byte) error {
		return greaterThan(body, expression, minimumLength)
	}
}

// LengthGreaterOrEqualThan is a function to asserts that value is greater or equal than the given length
// About expression - https://goessner.net/articles/JsonPath/
func LengthGreaterOrEqualThan(expression string, minimumLength int) cute.AssertBody {
	return func(body []byte) error {
		return greaterOrEqualThan(body, expression, minimumLength)
	}
}

// LengthLessThan is a function to asserts that value is less than the given length
// About expression - https://goessner.net/articles/JsonPath/
func LengthLessThan(expression string, maximumLength int) cute.AssertBody {
	return func(body []byte) error {
		return lessThan(body, expression, maximumLength)
	}
}

// LengthLessOrEqualThan is a function to asserts that value is less or equal than the given length
// About expression - https://goessner.net/articles/JsonPath/
func LengthLessOrEqualThan(expression string, maximumLength int) cute.AssertBody {
	return func(body []byte) error {
		return lessOrEqualThan(body, expression, maximumLength)
	}
}

// Present is a function to asserts that value is present
// value can be nil or 0
// About expression - https://goessner.net/articles/JsonPath/
func Present(expression string) cute.AssertBody {
	return func(body []byte) error {
		return present(body, expression)
	}
}

// NotEmpty is a function to asserts that value is present
// value can't be nil or 0
// About expression - https://goessner.net/articles/JsonPath/
func NotEmpty(expression string) cute.AssertBody {
	return func(body []byte) error {
		return notEmpty(body, expression)
	}
}

// NotPresent is a function to asserts that value is not present
// About expression - https://goessner.net/articles/JsonPath/
func NotPresent(expression string) cute.AssertBody {
	return func(body []byte) error {
		return notPresent(body, expression)
	}
}

// GetValueFromJSON is function for get value from json
func GetValueFromJSON(js []byte, expression string) ([]interface{}, error) {
	obj, err := oj.Parse(js)
	if err != nil {
		return nil, fmt.Errorf("could not parse json in GetValueFromJSON error: '%s'", err)
	}

	jsonPath, err := jp.ParseString(expression)
	if err != nil {
		return nil, fmt.Errorf("could not parse path in GetValueFromJSON error: '%s'", err)
	}

	res := jsonPath.Get(obj)

	if len(res) == 0 {
		return nil, fmt.Errorf("could not find element by path %v in JSON", expression)
	}

	return res, nil
}


================================================
FILE: asserts/json/json_test.go
================================================
package json

import (
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

type jsonTest struct {
	caseName   string
	data       string
	expression string
	expect     interface{}
	IsNilErr   bool
}

func TestDiff(t *testing.T) {
	testCases := []struct {
		name          string
		originalJSON  string
		bodyJSON      string
		expectedError string
	}{
		{
			name:          "SameJSON",
			originalJSON:  `{"key1": "value1", "key2": "value2"}`,
			bodyJSON:      `{"key1": "value1", "key2": "value2"}`,
			expectedError: "", // No error expected, JSONs are the same
		},
		{
			name:          "DifferentValueJSON",
			originalJSON:  `{"key1": "value1", "key2": "value2"}`,
			bodyJSON:      `{"key1": "value1", "key2": "value3"}`,
			expectedError: "JSON is not the same",
		},
		{
			name:          "MissingKeyJSON",
			originalJSON:  `{"key1": "value1", "key2": "value2"}`,
			bodyJSON:      `{"key1": "value1"}`,
			expectedError: "JSON is not the same",
		},
		{
			name:          "ExtraKeyJSON",
			originalJSON:  `{"key1": "value1"}`,
			bodyJSON:      `{"key1": "value1", "key2": "value2"}`,
			expectedError: "JSON is not the same",
		},
		{
			name:          "EmptyJSON",
			originalJSON:  `{}`,
			bodyJSON:      `{}`,
			expectedError: "", // No error expected, empty JSONs are the same
		},
	}

	for _, testCase := range testCases {
		t.Run(testCase.name, func(t *testing.T) {
			// Call the Diff function with the test input
			err := Diff(testCase.originalJSON)([]byte(testCase.bodyJSON))

			// Check if the error message matches the expected result
			if testCase.expectedError == "" {
				assert.NoError(t, err) // No error expected
			} else {
				assert.Error(t, err) // Error expected
				assert.Contains(t, err.Error(), testCase.expectedError)
			}
		})
	}
}

func TestNotPresent(t *testing.T) {
	tests := []jsonTest{
		{
			caseName:   "correct check array",
			data:       `{"o":["a", "b", "c"]}`,
			expression: "$.o",
		},
		{
			caseName:   "not present check",
			data:       `{"o":["a", "b", "c"]}`,
			expression: "$.b",
			IsNilErr:   true,
		},
		{
			caseName:   "not present check ",
			data:       `{"o":["a", "b", "c"]}`,
			expression: "$.o[0]",
		},
		{
			caseName:   "correct check map",
			data:       `{"o":[{"1":"a"}, {"2":"b"}, {"3":"c"}]}`,
			expression: "$.o[0]['1']",
		},
	}

	for _, test := range tests {
		err := NotPresent(test.expression)([]byte(test.data))

		if test.IsNilErr {
			require.NoError(t, err, "failed test %v", test.caseName)
		} else {
			require.Error(t, err, "failed test %v", test.caseName)
		}
	}
}

func TestPresent(t *testing.T) {
	tests := []jsonTest{
		{
			caseName:   "correct check array",
			data:       `{"o":["a", "b", "c"]}`,
			expression: "$.o",
			IsNilErr:   true,
		},
		{
			caseName:   "not present check",
			data:       `{"o":["a", "b", "c"]}`,
			expression: "$.b",
		},
		{
			caseName:   "correct present check array",
			data:       `{"o":["a", "b", "c"]}`,
			expression: "$.o[0]",
			IsNilErr:   true,
		},
		{
			caseName:   "correct check map",
			data:       `{"o":[{"1":"a"}, {"2":"b"}, {"3":"c"}]}`,
			expression: "$.o[0]['1']",
			IsNilErr:   true,
		},
		{
			caseName:   "check not correct path",
			data:       `{"o":["a", "b", "c"]}`,
			expression: "$.not_correct",
		},
		{
			caseName:   "empty integer",
			data:       `{"o":0}`,
			expression: "$.o",
			IsNilErr:   true,
		},
		{
			caseName:   "empty object",
			data:       `{"o":null}`,
			expression: "$.o",
			IsNilErr:   true,
		},
		{
			caseName:   "empty string",
			data:       `{"o":null, "b":""}`,
			expression: "$.b",
			IsNilErr:   true,
		},
	}

	for _, test := range tests {
		err := Present(test.expression)([]byte(test.data))

		if test.IsNilErr {
			require.NoError(t, err, "failed test %v", test.caseName)
		} else {
			require.Error(t, err, "failed test %v", test.caseName)
		}
	}
}

func TestNotEmpty(t *testing.T) {
	tests := []jsonTest{
		{
			caseName:   "correct check array",
			data:       `{"o":["a", "b", "c"]}`,
			expression: "$.o",
			IsNilErr:   true,
		},
		{
			caseName:   "not present check",
			data:       `{"o":["a", "b", "c"]}`,
			expression: "$.b",
		},
		{
			caseName:   "correct present check array",
			data:       `{"o":["a", "b", "c"]}`,
			expression: "$.o[0]",
			IsNilErr:   true,
		},
		{
			caseName:   "correct check map",
			data:       `{"o":[{"1":"a"}, {"2":"b"}, {"3":"c"}]}`,
			expression: "$.o[0]['1']",
			IsNilErr:   true,
		},
		{
			caseName:   "check not correct path",
			data:       `{"o":["a", "b", "c"]}`,
			expression: "$.not_correct",
		},
		{
			caseName:   "empty integer",
			data:       `{"o":0}`,
			expression: "$.o",
		},
		{
			caseName:   "empty object",
			data:       `{"o":null}`,
			expression: "$.o",
		},
		{
			caseName:   "empty string",
			data:       `{"o":null, "b":""}`,
			expression: "$.b",
		},
	}

	for _, test := range tests {
		err := NotEmpty(test.expression)([]byte(test.data))

		if test.IsNilErr {
			require.NoError(t, err, "failed test %v", test.caseName)
		} else {
			require.Error(t, err, "failed test %v", test.caseName)
		}
	}
}

func TestLength(t *testing.T) {
	tests := []jsonTest{
		{
			caseName:   "correct check array",
			data:       `{"o":["a", "b", "c"]}`,
			expression: "$.o",
			expect:     3,
			IsNilErr:   true,
		},
		{
			caseName:   "not correct check array",
			data:       `{"o":["a", "b", "c"]}`,
			expression: "$.o",
			expect:     4,
		},
		{
			caseName:   "correct check string",
			data:       `{"o":"123456"}`,
			expression: "$.o",
			expect:     6,
			IsNilErr:   true,
		},
		{
			caseName:   "not correct check string",
			data:       `{"o":"123456"}`,
			expression: "$.o",
			expect:     99,
		},
		{
			caseName:   "check not contain value",
			data:       `{"o":"123456"}`,
			expression: "$.a",
			expect:     1,
		},
		{
			caseName:   "correct check map",
			data:       `{"o":[{"1":"a"}, {"2":"b"}, {"3":"c"}]}`,
			expression: "$.o",
			expect:     3,
			IsNilErr:   true,
		},
	}

	for _, test := range tests {
		err := Length(test.expression, test.expect.(int))([]byte(test.data))

		if test.IsNilErr {
			require.NoError(t, err, "failed test %v", test.caseName)
		} else {
			require.Error(t, err, "failed test %v", test.caseName)
		}
	}
}

func TestLengthGreaterThan(t *testing.T) {
	tests := []jsonTest{
		{
			caseName:   "correct check array",
			data:       `{"o":["a", "b", "c"]}`,
			expression: "$.o",
			expect:     2,
			IsNilErr:   true,
		},
		{
			caseName:   "not correct check array",
			data:       `{"o":["a", "b", "c"]}`,
			expression: "$.o",
			expect:     4,
		},
		{
			caseName:   "not correct check array when equal",
			data:       `{"o":["a", "b", "c"]}`,
			expression: "$.o",
			expect:     3,
		},
		{
			caseName:   "correct check string",
			data:       `{"o":"123456"}`,
			expression: "$.o",
			expect:     4,
			IsNilErr:   true,
		},
		{
			caseName:   "not correct check string",
			data:       `{"o":"123456"}`,
			expression: "$.o",
			expect:     99,
		},
		{
			caseName:   "correct check map",
			data:       `{"o":[{"1":"a"}, {"2":"b"}, {"3":"c"}]}`,
			expression: "$.o",
			expect:     1,
			IsNilErr:   true,
		},
		{
			caseName:   "check not correct path",
			data:       `{"o":["a", "b", "c"]}`,
			expression: "$.not_correct",
			expect:     0,
		},
	}

	for _, test := range tests {
		err := LengthGreaterThan(test.expression, test.expect.(int))([]byte(test.data))

		if test.IsNilErr {
			require.NoError(t, err, "failed test %v", test.caseName)
		} else {
			require.Error(t, err, "failed test %v", test.caseName)
		}
	}
}

func TestLengthGreaterOrEqualThan(t *testing.T) {
	tests := []jsonTest{
		{
			caseName:   "correct check array",
			data:       `{"o":["a", "b", "c"]}`,
			expression: "$.o",
			expect:     2,
			IsNilErr:   true,
		},
		{
			caseName:   "correct check array when equal",
			data:       `{"o":["a", "b", "c"]}`,
			expression: "$.o",
			expect:     3,
			IsNilErr:   true,
		},
		{
			caseName:   "not correct check array",
			data:       `{"o":["a", "b", "c"]}`,
			expression: "$.o",
			expect:     4,
		},
		{
			caseName:   "correct check string",
			data:       `{"o":"123456"}`,
			expression: "$.o",
			expect:     4,
			IsNilErr:   true,
		},
		{
			caseName:   "correct check string when equal",
			data:       `{"o":"123456"}`,
			expression: "$.o",
			expect:     6,
			IsNilErr:   true,
		},
		{
			caseName:   "not correct check string",
			data:       `{"o":"123456"}`,
			expression: "$.o",
			expect:     99,
		},
		{
			caseName:   "correct check map",
			data:       `{"o":[{"1":"a"}, {"2":"b"}, {"3":"c"}]}`,
			expression: "$.o",
			expect:     1,
			IsNilErr:   true,
		},
		{
			caseName:   "correct check map when equal",
			data:       `{"o":[{"1":"a"}, {"2":"b"}, {"3":"c"}]}`,
			expression: "$.o",
			expect:     3,
			IsNilErr:   true,
		},
		{
			caseName:   "not correct check map",
			data:       `{"o":[{"1":"a"}, {"2":"b"}, {"3":"c"}]}`,
			expression: "$.o",
			expect:     5,
		},
		{
			caseName:   "check not correct path",
			data:       `{"o":["a", "b", "c"]}`,
			expression: "$.not_correct",
			expect:     0,
		},
	}

	for _, test := range tests {
		err := LengthGreaterOrEqualThan(test.expression, test.expect.(int))([]byte(test.data))

		if test.IsNilErr {
			require.NoError(t, err, "failed test %v", test.caseName)
		} else {
			require.Error(t, err, "failed test %v", test.caseName)
		}
	}
}

func TestLengthLessThan(t *testing.T) {
	tests := []jsonTest{
		{
			caseName:   "correct check array",
			data:       `{"o":["a", "b", "c"]}`,
			expression: "$.o",
			expect:     4,
			IsNilErr:   true,
		},
		{
			caseName:   "not correct check array",
			data:       `{"o":["a", "b", "c"]}`,
			expression: "$.o",
			expect:     3,
		},
		{
			caseName:   "correct check string",
			data:       `{"o":"123456"}`,
			expression: "$.o",
			expect:     7,
			IsNilErr:   true,
		},
		{
			caseName:   "not correct check string",
			data:       `{"o":"123456"}`,
			expression: "$.o",
			expect:     6,
		},
		{
			caseName:   "correct check map",
			data:       `{"o":[{"1":"a"}, {"2":"b"}, {"3":"c"}]}`,
			expression: "$.o",
			expect:     4,
			IsNilErr:   true,
		},
		{
			caseName:   "not correct check map",
			data:       `{"o":[{"1":"a"}, {"2":"b"}, {"3":"c"}]}`,
			expression: "$.o",
			expect:     3,
		},
		{
			caseName:   "check not correct path",
			data:       `{"o":["a", "b", "c"]}`,
			expression: "$.not_correct",
			expect:     0,
		},
	}

	for _, test := range tests {
		err := LengthLessThan(test.expression, test.expect.(int))([]byte(test.data))

		if test.IsNilErr {
			require.NoError(t, err, "failed test %v", test.caseName)
		} else {
			require.Error(t, err, "failed test %v", test.caseName)
		}
	}
}

func TestLengthLessOrEqualThan(t *testing.T) {
	tests := []jsonTest{
		{
			caseName:   "correct check array",
			data:       `{"o":["a", "b", "c"]}`,
			expression: "$.o",
			expect:     4,
			IsNilErr:   true,
		},
		{
			caseName:   "correct check array when equal",
			data:       `{"o":["a", "b", "c"]}`,
			expression: "$.o",
			expect:     3,
			IsNilErr:   true,
		},
		{
			caseName:   "not correct check array",
			data:       `{"o":["a", "b", "c"]}`,
			expression: "$.o",
			expect:     2,
		},
		{
			caseName:   "correct check string",
			data:       `{"o":"123456"}`,
			expression: "$.o",
			expect:     7,
			IsNilErr:   true,
		},
		{
			caseName:   "correct check string when equal",
			data:       `{"o":"123456"}`,
			expression: "$.o",
			expect:     6,
			IsNilErr:   true,
		},
		{
			caseName:   "not correct check string",
			data:       `{"o":"123456"}`,
			expression: "$.o",
			expect:     5,
		},
		{
			caseName:   "correct check map",
			data:       `{"o":[{"1":"a"}, {"2":"b"}, {"3":"c"}]}`,
			expression: "$.o",
			expect:     4,
			IsNilErr:   true,
		},
		{
			caseName:   "correct check map when equal",
			data:       `{"o":[{"1":"a"}, {"2":"b"}, {"3":"c"}]}`,
			expression: "$.o",
			expect:     3,
			IsNilErr:   true,
		},
		{
			caseName:   "not correct check map",
			data:       `{"o":[{"1":"a"}, {"2":"b"}, {"3":"c"}]}`,
			expression: "$.o",
			expect:     2,
		},
		{
			caseName:   "check not correct path",
			data:       `{"o":["a", "b", "c"]}`,
			expression: "$.not_correct",
			expect:     0,
		},
	}

	for _, test := range tests {
		err := LengthLessOrEqualThan(test.expression, test.expect.(int))([]byte(test.data))

		if test.IsNilErr {
			require.NoError(t, err, "failed test %v", test.caseName)
		} else {
			require.Error(t, err, "failed test %v", test.caseName)
		}
	}
}

func TestEqual(t *testing.T) {
	tests := []jsonTest{
		{
			caseName:   "valid json",
			data:       `{"first": 777, "second": [{"key_1": "some_key", "value": "some_value"}]}`,
			expression: "$.second[0].value",
			expect:     "some_value",
			IsNilErr:   true,
		},
		{
			caseName: "not valid json",
			data:     "{not_valid_json}",
		},
		{
			caseName:   "3rd party key",
			data:       `{"a":"as", "b":{"bs":"sb"}}`,
			expression: "$.l",
			expect:     nil,
		},
		{
			caseName:   "not array",
			data:       `{"a":"as", "b":{"bs":"sb"}}`,
			expression: "$.b[bs]",
		},
		{
			caseName:   "valid array",
			data:       `{"arr": ["one","two"]}`,
			expression: "$.arr",
			expect:     []string{"one", "two"},
			IsNilErr:   true,
		},
		{
			caseName:   "check equal map",
			data:       `{"a":"as", "b":{"bs":"sb"}}`,
			expression: "$.b",
			expect:     map[string]interface{}{"bs": "sb"},
			IsNilErr:   true,
		},
		{
			caseName:   "check equal string",
			data:       `{"a":"as", "b":{"bs":"sb"}}`,
			expression: "$.a",
			expect:     "as",
			IsNilErr:   true,
		},
		{
			caseName:   "check equal not correct string",
			data:       `{"a":"as", "b":{"bs":"sb"}}`,
			expression: "$.a",
			expect:     []byte("not_correct"),
		},
		{
			caseName:   "check 186135434",
			data:       `{"a":186135434, "b":{"bs":"sb"}}`,
			expression: "$.a",
			expect:     186135434,
			IsNilErr:   true,
		},
		{
			caseName:   "check float",
			data:       `{"a":1.0000001, "b":{"bs":"sb"}}`,
			expression: "$.a",
			expect:     1.0000001,
			IsNilErr:   true,
		},
		{
			caseName:   "check float 2",
			data:       `{"a":999.0000001, "b":{"bs":"sb"}}`,
			expression: "$.a",
			expect:     999.0000001,
			IsNilErr:   true,
		},
	}

	for _, test := range tests {
		err := Equal(test.expression, test.expect)([]byte(test.data))

		if test.IsNilErr {
			require.NoError(t, err, "failed test %v", test.caseName)
		} else {
			require.Error(t, err, "failed test %v", test.caseName)
		}
	}
}

func TestNotEqual(t *testing.T) {
	tests := []jsonTest{
		{
			caseName:   "valid json",
			data:       `{"first": 777, "second": [{"key_1": "some_key", "value": "some_value"}]}`,
			expression: "$.second[0].value",
			expect:     "some_value",
			IsNilErr:   false,
		},
		{
			caseName: "not valid json",
			data:     "{not_valid_json}",
		},
		{
			caseName:   "3rd party key",
			data:       `{"a":"as", "b":{"bs":"sb"}}`,
			expression: "$.l",
			expect:     nil,
		},
		{
			caseName:   "not array",
			data:       `{"a":"as", "b":{"bs":"sb"}}`,
			expression: "$.b[bs]",
			expect:     "sb",
		},
		{
			caseName:   "check equal map",
			data:       `{"a":"as", "b":{"bs":"sb"}}`,
			expression: "$.b",
			expect:     map[string]interface{}{"bs": "sb"},
			IsNilErr:   false,
		},
		{
			caseName:   "check equal string",
			data:       `{"a":"as", "b":{"bs":"sb"}}`,
			expression: "$.a",
			expect:     "as",
			IsNilErr:   false,
		},
	}

	for _, test := range tests {
		err := NotEqual(test.expression, test.expect)([]byte(test.data))

		if test.IsNilErr {
			require.NoError(t, err, "failed test %v", test.caseName)
		} else {
			require.Error(t, err, "failed test %v", test.caseName)
		}
	}
}

func TestEqualJSON(t *testing.T) {
	tests := []jsonTest{
		{
			caseName:   "valid json",
			data:       `{"first": 777, "second": [{"key_1": "some_key", "value": "some_value"}]}`,
			expression: "$.second[0].value",
			expect:     `"some_value"`,
			IsNilErr:   true,
		},
		{
			caseName: "not valid json",
			data:     "{not_valid_json}",
		},
		{
			caseName:   "3rd party key",
			data:       `{"a":"as", "b":{"bs":"sb"}}`,
			expression: "$.l",
		},
		{
			caseName:   "not array",
			data:       `{"a":"as", "b":{"bs":"sb"}}`,
			expression: "$.b[bs]",
		},
		{
			caseName:   "valid array",
			data:       `{"arr": ["one","two"]}`,
			expression: "$.arr",
			expect:     `["one", "two"]`,
			IsNilErr:   true,
		},
		{
			caseName:   "check equal map",
			data:       `{"a":"as", "b":{"bs":"sb"}}`,
			expression: "$.b",
			expect:     `{"bs": "sb"}`,
			IsNilErr:   true,
		},
		{
			caseName:   "check equal string",
			data:       `{"a":"as", "b":{"bs":"sb"}}`,
			expression: "$.a",
			expect:     `"as"`,
			IsNilErr:   true,
		},
		{
			caseName:   "check equal not correct string",
			data:       `{"a":"as", "b":{"bs":"sb"}}`,
			expression: "$.a",
			expect:     `"not_correct"`,
		},
		{
			caseName:   "check deep equal",
			data:       `{"a":"as", "b":{"bs":"sb"}}`,
			expression: "$",
			expect:     `{ "b": {"bs": "sb"}, "a":"as" }`,
			IsNilErr:   true,
		},
		{
			caseName:   "check deep equal not correct",
			data:       `{"a":"as", "b":{"bs":"sb"}}`,
			expression: "$",
			expect:     `{ "b": {"sb": "bs"}, "a":"as" }`,
		},
		{
			caseName:   "check 186135434",
			data:       `{"a":186135434, "b":{"bs":"sb"}}`,
			expression: "$.a",
			expect:     "186135434",
			IsNilErr:   true,
		},
		{
			caseName:   "check float",
			data:       `{"a":1.0000001, "b":{"bs":"sb"}}`,
			expression: "$.a",
			expect:     "1.0000001",
			IsNilErr:   true,
		},
		{
			caseName:   "check float 2",
			data:       `{"a":999.0000001, "b":{"bs":"sb"}}`,
			expression: "$.a",
			expect:     "999.0000001",
			IsNilErr:   true,
		},
	}

	for _, test := range tests {
		exp, _ := test.expect.(string)
		err := EqualJSON(test.expression, []byte(exp))([]byte(test.data))

		if test.IsNilErr {
			require.NoError(t, err, "failed test %v", test.caseName)
		} else {
			require.Error(t, err, "failed test %v", test.caseName)
		}
	}
}

func TestNotEqualJSON(t *testing.T) {
	tests := []jsonTest{
		{
			caseName:   "valid json",
			data:       `{"first": 777, "second": [{"key_1": "some_key", "value": "some_value"}]}`,
			expression: "$.second[0].value",
			expect:     `"some_value"`,
		},
		{
			caseName: "not valid json",
			data:     "{not_valid_json}",
		},
		{
			caseName:   "3rd party key",
			data:       `{"a":"as", "b":{"bs":"sb"}}`,
			expression: "$.l",
		},
		{
			caseName:   "not array",
			data:       `{"a":"as", "b":{"bs":"sb"}}`,
			expression: "$.b[bs]",
		},
		{
			caseName:   "valid array",
			data:       `{"arr": ["one","two"]}`,
			expression: "$.arr",
			expect:     `["one", "two"]`,
		},
		{
			caseName:   "check equal map",
			data:       `{"a":"as", "b":{"bs":"sb"}}`,
			expression: "$.b",
			expect:     `{"bs": "sb"}`,
		},
		{
			caseName:   "check equal string",
			data:       `{"a":"as", "b":{"bs":"sb"}}`,
			expression: "$.a",
			expect:     `"as"`,
		},
		{
			caseName:   "check equal not correct string",
			data:       `{"a":"as", "b":{"bs":"sb"}}`,
			expression: "$.a",
			expect:     `"not_correct"`,
			IsNilErr:   true,
		},
		{
			caseName:   "check deep equal",
			data:       `{"a":"as", "b":{"bs":"sb"}}`,
			expression: "$",
			expect:     `{ "b": {"bs": "sb"}, "a":"as" }`,
		},
		{
			caseName:   "check deep equal not correct",
			data:       `{"a":"as", "b":{"bs":"sb"}}`,
			expression: "$",
			expect:     `{ "b": {"sb": "bs"}, "a":"as" }`,
			IsNilErr:   true,
		},
		{
			caseName:   "check 186135434",
			data:       `{"a":186135434, "b":{"bs":"sb"}}`,
			expression: "$.a",
			expect:     "186135434",
		},
		{
			caseName:   "check float",
			data:       `{"a":1.0000001, "b":{"bs":"sb"}}`,
			expression: "$.a",
			expect:     "1.0000001",
		},
		{
			caseName:   "check float 2",
			data:       `{"a":999.0000001, "b":{"bs":"sb"}}`,
			expression: "$.a",
			expect:     "999.0000001",
		},
	}

	for _, test := range tests {
		exp, _ := test.expect.(string)
		err := NotEqualJSON(test.expression, []byte(exp))([]byte(test.data))

		if test.IsNilErr {
			require.NoError(t, err, "failed test %v", test.caseName)
		} else {
			require.Error(t, err, "failed test %v", test.caseName)
		}
	}
}

func TestGetValueFromJSON(t *testing.T) {
	testCases := []struct {
		name          string
		inputJSON     string
		expression    string
		expectedValue []interface{}
		expectedError string
	}{
		{
			name:          "ValidExpressionObject",
			inputJSON:     `{"key1": "value1", "key2": {"key3": "value3"}}`,
			expression:    "key2.key3",
			expectedValue: []interface{}{"value3"},
			expectedError: "", // No error expected
		},
		{
			name:          "ValidExpressionArray",
			inputJSON:     `{"key1": "value1", "key2": [1, 2, 3]}`,
			expression:    "key2[1]",
			expectedValue: []interface{}{int64(2)},
			expectedError: "", // No error expected
		},
		{
			name:          "ValidExpressionMap",
			inputJSON:     `{"key1": "value1", "key2": {"subkey1": "subvalue1"}}`,
			expression:    "key2",
			expectedValue: []interface{}{map[string]interface{}{"subkey1": "subvalue1"}},
			expectedError: "", // No error expected
		},
		{
			name:          "InvalidJSON",
			inputJSON:     `invalid json`,
			expression:    "key1",
			expectedValue: nil,
			expectedError: "could not parse json",
		},
		{
			name:          "InvalidExpression",
			inputJSON:     `{"key1": "value1"}`,
			expression:    "key2",
			expectedValue: nil,
			expectedError: "could not find element by path key2 in JSON",
		},
	}

	for _, testCase := range testCases {
		t.Run(testCase.name, func(t *testing.T) {
			// Call the GetValueFromJSON function with the test input
			value, err := GetValueFromJSON([]byte(testCase.inputJSON), testCase.expression)

			// Check if the error message matches the expected result
			if testCase.expectedError == "" {
				assert.NoError(t, err) // No error expected
			} else {
				assert.Error(t, err) // Error expected
				assert.Contains(t, err.Error(), testCase.expectedError)
			}

			// Check if the returned value is an array and matches the expected result
			assert.IsType(t, []interface{}{}, value)
			assert.Equal(t, testCase.expectedValue, value)
		})
	}
}


================================================
FILE: asserts/json/util.go
================================================
package json

import (
	"bytes"
	"fmt"
	"reflect"
	"strings"

	"github.com/ohler55/ojg/oj"
	"github.com/ozontech/cute/errors"
)

// Contains is a function to assert that a jsonpath expression extracts a value in an array
// Given the response is {"first": 777, "second": [{"key_1": "some_key", "value": "some_value"}]}, we can assert on the result like so `$.second[? @.key_1=="some_key"].value`, "some_value"
// About expression - https://goessner.net/articles/JsonPath/
func contains(data []byte, expression string, expect interface{}) error {
	values, err := GetValueFromJSON(data, expression)
	if err != nil {
		return err
	}

	for _, value := range values {
		ok, found := insideArray(value, expect)
		if !ok {
			return errors.NewAssertError("Contains", fmt.Sprintf("on path %v. %v could not be applied builtin len()", expression, expect), nil, nil)
		}

		if !found {
			return errors.NewAssertError("Contains", fmt.Sprintf("on path %v. expect %v, but actual %v", expression, expect, value), value, expect)
		}
	}

	return nil
}

func equalAbstract(data []byte, expression string, expect interface{}, name string) error {
	values, err := GetValueFromJSON(data, expression)
	if err != nil {
		return err
	}

	for _, value := range values {
		if !objectsAreEqual(value, expect) {
			return errors.NewAssertError(name, fmt.Sprintf("on path %v. expect %v, but actual %v", expression, expect, value), value, expect)
		}
	}

	return nil
}

func notEqualAbstract(data []byte, expression string, expect interface{}, name string) error {
	values, err := GetValueFromJSON(data, expression)
	if err != nil {
		return err
	}

	for _, value := range values {
		if objectsAreEqual(value, expect) {
			return errors.NewAssertError(name, fmt.Sprintf("on path %v. expect %v, but actual %v", expression, expect, value), value, expect)
		}
	}

	return nil
}

// Equal is a function to assert that a jsonpath expression matches the given value
// About expression - https://goessner.net/articles/JsonPath/
func equal(data []byte, expression string, expect interface{}) error {
	return equalAbstract(data, expression, expect, "Equal")
}

// NotEqual is a function to check json path expression value is not equal to given value
// About expression - https://goessner.net/articles/JsonPath/
func notEqual(data []byte, expression string, expect interface{}) error {
	return notEqualAbstract(data, expression, expect, "NotEqual")
}

// EqualJSON is a function to check json path expression value is equal to given json
// About expression - https://goessner.net/articles/JsonPath/
func equalJSON(data []byte, expression string, expect []byte) error {
	obj, err := oj.Parse(expect)
	if err != nil {
		return fmt.Errorf("could not parse json in EqualJSON error: '%s'", err)
	}

	return equalAbstract(data, expression, obj, "EqualJSON")
}

// NotEqualJSON is a function to check json path expression value is not equal to given json
// About expression - https://goessner.net/articles/JsonPath/
func notEqualJSON(data []byte, expression string, expect []byte) error {
	obj, err := oj.Parse(expect)
	if err != nil {
		return fmt.Errorf("could not parse json in NotEqualJSON error: '%s'", err)
	}

	return notEqualAbstract(data, expression, obj, "NotEqualJSON")
}

// Length is a function to asserts that value is the expected length
// About expression - https://goessner.net/articles/JsonPath/
func length(data []byte, expression string, expectLength int) error {
	values, err := GetValueFromJSON(data, expression)
	if err != nil {
		return err
	}

	for _, value := range values {
		v := reflect.ValueOf(value)
		if v.Len() != expectLength {
			return errors.NewAssertError("Length", fmt.Sprintf("on path %v. expect lenght %v, but actual %v", expression, expectLength, v.Len()), v.Len(), expectLength)
		}
	}

	return nil
}

// GreaterThan is a function to asserts that value is greater than the given length
// About expression - https://goessner.net/articles/JsonPath/
func greaterThan(data []byte, expression string, minimumLength int) error {
	values, err := GetValueFromJSON(data, expression)
	if err != nil {
		return err
	}

	for _, value := range values {
		v := reflect.ValueOf(value)
		if v.Len() <= minimumLength {
			return errors.NewAssertError("GreaterThan", fmt.Sprintf("on path %v. %v is greater than %v", expression, v.Len(), minimumLength), v.Len(), minimumLength)
		}
	}

	return nil
}

// GreaterOrEqualThan is a function to asserts that value is greater or equal than the given length
// About expression - https://goessner.net/articles/JsonPath/
func greaterOrEqualThan(data []byte, expression string, minimumLength int) error {
	values, err := GetValueFromJSON(data, expression)
	if err != nil {
		return err
	}

	for _, value := range values {
		v := reflect.ValueOf(value)
		if v.Len() < minimumLength {
			return errors.NewAssertError("GreaterOrEqualThan", fmt.Sprintf("on path %v. %v is greater or equal than %v", expression, v.Len(), minimumLength), v.Len(), minimumLength)
		}
	}

	return nil
}

// LessThan is a function to asserts that value is less than the given length
// About expression - https://goessner.net/articles/JsonPath/
func lessThan(data []byte, expression string, maximumLength int) error {
	values, err := GetValueFromJSON(data, expression)
	if err != nil {
		return err
	}

	for _, value := range values {
		v := reflect.ValueOf(value)
		if v.Len() >= maximumLength {
			return errors.NewAssertError("LessThan", fmt.Sprintf("on path %v. %v is less than %v", expression, v.Len(), maximumLength), v.Len(), maximumLength)
		}
	}

	return nil
}

// LessOrEqualThan is a function to asserts that value is less or equal than the given length
// About expression - https://goessner.net/articles/JsonPath/
func lessOrEqualThan(data []byte, expression string, maximumLength int) error {
	values, err := GetValueFromJSON(data, expression)
	if err != nil {
		return err
	}

	for _, value := range values {
		v := reflect.ValueOf(value)
		if v.Len() > maximumLength {
			return errors.NewAssertError("LessThan", fmt.Sprintf("on path %v. %v is less or equal than %v", expression, v.Len(), maximumLength), v.Len(), maximumLength)
		}
	}

	return nil
}

// notEmpty is a function to asserts that value is not empty (!= 0, != null)
// About expression - https://goessner.net/articles/JsonPath/
func notEmpty(data []byte, expression string) error {
	values, _ := GetValueFromJSON(data, expression)

	if len(values) == 0 {
		return errors.NewAssertError("NotEmpty", fmt.Sprintf("on path %v. value is not present", expression), nil, nil)
	}

	for _, value := range values {
		if isEmpty(value) {
			return errors.NewAssertError("NotEmpty", fmt.Sprintf("on path %v. value is not present", expression), nil, nil)
		}
	}

	return nil
}

// Present is a function to asserts that value is present
// value can be 0 or null
// About expression - https://goessner.net/articles/JsonPath/
func present(data []byte, expression string) error {
	values, err := GetValueFromJSON(data, expression)
	if err != nil || len(values) == 0 {
		return errors.NewAssertError("Present", fmt.Sprintf("on path %v. value not present", expression), nil, nil)
	}

	return nil
}

// NotPresent is a function to asserts that value is not present
// About expression - https://goessner.net/articles/JsonPath/
func notPresent(data []byte, expression string) error {
	values, _ := GetValueFromJSON(data, expression)

	for _, value := range values {
		if !isEmpty(value) {
			return errors.NewAssertError("NotPresent", fmt.Sprintf("on path %v. value present", expression), nil, nil)
		}
	}

	return nil
}

func objectsAreEqual(expect, actual interface{}) bool {
	if reflect.DeepEqual(expect, actual) {
		return true
	}

	if expect == nil || actual == nil {
		return expect == actual
	}

	if fmt.Sprintf("%v", expect) == fmt.Sprintf("%v", actual) {
		return true
	}

	exp, ok := expect.([]byte)
	if !ok {
		return reflect.DeepEqual(expect, actual)
	}

	act, ok := actual.([]byte)
	if !ok {
		return false
	}

	if exp == nil || act == nil {
		return exp == nil && act == nil
	}

	return bytes.Equal(exp, act)
}

func isEmpty(object interface{}) bool {
	if object == nil {
		return true
	}

	objValue := reflect.ValueOf(object)

	switch objValue.Kind() {
	case reflect.Ptr:
		if objValue.IsNil() {
			return true
		}

		deref := objValue.Elem().Interface()

		return isEmpty(deref)
	case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice:
		return objValue.Len() == 0
	default:
		zero := reflect.Zero(objValue.Type())
		return reflect.DeepEqual(object, zero.Interface())
	}
}

func insideArray(list interface{}, element interface{}) (ok, found bool) {
	var (
		listValue    = reflect.ValueOf(list)
		elementValue = reflect.ValueOf(element)
	)

	defer func() {
		if err := recover(); err != nil {
			ok = false
			found = false
		}
	}()

	if reflect.TypeOf(list).Kind() == reflect.String {
		return true, strings.Contains(listValue.String(), elementValue.String())
	}

	if reflect.TypeOf(list).Kind() == reflect.Map {
		mapKeys := listValue.MapKeys()

		for i := 0; i < len(mapKeys); i++ {
			if objectsAreEqual(mapKeys[i].Interface(), element) {
				return true, true
			}
		}

		return true, false
	}

	for i := 0; i < listValue.Len(); i++ {
		if objectsAreEqual(listValue.Index(i).Interface(), element) {
			return true, true
		}
	}

	return true, false
}


================================================
FILE: builder.go
================================================
package cute

import (
	"net/http"
	"time"
)

const defaultHTTPTimeout = 30

var (
	errorAssertIsNil = "assert must be not nil"
)

// HTTPTestMaker is a creator tests
type HTTPTestMaker struct {
	httpClient    *http.Client
	middleware    *Middleware
	jsonMarshaler JSONMarshaler
}

// NewHTTPTestMaker is function for set options for all cute.
// For example, you can set timeout for all requests  or set custom http client
// Options:
// - WithCustomHTTPTimeout - set timeout for all requests
// - WithHTTPClient - set custom http client
// - WithCustomHTTPRoundTripper - set custom http round tripper
// - WithJSONMarshaler - set custom json marshaler
// - WithMiddlewareAfter - set function which will run AFTER test execution
// - WithMiddlewareAfterT - set function which will run AFTER test execution with TB
// - WithMiddlewareBefore - set function which will run BEFORE test execution
// - WithMiddlewareBeforeT - set function which will run BEFORE test execution with TB
func NewHTTPTestMaker(opts ...Option) *HTTPTestMaker {
	var (
		o = &options{
			middleware: new(Middleware),
		}

		timeout                    = defaultHTTPTimeout * time.Second
		roundTripper               = http.DefaultTransport
		jsMarshaler  JSONMarshaler = &jsonMarshaler{}
	)

	for _, opt := range opts {
		opt(o)
	}

	if o.httpTimeout != 0 {
		timeout = o.httpTimeout
	}

	if o.httpRoundTripper != nil { //nolint
		roundTripper = o.httpRoundTripper
	}

	httpClient := &http.Client{
		Transport: roundTripper,
		Timeout:   timeout,
	}

	if o.httpClient != nil {
		httpClient = o.httpClient
	}

	if o.jsonMarshaler != nil {
		jsMarshaler = o.jsonMarshaler
	}

	m := &HTTPTestMaker{
		httpClient:    httpClient,
		jsonMarshaler: jsMarshaler,
		middleware:    o.middleware,
	}

	return m
}

// NewTestBuilder is a function for initialization foundation for cute
func (m *HTTPTestMaker) NewTestBuilder() AllureBuilder {
	tests := createDefaultTests(m)

	return &cute{
		baseProps:    m,
		countTests:   0,
		tests:        tests,
		allureInfo:   new(allureInformation),
		allureLinks:  new(allureLinks),
		allureLabels: new(allureLabels),
		parallel:     false,
	}
}

func createDefaultTests(m *HTTPTestMaker) []*Test {
	tests := make([]*Test, 1)
	tests[0] = createDefaultTest(m)

	return tests
}

func createDefaultTest(m *HTTPTestMaker) *Test {
	return &Test{
		httpClient:    m.httpClient,
		jsonMarshaler: m.jsonMarshaler,
		Middleware:    createMiddlewareFromTemplate(m.middleware),
		AllureStep:    new(AllureStep),
		Request: &Request{
			Retry: new(RequestRetryPolitic),
		},
		Expect: &Expect{JSONSchema: new(ExpectJSONSchema)},
	}
}

func createMiddlewareFromTemplate(m *Middleware) *Middleware {
	after := make([]AfterExecute, 0, len(m.After))
	after = append(after, m.After...)

	afterT := make([]AfterExecuteT, 0, len(m.AfterT))
	afterT = append(afterT, m.AfterT...)

	before := make([]BeforeExecute, 0, len(m.Before))
	before = append(before, m.Before...)

	beforeT := make([]BeforeExecuteT, 0, len(m.BeforeT))
	beforeT = append(beforeT, m.BeforeT...)

	middleware := &Middleware{
		After:   after,
		AfterT:  afterT,
		Before:  before,
		BeforeT: beforeT,
	}

	return middleware
}

func (qt *cute) Create() MiddlewareRequest {
	return qt
}

func (qt *cute) CreateStep(name string) MiddlewareRequest {
	qt.tests[qt.countTests].AllureStep.Name = name

	return qt
}

func (qt *cute) CreateRequest() RequestHTTPBuilder {
	return qt
}


================================================
FILE: builder_allure.go
================================================
package cute

import (
	"fmt"

	"github.com/ozontech/allure-go/pkg/allure"
)

func (qt *cute) Parallel() AllureBuilder {
	qt.parallel = true

	return qt
}

func (qt *cute) Title(title string) AllureBuilder {
	qt.allureInfo.title = title

	return qt
}

func (qt *cute) Epic(epic string) AllureBuilder {
	qt.allureLabels.epic = epic

	return qt
}

func (qt *cute) Titlef(format string, args ...interface{}) AllureBuilder {
	qt.allureInfo.title = fmt.Sprintf(format, args...)

	return qt
}

func (qt *cute) Descriptionf(format string, args ...interface{}) AllureBuilder {
	qt.allureInfo.description = fmt.Sprintf(format, args...)

	return qt
}

func (qt *cute) Stage(stage string) AllureBuilder {
	qt.allureInfo.stage = stage

	return qt
}

func (qt *cute) Stagef(format string, args ...interface{}) AllureBuilder {
	qt.allureInfo.stage = fmt.Sprintf(format, args...)

	return qt
}

func (qt *cute) Layer(value string) AllureBuilder {
	qt.allureLabels.layer = value

	return qt
}

func (qt *cute) TmsLink(tmsLink string) AllureBuilder {
	qt.allureLinks.tmsLink = tmsLink

	return qt
}

func (qt *cute) TmsLinks(tmsLinks ...string) AllureBuilder {
	qt.allureLinks.tmsLinks = append(qt.allureLinks.tmsLinks, tmsLinks...)

	return qt
}

func (qt *cute) SetIssue(issue string) AllureBuilder {
	qt.allureLinks.issue = issue

	return qt
}

func (qt *cute) SetTestCase(testCase string) AllureBuilder {
	qt.allureLinks.testCase = testCase

	return qt
}

func (qt *cute) Link(link *allure.Link) AllureBuilder {
	qt.allureLinks.link = link

	return qt
}

func (qt *cute) ID(value string) AllureBuilder {
	qt.allureLabels.id = value

	return qt
}

func (qt *cute) AllureID(value string) AllureBuilder {
	qt.allureLabels.allureID = value

	return qt
}

func (qt *cute) AddSuiteLabel(value string) AllureBuilder {
	qt.allureLabels.suiteLabel = value

	return qt
}

func (qt *cute) AddSubSuite(value string) AllureBuilder {
	qt.allureLabels.subSuite = value

	return qt
}

func (qt *cute) AddParentSuite(value string) AllureBuilder {
	qt.allureLabels.parentSuite = value

	return qt
}

func (qt *cute) Story(value string) AllureBuilder {
	qt.allureLabels.story = value

	return qt
}

func (qt *cute) Tag(value string) AllureBuilder {
	qt.allureLabels.tag = value

	return qt
}

func (qt *cute) Severity(value allure.SeverityType) AllureBuilder {
	qt.allureLabels.severity = value

	return qt
}

func (qt *cute) Owner(value string) AllureBuilder {
	qt.allureLabels.owner = value

	return qt
}

func (qt *cute) Lead(value string) AllureBuilder {
	qt.allureLabels.lead = value

	return qt
}

func (qt *cute) Label(label *allure.Label) AllureBuilder {
	qt.allureLabels.label = label

	return qt
}

func (qt *cute) Labels(labels ...*allure.Label) AllureBuilder {
	qt.allureLabels.labels = labels

	return qt
}

func (qt *cute) Description(description string) AllureBuilder {
	qt.allureInfo.description = description

	return qt
}

func (qt *cute) Tags(tags ...string) AllureBuilder {
	qt.allureLabels.tags = tags

	return qt
}

func (qt *cute) Feature(feature string) AllureBuilder {
	qt.allureLabels.feature = feature

	return qt
}


================================================
FILE: builder_asserts.go
================================================
package cute

import "time"

func (qt *cute) AssertBody(asserts ...AssertBody) ExpectHTTPBuilder {
	trace := getTrace()

	for _, assert := range asserts {
		if assert == nil {
			panic(errorAssertIsNil)
		}

		qt.tests[qt.countTests].Expect.AssertBody = append(qt.tests[qt.countTests].Expect.AssertBody, assertBodyWithTrace(assert, trace))
	}

	return qt
}

func (qt *cute) OptionalAssertBody(asserts ...AssertBody) ExpectHTTPBuilder {
	trace := getTrace()

	for _, assert := range asserts {
		if assert == nil {
			panic(errorAssertIsNil)
		}

		qt.tests[qt.countTests].Expect.AssertBody = append(qt.tests[qt.countTests].Expect.AssertBody, assertBodyWithTrace(optionalAssertBody(assert), trace))
	}

	return qt
}

func (qt *cute) BrokenAssertBody(asserts ...AssertBody) ExpectHTTPBuilder {
	trace := getTrace()

	for _, assert := range asserts {
		if assert == nil {
			panic(errorAssertIsNil)
		}

		qt.tests[qt.countTests].Expect.AssertBody = append(qt.tests[qt.countTests].Expect.AssertBody, assertBodyWithTrace(brokenAssertBody(assert), trace))
	}

	return qt
}

func (qt *cute) RequireBody(asserts ...AssertBody) ExpectHTTPBuilder {
	trace := getTrace()

	for _, assert := range asserts {
		if assert == nil {
			panic(errorAssertIsNil)
		}

		qt.tests[qt.countTests].Expect.AssertBody = append(qt.tests[qt.countTests].Expect.AssertBody, assertBodyWithTrace(requireAssertBody(assert), trace))
	}

	return qt
}

func (qt *cute) AssertHeaders(asserts ...AssertHeaders) ExpectHTTPBuilder {
	trace := getTrace()

	for _, assert := range asserts {
		if assert == nil {
			panic(errorAssertIsNil)
		}

		qt.tests[qt.countTests].Expect.AssertHeaders = append(qt.tests[qt.countTests].Expect.AssertHeaders, assertHeadersWithTrace(assert, trace))
	}

	return qt
}

func (qt *cute) OptionalAssertHeaders(asserts ...AssertHeaders) ExpectHTTPBuilder {
	trace := getTrace()

	for _, assert := range asserts {
		if assert == nil {
			panic(errorAssertIsNil)
		}

		qt.tests[qt.countTests].Expect.AssertHeaders = append(qt.tests[qt.countTests].Expect.AssertHeaders, assertHeadersWithTrace(optionalAssertHeaders(assert), trace))
	}

	return qt
}

func (qt *cute) RequireHeaders(asserts ...AssertHeaders) ExpectHTTPBuilder {
	trace := getTrace()

	for _, assert := range asserts {
		if assert == nil {
			panic(errorAssertIsNil)
		}

		qt.tests[qt.countTests].Expect.AssertHeaders = append(qt.tests[qt.countTests].Expect.AssertHeaders, assertHeadersWithTrace(requireAssertHeaders(assert), trace))
	}

	return qt
}

func (qt *cute) BrokenAssertHeaders(asserts ...AssertHeaders) ExpectHTTPBuilder {
	trace := getTrace()

	for _, assert := range asserts {
		if assert == nil {
			panic(errorAssertIsNil)
		}

		qt.tests[qt.countTests].Expect.AssertHeaders = append(qt.tests[qt.countTests].Expect.AssertHeaders, assertHeadersWithTrace(brokenAssertHeaders(assert), trace))
	}

	return qt
}

func (qt *cute) AssertResponse(asserts ...AssertResponse) ExpectHTTPBuilder {
	trace := getTrace()

	for _, assert := range asserts {
		if assert == nil {
			panic(errorAssertIsNil)
		}

		qt.tests[qt.countTests].Expect.AssertResponse = append(qt.tests[qt.countTests].Expect.AssertResponse, assertResponseWithTrace(assert, trace))
	}

	return qt
}

func (qt *cute) OptionalAssertResponse(asserts ...AssertResponse) ExpectHTTPBuilder {
	trace := getTrace()

	for _, assert := range asserts {
		if assert == nil {
			panic(errorAssertIsNil)
		}

		qt.tests[qt.countTests].Expect.AssertResponse = append(qt.tests[qt.countTests].Expect.AssertResponse, assertResponseWithTrace(optionalAssertResponse(assert), trace))
	}

	return qt
}

func (qt *cute) RequireResponse(asserts ...AssertResponse) ExpectHTTPBuilder {
	trace := getTrace()

	for _, assert := range asserts {
		if assert == nil {
			panic(errorAssertIsNil)
		}

		qt.tests[qt.countTests].Expect.AssertResponse = append(qt.tests[qt.countTests].Expect.AssertResponse, assertResponseWithTrace(requireAssertResponse(assert), trace))
	}

	return qt
}

func (qt *cute) BrokenAssertResponse(asserts ...AssertResponse) ExpectHTTPBuilder {
	trace := getTrace()

	for _, assert := range asserts {
		if assert == nil {
			panic(errorAssertIsNil)
		}

		qt.tests[qt.countTests].Expect.AssertResponse = append(qt.tests[qt.countTests].Expect.AssertResponse, assertResponseWithTrace(brokenAssertResponse(assert), trace))
	}

	return qt
}

func (qt *cute) AssertBodyT(asserts ...AssertBodyT) ExpectHTTPBuilder {
	trace := getTrace()

	for _, assert := range asserts {
		if assert == nil {
			panic(errorAssertIsNil)
		}

		qt.tests[qt.countTests].Expect.AssertBodyT = append(qt.tests[qt.countTests].Expect.AssertBodyT, assertBodyTWithTrace(assert, trace))
	}

	return qt
}

func (qt *cute) OptionalAssertBodyT(asserts ...AssertBodyT) ExpectHTTPBuilder {
	trace := getTrace()

	for _, assert := range asserts {
		if assert == nil {
			panic(errorAssertIsNil)
		}

		qt.tests[qt.countTests].Expect.AssertBodyT = append(qt.tests[qt.countTests].Expect.AssertBodyT, assertBodyTWithTrace(optionalAssertBodyT(assert), trace))
	}

	return qt
}

func (qt *cute) BrokenAssertBodyT(asserts ...AssertBodyT) ExpectHTTPBuilder {
	trace := getTrace()

	for _, assert := range asserts {
		if assert == nil {
			panic(errorAssertIsNil)
		}

		qt.tests[qt.countTests].Expect.AssertBodyT = append(qt.tests[qt.countTests].Expect.AssertBodyT, assertBodyTWithTrace(brokenAssertBodyT(assert), trace))
	}

	return qt
}

func (qt *cute) RequireBodyT(asserts ...AssertBodyT) ExpectHTTPBuilder {
	trace := getTrace()

	for _, assert := range asserts {
		if assert == nil {
			panic(errorAssertIsNil)
		}

		qt.tests[qt.countTests].Expect.AssertBodyT = append(qt.tests[qt.countTests].Expect.AssertBodyT, assertBodyTWithTrace(requireAssertBodyT(assert), trace))
	}

	return qt
}

func (qt *cute) AssertHeadersT(asserts ...AssertHeadersT) ExpectHTTPBuilder {
	trace := getTrace()

	for _, assert := range asserts {
		if assert == nil {
			panic(errorAssertIsNil)
		}

		qt.tests[qt.countTests].Expect.AssertHeadersT = append(qt.tests[qt.countTests].Expect.AssertHeadersT, assertHeadersTWithTrace(assert, trace))
	}

	return qt
}

func (qt *cute) OptionalAssertHeadersT(asserts ...AssertHeadersT) ExpectHTTPBuilder {
	trace := getTrace()

	for _, assert := range asserts {
		if assert == nil {
			panic(errorAssertIsNil)
		}

		qt.tests[qt.countTests].Expect.AssertHeadersT = append(qt.tests[qt.countTests].Expect.AssertHeadersT, assertHeadersTWithTrace(optionalAssertHeadersT(assert), trace))
	}

	return qt
}

func (qt *cute) RequireHeadersT(asserts ...AssertHeadersT) ExpectHTTPBuilder {
	trace := getTrace()

	for _, assert := range asserts {
		if assert == nil {
			panic(errorAssertIsNil)
		}

		qt.tests[qt.countTests].Expect.AssertHeadersT = append(qt.tests[qt.countTests].Expect.AssertHeadersT, assertHeadersTWithTrace(requireAssertHeadersT(assert), trace))
	}

	return qt
}

func (qt *cute) BrokenAssertHeadersT(asserts ...AssertHeadersT) ExpectHTTPBuilder {
	trace := getTrace()

	for _, assert := range asserts {
		if assert == nil {
			panic(errorAssertIsNil)
		}

		qt.tests[qt.countTests].Expect.AssertHeadersT = append(qt.tests[qt.countTests].Expect.AssertHeadersT, assertHeadersTWithTrace(brokenAssertHeadersT(assert), trace))
	}

	return qt
}

func (qt *cute) AssertResponseT(asserts ...AssertResponseT) ExpectHTTPBuilder {
	trace := getTrace()

	for _, assert := range asserts {
		if assert == nil {
			panic(errorAssertIsNil)
		}

		qt.tests[qt.countTests].Expect.AssertResponseT = append(qt.tests[qt.countTests].Expect.AssertResponseT, assertResponseTWithTrace(assert, trace))
	}

	return qt
}

func (qt *cute) OptionalAssertResponseT(asserts ...AssertResponseT) ExpectHTTPBuilder {
	trace := getTrace()

	for _, assert := range asserts {
		if assert == nil {
			panic(errorAssertIsNil)
		}

		qt.tests[qt.countTests].Expect.AssertResponseT = append(qt.tests[qt.countTests].Expect.AssertResponseT, assertResponseTWithTrace(optionalAssertResponseT(assert), trace))
	}

	return qt
}

func (qt *cute) BrokenAssertResponseT(asserts ...AssertResponseT) ExpectHTTPBuilder {
	trace := getTrace()

	for _, assert := range asserts {
		if assert == nil {
			panic(errorAssertIsNil)
		}

		qt.tests[qt.countTests].Expect.AssertResponseT = append(qt.tests[qt.countTests].Expect.AssertResponseT, assertResponseTWithTrace(brokenAssertResponseT(assert), trace))
	}

	return qt
}

func (qt *cute) RequireResponseT(asserts ...AssertResponseT) ExpectHTTPBuilder {
	trace := getTrace()

	for _, assert := range asserts {
		if assert == nil {
			panic(errorAssertIsNil)
		}

		qt.tests[qt.countTests].Expect.AssertResponseT = append(qt.tests[qt.countTests].Expect.AssertResponseT, assertResponseTWithTrace(requireAssertResponseT(assert), trace))
	}

	return qt
}

func (qt *cute) ExpectExecuteTimeout(t time.Duration) ExpectHTTPBuilder {
	qt.tests[qt.countTests].Expect.ExecuteTime = t

	return qt
}

func (qt *cute) ExpectStatus(code int) ExpectHTTPBuilder {
	qt.tests[qt.countTests].Expect.Code = code

	return qt
}

func (qt *cute) ExpectJSONSchemaString(schema string) ExpectHTTPBuilder {
	qt.tests[qt.countTests].Expect.JSONSchema.String = schema

	return qt
}

func (qt *cute) ExpectJSONSchemaByte(schema []byte) ExpectHTTPBuilder {
	qt.tests[qt.countTests].Expect.JSONSchema.Byte = schema

	return qt
}

func (qt *cute) ExpectJSONSchemaFile(filePath string) ExpectHTTPBuilder {
	qt.tests[qt.countTests].Expect.JSONSchema.File = filePath

	return qt
}


================================================
FILE: builder_middleware.go
================================================
package cute

func (qt *cute) StepName(name string) MiddlewareRequest {
	qt.tests[qt.countTests].AllureStep.Name = name

	return qt
}

func (qt *cute) BeforeExecute(fs ...BeforeExecute) MiddlewareRequest {
	qt.tests[qt.countTests].Middleware.Before = append(qt.tests[qt.countTests].Middleware.Before, fs...)

	return qt
}

func (qt *cute) BeforeExecuteT(fs ...BeforeExecuteT) MiddlewareRequest {
	qt.tests[qt.countTests].Middleware.BeforeT = append(qt.tests[qt.countTests].Middleware.BeforeT, fs...)

	return qt
}

func (qt *cute) After(fs ...AfterExecute) ExpectHTTPBuilder {
	qt.tests[qt.countTests].Middleware.After = append(qt.tests[qt.countTests].Middleware.After, fs...)

	return qt
}

func (qt *cute) AfterT(fs ...AfterExecuteT) ExpectHTTPBuilder {
	qt.tests[qt.countTests].Middleware.AfterT = append(qt.tests[qt.countTests].Middleware.AfterT, fs...)

	return qt
}

func (qt *cute) AfterExecute(fs ...AfterExecute) MiddlewareRequest {
	qt.tests[qt.countTests].Middleware.After = append(qt.tests[qt.countTests].Middleware.After, fs...)

	return qt
}

func (qt *cute) AfterExecuteT(fs ...AfterExecuteT) MiddlewareRequest {
	qt.tests[qt.countTests].Middleware.AfterT = append(qt.tests[qt.countTests].Middleware.AfterT, fs...)

	return qt
}

func (qt *cute) AfterTestExecute(fs ...AfterExecute) NextTestBuilder {
	previousTest := 0
	if qt.countTests != 0 {
		previousTest = qt.countTests - 1
	}

	qt.tests[previousTest].Middleware.After = append(qt.tests[previousTest].Middleware.After, fs...)

	return qt
}

func (qt *cute) AfterTestExecuteT(fs ...AfterExecuteT) NextTestBuilder {
	previousTest := 0
	if qt.countTests != 0 {
		previousTest = qt.countTests - 1
	}

	qt.tests[previousTest].Middleware.AfterT = append(qt.tests[previousTest].Middleware.AfterT, fs...)

	return qt
}


================================================
FILE: builder_option.go
================================================
package cute

import (
	"net/http"
	"time"
)

type options struct {
	httpClient       *http.Client
	httpTimeout      time.Duration
	httpRoundTripper http.RoundTripper

	jsonMarshaler JSONMarshaler

	middleware *Middleware
}

// Option ...
type Option func(*options)

// WithHTTPClient is a function for set custom http client
func WithHTTPClient(client *http.Client) Option {
	return func(o *options) {
		o.httpClient = client
	}
}

// WithJSONMarshaler is a function for set custom json marshaler
func WithJSONMarshaler(m JSONMarshaler) Option {
	return func(o *options) {
		o.jsonMarshaler = m
	}
}

// WithCustomHTTPTimeout is a function for set custom http client timeout
func WithCustomHTTPTimeout(t time.Duration) Option {
	return func(o *options) {
		o.httpTimeout = t
	}
}

// WithCustomHTTPRoundTripper is a function for set custom http round tripper
func WithCustomHTTPRoundTripper(r http.RoundTripper) Option {
	return func(o *options) {
		o.httpRoundTripper = r
	}
}

// WithMiddlewareAfter is function for set function which will run AFTER test execution
func WithMiddlewareAfter(after ...AfterExecute) Option {
	return func(o *options) {
		o.middleware.After = append(o.middleware.After, after...)
	}
}

// WithMiddlewareAfterT is function for set function which will run AFTER test execution
func WithMiddlewareAfterT(after ...AfterExecuteT) Option {
	return func(o *options) {
		o.middleware.AfterT = append(o.middleware.AfterT, after...)
	}
}

// WithMiddlewareBefore is function for set function which will run BEFORE test execution
func WithMiddlewareBefore(before ...BeforeExecute) Option {
	return func(o *options) {
		o.middleware.Before = append(o.middleware.Before, before...)
	}
}

// WithMiddlewareBeforeT is function for set function which will run BEFORE test execution
func WithMiddlewareBeforeT(beforeT ...BeforeExecuteT) Option {
	return func(o *options) {
		o.middleware.BeforeT = append(o.middleware.BeforeT, beforeT...)
	}
}


================================================
FILE: builder_request.go
================================================
package cute

import (
	"net/http"
	"time"
)

// RequestRepeat is a function for set options in request
// if response.Code != Expect.Code, than request will repeat Count counts with Delay delay.
// Default delay is 1 second.
// Deprecated: use RequestRetry instead
func (qt *cute) RequestRepeat(count int) RequestHTTPBuilder {
	qt.tests[qt.countTests].Request.Retry.Count = count

	return qt
}

// RequestRepeatDelay set delay for request repeat.
// if response.Code != Expect.Code, than request will repeat Count counts with Delay delay.
// Default delay is 1 second.
// Deprecated: use RequestRetryDelay instead
func (qt *cute) RequestRepeatDelay(delay time.Duration) RequestHTTPBuilder {
	qt.tests[qt.countTests].Request.Retry.Delay = delay

	return qt
}

// RequestRepeatPolitic set politic for request repeat.
// if response.Code != Expect.Code, than request will repeat Count counts with Delay delay.
// if Optional is true and request is failed, than test step allure will be skipped, and t.Fail() will not execute.
// If Broken is true and request is failed, than test step allure will be broken, and t.Fail() will not execute.
// Deprecated: use RequestRetryPolitic instead
func (qt *cute) RequestRepeatPolitic(politic *RequestRepeatPolitic) RequestHTTPBuilder {
	if politic == nil {
		panic("politic is nil in RequestRetryPolitic")
	}

	qt.tests[qt.countTests].Request.Retry = &RequestRetryPolitic{
		Count:    politic.Count,
		Delay:    politic.Delay,
		Optional: politic.Optional,
		Broken:   politic.Broken,
	}

	return qt
}

// RequestRepeatOptional set option politic for request repeat.
// if Optional is true and request is failed, than test step allure will be skipped, and t.Fail() will not execute.
// Deprecated: use RequestRetryOptional instead
func (qt *cute) RequestRepeatOptional(option bool) RequestHTTPBuilder {
	qt.tests[qt.countTests].Request.Retry.Optional = option

	return qt
}

// RequestRepeatBroken set broken politic for request repeat.
// If Broken is true and request is failed, than test step allure will be broken, and t.Fail() will not execute.
// Deprecated: use RequestRetryBroken instead
func (qt *cute) RequestRepeatBroken(broken bool) RequestHTTPBuilder {
	qt.tests[qt.countTests].Request.Retry.Broken = broken

	return qt
}

// RequestRetry is a function for set options in request
// if response.Code != Expect.Code, than request will repeat Count counts with Delay delay.
// Default delay is 1 second.
func (qt *cute) RequestRetry(count int) RequestHTTPBuilder {
	qt.tests[qt.countTests].Request.Retry.Count = count

	return qt
}

// RequestRetryDelay set delay for request repeat.
// if response.Code != Expect.Code, than request will repeat Count counts with Delay delay.
// Default delay is 1 second.
func (qt *cute) RequestRetryDelay(delay time.Duration) RequestHTTPBuilder {
	qt.tests[qt.countTests].Request.Retry.Delay = delay

	return qt
}

// RequestRetryPolitic set politic for request repeat.
// if response.Code != Expect.Code, than request will repeat Count counts with Delay delay.
// if Optional is true and request is failed, than test step allure will be skipped, and t.Fail() will not execute.
// If Broken is true and request is failed, than test step allure will be broken, and t.Fail() will not execute.
func (qt *cute) RequestRetryPolitic(politic *RequestRetryPolitic) RequestHTTPBuilder {
	if politic == nil {
		panic("politic is nil in RequestRetryPolitic")
	}

	qt.tests[qt.countTests].Request.Retry = politic

	return qt
}

// RequestRetryOptional set option politic for request repeat.
// if Optional is true and request is failed, than test step allure will be skipped, and t.Fail() will not execute.
func (qt *cute) RequestRetryOptional(option bool) RequestHTTPBuilder {
	qt.tests[qt.countTests].Request.Retry.Optional = option

	return qt
}

// RequestRetryBroken set broken politic for request repeat.
// If Broken is true and request is failed, than test step allure will be broken, and t.Fail() will not execute.
func (qt *cute) RequestRetryBroken(broken bool) RequestHTTPBuilder {
	qt.tests[qt.countTests].Request.Retry.Broken = broken

	return qt
}

// RequestSanitizerHook assigns the provided RequestSanitizerHook to the test,
// allowing URL sanitization before logging or reporting.
func (qt *cute) RequestSanitizerHook(hook RequestSanitizerHook) RequestHTTPBuilder {
	qt.tests[qt.countTests].RequestSanitizer = hook

	return qt
}

// ResponseSanitizerHook assigns the provided ResponseSanitizerHook to the test,
// allowing URL sanitization before logging or reporting.
func (qt *cute) ResponseSanitizerHook(hook ResponseSanitizerHook) RequestHTTPBuilder {
	qt.tests[qt.countTests].ResponseSanitizer = hook

	return qt
}

func (qt *cute) Request(r *http.Request) ExpectHTTPBuilder {
	qt.tests[qt.countTests].Request.Base = r

	return qt
}

func (qt *cute) RequestBuilder(r ...RequestBuilder) ExpectHTTPBuilder {
	qt.tests[qt.countTests].Request.Builders = append(qt.tests[qt.countTests].Request.Builders, r...)

	return qt
}


================================================
FILE: builder_retry.go
================================================
package cute

import "time"

// Retry is a function for configure test repeat
// if response.Code != Expect.Code or any of asserts are failed/broken than test will repeat counts with delay.
// Default delay is 1 second.
func (qt *cute) Retry(count int) MiddlewareRequest {
	if count < 1 {
		panic("count must be greater than 0")
	}

	qt.tests[qt.countTests].Retry.MaxAttempts = count

	return qt
}

// RetryDelay set delay for test repeat.
// if response.Code != Expect.Code or any of asserts are failed/broken than test will repeat counts with delay.
// Default delay is 1 second.
func (qt *cute) RetryDelay(delay time.Duration) MiddlewareRequest {
	if delay < 0 {
		panic("delay must be greater than or equal to 0")
	}

	qt.tests[qt.countTests].Retry.Delay = delay

	return qt
}


================================================
FILE: builder_table.go
================================================
package cute

import "net/http"

func (qt *cute) CreateTableTest() MiddlewareTable {
	qt.isTableTest = true

	return qt
}

func (qt *cute) PutNewTest(name string, r *http.Request, expect *Expect) TableTest {
	// Validate, that first step is empty
	if qt.countTests == 0 {
		if qt.tests[0].Request.Base == nil &&
			len(qt.tests[0].Request.Builders) == 0 {
			qt.tests[0].Expect = expect
			qt.tests[0].Name = name
			qt.tests[0].Request.Base = r

			return qt
		}
	}

	newTest := createDefaultTest(qt.baseProps)
	newTest.Expect = expect
	newTest.Name = name
	newTest.Request.Base = r
	qt.tests = append(qt.tests, newTest)
	qt.countTests++ // async?

	return qt
}

func (qt *cute) PutTests(tests ...*Test) TableTest {
	for _, test := range tests {
		// Fill common fields
		qt.fillBaseProps(test)

		// Validate, that first step is empty
		if qt.countTests == 0 {
			if qt.tests[0].Request.Base == nil &&
				len(qt.tests[0].Request.Builders) == 0 {
				qt.tests[0] = test

				continue
			}
		}

		qt.tests = append(qt.tests, test)
		qt.countTests++
	}

	return qt
}

func (qt *cute) fillBaseProps(t *Test) {
	if qt.baseProps == nil {
		return
	}

	if qt.baseProps.httpClient != nil {
		t.httpClient = qt.baseProps.httpClient
	}

	if qt.baseProps.jsonMarshaler != nil {
		t.jsonMarshaler = qt.baseProps.jsonMarshaler
	}

	if t.Middleware == nil {
		t.Middleware = createMiddlewareFromTemplate(qt.baseProps.middleware)
	} else {
		t.Middleware.After = append(t.Middleware.After, qt.baseProps.middleware.After...)
		t.Middleware.AfterT = append(t.Middleware.AfterT, qt.baseProps.middleware.AfterT...)
		t.Middleware.Before = append(t.Middleware.Before, qt.baseProps.middleware.Before...)
		t.Middleware.BeforeT = append(t.Middleware.BeforeT, qt.baseProps.middleware.BeforeT...)
	}
}

func (qt *cute) NextTest() NextTestBuilder {
	qt.countTests++ // async?

	qt.tests = append(qt.tests, createDefaultTest(qt.baseProps))

	return qt
}


================================================
FILE: builder_table_test.go
================================================
package cute

import (
	"net/http"
	"testing"

	"github.com/stretchr/testify/require"
)

func TestFillBaseProps_WhenBasePropsIsNil(t *testing.T) {
	testObj := &Test{}
	cuteObj := &cute{}

	cuteObj.fillBaseProps(testObj)

	require.Nil(t, testObj.httpClient)
	require.Nil(t, testObj.jsonMarshaler)
	require.Nil(t, testObj.Middleware)
}

func TestFillBaseProps_WhenBasePropsIsNotNil(t *testing.T) {
	testObj := &Test{}
	cuteObj := &cute{}

	qtBaseProps := &HTTPTestMaker{
		httpClient:    &http.Client{},
		jsonMarshaler: &jsonMarshaler{},
		middleware: &Middleware{
			After: []AfterExecute{
				func(*http.Response, []error) error {
					return nil
				},
				func(*http.Response, []error) error {
					return nil
				},
			},
			AfterT: []AfterExecuteT{func(T, *http.Response, []error) error { return nil }},
			Before: []BeforeExecute{
				func(*http.Request) error {
					return nil
				},
				func(*http.Request) error {
					return nil
				},
			},
			BeforeT: []BeforeExecuteT{
				func(T, *http.Request) error { return nil },
				func(T, *http.Request) error {
					return nil
				},
			},
		},
	}
	cuteObj.baseProps = qtBaseProps

	cuteObj.fillBaseProps(testObj)

	require.Equal(t, qtBaseProps.httpClient, testObj.httpClient)
	require.Equal(t, qtBaseProps.jsonMarshaler, testObj.jsonMarshaler)
	require.Len(t, testObj.Middleware.After, len(qtBaseProps.middleware.After))
	require.Len(t, testObj.Middleware.AfterT, len(qtBaseProps.middleware.AfterT))
	require.Len(t, testObj.Middleware.Before, len(qtBaseProps.middleware.Before))
	require.Len(t, testObj.Middleware.BeforeT, len(qtBaseProps.middleware.BeforeT))
}

func TestFillBaseProps_WhenBasePropsIsNotNil_After(t *testing.T) {
	testObj := &Test{
		Middleware: &Middleware{
			After: []AfterExecute{
				func(*http.Response, []error) error {
					return nil
				},
			},
		},
	}
	cuteObj := &cute{}

	qtBaseProps := &HTTPTestMaker{
		httpClient:    &http.Client{},
		jsonMarshaler: &jsonMarshaler{},
		middleware: &Middleware{
			After: []AfterExecute{
				func(*http.Response, []error) error {
					return nil
				},
				func(*http.Response, []error) error {
					return nil
				},
			},
			BeforeT: []BeforeExecuteT{
				func(T, *http.Request) error { return nil },
				func(T, *http.Request) error {
					return nil
				},
			},
		},
	}
	cuteObj.baseProps = qtBaseProps

	cuteObj.fillBaseProps(testObj)

	require.Equal(t, qtBaseProps.httpClient, testObj.httpClient)
	require.Equal(t, qtBaseProps.jsonMarshaler, testObj.jsonMarshaler)
	require.Len(t, testObj.Middleware.After, len(qtBaseProps.middleware.After)+1)
	require.Len(t, testObj.Middleware.AfterT, len(qtBaseProps.middleware.AfterT))
	require.Len(t, testObj.Middleware.Before, len(qtBaseProps.middleware.Before))
	require.Len(t, testObj.Middleware.BeforeT, len(qtBaseProps.middleware.BeforeT))
}

func TestFillBaseProps_WhenBasePropsIsNotNil_Middleware(t *testing.T) {
	testObj := &Test{
		Middleware: &Middleware{
			After: []AfterExecute{
				func(*http.Response, []error) error {
					return nil
				},
				func(*http.Response, []error) error {
					return nil
				},
			},
			AfterT: []AfterExecuteT{
				func(T, *http.Response, []error) error {
					return nil
				},
				func(T, *http.Response, []error) error {
					return nil
				},
				func(T, *http.Response, []error) error {
					return nil
				},
			},
			Before: []BeforeExecute{
				func(*http.Request) error {
					return nil
				},
				func(*http.Request) error {
					return nil
				},
				func(*http.Request) error {
					return nil
				},
				func(*http.Request) error {
					return nil
				},
			},
			BeforeT: []BeforeExecuteT{
				func(T, *http.Request) error {
					return nil
				},
			},
		},
	}
	cuteObj := &cute{}

	qtBaseProps := &HTTPTestMaker{
		httpClient:    &http.Client{},
		jsonMarshaler: &jsonMarshaler{},
		middleware: &Middleware{
			After: []AfterExecute{
				func(*http.Response, []error) error {
					return nil
				},
				func(*http.Response, []error) error {
					return nil
				},
			},
			AfterT: []AfterExecuteT{func(T, *http.Response, []error) error { return nil }},
			Before: []BeforeExecute{
				func(*http.Request) error {
					return nil
				},
				func(*http.Request) error {
					return nil
				},
			},
			BeforeT: []BeforeExecuteT{
				func(T, *http.Request) error { return nil },
				func(T, *http.Request) error {
					return nil
				},
			},
		},
	}
	cuteObj.baseProps = qtBaseProps

	cuteObj.fillBaseProps(testObj)

	require.Equal(t, qtBaseProps.httpClient, testObj.httpClient)
	require.Equal(t, qtBaseProps.jsonMarshaler, testObj.jsonMarshaler)
	require.Len(t, testObj.Middleware.After, len(qtBaseProps.middleware.After)+2)
	require.Len(t, testObj.Middleware.AfterT, len(qtBaseProps.middleware.AfterT)+3)
	require.Len(t, testObj.Middleware.Before, len(qtBaseProps.middleware.Before)+4)
	require.Len(t, testObj.Middleware.BeforeT, len(qtBaseProps.middleware.BeforeT)+1)
}


================================================
FILE: builder_test.go
================================================
package cute

import (
	"net/http"
	"testing"
	"time"

	"github.com/ozontech/allure-go/pkg/allure"
	"github.com/stretchr/testify/require"
)

func TestBuilderAfterTest(t *testing.T) {
	var (
		maker = NewHTTPTestMaker()
	)

	ht := maker.NewTestBuilder().
		Create().
		RequestBuilder().
		NextTest().
		AfterTestExecute(
			func(response *http.Response, errors []error) error {
				return nil
			},
			func(response *http.Response, errors []error) error {
				return nil
			}).
		AfterTestExecuteT(
			func(t T, response *http.Response, errors []error) error {

				return nil
			},
			func(t T, response *http.Response, errors []error) error {

				return nil
			},
			func(t T, response *http.Response, errors []error) error {

				return nil
			},
		)

	res := ht.(*cute)
	require.Len(t, res.tests[0].Middleware.After, 2)
	require.Len(t, res.tests[0].Middleware.AfterT, 3)
}

func TestBuilderAfterTestTwoStep(t *testing.T) {
	var (
		maker = NewHTTPTestMaker(
			WithMiddlewareBefore(
				func(request *http.Request) error {
					return nil
				},
				func(request *http.Request) error {
					return nil
				},
			),
			WithMiddlewareBeforeT(
				func(t T, request *http.Request) error {
					return nil
				},
			),
			WithMiddlewareAfter(
				func(response *http.Response, errors []error) error {
					return nil
				},
			),
			WithMiddlewareAfterT(
				func(t T, response *http.Response, errors []error) error {
					return nil
				},
				func(t T, response *http.Response, errors []error) error {
					return nil
				},
				func(t T, response *http.Response, errors []error) error {
					return nil
				},
			),
		)
	)

	ht :=
		maker.NewTestBuilder().
			Create().
			RequestBuilder().
			NextTest().
			AfterTestExecute(
				func(response *http.Response, errors []error) error {
					return nil
				},
				func(response *http.Response, errors []error) error {
					return nil
				}).
			AfterTestExecuteT(
				func(t T, response *http.Response, errors []error) error {

					return nil
				},
				func(t T, response *http.Response, errors []error) error {

					return nil
				},
				func(t T, response *http.Response, errors []error) error {

					return nil
				},
			).
			Create().
			AfterExecute(
				func(response *http.Response, errors []error) error {

					return nil
				},
			).
			AfterExecuteT(
				func(t T, response *http.Response, errors []error) error {

					return nil
				}).
			RequestBuilder().
			NextTest().
			AfterTestExecute(
				func(response *http.Response, errors []error) error {

					return nil
				},
			)

	res := ht.(*cute)
	require.Len(t, res.tests[0].Middleware.After, 2+1)
	require.Len(t, res.tests[0].Middleware.Before, 2)
	require.Len(t, res.tests[0].Middleware.BeforeT, 1)
	require.Len(t, res.tests[0].Middleware.AfterT, 3+3)

	require.Len(t, res.tests[1].Middleware.After, 2+1)
	require.Len(t, res.tests[1].Middleware.AfterT, 1+3)
	require.Len(t, res.tests[1].Middleware.Before, 2)
	require.Len(t, res.tests[1].Middleware.BeforeT, 1)
}

func TestNewTestBuilder(t *testing.T) {
	var (
		maker = NewHTTPTestMaker()
		ht    = maker.NewTestBuilder().(*cute)
	)

	require.NotNil(t, ht.tests)
	require.Len(t, ht.tests, 1)
	require.NotNil(t, ht.tests[0].Request)
	require.NotNil(t, ht.tests[0].Middleware)
	require.NotNil(t, ht.tests[0].AllureStep)
	require.NotNil(t, ht.allureInfo)
	require.NotNil(t, ht.baseProps.httpClient)
}

func TestHTTPTestMaker(t *testing.T) {
	var (
		maker          = NewHTTPTestMaker()
		ht             = maker.NewTestBuilder()
		title          = "title"
		epic           = "epic"
		desc           = "desc"
		feature        = "feature"
		tags           = []string{"tag_1", "tag_2"}
		stepName       = "stepname"
		req, _         = http.NewRequest(http.MethodGet, "https://site.go", nil)
		executeTime    = time.Duration(10)
		status         = 400
		schemaStg      = "some_json_schema"
		schemaBt       = []byte("some_json_schema")
		schemaFile     = "file_path"
		id             = "ID"
		addSuiteLabel  = "AddSuiteLabel"
		addSubSuite    = "AddSubSuite"
		addParentSuite = "AddParentSuite"
		story          = "Story"
		tag            = "Tag"
		allureID       = "AllureID"
		owner          = "Owner"
		lead           = "Lead"
		label          = &allure.Label{Name: "kek", Value: "lol"}
		setIssue       = "SetIssue"
		setTestCase    = "SetTestCase"
		repeatCount    = 10
		repeatDelay    = time.Duration(10)
		link           = &allure.Link{
			Name: "link",
			Type: "type",
			URL:  "http://go.go",
		}
		labels = []*allure.Label{
			{
				Name:  "label_1",
				Value: "value_1",
			},
			{
				Name:  "label_2",
				Value: "value_2",
			},
		}

		assertHeaders = []AssertHeaders{
			func(headers http.Header) error {
				return nil
			},
		}
		assertHeadersT = []AssertHeadersT{
			func(t T, headers http.Header) error {
				return nil
			},
			func(t T, headers http.Header) error {
				return nil
			},
		}

		assertBody = []AssertBody{
			func(body []byte) error {
				return nil
			},
		}
		assertBodyT = []AssertBodyT{
			func(t T, body []byte) error {
				return nil
			},
			func(t T, body []byte) error {
				return nil
			},
		}

		assertResponse = []AssertResponse{
			func(resp *http.Response) error {
				return nil
			},
		}
		assertResponseT = []AssertResponseT{
			func(t T, resp *http.Response) error {
				return nil
			},
			func(t T, resp *http.Response) error {
				return nil
			},
		}
		after = []AfterExecute{
			func(response *http.Response, errors []error) error {

				return nil
			},
			func(response *http.Response, errors []error) error {

				return nil
			},
		}
		afterT = []AfterExecuteT{
			func(t T, response *http.Response, errors []error) error {

				return nil
			},
			func(t T, response *http.Response, errors []error) error {

				return nil
			},
		}
	)

	ht.
		Title(title).
		Tags(tags...).
		Epic(epic).
		Feature(feature).
		ID(id).
		AddSuiteLabel(addSuiteLabel).
		AddSubSuite(addSubSuite).
		AddParentSuite(addParentSuite).
		Story(story).
		Tag(tag).
		Severity(allure.CRITICAL).
		AllureID(allureID).
		Owner(owner).
		Lead(lead).
		Label(label).
		Labels(labels...).
		SetIssue(setIssue).
		SetTestCase(setTestCase).
		Link(link).
		Description(desc).
		CreateStep(stepName).
		RequestRetry(repeatCount).
		RequestRetryDelay(repeatDelay).
		Request(req).
		ExpectExecuteTimeout(executeTime).
		ExpectStatus(status).
		ExpectJSONSchemaByte(schemaBt).
		ExpectJSONSchemaString(schemaStg).
		ExpectJSONSchemaFile(schemaFile).
		AssertHeaders(assertHeaders...).
		AssertHeadersT(assertHeadersT...).
		AssertBody(assertBody...).
		AssertBodyT(assertBodyT...).
		AssertResponse(assertResponse...).
		AssertResponseT(assertResponseT...).
		After(after...).
		AfterT(afterT...)

	resHt := ht.(*cute)
	resTest := resHt.tests[0]

	require.Equal(t, title, resHt.allureInfo.title)
	require.Equal(t, tags, resHt.allureLabels.tags)
	require.Equal(t, desc, resHt.allureInfo.description)
	require.Equal(t, feature, resHt.allureLabels.feature)
	require.Equal(t, epic, resHt.allureLabels.epic)
	require.Equal(t, stepName, resTest.AllureStep.Name)
	require.Equal(t, req, resTest.Request.Base)
	require.Equal(t, executeTime, resTest.Expect.ExecuteTime)
	require.Equal(t, status, resTest.Expect.Code)
	require.Equal(t, schemaBt, resTest.Expect.JSONSchema.Byte)
	require.Equal(t, schemaStg, resTest.Expect.JSONSchema.String)
	require.Equal(t, schemaFile, resTest.Expect.JSONSchema.File)
	require.Equal(t, id, resHt.allureLabels.id)
	require.Equal(t, addSuiteLabel, resHt.allureLabels.suiteLabel)
	require.Equal(t, addSubSuite, resHt.allureLabels.subSuite)
	require.Equal(t, addParentSuite, resHt.allureLabels.parentSuite)
	require.Equal(t, story, resHt.allureLabels.story)
	require.Equal(t, tag, resHt.allureLabels.tag)
	require.Equal(t, owner, resHt.allureLabels.owner)
	require.Equal(t, lead, resHt.allureLabels.lead)
	require.Equal(t, label, resHt.allureLabels.label)
	require.Equal(t, allureID, resHt.allureLabels.allureID)
	require.Equal(t, setIssue, resHt.allureLinks.issue)
	require.Equal(t, setTestCase, resHt.allureLinks.testCase)
	require.Equal(t, link, resHt.allureLinks.link)
	require.Equal(t, repeatCount, resTest.Request.Retry.Count)
	require.Equal(t, repeatDelay, resTest.Request.Retry.Delay)

	require.Equal(t, len(assertHeaders), len(resTest.Expect.AssertHeaders))
	require.Equal(t, len(assertHeadersT), len(resTest.Expect.AssertHeadersT))

	require.Equal(t, len(assertBody), len(resTest.Expect.AssertBody))
	require.Equal(t, len(assertBodyT), len(resTest.Expect.AssertBodyT))

	require.Equal(t, len(assertResponse), len(resTest.Expect.AssertResponse))
	require.Equal(t, len(assertResponseT), len(resTest.Expect.AssertResponseT))

	require.Equal(t, len(after), len(resTest.Middleware.After))
	require.Equal(t, len(afterT), len(resTest.Middleware.AfterT))
}

func TestCreateDefaultTest(t *testing.T) {
	resTest := createDefaultTest(&HTTPTestMaker{httpClient: http.DefaultClient, middleware: new(Middleware)})

	require.Equal(t, &Test{
		httpClient: http.DefaultClient,
		Name:       "",
		AllureStep: new(AllureStep),
		Middleware: &Middleware{
			After:   make([]AfterExecute, 0),
			AfterT:  make([]AfterExecuteT, 0),
			Before:  make([]BeforeExecute, 0),
			BeforeT: make([]BeforeExecuteT, 0),
		},
		Request: &Request{
			Retry: new(RequestRetryPolitic),
		},
		Expect: &Expect{
			JSONSchema: new(ExpectJSONSchema),
		},
	}, resTest)
}

func TestCreateTableTest(t *testing.T) {
	c := &cute{}
	c.CreateTableTest()

	require.True(t, c.isTableTest)
}

func TestPutNewTest(t *testing.T) {
	tests := make([]*Test, 1)
	tests[0] = createDefaultTest(&HTTPTestMaker{httpClient: http.DefaultClient, middleware: new(Middleware)})

	var (
		c = &cute{tests: tests, baseProps: &HTTPTestMaker{
			middleware: &Middleware{},
		}}
		reqOne, _    = http.NewRequest("GET", "URL_1", nil)
		expectOne    = &Expect{Code: 200}
		reqSecond, _ = http.NewRequest("POST", "URL_1", nil)
		expectSecond = &Expect{Code: 400}
	)

	c.PutNewTest("name_1", reqOne, expectOne)
	c.PutNewTest("name_2", reqSecond, expectSecond)

	require.Equal(t, c.tests[0].Name, "name_1")
	require.Equal(t, c.tests[0].Expect, expectOne)
	require.Equal(t, c.tests[0].Request.Base, reqOne)

	require.Equal(t, c.tests[1].Name, "name_2")
	require.Equal(t, c.tests[1].Expect, expectSecond)
	require.Equal(t, c.tests[1].Request.Base, reqSecond)
}

func TestPutTests(t *testing.T) {
	var (
		tests        = createDefaultTests(&HTTPTestMaker{httpClient: http.DefaultClient, middleware: new(Middleware)})
		c            = &cute{tests: tests}
		reqOne, _    = http.NewRequest("GET", "URL_1", nil)
		expectOne    = &Expect{Code: 200}
		reqSecond, _ = http.NewRequest("POST", "URL_1", nil)
		expectSecond = &Expect{Code: 400}
	)

	tests = append(tests,
		&Test{
			Name: "name_1",
			Request: &Request{
				Base: reqOne,
			},
			Expect: expectOne,
		},
		&Test{
			Name: "name_2",
			Request: &Request{
				Base: reqSecond,
			},
			Expect: expectSecond,
		},
	)

	c.PutTests(tests...)

	require.Equal(t, c.tests[0].Name, "name_1")
	require.Equal(t, c.tests[0].Expect, expectOne)
	require.Equal(t, c.tests[0].Request.Base, reqOne)

	require.Equal(t, c.tests[1].Name, "name_2")
	require.Equal(t, c.tests[1].Expect, expectSecond)
	require.Equal(t, c.tests[1].Request.Base, reqSecond)
}

func TestCreateHTTPTestMakerWithHttpClient(t *testing.T) {
	cli := &http.Client{
		Transport:     nil,
		CheckRedirect: nil,
		Jar:           nil,
		Timeout:       100,
	}

	maker := NewHTTPTestMaker(WithHTTPClient(cli))

	require.Equal(t, cli, maker.httpClient)
	require.Equal(t, time.Duration(100), maker.httpClient.Timeout)
}

type rt struct {
}

func (r *rt) RoundTrip(*http.Request) (*http.Response, error) {
	return nil, nil
}

func TestCreateHTTPMakerOps(t *testing.T) {
	timeout := time.Second * 100
	roundTripper := &rt{}

	maker := NewHTTPTestMaker(
		WithCustomHTTPTimeout(timeout),
		WithCustomHTTPRoundTripper(roundTripper),
	)

	require.Equal(t, timeout, maker.httpClient.Timeout)
	require.Equal(t, roundTripper, maker.httpClient.Transport)
}


================================================
FILE: cute.go
================================================
package cute

import (
	"context"
	"strings"
	"testing"

	"github.com/ozontech/allure-go/pkg/allure"
	"github.com/ozontech/allure-go/pkg/framework/core/allure_manager/manager"
	"github.com/ozontech/allure-go/pkg/framework/core/common"
	"github.com/ozontech/allure-go/pkg/framework/provider"
)

type cute struct {
	baseProps *HTTPTestMaker

	parallel bool

	allureInfo   *allureInformation
	allureLinks  *allureLinks
	allureLabels *allureLabels

	countTests int // Общее количество тестов.

	isTableTest bool
	tests       []*Test
}

type allureInformation struct {
	title       string
	description string
	stage       string
}

type allureLabels struct {
	id          string
	feature     string
	epic        string
	tag         string
	tags        []string
	suiteLabel  string
	subSuite    string
	parentSuite string
	story       string
	severity    allure.SeverityType
	owner       string
	lead        string
	label       *allure.Label
	labels      []*allure.Label
	allureID    string
	layer       string
}

type allureLinks struct {
	issue    string
	testCase string
	link     *allure.Link
	tmsLink  string
	tmsLinks []string
}

func (qt *cute) ExecuteTest(ctx context.Context, t tProvider) []ResultsHTTPBuilder {
	var internalT allureProvider

	if t == nil {
		panic("could not start test without testing.T")
	}

	stepCtx, isStepCtx := t.(provider.StepCtx)
	if isStepCtx {
		return qt.executeTestsInsideStep(ctx, stepCtx)
	}

	tOriginal, ok := t.(*testing.T)
	if ok {
		newT := createAllureT(tOriginal)
		if !qt.isTableTest {
			defer newT.FinishTest() //nolint
		}

		internalT = newT
	}

	allureT, ok := t.(provider.T)
	if ok {
		internalT = allureT
	}

	if qt.parallel {
		internalT.Parallel()
	}

	return qt.executeTests(ctx, internalT)
}

func createAllureT(t *testing.T) *common.Common {
	var (
		newT        = common.NewT(t)
		callers     = strings.Split(t.Name(), "/")
		providerCfg = manager.NewProviderConfig().
				WithFullName(t.Name()).
				WithPackageName("package").
				WithSuiteName(t.Name()).
				WithRunner(callers[0])
		newProvider = manager.NewProvider(providerCfg)
	)

	newProvider.NewTest(t.Name(), "package")

	newT.SetProvider(newProvider)
	newT.Provider.TestContext()

	return newT
}

// executeTests is method for run tests
// It's could be table tests or usual tests
func (qt *cute) executeTests(ctx context.Context, allureProvider allureProvider) []ResultsHTTPBuilder {
	var (
		res = make([]ResultsHTTPBuilder, 0)
	)

	// Cycle for change number of Test
	for i := 0; i <= qt.countTests; i++ {
		currentTest := qt.tests[i]

		// Execute by new T for table tests
		if qt.isTableTest {
			tableTestName := currentTest.Name

			allureProvider.Run(tableTestName, func(inT provider.T) {
				// Set current test name
				inT.Title(tableTestName)

				res = append(res, qt.executeInsideAllure(ctx, inT, currentTest))
			})
		} else {
			currentTest.Name = allureProvider.Name()

			// set labels
			qt.setAllureInformation(allureProvider)

			res = append(res, qt.executeInsideAllure(ctx, allureProvider, currentTest))
		}
	}

	return res
}

// executeInsideAllure is method for run test inside allure
// It's could be table tests or usual tests
func (qt *cute) executeInsideAllure(ctx context.Context, allureProvider allureProvider, currentTest *Test) ResultsHTTPBuilder {
	resT := currentTest.executeInsideAllure(ctx, allureProvider)

	// Remove from base struct all asserts
	currentTest.clearFields()

	return resT
}

// executeTestsInsideStep is method for run group of tests inside provider.StepCtx
func (qt *cute) executeTestsInsideStep(ctx context.Context, stepCtx provider.StepCtx) []ResultsHTTPBuilder {
	var (
		res = make([]ResultsHTTPBuilder, 0)
	)

	// Cycle for change number of Test
	for i := 0; i <= qt.countTests; i++ {
		currentTest := qt.tests[i]

		result := currentTest.executeInsideStep(ctx, stepCtx)

		// Remove from base struct all asserts
		currentTest.clearFields()

		res = append(res, result)
	}

	return res
}


================================================
FILE: errors/broken.go
================================================
package errors

// BrokenError is an interface for set errors like Broken errors.
// If the function returns an error, which implements this interface, the allure step will has a broken status
type BrokenError interface {
	IsBroken() bool
	SetBroken(bool)
	Error() string
}

// NewBrokenError returns error with a Broken tag for Allure
func NewBrokenError(err string) error {
	return &CuteError{
		Broken:  true,
		Message: err,
	}
}

// WrapBrokenError returns error with a Broken tag for Allure
func WrapBrokenError(err error) error {
	return &CuteError{
		Broken: true,
		Err:    err,
	}
}


================================================
FILE: errors/error.go
================================================
package errors

import "fmt"

const (
	// ActualField is a key for actual value in error fields
	ActualField = "Actual"
	// ExpectedField is a key for expected value in error fields
	ExpectedField = "Expected"
)

// AssertError is a common interface for all errors in the package
type AssertError interface {
	error
	WithNameError
	WithFields
	WithAttachments
	WithTrace
}

// WithNameError is interface for creates allure step.
// If function returns error, which implement this interface, allure step will create automatically
type WithNameError interface {
	GetName() string
	SetName(string)
}

// WithFields is interface for put parameters in allure step.
// If function returns error, which implement this interface, parameters will add to allure step
type WithFields interface {
	GetFields() map[string]interface{}
	PutFields(map[string]interface{})
}

// WithTrace is interface for put trace in logs
type WithTrace interface {
	GetTrace() string
	SetTrace(string)
}

// Attachment represents an attachment to Allure with properties like name, MIME type, and content.
type Attachment struct {
	Name     string // Name of the attachment.
	MimeType string // MIME type of the attachment.
	Content  []byte // Content of the attachment.
}

// WithAttachments is an interface that defines methods for managing attachments.
type WithAttachments interface {
	GetAttachments() []*Attachment
	PutAttachment(a *Attachment)
}

// CuteError is a struct for error with additional fields for allure and logs
type CuteError struct {
	// Optional is a flag to determine if the error is optional
	// If the error is optional, it will not fail the test
	Optional bool
	// Require is a flag to determine if the error is required
	// If the error is required, it will fail the test
	Require bool
	// Broken is a flag to determine if the error is broken
	// If the error is broken, it will fail the test and mark the test as broken in allure
	Broken bool

	// Name is a name of the error
	Name string
	// Message is a message of the error
	Message string
	// Err is a wrapped error
	Err error

	// Trace is a trace of the error
	// It could be a file path, function name, or any other information
	Trace string

	// Fields is a map of additional fields for the error
	// It could be actual and expected values, parameters, or any other information
	// ActualField and ExpectedField fields will be logged
	Fields map[string]interface{}
	// Attachments is a slice of attachments for the error
	Attachments []*Attachment
}

// NewCuteError is the function, which creates cute error with "Name" and "Message" for allure
func NewCuteError(name string, err error) *CuteError {
	return &CuteError{
		Name: name,
		Err:  err,
	}
}

// NewAssertError is the function, which creates error with "Actual" and "Expected" for allure
func NewAssertError(name string, message string, actual interface{}, expected interface{}) error {
	return &CuteError{
		Name:    name,
		Message: message,
		Fields: map[string]interface{}{
			ActualField:   actual,
			ExpectedField: expected,
		},
	}
}

// NewAssertErrorWithMessage is the function, which creates error with "Name" and "Message" for allure
// Deprecated: use NewEmptyAssertError instead
func NewAssertErrorWithMessage(name string, message string) error {
	return NewEmptyAssertError(name, message)
}

// NewEmptyAssertError is the function, which creates error with "Name" and "Message" for allure
// Returns AssertError with empty fields
// You can use PutFields and PutAttachment to add additional information
// You can use SetOptional, SetRequire, SetBroken to change error behavior
func NewEmptyAssertError(name string, message string) AssertError {
	return &CuteError{
		Name:    name,
		Message: message,
		Fields:  map[string]interface{}{},
	}
}

// Unwrap is a method to get wrapped error
// It is used for errors.Is and errors.As functions
func (a *CuteError) Unwrap() error {
	return a.Err
}

// Error is a method to get error message
// It is used for fmt.Errorf and fmt.Println functions
func (a *CuteError) Error() string {
	if a.Trace == "" {
		return a.Message
	}

	errText := a.Message

	if a.Err != nil {
		errText = a.Err.Error()
	}

	return fmt.Sprintf("%s\nCalled from: %s", errText, a.Trace)
}

// GetName is a method to get error name
// It is used for allure step name
func (a *CuteError) GetName() string {
	return a.Name
}

// SetName is a method to set error name
// It is used for allure step name
func (a *CuteError) SetName(name string) {
	a.Name = name
}

// GetFields ...
func (a *CuteError) GetFields() map[string]interface{} {
	return a.Fields
}

// PutFields ...
func (a *CuteError) PutFields(fields map[string]interface{}) {
	for k, v := range fields {
		a.Fields[k] = v
	}
}

// GetAttachments ...
func (a *CuteError) GetAttachments() []*Attachment {
	return a.Attachments
}

// PutAttachment ...
func (a *CuteError) PutAttachment(attachment *Attachment) {
	a.Attachments = append(a.Attachments, attachment)
}

// IsOptional ...
func (a *CuteError) IsOptional() bool {
	return a.Optional
}

// SetOptional ...
func (a *CuteError) SetOptional(opt bool) {
	a.Optional = opt
}

// IsRequire ...
func (a *CuteError) IsRequire() bool {
	return a.Require
}

// SetRequire ...
func (a *CuteError) SetRequire(b bool) {
	a.Require = b
}

// IsBroken ...
func (a *CuteError) IsBroken() bool {
	return a.Broken
}

// SetBroken ...
func (a *CuteError) SetBroken(b bool) {
	a.Broken = b
}

// GetTrace ...
func (a *CuteError) GetTrace() string {
	return a.Trace
}

// SetTrace ...
func (a *CuteError) SetTrace(trace string) {
	a.Trace = trace
}


================================================
FILE: errors/optional.go
================================================
package errors

// OptionalError is an interface for set errors like Optional errors.
// If the function returns an error, which implements this interface, the allure step will has to skip status
type OptionalError interface {
	IsOptional() bool
	SetOptional(bool)
}

// NewOptionalError returns error with an Optional tag for Allure
func NewOptionalError(err string) error {
	return &CuteError{
		Optional: true,
		Message:  err,
	}
}

// WrapOptionalError returns error with an Optional tag for Allure
func WrapOptionalError(err error) error {
	return &CuteError{
		Optional: true,
		Err:      err,
	}
}


================================================
FILE: errors/require.go
================================================
package errors

// RequireError is an interface for set errors like require error.
// If the function returns an error, which implements this interface, the allure step will has failed status
type RequireError interface {
	IsRequire() bool
	SetRequire(bool)
}

type requireError struct {
	err     error
	require bool
}

// NewRequireError returns error with flag for execute t.FailNow() and finish test after this error
func NewRequireError(err string) error {
	return &CuteError{
		Require: true,
		Message: err,
	}
}

// WrapRequireError returns error with flag for execute t.FailNow() and finish test after this error
func WrapRequireError(err error) error {
	return &CuteError{
		Require: true,
		Err:     err,
	}
}


================================================
FILE: errors/trace.go
================================================
package errors

// NewErrorWithTrace is a function for create error with trace
func NewErrorWithTrace(err, trace string) error {
	return &CuteError{
		Trace:   trace,
		Message: err,
	}
}

// WrapErrorWithTrace is a function for wrap error with trace
func WrapErrorWithTrace(err error, trace string) error {
	return &CuteError{
		Trace: trace,
		Err:   err,
	}
}


================================================
FILE: examples/custom_asserts.go
================================================
package examples

import (
	"errors"
	"net/http"

	"github.com/ozontech/allure-go/pkg/allure"
	"github.com/ozontech/cute"
	cuteErrors "github.com/ozontech/cute/errors"
	"github.com/stretchr/testify/require"
)

func CustomAssertBodyWithCustomError() cute.AssertBody {
	return func(bytes []byte) error {
		if len(bytes) == 0 {
			return cuteErrors.NewAssertError("customAssertBodyWithCustomError", "body must be not empty", "len is 0", "len more 0")
		}

		return nil
	}
}

func CustomAssertBody() cute.AssertBody {
	return func(bytes []byte) error {
		if len(bytes) == 0 {
			return errors.New("response body is empty")
		}

		return nil
	}
}

func CustomAssertBodyT() cute.AssertBodyT {
	return func(t cute.T, bytes []byte) error {
		t.WithNewParameters("example_parameter", "example")
		require.GreaterOrEqual(t, len(bytes), 100)
		return nil
	}
}

func CustomAssertBodyWithAllureStep() cute.AssertBodyT {
	return func(t cute.T, bytes []byte) error {

		step := allure.NewSimpleStep("Custom assert step")
		defer func() {
			t.Step(step)
		}()

		if len(bytes) == 0 {
			step.Status = allure.Failed
			step.WithAttachments(allure.NewAttachment("Error", allure.Text, []byte("response body is empty")))

			return nil
		}

		return nil
	}
}

func CustomAssertHeaders() cute.AssertHeaders {
	return func(headers http.Header) error {
		if len(headers) == 0 {
			return errors.New("response without headers")
		}

		return nil
	}
}

func CustomAssertResponse() cute.AssertResponse {
	return func(resp *http.Response) error {
		if resp.ContentLength == 0 {
			return errors.New("content length is zero")
		}

		return nil
	}
}


================================================
FILE: examples/inside_step_test.go
================================================
//go:build example
// +build example

package examples

import (
	"context"
	"net/http"
	"net/url"
	"testing"
	"time"

	"github.com/ozontech/allure-go/pkg/framework/provider"
	"github.com/ozontech/allure-go/pkg/framework/runner"

	"github.com/ozontech/cute"
)

func TestInsideStep(t *testing.T) {
	runner.Run(t, "Single test with allure-go Runner", func(t provider.T) {

		t.WithNewStep("First step", func(sCtx provider.StepCtx) {
			sCtx.NewStep("Inside first step")
		})

		t.WithNewStep("Step name", func(sCtx provider.StepCtx) {
			u, _ := url.Parse("https://jsonplaceholder.typicode.com/posts/1/comments")

			cute.NewTestBuilder().
				Title("Super simple test").
				Tags("simple", "suite", "some_local_tag", "json").
				Parallel().
				Create().
				RequestBuilder(
					cute.WithHeaders(map[string][]string{
						"some_header": []string{"something"},
					}),
					cute.WithURL(u),
					cute.WithMethod(http.MethodPost),
				).
				ExpectExecuteTimeout(10*time.Second).
				ExpectStatus(http.StatusCreated).
				ExecuteTest(context.Background(), sCtx)
		})
	})

}


================================================
FILE: examples/masked_data_test.go
================================================
//go:build example
// +build example

package examples

import (
	"context"
	"net/http"
	"net/url"
	"testing"
	"time"

	"github.com/ozontech/allure-go/pkg/framework/provider"
	"github.com/ozontech/allure-go/pkg/framework/runner"

	"github.com/ozontech/cute"
)

func TestSanitizer(t *testing.T) {
	runner.Run(t, "Single test with request and response sanitizer", func(t provider.T) {

		t.WithNewStep("First step", func(sCtx provider.StepCtx) {
			sCtx.NewStep("Inside first step")
		})

		t.WithNewStep("Step name", func(sCtx provider.StepCtx) {
			u, _ := url.Parse("https://jsonplaceholder.typicode.com/posts/1/comments?example=11")
			query := u.Query()
			query.Set("name", "Vasya")
			u.RawQuery = query.Encode()

			cute.NewTestBuilder().
				Title("Super simple test").
				Tags("simple", "suite", "some_local_tag", "json").
				Parallel().
				Create().
				RequestSanitizerHook(func(req *http.Request) {
					req.URL.Path = "/path/masked"

					values := req.URL.Query()
					values.Set("example", "masked")

					req.URL.RawQuery = values.Encode()

					req.Header["some_header"] = []string{"masked"}
				}).
				ResponseSanitizerHook(func(resp *http.Response) {
					resp.Header["some_header"] = []string{"masked"}
					resp.Header["Content-Type"] = []string{"masked"}
				}).
				RequestBuilder(
					cute.WithHeaders(map[string][]string{
						"some_header": []string{"something"},
					}),
					cute.WithURL(u),
					cute.WithMethod(http.MethodPost),
				).
				ExpectExecuteTimeout(10*time.Second).
				ExpectStatus(http.StatusCreated).
				ExecuteTest(context.Background(), sCtx)
		})
	})

}


================================================
FILE: examples/parallel_test.go
================================================
//go:build example
// +build example

package examples

import (
	"context"
	"net/http"
	"testing"
	"time"

	"github.com/ozontech/allure-go/pkg/framework/provider"
	"github.com/ozontech/cute"
)

func Test_Async_1(t *testing.T) {
	cute.NewTestBuilder().
		Title("Title async test 1").
		Tags("parallel_test").
		Parallel().
		Create().
		BeforeExecuteT(
			func(t cute.T, r *http.Request) error {
				t.WithNewStep("insideBefore", func(stepCtx provider.StepCtx) {
					time.Sleep(time.Second)
					now := time.Now()
					stepCtx.Logf("Test 1. Start time %v", now)
					stepCtx.WithNewParameters("Test 1. Time", now)
				})

				return nil
			},
		).
		AfterExecuteT(
			func(t cute.T, resp *http.Response, errs []error) error {
				t.WithNewStep("insideAfter", func(stepCtx provider.StepCtx) {
					now := time.Now()
					stepCtx.Logf("Test 1. Stop time %v", now)
					stepCtx.WithNewParameters("Test 1. Stop time", now)
				})

				return nil
			}).
		RequestBuilder(
			cute.WithURI("https://jsonplaceholder.typicode.com/posts/1/comments"),
			cute.WithMethod(http.MethodGet),
		).
		ExecuteTest(context.Background(), t)
}

func Test_Async_2(t *testing.T) {
	cute.NewTestBuilder().
		Title("Title async test 2").
		Tags("parallel_test").
		Parallel().
		Create().
		BeforeExecuteT(
			func(t cute.T, r *http.Request) error {
				t.WithNewStep("insideBefore", func(stepCtx provider.StepCtx) {
					now := time.Now()
					stepCtx.Logf("Test 2. Start time %v", now)
					stepCtx.WithNewParameters("Test 2. Start time", now)
					time.Sleep(2 * time.Second)
				})

				return nil
			},
		).
		AfterExecuteT(
			func(t cute.T, resp *http.Response, errs []error) error {
				t.WithNewStep("insideAfter", func(stepCtx provider.StepCtx) {
					now := time.Now()
					stepCtx.Logf("test 2. Stop time %v", now)
					stepCtx.WithNewParameters("Test 2. Stop time", now)
				})

				return nil
			}).
		RequestBuilder(
			cute.WithURI("https://jsonplaceholder.typicode.com/posts/1/comments"),
			cute.WithMethod(http.MethodGet),
		).
		ExpectStatus(200).
		ExecuteTest(context.Background(), t)
}


================================================
FILE: examples/single_test.go
================================================
//go:build example
// +build example

package examples

import (
	"context"
	"errors"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"path"
	"testing"
	"time"

	"github.com/ozontech/allure-go/pkg/allure"
	"github.com/ozontech/allure-go/pkg/framework/provider"
	"github.com/ozontech/allure-go/pkg/framework/runner"
	cuteErrors "github.com/ozontech/cute/errors"

	"github.com/ozontech/cute"
	"github.com/ozontech/cute/asserts/json"
)

func Test_Single_1(t *testing.T) {
	cute.NewTestBuilder().
		Title("Single test with default T").
		Tag("single_test").
		Description("some_description").
		Parallel().
		Create().
		RequestRetry(3).
		RequestBuilder(
			cute.WithURI("https://jsonplaceholder.typicode.com/posts/1/comments"),
			cute.WithMarshalBody(struct {
				Name string `json:"name"`
			}{
				Name: "Vasya Pupkin",
			}),
			cute.WithQueryKV("socks", "42"),
			cute.WithMethod(http.MethodGet),
		).
		ExpectExecuteTimeout(10*time.Second).
		ExpectStatus(http.StatusOK).
		AssertBody(json.Diff("{\"aaa\":\"bb\"}")).
		AssertBody(
			json.Present("$[1].name"),
			json.Present("$[0].passport"), // Example fail
			json.Equal("$[0].email", "Eliseo@gardner.biz"),
			CustomAssertBody(),
		).
		AssertBodyT(func(t cute.T, body []byte) error {
			t.Step(allure.NewSimpleStep("inside Assert body. 1 ", allure.NewParameters("key", "value")...))

			return nil
		}).
		After(
			func(response *http.Response, errors []error) error {
				b, err := io.ReadAll(response.Body)
				if err != nil {
					return err
				}

				email, err := json.GetValueFromJSON(b, "$[0].email")
				if err != nil {
					return err
				}

				fmt.Println("Email from test", email)

				return nil
			},
		).
		ExecuteTest(context.Background(), t)
}

func Test_Single_Broken(t *testing.T) {
	cute.NewTestBuilder().
		Title("Test_Single_Broken").
		Create().
		RequestBuilder(
			cute.WithURI("https://jsonplaceholder.typicode.com/posts/1/comments"),
		).
		BrokenAssertBodyT(func(t cute.T, body []byte) error {
			return errors.New("example broken error")
		}).
		ExpectStatus(http.StatusOK).
		NextTest().
		Create().
		RequestBuilder(
			cute.WithURI("https://jsonplaceholder.typicode.com/posts/1/comments"),
		).
		AssertBody(func(body []byte) error {
			return errors.New("it's NOT must be run")
		},
		).
		ExecuteTest(context.Background(), t)

	t.Skip()
}

func Test_Single_RepeatPolitic_Optional_Success_Test(t *testing.T) {
	cute.NewTestBuilder().
		Title("Test_Single_RepeatPolitic_Optional_Success_Test").
		Create().
		RequestRetry(2).
		RequestRetryOptional(true).
		RequestBuilder(
			cute.WithURI("https://jsonplaceholder.typicode.com/posts/1/comments"),
		).
		BrokenAssertBodyT(func(t cute.T, body []byte) error {
			return errors.New("example broken error")
		}).
		ExpectStatus(http.StatusCreated).
		ExecuteTest(context.Background(), t)

	t.Logf("You should see it")
}

func Test_Single_RepeatPolitic_Broken_Failed_Test(t *testing.T) {
	cute.NewTestBuilder().
		Title("Test_Single_RepeatPolitic_Broken_Failed_Test").
		Create().
		RequestRetry(2).
		RequestRetryOptional(false).
		RequestBuilder(
			cute.WithURI("https://jsonplaceholder.typicode.com/posts/1/comments"),
		).
		BrokenAssertBodyT(func(t cute.T, body []byte) error {
			return errors.New("example broken error")
		}).
		ExpectStatus(http.StatusCreated).
		ExecuteTest(context.Background(), t)

	t.Logf("You should see it")
}

func Test_Single_Broken_2(t *testing.T) {
	cute.NewTestBuilder().
		Title("Test_Single_Broken_2").
		Create().
		RequestBuilder(
			cute.WithURI("https://jsonplaceholder.typicode.com/posts/1/comments"),
		).
		AssertBodyT(func(t cute.T, body []byte) error {
			err := errors.New("example broken error")
			return cuteErrors.WrapBrokenError(err)
		}).
		ExpectStatus(http.StatusOK).
		NextTest().
		Create().
		RequestBuilder(
			cute.WithURI("https://jsonplaceholder.typicode.com/posts/1/comments"),
		).
		AssertBody(func(body []byte) error {
			return errors.New("it's NOT must be run")
		},
		).
		ExecuteTest(context.Background(), t)
}

func Test_Single_2_AllureRunner(t *testing.T) {
	runner.Run(t, "Single test with allure-go Runner", func(t provider.T) {
		var (
			testMaker   = cute.NewHTTPTestMaker()
			testBuilder = testMaker.NewTestBuilder()
		)

		u, _ := url.Parse("https://jsonplaceholder.typicode.com/")
		u.Path = path.Join(u.Path, "/posts/1/comments")

		testBuilder.
			Title("Single test with allure.T and repeat errors").
			Tag("single_test").
			Description("some_description").
			Create().
			RequestRetryDelay(3*time.Second). // delay before new try
			RequestRetry(3).                  // count attempts
			RequestBuilder(
				cute.WithURL(u),
				cute.WithMethod(http.MethodGet),
			).
			ExpectExecuteTimeout(10*time.Second).
			ExpectStatus(http.StatusBadGateway).
			AssertBody(
				json.Equal("$[0].email", "Eliseo@gardner.biz"),
				json.Present("$[1].name"),
			).
			OptionalAssertBody(
				json.Present("$[0].photo"), // Example optional fail
			).
			ExecuteTest(context.Background(), t)
	})
}


================================================
FILE: examples/suite/common.go
================================================
package suite

import (
	"net/url"

	"github.com/ozontech/allure-go/pkg/framework/provider"
	"github.com/ozontech/allure-go/pkg/framework/suite"
	"github.com/stretchr/testify/require"

	"github.com/ozontech/cute"
)

type ExampleSuite struct {
	suite.Suite
	host *url.URL

	testMaker *cute.HTTPTestMaker
}

func (i *ExampleSuite) BeforeAll(t provider.T) {
	// Prepare http test builder
	i.testMaker = cute.NewHTTPTestMaker()

	// Preparing host
	host, err := url.Parse("https://jsonplaceholder.typicode.com/")
	require.NoError(t, err)

	i.host = host
}

func (i *ExampleSuite) BeforeEach(t provider.T) {
	t.Feature("ExampleSuite")
	t.Tags("some_global_tag")
}


================================================
FILE: examples/suite/main_test.go
================================================
//go:build example
// +build example

package suite

import (
	"os"
	"testing"

	"github.com/ozontech/allure-go/pkg/framework/suite"
)

func TestExampleSuite(t *testing.T) {
	os.Setenv("ALLURE_OUTPUT_PATH", "../") // custom, read Readme.md for more info
	suite.RunSuite(t, new(ExampleSuite))
}


================================================
FILE: examples/suite/one_step.go
================================================
package suite

import (
	"context"
	"net/http"
	"net/url"
	"path"
	"time"

	"github.com/ozontech/allure-go/pkg/framework/provider"
	"github.com/ozontech/cute"
	"github.com/ozontech/cute/asserts/headers"
	"github.com/ozontech/cute/asserts/json"
	"github.com/ozontech/cute/examples"
)

/*
	Example testing HTTP GET and validate body.
	Validate:
		1) Execute time
		2) Status code
		3) Validate body by json schema
		4) Validate fields in json

Response:
[

	{
	  "postId": 1,
	  "id": 1,
	  "name": "id labore ex et quam laborum",
	  "email": "Eliseo@gardner.biz",
	  "body": "laudantium enim quasi est quidem magnam voluptate ipsam eos\ntempora quo necessitatibus\ndolor quam autem quasi\nreiciendis et nam sapiente accusantium"
	},
	{
	  "postId": 1,
	  "id": 2,
	  "name": "quo vero reiciendis velit similique earum",
	  "email": "Jayne_Kuhic@sydney.com",
	  "body": "est natus enim nihil est dolore omnis voluptatem numquam\net omnis occaecati quod ullam at\nvoluptatem error expedita pariatur\nnihil sint nostrum voluptatem reiciendis et"
	},
	{
	  "postId": 1,
	  "id": 3,
	  "name": "odio adipisci rerum aut animi",
	  "email": "Nikita@garfield.biz",
	  "body": "quia molestiae reprehenderit quasi aspernatur\naut expedita occaecati aliquam eveniet laudantium\nomnis quibusdam delectus saepe quia accusamus maiores nam est\ncum et ducimus et vero voluptates excepturi deleniti ratione"
	},
	{
	  "postId": 1,
	  "id": 4,
	  "name": "alias odio sit",
	  "email": "Lew@alysha.tv",
	  "body": "non et atque\noccaecati deserunt quas accusantium unde odit nobis qui voluptatem\nquia voluptas consequuntur itaque dolor\net qui rerum deleniti ut occaecati"
	},
	{
	  "postId": 1,
	  "id": 5,
	  "name": "vero eaque aliquid doloribus et culpa",
	  "email": "Hayden@althea.biz",
	  "body": "harum non quasi et ratione\ntempore iure ex voluptates in ratione\nharum architecto fugit inventore cupiditate\nvoluptates magni quo et"
	}

]
*/
func (i *ExampleSuite) Test_OneStep(t provider.T) {
	var (
		testBuilder = i.testMaker.NewTestBuilder()
	)

	u, _ := url.Parse(i.host.String())
	u.Path = path.Join(u.Path, "/posts/1/comments")

	testBuilder.
		Title("Test with one step").
		Tags("one_stp", "some_local_tag", "suite", "json").
		Feature("some_feature").
		Epic("some_epic").
		Description("some_description").
		Parallel().
		CreateStep("Example GET json request").
		AfterExecuteT(func(t cute.T, resp *http.Response, errs []error) error {
			if len(errs) != 0 {
				return nil
			}

			/*
			 Implement some logic
			*/

			return nil
		},

			// After failed test
			func(t cute.T, resp *http.Response, errs []error) error {
				if len(errs) == 0 {
					return nil
				}

				/*
				 Implement some logic
				*/

				return nil
			},
		).
		RequestBuilder(
			cute.WithHeaders(map[string][]string{
				"some_header":       []string{"something"},
				"some_array_header": []string{"1", "2", "3", "some_thing"},
			}),
			cute.WithURL(u),
			cute.WithMethod(http.MethodGet),
		).
		ExpectExecuteTimeout(10*time.Second).
		ExpectJSONSchemaFile("file://./resources/example_valid_request.json").
		ExpectStatus(http.StatusOK).
		AssertBody(
			json.Equal("$[0].email", "Eliseo@gardner.biz"),
			json.Present("$[1].name"),
			json.NotPresent("$[1].some_not_present"),
			json.LengthGreaterThan("$", 3),
			json.Length("$", 5),
			json.LengthLessThan("$", 100),
			json.NotEqual("$[3].name", "kekekekeke"),

			// Custom assert body
			examples.CustomAssertBody(),
		).
		AssertBodyT(
			// Custom assert body with testing.tb
			examples.CustomAssertBodyT(),

			func(t cute.T, body []byte) error {
				/*
					Implement here logic with TB
				*/
				time.Sleep(5 * time.Second)
				return nil
			},
		).
		AssertHeaders(
			headers.Present("Content-Type"),

			// Custom assert headers
			examples.CustomAssertHeaders(),
		).
		AssertResponse(
			examples.CustomAssertResponse(),
		).
		ExecuteTest(context.Background(), t)
}


================================================
FILE: examples/suite/one_step_errors.go
================================================
package suite

import (
	"context"
	"errors"
	"net/http"
	"time"

	"github.com/ozontech/allure-go/pkg/framework/provider"
	"github.com/ozontech/cute"
	"github.com/ozontech/cute/asserts/headers"
	"github.com/ozontech/cute/asserts/json"
	cuteErrors "github.com/ozontech/cute/errors"
	"github.com/ozontech/cute/examples"
)

func (i *ExampleSuite) Test_OneStep_Errors(t provider.T) {
	var (
		testBuilder = i.testMaker.NewTestBuilder()
	)

	testBuilder.
		Title("Test with errors").
		Tags("one_step", "some_local_tag", "suite", "json").
		Parallel().
		CreateStep("Example GET json request").
		RequestBuilder(
			cute.WithHeaders(map[string][]string{
				"some_header":       []string{"something"},
				"some_array_header": []string{"1", "2", "3", "some_thing"},
			}),
			cute.WithURI(i.host.String()+"/posts/1/comments"),
			cute.WithMethod(http.MethodGet),
			cute.WithMarshalBody(
				map[string]interface{}{
					"key": "value",
					"more_key": map[string]interface{}{
						"some_value": "sss",
					},
				},
			),
		).
		ExpectExecuteTimeout(10*time.Second).
		ExpectJSONSchemaFile("file://./resources/example_valid_request.json").
		AssertBody(
			json.Equal("$[0].email", "something"),
			json.Present("$[1].not_present"),
			json.LengthGreaterThan("$", 99999),
			json.Length("$", 0),
			// Custom assert body
			examples.CustomAssertBody(),
			examples.CustomAssertBodyWithCustomError(),
		).
		AssertHeaders(
			headers.Present("Content-Type"),

			// Custom assert headers
			examples.CustomAssertHeaders(),
		).
		AssertResponse(
			examples.CustomAssertResponse(),
		).
		AssertHeadersT(
			func(t cute.T, headers http.Header) error {
				// Example pretty print error
				return cuteErrors.NewAssertError("custom_assert", "example custom assert", "empty", "not empty") //
			},
		).
		// Example optional
		OptionalAssertBody( // example optional assert
			func(body []byte) error {
				return errors.New("some optional error from OptionalAssert")
			},
		).
		AssertBody(
			func(body []byte) error {
				return cuteErrors.NewOptionalError("some optional error from creator") // example optional error
			},
		).
		ExecuteTest(context.Background(), t)
}


================================================
FILE: examples/suite/resources/example_valid_request.json
================================================
{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "array",
  "items": [
    {
      "type": "object",
      "properties": {
        "postId": {
          "type": "integer"
        },
        "id": {
          "type": "integer"
        },
        "name": {
          "type": "string"
        },
        "email": {
          "type": "string"
        },
        "body": {
          "type": "string"
        }
      },
      "required": [
        "postId",
        "id",
        "name",
        "email",
        "body"
      ]
    },
    {
      "type": "object",
      "properties": {
        "postId": {
          "type": "integer"
        },
        "id": {
          "type": "integer"
        },
        "name": {
          "type": "string"
        },
        "email": {
          "type": "string"
        },
        "body": {
          "type": "string"
        }
      },
      "required": [
        "postId",
        "id",
        "name",
        "email",
        "body"
      ]
    },
    {
      "type": "object",
      "properties": {
        "postId": {
          "type": "integer"
        },
        "id": {
          "type": "integer"
        },
        "name": {
          "type": "string"
        },
        "email": {
          "type": "string"
        },
        "body": {
          "type": "string"
        }
      },
      "required": [
        "postId",
        "id",
        "name",
        "email",
        "body"
      ]
    },
    {
      "type": "object",
      "properties": {
        "postId": {
          "type": "integer"
        },
        "id": {
          "type": "integer"
        },
        "name": {
          "type": "string"
        },
        "email": {
          "type": "string"
        },
        "body": {
          "type": "string"
        }
      },
      "required": [
        "postId",
        "id",
        "name",
        "email",
        "body"
      ]
    },
    {
      "type": "object",
      "properties": {
        "postId": {
          "type": "integer"
        },
        "id": {
          "type": "integer"
        },
        "name": {
          "type": "string"
        },
        "email": {
          "type": "string"
        },
        "body": {
          "type": "string"
        }
      },
      "required": [
        "postId",
        "id",
        "name",
        "email",
        "body"
      ]
    }
  ]
}

================================================
FILE: examples/suite/simple.go
================================================
package suite

import (
	"context"
	"net/http"
	"net/url"
	"time"

	"github.com/ozontech/allure-go/pkg/framework/provider"
	"github.com/ozontech/cute"
)

/*
	Example simple request
	Validate:
		1) Execute time
		2) Status code

*/

func (i *ExampleSuite) Test_Simple(t provider.T) {
	var (
		testMaker   = cute.NewHTTPTestMaker()
		testBuilder = testMaker.NewTestBuilder()
	)

	u, _ := url.Parse("https://jsonplaceholder.typicode.com/posts/1/comments")

	testBuilder.
		Title("Super simple test").
		Tags("simple", "suite", "some_local_tag", "json").
		Parallel().
		Create().
		RequestBuilder(
			cute.WithHeaders(map[string][]string{
				"some_header": []string{"something"},
			}),
			cute.WithURL(u),
			cute.WithMethod(http.MethodPost),
		).
		ExpectExecuteTimeout(10*time.Second).
		ExpectStatus(http.StatusCreated).
		ExecuteTest(context.Background(), t)
}


================================================
FILE: examples/suite/two_steps.go
================================================
package suite

import (
	"context"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"path"
	"strings"
	"time"

	"github.com/ozontech/allure-go/pkg/framework/provider"
	"github.com/ozontech/cute"
	"github.com/ozontech/cute/examples"
)

/*

	Example testing HTTP POST, validate body and make second request.
	Validate:
		1) Execute time
		2) Status code

*/

func (i *ExampleSuite) Test_TwoSteps(t provider.T) {
	var (
		testBuilder = i.testMaker.NewTestBuilder()

		// Request body
		r = `
{
    "result": {
        "author": "Yours Truly",
        "date": "15.11.1993",
        "slides": [
            {
                "title": "Beer",
                "type": "drink"
            },
            {
                "title": "Apple",
                "type": "fruit"
            },
            {
                "title": "Orange",
                "type": "fruit"
            }
        ],
        "Info": {
            "shop": "BigShopPlus",
            "address": "address"
        },
        "title": "Sample Show"
    }
}
	`
	)

	u, _ := url.Parse(i.host.String())
	u.Path = path.Join(u.Path, "/posts/1/comments")

	req, _ := http.NewRequest(http.MethodPost, u.String(), ioutil.NopCloser(strings.NewReader(r)))
	req.Header = map[string][]string{
		"some_auth_token": []string{fmt.Sprint(11111)},
	}

	testBuilder.
		Title("Test in suite with two steps").
		Tags("suite", "some_tag").
		Parallel().
		CreateStep("Creat entry /posts/1").

		// CreateWithStep first step

		Request(req).
		ExpectExecuteTimeout(10*time.Second).
		ExpectStatus(http.StatusCreated).
		AssertBody(
			// Custom assert body
			examples.CustomAssertBody(),
		).
		NextTest().
		CreateStep("Delete entry").

		// CreateWithStep second step for delete
		RequestBuilder(
			cute.WithURL(u),
			cute.WithMethod(http.MethodDelete),
			cute.WithHeaders(map[string][]string{
				"some_auth_token": []string{fmt.Sprint(11111)},
			}),
		).
		ExecuteTest(context.Background(), t)
}


================================================
FILE: examples/table_test/table_test.go
================================================
//go:build example
// +build example

package table_test

import (
	"context"
	"fmt"
	"net/http"
	"net/url"
	"os"
	"strconv"
	"testing"
	"time"

	"github.com/ozontech/cute"
	"github.com/ozontech/cute/asserts/json"
	"github.com/ozontech/cute/errors"
)

func init() {
	os.Setenv("ALLURE_OUTPUT_PATH", "../") // custom, read Readme.md for more info
}

func Test_Table(t *testing.T) {
	u, _ := url.Parse("https://jsonplaceholder.typicode.com/posts/1/comments")

	req, _ := http.NewRequest(http.MethodPost, u.String(), nil)
	req.Header = map[string][]string{
		"some_auth_token": []string{fmt.Sprint(11111)},
	}
	cute.NewTestBuilder().
		Title("Example put tests in table test").
		Tag("table_test").
		CreateTableTest().
		PutNewTest(
			"Execute validation 1",
			req,
			&cute.Expect{
				Code: 201,
			}).
		PutNewTest(
			"Execute validation 2",
			req,
			&cute.Expect{
				AssertBody: []cute.AssertBody{
					json.Equal("$[0].email", "Eliseo@gardner.biz"),
					json.Present("$[1].name"),
				},
			},
		).
		ExecuteTest(context.Background(), t)
}

func Test_Table_Array(t *testing.T) {
	tests := []*cute.Test{
		{
			Name:       "Create something",
			Middleware: nil,
			Request: &cute.Request{
				Builders: []cute.RequestBuilder{
					cute.WithURI("https://jsonplaceholder.typicode.com/posts/1/comments"),
					cute.WithMethod(http.MethodPost),
				},
			},
			Expect: &cute.Expect{
				Code: 200,
			},
		},
		{
			Name:       "Delete something",
			Middleware: nil,
			Request: &cute.Request{
				Builders: []cute.RequestBuilder{
					cute.WithURI("https://jsonplaceholder.typicode.com/posts/1/comments"),
					cute.WithMethod(http.MethodGet),
				},
			},
			Expect: &cute.Expect{
				Code: 200,
				AssertBody: []cute.AssertBody{
					json.Equal("$[0].email", "Eliseo@gardner.biz"),
					json.Present("$[1].name"),
					func(body []byte) error {
						return errors.NewAssertError("example error", "example message", nil, nil)
					},
				},
			},
		},
	}

	cute.NewTestBuilder().
		Title("Example table test").
		Tag("table_test").
		Description("Execute array tests").
		CreateTableTest().
		PutTests(tests...).
		ExecuteTest(context.Background(), t)
}

func Test_One_Execute(t *testing.T) {
	test := &cute.Test{
		Name: "test_1",
		Request: &cute.Request{
			Builders: []cute.RequestBuilder{
				cute.WithURI("https://jsonplaceholder.typicode.com/posts/1/comments"),
				cute.WithMethod(http.MethodGet),
			},
		},
		Expect: nil,
	}

	test.Execute(context.Background(), t)
}

func Test_Array_Retry_OptionalFirstTries(t *testing.T) {
	tests := []*cute.Test{
		{
			Name: "test_1",

			Retry: &cute.Retry{
				MaxAttempts: 10,
				Delay:       1 * time.Second,
			},
			Middleware: nil,
			Request: &cute.Request{
				Builders: []cute.RequestBuilder{
					cute.WithURI("https://httpstat.us/Random/201,202"),
					cute.WithMethod(http.MethodGet),
				},
			},
			Expect: &cute.Expect{
				Code: 201,
			},
		},
		{
			Name: "test_2",
			Retry: &cute.Retry{
				MaxAttempts: 10,
				Delay:       1 * time.Second,
			},
			Middleware: nil,
			Request: &cute.Request{
				Builders: []cute.RequestBuilder{
					cute.WithURI("https://httpstat.us/Random/403,404"),
					cute.WithMethod(http.MethodGet),
					cute.WithMarshalBody([]byte("{\"test\":\"abc\"}")),
				},
			},
			Expect: &cute.Expect{
				Code: 404,
			},
		},
	}

	for _, test := range tests {
		test.Execute(context.Background(), t)
	}
}

func Test_Array_Retry_OptionalFirstTries_UltimatelyFailing(t *testing.T) {
	tests := []*cute.Test{
		{
			Name: "test_1",

			Retry: &cute.Retry{
				MaxAttempts: 4,
				Delay:       1 * time.Second,
			},
			Middleware: nil,
			Request: &cute.Request{
				Builders: []cute.RequestBuilder{
					cute.WithURI("https://httpstat.us/Random/202,200"),
					cute.WithMethod(http.MethodGet),
				},
			},
			Expect: &cute.Expect{
				Code: 201,
			},
		},
		{
			Name: "test_2",
			Retry: &cute.Retry{
				MaxAttempts: 3,
				Delay:       1 * time.Second,
			},
			Middleware: nil,
			Request: &cute.Request{
				Builders: []cute.RequestBuilder{
					cute.WithURI("https://httpstat.us/Random/403,401"),
					cute.WithMethod(http.MethodGet),
				},
			},
			Expect: &cute.Expect{
				Code: 404,
			},
		},
	}

	for _, test := range tests {
		test.Execute(context.Background(), t)
	}
}

func Test_Array_TimeoutRetry(t *testing.T) {
	var executeTimeout = 3000

	tests := []*cute.Test{
		{
			Retry: &cute.Retry{
				MaxAttempts: 2,
			},
			Name: "test_timeout",
			Middleware: &cute.Middleware{
				Before: []cute.BeforeExecute{
					cute.BeforeExecute(func(request *http.Request) error {
						query := request.URL.Query()
						query.Set("sleep", strconv.Itoa(executeTimeout))
						request.URL.RawQuery = query.Encode()
						executeTimeout = executeTimeout - 1000
						return nil
					}),
				},
			},
			Request: &cute.Request{
				Builders: []cute.RequestBuilder{
					cute.WithURI("https://httpstat.us/202?sleep=3000"),
					cute.WithBody([]byte("{\"test\":\"abc\"}")),
					cute.WithMethod(http.MethodGet),
				},
			},
			Expect: &cute.Expect{
				Code:        202,
				ExecuteTime: 3 * time.Second,
			},
		},
	}

	for _, test := range tests {
		test.Execute(context.Background(), t)
	}
}

func Test_Array(t *testing.T) {
	tests := []*cute.Test{
		{
			Name:       "test_1",
			Middleware: nil,
			Request: &cute.Request{
				Builders: []cute.RequestBuilder{
					cute.WithURI("https://jsonplaceholder.typicode.com/posts/1/comments"),
					cute.WithMethod(http.MethodPost),
				},
			},
			Expect: &cute.Expect{
				Code: 201,
			},
		},
		{
			Name:       "test_2",
			Middleware: nil,
			Request: &cute.Request{
				Builders: []cute.RequestBuilder{
					cute.WithURI("https://jsonplaceholder.typicode.com/posts/1/comments"),
					cute.WithMethod(http.MethodGet),
				},
			},
			Expect: &cute.Expect{
				Code: 200,
				AssertBody: []cute.AssertBody{
					json.Equal("$[0].email", "Eliseo@gardner.biz"),
					json.Present("$[1].name"),
					func(body []byte) error {
						return errors.NewAssertError("example error", "example message", nil, nil)
					},
				},
			},
		},
	}

	for _, test := range tests {
		test.Execute(context.Background(), t)
	}
}

func Test_Array_All_Parallel(t *testing.T) {
	tests := []*cute.Test{
		{
			Name:       "test_201",
			Parallel:   true,
			Middleware: nil,
			Request: &cute.Request{
				Builders: []cute.RequestBuilder{
					cute.WithURI("https://httpstat.us/201"),
					cute.WithMethod(http.MethodGet),
				},
			},
			Expect: &cute.Expect{
				Code: 201,
			},
		},
		{
			Name:       "test_200_delay_5s",
			Parallel:   true,
			Middleware: nil,
			Request: &cute.Request{
				Builders: []cute.RequestBuilder{
					cute.WithURI("https://httpstat.us/200?sleep=5000"),
					cute.WithMethod(http.MethodGet),
				},
			},
			Expect: &cute.Expect{
				Code: 200,
			},
		},
		{
			Name:       "test_202_delay_3s",
			Parallel:   true,
			Middleware: nil,
			Request: &cute.Request{
				Builders: []cute.RequestBuilder{
					cute.WithURI("https://httpstat.us/202?sleep=3000"),
					cute.WithMethod(http.MethodGet),
				},
			},
			Expect: &cute.Expect{
				Code: 202,
			},
		},
		{
			Name:       "test_203",
			Parallel:   true,
			Middleware: nil,
			Request: &cute.Request{
				Builders: []cute.RequestBuilder{
					cute.WithURI("https://httpstat.us/203"),
					cute.WithMethod(http.MethodGet),
				},
			},
			Expect: &cute.Expect{
				Code: 203,
			},
		},
	}

	for _, test := range tests {
		test.Execute(context.Background(), t)
	}
}

func Test_Array_Some_Parallel(t *testing.T) {
	tests := []*cute.Test{
		{
			Name:       "test_parallel_1",
			Parallel:   true,
			Middleware: nil,
			Request: &cute.Request{
				Builders: []cute.RequestBuilder{
					cute.WithURI("https://httpstat.us/201?sleep=1000"),
					cute.WithMethod(http.MethodGet),
				},
			},
			Expect: &cute.Expect{
				Code: 201,
			},
		},
		{
			Name:       "test_parallel_2",
			Parallel:   true,
			Middleware: nil,
			Request: &cute.Request{
				Builders: []cute.RequestBuilder{
					cute.WithURI("https://httpstat.us/202?sleep=1000"),
					cute.WithMethod(http.MethodGet),
				},
			},
			Expect: &cute.Expect{
				Code: 202,
			},
		},
		{
			Name:       "test_1_sequential",
			Parallel:   false,
			Middleware: nil,
			Request: &cute.Request{
				Builders: []cute.RequestBuilder{
					cute.WithURI("https://jsonplaceholder.typicode.com/posts/1/comments"),
					cute.WithMethod(http.MethodPost),
				},
			},
			Expect: &cute.Expect{
				Code: 201,
			},
		},
		{
			Name:       "test_2_sequential",
			Parallel:   false,
			Middleware: nil,
			Request: &cute.Request{
				Builders: []cute.RequestBuilder{
					cute.WithURI("https://jsonplaceholder.typicode.com/posts/1/comments"),
					cute.WithMethod(http.MethodGet),
				},
			},
			Expect: &cute.Expect{
				Code: 200,
				AssertBody: []cute.AssertBody{
					json.Equal("$[0].email", "Eliseo@gardner.biz"),
					json.Present("$[1].name"),
				},
			},
		},
	}

	for _, test := range tests {
		test.Execute(context.Background(), t)
	}
}

func Test_Array_Retry(t *testing.T) {
	tests := []*cute.Test{
		{
			Name:     "test_1",
			Parallel: true,
			Retry: &cute.Retry{
				MaxAttempts: 10,
				Delay:       1,
			},
			Middleware: nil,
			Request: &cute.Request{
				Builders: []cute.RequestBuilder{
					cute.WithURI("https://httpstat.us/Random/201,202"),
					cute.WithMethod(http.MethodGet),
				},
			},
			Expect: &cute.Expect{
				Code: 201,
			},
		},
		{
			Name:     "test_2",
			Parallel: true,
			Retry: &cute.Retry{
				MaxAttempts: 10,
				Delay:       1,
			},
			Middleware: nil,
			Request: &cute.Request{
				Builders: []cute.RequestBuilder{
					cute.WithURI("https://httpstat.us/Random/403,404"),
					cute.WithMethod(http.MethodGet),
				},
			},
			Expect: &cute.Expect{
				Code: 404,
			},
		},
	}

	for _, test := range tests {
		test.Execute(context.Background(), t)
	}
}

func Test_Array_Timeout(t *testing.T) {
	tests := []*cute.Test{
		{
			Name:       "test_timeout",
			Middleware: nil,
			Request: &cute.Request{
				Builders: []cute.RequestBuilder{
					cute.WithURI("https://httpstat.us/202?sleep=3000"),
					cute.WithMethod(http.MethodGet),
				},
			},
			Expect: &cute.Expect{
				Code:        202,
				ExecuteTime: 2 * time.Second,
			},
		},
	}

	for _, test := range tests {
		test.Execute(context.Background(), t)
	}
}


================================================
FILE: examples/two_step_test.go
================================================
//go:build example
// +build example

package examples

import (
	"context"
	"errors"
	"fmt"
	"net/http"
	"testing"
	"time"

	"github.com/ozontech/allure-go/pkg/framework/provider"
	"github.com/ozontech/allure-go/pkg/framework/runner"
	"github.com/ozontech/cute"
)

func Test_TwoSteps_1(t *testing.T) {
	cute.NewTestBuilder().
		Title("Test with two requests.").
		Tags("two_steps").
		Parallel().
		CreateStep("Create entry /posts/1").

		// CreateWithStep first step

		RequestBuilder(
			cute.WithURI("https://jsonplaceholder.typicode.com/posts/1/comments"),
			cute.WithMethod(http.MethodGet),
		).
		ExpectExecuteTimeout(10*time.Second).
		ExpectStatus(http.StatusCreated).
		NextTest().
		CreateStep("Delete entry").

		// CreateWithStep second step for delete
		RequestBuilder(
			cute.WithURI("https://jsonplaceholder.typicode.com/posts/1/comments"),
			cute.WithMethod(http.MethodDelete),
			cute.WithHeaders(map[string][]string{
				"some_auth_token": []string{fmt.Sprint(11111)},
			}),
		).
		ExecuteTest(context.Background(), t)
}

func Test_TwoSteps_2_AllureRunner(t *testing.T) {
	runner.Run(t, "Test with two steps", func(t provider.T) {
		testBuilder := cute.NewHTTPTestMaker().NewTestBuilder()

		testBuilder.
			Title("Test with two requests executed by allure-go").
			Tag("two_steps").
			Description("some_description").
			CreateStep("Request 1").
			RequestBuilder(
				cute.WithURI("https://jsonplaceholder.typicode.com/posts/1/comments"),
				cute.WithMethod(http.MethodGet),
			).
			ExpectStatus(http.StatusOK).
			ExecuteTest(context.Background(), t)

		testBuilder.
			CreateStep("Request 2").
			RequestBuilder(
				cute.WithURI("https://jsonplaceholder.typicode.com/posts/2/comments"),
				cute.WithMethod(http.MethodGet),
			).
			ExpectExecuteTimeout(10*time.Second).
			ExpectStatus(http.StatusOK).
			ExecuteTest(context.Background(), t)
	})
}

func Test_TwoSteps_3(t *testing.T) {
	responseCode := 0

	// First step.
	cute.NewTestBuilder().
		Title("Test with two requests and parse body.").
		Tag("two_steps").
		Create().
		RequestBuilder(
			cute.WithURI("https://jsonplaceholder.typicode.com/posts/1/comments"),
			cute.WithMethod(http.MethodGet),
		).
		ExpectStatus(http.StatusOK).
		RequireBody(func(body []byte) error {
			return errors.New("example")
		}).
		NextTest().
		AfterTestExecute(func(response *http.Response, errors []error) error { // Execute after first step
			responseCode = response.StatusCode

			fmt.Println("Hello from after test execute")
			fmt.Println("Response code", responseCode)

			return nil
		}).
		// Second step. This test isn't run, because previous test has failed require validation
		Create().
		RequestBuilder(
			cute.WithURI("https://jsonplaceholder.typicode.com/posts/2/comments"),
			cute.WithMethod(http.MethodDelete),
		).
		ExecuteTest(context.Background(), t)

	fmt.Println("Response code from first request", responseCode)
}


================================================
FILE: examples/upload_file_test.go
================================================
//go:build example_upload_file
// +build example_upload_file

package examples

import (
	"context"
	"net/http"
	"testing"

	"github.com/ozontech/cute"
)

func TestUploadFile(t *testing.T) {
	cute.NewTestBuilder().
		Title("Upload file").
		Create().
		RequestBuilder(
			cute.WithURI("http://localhost:7000/v1/banner"),
			cute.WithMethod("POST"),
			cute.WithFormKV("body", []byte("{\"name\": \"Vasya\"}")), // Fill the form with the body
			cute.WithFileFormKV("image", &cute.File{ // Fill the form with the file
				Path: "/vasya/thebestmypicture.png",
			}),
		).
		ExpectStatus(http.StatusOK).
		ExecuteTest(context.Background(), t)
}


================================================
FILE: go.mod
================================================
module github.com/ozontech/cute

go 1.21

require (
	github.com/josephburnett/jd v1.7.1
	github.com/ohler55/ojg v1.21.1
	github.com/ozontech/allure-go/pkg/allure v0.6.13
	github.com/ozontech/allure-go/pkg/framework v0.6.31
	github.com/stretchr/testify v1.8.4
	github.com/xeipuuv/gojsonschema v1.2.0
	moul.io/http2curl/v2 v2.3.0
)

require (
	github.com/davecgh/go-spew v1.1.1 // indirect
	github.com/go-openapi/jsonpointer v0.19.5 // indirect
	github.com/go-openapi/swag v0.21.1 // indirect
	github.com/google/uuid v1.3.0 // indirect
	github.com/josharian/intern v1.0.0 // indirect
	github.com/mailru/easyjson v0.7.7 // indirect
	github.com/pkg/errors v0.9.1 // indirect
	github.com/pmezard/go-difflib v1.0.0 // indirect
	github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
	github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
	gopkg.in/yaml.v2 v2.4.0 // indirect
	gopkg.in/yaml.v3 v3.0.1 // indirect
)


================================================
FILE: go.sum
================================================
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.21.1 h1:wm0rhTb5z7qpJRHBdPOMuY4QjVUMbF6/kwoYeRAOrKU=
github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/josephburnett/jd v1.7.1 h1:oXBPMS+SNnILTMGj1fWLK9pexpeJUXtbVFfRku/PjBU=
github.com/josephburnett/jd v1.7.1/go.mod h1:R8ZnZnLt2D4rhW4NvBc/USTo6mzyNT6fYNIIWOJA9GY=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/ohler55/ojg v1.21.1 h1:b2RLUaDcy9gvn46dmhTjezu/TDauoR0/kgKTqkwIxto=
github.com/ohler55/ojg v1.21.1/go.mod h1:gQhDVpQLqrmnd2eqGAvJtn+NfKoYJbe/A4Sj3/Vro4o=
github.com/ozontech/allure-go/pkg/allure v0.6.13 h1:vkLSIvOEERHTxe+oq8DXDu/m+kLnVUkrXNN8xTKuKU4=
github.com/ozontech/allure-go/pkg/allure v0.6.13/go.mod h1:4oEG2yq+DGOzJS/ZjPc87C/mx3tAnlYpYonk77Ru/vQ=
github.com/ozontech/allure-go/pkg/framework v0.6.31 h1:u32AqB9/JkzcL5vSl8PSUmMZbsVTmoriDylI3FIYgX4=
github.com/ozontech/allure-go/pkg/framework v0.6.31/go.mod h1:wfqY4e4+w4BoRFDxHp7TNcdWfcCOWJV3BjrUqUughWY=
github.com/pkg/diff v0.0.0-20200914180035-5b29258ca4f7/go.mod h1:zO8QMzTeZd5cpnIkz/Gn6iK0jDfGicM1nynOkkPIl28=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/tailscale/depaware v0.0.0-20210622194025-720c4b409502/go.mod h1:p9lPsd+cx33L3H9nNoecRRxPssFKUwwI50I3pZ0yT+8=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1
Download .txt
gitextract_fkbtdg57/

├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   └── feature_request.md
│   └── workflows/
│       └── main.yml
├── .gitignore
├── .golangci.yaml
├── LICENSE
├── Makefile
├── README.MD
├── allure.go
├── assert.go
├── assert_broken.go
├── assert_broken_test.go
├── assert_optional.go
├── assert_optional_test.go
├── assert_require.go
├── assert_require_test.go
├── assert_trace.go
├── asserts/
│   ├── headers/
│   │   ├── headers.go
│   │   └── headers_test.go
│   └── json/
│       ├── json.go
│       ├── json_test.go
│       └── util.go
├── builder.go
├── builder_allure.go
├── builder_asserts.go
├── builder_middleware.go
├── builder_option.go
├── builder_request.go
├── builder_retry.go
├── builder_table.go
├── builder_table_test.go
├── builder_test.go
├── cute.go
├── errors/
│   ├── broken.go
│   ├── error.go
│   ├── optional.go
│   ├── require.go
│   └── trace.go
├── examples/
│   ├── custom_asserts.go
│   ├── inside_step_test.go
│   ├── masked_data_test.go
│   ├── parallel_test.go
│   ├── single_test.go
│   ├── suite/
│   │   ├── common.go
│   │   ├── main_test.go
│   │   ├── one_step.go
│   │   ├── one_step_errors.go
│   │   ├── resources/
│   │   │   └── example_valid_request.json
│   │   ├── simple.go
│   │   └── two_steps.go
│   ├── table_test/
│   │   └── table_test.go
│   ├── two_step_test.go
│   └── upload_file_test.go
├── go.mod
├── go.sum
├── init.go
├── interface.go
├── internal/
│   └── utils/
│       ├── body.go
│       └── json.go
├── json_marshaler.go
├── jsonschema.go
├── jsonschema_test.go
├── logger.go
├── provider.go
├── request.go
├── request_test.go
├── result.go
├── result_test.go
├── roundtripper.go
├── step.go
├── test.go
└── test_test.go
Download .txt
SYMBOL INDEX (470 symbols across 61 files)

FILE: allure.go
  method setAllureInformation (line 3) | func (qt *cute) setAllureInformation(t allureProvider) {
  method setLinksAllure (line 10) | func (qt *cute) setLinksAllure(t linksAllureProvider) {
  method setLabelsAllure (line 32) | func (qt *cute) setLabelsAllure(t labelsAllureProvider) {
  method setInfoAllure (line 98) | func (qt *cute) setInfoAllure(t infoAllureProvider) {

FILE: assert.go
  type AssertBody (line 18) | type AssertBody
  type AssertHeaders (line 24) | type AssertHeaders
  type AssertResponse (line 27) | type AssertResponse
  type AssertBodyT (line 34) | type AssertBodyT
  type AssertHeadersT (line 39) | type AssertHeadersT
  type AssertResponseT (line 44) | type AssertResponseT
  method assertHeaders (line 46) | func (it *Test) assertHeaders(t internalT, headers http.Header) []error {
  method assertResponse (line 78) | func (it *Test) assertResponse(t internalT, resp *http.Response) []error {
  method assertBody (line 110) | func (it *Test) assertBody(t internalT, body []byte) []error {

FILE: assert_broken.go
  function brokenAssertHeaders (line 9) | func brokenAssertHeaders(assert AssertHeaders) AssertHeaders {
  function brokenAssertBody (line 17) | func brokenAssertBody(assert AssertBody) AssertBody {
  function brokenAssertResponse (line 25) | func brokenAssertResponse(assert AssertResponse) AssertResponse {
  function brokenAssertHeadersT (line 33) | func brokenAssertHeadersT(assert AssertHeadersT) AssertHeadersT {
  function brokenAssertBodyT (line 41) | func brokenAssertBodyT(assert AssertBodyT) AssertBodyT {
  function brokenAssertResponseT (line 49) | func brokenAssertResponseT(assert AssertResponseT) AssertResponseT {
  function wrapBrokenError (line 57) | func wrapBrokenError(err error) error {

FILE: assert_broken_test.go
  function TestBrokenAssertResponse (line 13) | func TestBrokenAssertResponse(t *testing.T) {
  function TestBrokenAssertResponseT (line 26) | func TestBrokenAssertResponseT(t *testing.T) {
  function TestBrokenAssertHeaders (line 39) | func TestBrokenAssertHeaders(t *testing.T) {
  function TestBrokenAssertHeadersT (line 52) | func TestBrokenAssertHeadersT(t *testing.T) {
  function TestBrokenAssertBody (line 65) | func TestBrokenAssertBody(t *testing.T) {
  function TestBrokenAssertBodyT (line 78) | func TestBrokenAssertBodyT(t *testing.T) {
  function TestWrapBrokenError (line 91) | func TestWrapBrokenError(t *testing.T) {

FILE: assert_optional.go
  function optionalAssertHeaders (line 9) | func optionalAssertHeaders(assert AssertHeaders) AssertHeaders {
  function optionalAssertBody (line 17) | func optionalAssertBody(assert AssertBody) AssertBody {
  function optionalAssertResponse (line 25) | func optionalAssertResponse(assert AssertResponse) AssertResponse {
  function optionalAssertHeadersT (line 33) | func optionalAssertHeadersT(assert AssertHeadersT) AssertHeadersT {
  function optionalAssertBodyT (line 41) | func optionalAssertBodyT(assert AssertBodyT) AssertBodyT {
  function optionalAssertResponseT (line 49) | func optionalAssertResponseT(assert AssertResponseT) AssertResponseT {
  function wrapOptionalError (line 57) | func wrapOptionalError(err error) error {

FILE: assert_optional_test.go
  function TestOptionalAssertResponse (line 13) | func TestOptionalAssertResponse(t *testing.T) {
  function TestOptionalAssertResponseT (line 26) | func TestOptionalAssertResponseT(t *testing.T) {
  function TestOptionalAssertHeaders (line 39) | func TestOptionalAssertHeaders(t *testing.T) {
  function TestOptionalAssertHeadersT (line 52) | func TestOptionalAssertHeadersT(t *testing.T) {
  function TestOptionalAssertBody (line 65) | func TestOptionalAssertBody(t *testing.T) {
  function TestOptionalAssertBodyT (line 78) | func TestOptionalAssertBodyT(t *testing.T) {
  function TestWrapOptionalError (line 91) | func TestWrapOptionalError(t *testing.T) {

FILE: assert_require.go
  function requireAssertHeaders (line 9) | func requireAssertHeaders(assert AssertHeaders) AssertHeaders {
  function requireAssertBody (line 17) | func requireAssertBody(assert AssertBody) AssertBody {
  function requireAssertResponse (line 25) | func requireAssertResponse(assert AssertResponse) AssertResponse {
  function requireAssertHeadersT (line 33) | func requireAssertHeadersT(assert AssertHeadersT) AssertHeadersT {
  function requireAssertBodyT (line 41) | func requireAssertBodyT(assert AssertBodyT) AssertBodyT {
  function requireAssertResponseT (line 49) | func requireAssertResponseT(assert AssertResponseT) AssertResponseT {
  function wrapRequireError (line 57) | func wrapRequireError(err error) error {

FILE: assert_require_test.go
  function TestRequireAssertResponse (line 13) | func TestRequireAssertResponse(t *testing.T) {
  function TestRequireAssertResponseT (line 26) | func TestRequireAssertResponseT(t *testing.T) {
  function TestRequireAssertHeaders (line 39) | func TestRequireAssertHeaders(t *testing.T) {
  function TestRequireAssertHeadersT (line 52) | func TestRequireAssertHeadersT(t *testing.T) {
  function TestRequireAssertBody (line 65) | func TestRequireAssertBody(t *testing.T) {
  function TestRequireAssertBodyT (line 78) | func TestRequireAssertBodyT(t *testing.T) {
  function TestWrapRequireError (line 91) | func TestWrapRequireError(t *testing.T) {

FILE: assert_trace.go
  function assertHeadersWithTrace (line 12) | func assertHeadersWithTrace(assert AssertHeaders, trace string) AssertHe...
  function assertBodyWithTrace (line 21) | func assertBodyWithTrace(assert AssertBody, trace string) AssertBody {
  function assertResponseWithTrace (line 30) | func assertResponseWithTrace(assert AssertResponse, trace string) Assert...
  function assertHeadersTWithTrace (line 39) | func assertHeadersTWithTrace(assert AssertHeadersT, trace string) Assert...
  function assertBodyTWithTrace (line 48) | func assertBodyTWithTrace(assert AssertBodyT, trace string) AssertBodyT {
  function assertResponseTWithTrace (line 57) | func assertResponseTWithTrace(assert AssertResponseT, trace string) Asse...
  function wrapWithTrace (line 66) | func wrapWithTrace(err error, trace string) error {
  function getTrace (line 80) | func getTrace() string {

FILE: asserts/headers/headers.go
  function Present (line 12) | func Present(key string) cute.AssertHeaders {
  function NotPresent (line 23) | func NotPresent(key string) cute.AssertHeaders {

FILE: asserts/headers/headers_test.go
  function TestPresent (line 10) | func TestPresent(t *testing.T) {
  function TestPresentError (line 19) | func TestPresentError(t *testing.T) {
  function TestNotPresent (line 28) | func TestNotPresent(t *testing.T) {
  function TestNotPresentError (line 37) | func TestNotPresentError(t *testing.T) {

FILE: asserts/json/json.go
  function Diff (line 14) | func Diff(original string) cute.AssertBody {
  function Contains (line 44) | func Contains(expression string, expect interface{}) cute.AssertBody {
  function Equal (line 52) | func Equal(expression string, expect interface{}) cute.AssertBody {
  function NotEqual (line 60) | func NotEqual(expression string, expect interface{}) cute.AssertBody {
  function EqualJSON (line 68) | func EqualJSON(expression string, expect []byte) cute.AssertBody {
  function NotEqualJSON (line 76) | func NotEqualJSON(expression string, expect []byte) cute.AssertBody {
  function Length (line 84) | func Length(expression string, expectLength int) cute.AssertBody {
  function LengthGreaterThan (line 92) | func LengthGreaterThan(expression string, minimumLength int) cute.Assert...
  function LengthGreaterOrEqualThan (line 100) | func LengthGreaterOrEqualThan(expression string, minimumLength int) cute...
  function LengthLessThan (line 108) | func LengthLessThan(expression string, maximumLength int) cute.AssertBody {
  function LengthLessOrEqualThan (line 116) | func LengthLessOrEqualThan(expression string, maximumLength int) cute.As...
  function Present (line 125) | func Present(expression string) cute.AssertBody {
  function NotEmpty (line 134) | func NotEmpty(expression string) cute.AssertBody {
  function NotPresent (line 142) | func NotPresent(expression string) cute.AssertBody {
  function GetValueFromJSON (line 149) | func GetValueFromJSON(js []byte, expression string) ([]interface{}, erro...

FILE: asserts/json/json_test.go
  type jsonTest (line 10) | type jsonTest struct
  function TestDiff (line 18) | func TestDiff(t *testing.T) {
  function TestNotPresent (line 73) | func TestNotPresent(t *testing.T) {
  function TestPresent (line 109) | func TestPresent(t *testing.T) {
  function TestNotEmpty (line 170) | func TestNotEmpty(t *testing.T) {
  function TestLength (line 228) | func TestLength(t *testing.T) {
  function TestLengthGreaterThan (line 282) | func TestLengthGreaterThan(t *testing.T) {
  function TestLengthGreaterOrEqualThan (line 342) | func TestLengthGreaterOrEqualThan(t *testing.T) {
  function TestLengthLessThan (line 423) | func TestLengthLessThan(t *testing.T) {
  function TestLengthLessOrEqualThan (line 483) | func TestLengthLessOrEqualThan(t *testing.T) {
  function TestEqual (line 564) | func TestEqual(t *testing.T) {
  function TestNotEqual (line 649) | func TestNotEqual(t *testing.T) {
  function TestEqualJSON (line 701) | func TestEqualJSON(t *testing.T) {
  function TestNotEqualJSON (line 799) | func TestNotEqualJSON(t *testing.T) {
  function TestGetValueFromJSON (line 891) | func TestGetValueFromJSON(t *testing.T) {

FILE: asserts/json/util.go
  function contains (line 16) | func contains(data []byte, expression string, expect interface{}) error {
  function equalAbstract (line 36) | func equalAbstract(data []byte, expression string, expect interface{}, n...
  function notEqualAbstract (line 51) | func notEqualAbstract(data []byte, expression string, expect interface{}...
  function equal (line 68) | func equal(data []byte, expression string, expect interface{}) error {
  function notEqual (line 74) | func notEqual(data []byte, expression string, expect interface{}) error {
  function equalJSON (line 80) | func equalJSON(data []byte, expression string, expect []byte) error {
  function notEqualJSON (line 91) | func notEqualJSON(data []byte, expression string, expect []byte) error {
  function length (line 102) | func length(data []byte, expression string, expectLength int) error {
  function greaterThan (line 120) | func greaterThan(data []byte, expression string, minimumLength int) error {
  function greaterOrEqualThan (line 138) | func greaterOrEqualThan(data []byte, expression string, minimumLength in...
  function lessThan (line 156) | func lessThan(data []byte, expression string, maximumLength int) error {
  function lessOrEqualThan (line 174) | func lessOrEqualThan(data []byte, expression string, maximumLength int) ...
  function notEmpty (line 192) | func notEmpty(data []byte, expression string) error {
  function present (line 211) | func present(data []byte, expression string) error {
  function notPresent (line 222) | func notPresent(data []byte, expression string) error {
  function objectsAreEqual (line 234) | func objectsAreEqual(expect, actual interface{}) bool {
  function isEmpty (line 264) | func isEmpty(object interface{}) bool {
  function insideArray (line 288) | func insideArray(list interface{}, element interface{}) (ok, found bool) {

FILE: builder.go
  constant defaultHTTPTimeout (line 8) | defaultHTTPTimeout = 30
  type HTTPTestMaker (line 15) | type HTTPTestMaker struct
    method NewTestBuilder (line 78) | func (m *HTTPTestMaker) NewTestBuilder() AllureBuilder {
  function NewHTTPTestMaker (line 32) | func NewHTTPTestMaker(opts ...Option) *HTTPTestMaker {
  function createDefaultTests (line 92) | func createDefaultTests(m *HTTPTestMaker) []*Test {
  function createDefaultTest (line 99) | func createDefaultTest(m *HTTPTestMaker) *Test {
  function createMiddlewareFromTemplate (line 112) | func createMiddlewareFromTemplate(m *Middleware) *Middleware {
  method Create (line 135) | func (qt *cute) Create() MiddlewareRequest {
  method CreateStep (line 139) | func (qt *cute) CreateStep(name string) MiddlewareRequest {
  method CreateRequest (line 145) | func (qt *cute) CreateRequest() RequestHTTPBuilder {

FILE: builder_allure.go
  method Parallel (line 9) | func (qt *cute) Parallel() AllureBuilder {
  method Title (line 15) | func (qt *cute) Title(title string) AllureBuilder {
  method Epic (line 21) | func (qt *cute) Epic(epic string) AllureBuilder {
  method Titlef (line 27) | func (qt *cute) Titlef(format string, args ...interface{}) AllureBuilder {
  method Descriptionf (line 33) | func (qt *cute) Descriptionf(format string, args ...interface{}) AllureB...
  method Stage (line 39) | func (qt *cute) Stage(stage string) AllureBuilder {
  method Stagef (line 45) | func (qt *cute) Stagef(format string, args ...interface{}) AllureBuilder {
  method Layer (line 51) | func (qt *cute) Layer(value string) AllureBuilder {
  method TmsLink (line 57) | func (qt *cute) TmsLink(tmsLink string) AllureBuilder {
  method TmsLinks (line 63) | func (qt *cute) TmsLinks(tmsLinks ...string) AllureBuilder {
  method SetIssue (line 69) | func (qt *cute) SetIssue(issue string) AllureBuilder {
  method SetTestCase (line 75) | func (qt *cute) SetTestCase(testCase string) AllureBuilder {
  method Link (line 81) | func (qt *cute) Link(link *allure.Link) AllureBuilder {
  method ID (line 87) | func (qt *cute) ID(value string) AllureBuilder {
  method AllureID (line 93) | func (qt *cute) AllureID(value string) AllureBuilder {
  method AddSuiteLabel (line 99) | func (qt *cute) AddSuiteLabel(value string) AllureBuilder {
  method AddSubSuite (line 105) | func (qt *cute) AddSubSuite(value string) AllureBuilder {
  method AddParentSuite (line 111) | func (qt *cute) AddParentSuite(value string) AllureBuilder {
  method Story (line 117) | func (qt *cute) Story(value string) AllureBuilder {
  method Tag (line 123) | func (qt *cute) Tag(value string) AllureBuilder {
  method Severity (line 129) | func (qt *cute) Severity(value allure.SeverityType) AllureBuilder {
  method Owner (line 135) | func (qt *cute) Owner(value string) AllureBuilder {
  method Lead (line 141) | func (qt *cute) Lead(value string) AllureBuilder {
  method Label (line 147) | func (qt *cute) Label(label *allure.Label) AllureBuilder {
  method Labels (line 153) | func (qt *cute) Labels(labels ...*allure.Label) AllureBuilder {
  method Description (line 159) | func (qt *cute) Description(description string) AllureBuilder {
  method Tags (line 165) | func (qt *cute) Tags(tags ...string) AllureBuilder {
  method Feature (line 171) | func (qt *cute) Feature(feature string) AllureBuilder {

FILE: builder_asserts.go
  method AssertBody (line 5) | func (qt *cute) AssertBody(asserts ...AssertBody) ExpectHTTPBuilder {
  method OptionalAssertBody (line 19) | func (qt *cute) OptionalAssertBody(asserts ...AssertBody) ExpectHTTPBuil...
  method BrokenAssertBody (line 33) | func (qt *cute) BrokenAssertBody(asserts ...AssertBody) ExpectHTTPBuilder {
  method RequireBody (line 47) | func (qt *cute) RequireBody(asserts ...AssertBody) ExpectHTTPBuilder {
  method AssertHeaders (line 61) | func (qt *cute) AssertHeaders(asserts ...AssertHeaders) ExpectHTTPBuilder {
  method OptionalAssertHeaders (line 75) | func (qt *cute) OptionalAssertHeaders(asserts ...AssertHeaders) ExpectHT...
  method RequireHeaders (line 89) | func (qt *cute) RequireHeaders(asserts ...AssertHeaders) ExpectHTTPBuild...
  method BrokenAssertHeaders (line 103) | func (qt *cute) BrokenAssertHeaders(asserts ...AssertHeaders) ExpectHTTP...
  method AssertResponse (line 117) | func (qt *cute) AssertResponse(asserts ...AssertResponse) ExpectHTTPBuil...
  method OptionalAssertResponse (line 131) | func (qt *cute) OptionalAssertResponse(asserts ...AssertResponse) Expect...
  method RequireResponse (line 145) | func (qt *cute) RequireResponse(asserts ...AssertResponse) ExpectHTTPBui...
  method BrokenAssertResponse (line 159) | func (qt *cute) BrokenAssertResponse(asserts ...AssertResponse) ExpectHT...
  method AssertBodyT (line 173) | func (qt *cute) AssertBodyT(asserts ...AssertBodyT) ExpectHTTPBuilder {
  method OptionalAssertBodyT (line 187) | func (qt *cute) OptionalAssertBodyT(asserts ...AssertBodyT) ExpectHTTPBu...
  method BrokenAssertBodyT (line 201) | func (qt *cute) BrokenAssertBodyT(asserts ...AssertBodyT) ExpectHTTPBuil...
  method RequireBodyT (line 215) | func (qt *cute) RequireBodyT(asserts ...AssertBodyT) ExpectHTTPBuilder {
  method AssertHeadersT (line 229) | func (qt *cute) AssertHeadersT(asserts ...AssertHeadersT) ExpectHTTPBuil...
  method OptionalAssertHeadersT (line 243) | func (qt *cute) OptionalAssertHeadersT(asserts ...AssertHeadersT) Expect...
  method RequireHeadersT (line 257) | func (qt *cute) RequireHeadersT(asserts ...AssertHeadersT) ExpectHTTPBui...
  method BrokenAssertHeadersT (line 271) | func (qt *cute) BrokenAssertHeadersT(asserts ...AssertHeadersT) ExpectHT...
  method AssertResponseT (line 285) | func (qt *cute) AssertResponseT(asserts ...AssertResponseT) ExpectHTTPBu...
  method OptionalAssertResponseT (line 299) | func (qt *cute) OptionalAssertResponseT(asserts ...AssertResponseT) Expe...
  method BrokenAssertResponseT (line 313) | func (qt *cute) BrokenAssertResponseT(asserts ...AssertResponseT) Expect...
  method RequireResponseT (line 327) | func (qt *cute) RequireResponseT(asserts ...AssertResponseT) ExpectHTTPB...
  method ExpectExecuteTimeout (line 341) | func (qt *cute) ExpectExecuteTimeout(t time.Duration) ExpectHTTPBuilder {
  method ExpectStatus (line 347) | func (qt *cute) ExpectStatus(code int) ExpectHTTPBuilder {
  method ExpectJSONSchemaString (line 353) | func (qt *cute) ExpectJSONSchemaString(schema string) ExpectHTTPBuilder {
  method ExpectJSONSchemaByte (line 359) | func (qt *cute) ExpectJSONSchemaByte(schema []byte) ExpectHTTPBuilder {
  method ExpectJSONSchemaFile (line 365) | func (qt *cute) ExpectJSONSchemaFile(filePath string) ExpectHTTPBuilder {

FILE: builder_middleware.go
  method StepName (line 3) | func (qt *cute) StepName(name string) MiddlewareRequest {
  method BeforeExecute (line 9) | func (qt *cute) BeforeExecute(fs ...BeforeExecute) MiddlewareRequest {
  method BeforeExecuteT (line 15) | func (qt *cute) BeforeExecuteT(fs ...BeforeExecuteT) MiddlewareRequest {
  method After (line 21) | func (qt *cute) After(fs ...AfterExecute) ExpectHTTPBuilder {
  method AfterT (line 27) | func (qt *cute) AfterT(fs ...AfterExecuteT) ExpectHTTPBuilder {
  method AfterExecute (line 33) | func (qt *cute) AfterExecute(fs ...AfterExecute) MiddlewareRequest {
  method AfterExecuteT (line 39) | func (qt *cute) AfterExecuteT(fs ...AfterExecuteT) MiddlewareRequest {
  method AfterTestExecute (line 45) | func (qt *cute) AfterTestExecute(fs ...AfterExecute) NextTestBuilder {
  method AfterTestExecuteT (line 56) | func (qt *cute) AfterTestExecuteT(fs ...AfterExecuteT) NextTestBuilder {

FILE: builder_option.go
  type options (line 8) | type options struct
  type Option (line 19) | type Option
  function WithHTTPClient (line 22) | func WithHTTPClient(client *http.Client) Option {
  function WithJSONMarshaler (line 29) | func WithJSONMarshaler(m JSONMarshaler) Option {
  function WithCustomHTTPTimeout (line 36) | func WithCustomHTTPTimeout(t time.Duration) Option {
  function WithCustomHTTPRoundTripper (line 43) | func WithCustomHTTPRoundTripper(r http.RoundTripper) Option {
  function WithMiddlewareAfter (line 50) | func WithMiddlewareAfter(after ...AfterExecute) Option {
  function WithMiddlewareAfterT (line 57) | func WithMiddlewareAfterT(after ...AfterExecuteT) Option {
  function WithMiddlewareBefore (line 64) | func WithMiddlewareBefore(before ...BeforeExecute) Option {
  function WithMiddlewareBeforeT (line 71) | func WithMiddlewareBeforeT(beforeT ...BeforeExecuteT) Option {

FILE: builder_request.go
  method RequestRepeat (line 12) | func (qt *cute) RequestRepeat(count int) RequestHTTPBuilder {
  method RequestRepeatDelay (line 22) | func (qt *cute) RequestRepeatDelay(delay time.Duration) RequestHTTPBuild...
  method RequestRepeatPolitic (line 33) | func (qt *cute) RequestRepeatPolitic(politic *RequestRepeatPolitic) Requ...
  method RequestRepeatOptional (line 51) | func (qt *cute) RequestRepeatOptional(option bool) RequestHTTPBuilder {
  method RequestRepeatBroken (line 60) | func (qt *cute) RequestRepeatBroken(broken bool) RequestHTTPBuilder {
  method RequestRetry (line 69) | func (qt *cute) RequestRetry(count int) RequestHTTPBuilder {
  method RequestRetryDelay (line 78) | func (qt *cute) RequestRetryDelay(delay time.Duration) RequestHTTPBuilder {
  method RequestRetryPolitic (line 88) | func (qt *cute) RequestRetryPolitic(politic *RequestRetryPolitic) Reques...
  method RequestRetryOptional (line 100) | func (qt *cute) RequestRetryOptional(option bool) RequestHTTPBuilder {
  method RequestRetryBroken (line 108) | func (qt *cute) RequestRetryBroken(broken bool) RequestHTTPBuilder {
  method RequestSanitizerHook (line 116) | func (qt *cute) RequestSanitizerHook(hook RequestSanitizerHook) RequestH...
  method ResponseSanitizerHook (line 124) | func (qt *cute) ResponseSanitizerHook(hook ResponseSanitizerHook) Reques...
  method Request (line 130) | func (qt *cute) Request(r *http.Request) ExpectHTTPBuilder {
  method RequestBuilder (line 136) | func (qt *cute) RequestBuilder(r ...RequestBuilder) ExpectHTTPBuilder {

FILE: builder_retry.go
  method Retry (line 8) | func (qt *cute) Retry(count int) MiddlewareRequest {
  method RetryDelay (line 21) | func (qt *cute) RetryDelay(delay time.Duration) MiddlewareRequest {

FILE: builder_table.go
  method CreateTableTest (line 5) | func (qt *cute) CreateTableTest() MiddlewareTable {
  method PutNewTest (line 11) | func (qt *cute) PutNewTest(name string, r *http.Request, expect *Expect)...
  method PutTests (line 34) | func (qt *cute) PutTests(tests ...*Test) TableTest {
  method fillBaseProps (line 56) | func (qt *cute) fillBaseProps(t *Test) {
  method NextTest (line 79) | func (qt *cute) NextTest() NextTestBuilder {

FILE: builder_table_test.go
  function TestFillBaseProps_WhenBasePropsIsNil (line 10) | func TestFillBaseProps_WhenBasePropsIsNil(t *testing.T) {
  function TestFillBaseProps_WhenBasePropsIsNotNil (line 21) | func TestFillBaseProps_WhenBasePropsIsNotNil(t *testing.T) {
  function TestFillBaseProps_WhenBasePropsIsNotNil_After (line 66) | func TestFillBaseProps_WhenBasePropsIsNotNil_After(t *testing.T) {
  function TestFillBaseProps_WhenBasePropsIsNotNil_Middleware (line 110) | func TestFillBaseProps_WhenBasePropsIsNotNil_Middleware(t *testing.T) {

FILE: builder_test.go
  function TestBuilderAfterTest (line 12) | func TestBuilderAfterTest(t *testing.T) {
  function TestBuilderAfterTestTwoStep (line 48) | func TestBuilderAfterTestTwoStep(t *testing.T) {
  function TestNewTestBuilder (line 142) | func TestNewTestBuilder(t *testing.T) {
  function TestHTTPTestMaker (line 157) | func TestHTTPTestMaker(t *testing.T) {
  function TestCreateDefaultTest (line 349) | func TestCreateDefaultTest(t *testing.T) {
  function TestCreateTableTest (line 371) | func TestCreateTableTest(t *testing.T) {
  function TestPutNewTest (line 378) | func TestPutNewTest(t *testing.T) {
  function TestPutTests (line 404) | func TestPutTests(t *testing.T) {
  function TestCreateHTTPTestMakerWithHttpClient (line 442) | func TestCreateHTTPTestMakerWithHttpClient(t *testing.T) {
  type rt (line 456) | type rt struct
    method RoundTrip (line 459) | func (r *rt) RoundTrip(*http.Request) (*http.Response, error) {
  function TestCreateHTTPMakerOps (line 463) | func TestCreateHTTPMakerOps(t *testing.T) {

FILE: cute.go
  type cute (line 14) | type cute struct
    method ExecuteTest (line 62) | func (qt *cute) ExecuteTest(ctx context.Context, t tProvider) []Result...
    method executeTests (line 118) | func (qt *cute) executeTests(ctx context.Context, allureProvider allur...
    method executeInsideAllure (line 152) | func (qt *cute) executeInsideAllure(ctx context.Context, allureProvide...
    method executeTestsInsideStep (line 162) | func (qt *cute) executeTestsInsideStep(ctx context.Context, stepCtx pr...
  type allureInformation (line 29) | type allureInformation struct
  type allureLabels (line 35) | type allureLabels struct
  type allureLinks (line 54) | type allureLinks struct
  function createAllureT (line 96) | func createAllureT(t *testing.T) *common.Common {

FILE: errors/broken.go
  type BrokenError (line 5) | type BrokenError interface
  function NewBrokenError (line 12) | func NewBrokenError(err string) error {
  function WrapBrokenError (line 20) | func WrapBrokenError(err error) error {

FILE: errors/error.go
  constant ActualField (line 7) | ActualField = "Actual"
  constant ExpectedField (line 9) | ExpectedField = "Expected"
  type AssertError (line 13) | type AssertError interface
  type WithNameError (line 23) | type WithNameError interface
  type WithFields (line 30) | type WithFields interface
  type WithTrace (line 36) | type WithTrace interface
  type Attachment (line 42) | type Attachment struct
  type WithAttachments (line 49) | type WithAttachments interface
  type CuteError (line 55) | type CuteError struct
    method Unwrap (line 125) | func (a *CuteError) Unwrap() error {
    method Error (line 131) | func (a *CuteError) Error() string {
    method GetName (line 147) | func (a *CuteError) GetName() string {
    method SetName (line 153) | func (a *CuteError) SetName(name string) {
    method GetFields (line 158) | func (a *CuteError) GetFields() map[string]interface{} {
    method PutFields (line 163) | func (a *CuteError) PutFields(fields map[string]interface{}) {
    method GetAttachments (line 170) | func (a *CuteError) GetAttachments() []*Attachment {
    method PutAttachment (line 175) | func (a *CuteError) PutAttachment(attachment *Attachment) {
    method IsOptional (line 180) | func (a *CuteError) IsOptional() bool {
    method SetOptional (line 185) | func (a *CuteError) SetOptional(opt bool) {
    method IsRequire (line 190) | func (a *CuteError) IsRequire() bool {
    method SetRequire (line 195) | func (a *CuteError) SetRequire(b bool) {
    method IsBroken (line 200) | func (a *CuteError) IsBroken() bool {
    method SetBroken (line 205) | func (a *CuteError) SetBroken(b bool) {
    method GetTrace (line 210) | func (a *CuteError) GetTrace() string {
    method SetTrace (line 215) | func (a *CuteError) SetTrace(trace string) {
  function NewCuteError (line 86) | func NewCuteError(name string, err error) *CuteError {
  function NewAssertError (line 94) | func NewAssertError(name string, message string, actual interface{}, exp...
  function NewAssertErrorWithMessage (line 107) | func NewAssertErrorWithMessage(name string, message string) error {
  function NewEmptyAssertError (line 115) | func NewEmptyAssertError(name string, message string) AssertError {

FILE: errors/optional.go
  type OptionalError (line 5) | type OptionalError interface
  function NewOptionalError (line 11) | func NewOptionalError(err string) error {
  function WrapOptionalError (line 19) | func WrapOptionalError(err error) error {

FILE: errors/require.go
  type RequireError (line 5) | type RequireError interface
  type requireError (line 10) | type requireError struct
  function NewRequireError (line 16) | func NewRequireError(err string) error {
  function WrapRequireError (line 24) | func WrapRequireError(err error) error {

FILE: errors/trace.go
  function NewErrorWithTrace (line 4) | func NewErrorWithTrace(err, trace string) error {
  function WrapErrorWithTrace (line 12) | func WrapErrorWithTrace(err error, trace string) error {

FILE: examples/custom_asserts.go
  function CustomAssertBodyWithCustomError (line 13) | func CustomAssertBodyWithCustomError() cute.AssertBody {
  function CustomAssertBody (line 23) | func CustomAssertBody() cute.AssertBody {
  function CustomAssertBodyT (line 33) | func CustomAssertBodyT() cute.AssertBodyT {
  function CustomAssertBodyWithAllureStep (line 41) | func CustomAssertBodyWithAllureStep() cute.AssertBodyT {
  function CustomAssertHeaders (line 60) | func CustomAssertHeaders() cute.AssertHeaders {
  function CustomAssertResponse (line 70) | func CustomAssertResponse() cute.AssertResponse {

FILE: examples/inside_step_test.go
  function TestInsideStep (line 19) | func TestInsideStep(t *testing.T) {

FILE: examples/masked_data_test.go
  function TestSanitizer (line 19) | func TestSanitizer(t *testing.T) {

FILE: examples/parallel_test.go
  function Test_Async_1 (line 16) | func Test_Async_1(t *testing.T) {
  function Test_Async_2 (line 51) | func Test_Async_2(t *testing.T) {

FILE: examples/single_test.go
  function Test_Single_1 (line 26) | func Test_Single_1(t *testing.T) {
  function Test_Single_Broken (line 78) | func Test_Single_Broken(t *testing.T) {
  function Test_Single_RepeatPolitic_Optional_Success_Test (line 103) | func Test_Single_RepeatPolitic_Optional_Success_Test(t *testing.T) {
  function Test_Single_RepeatPolitic_Broken_Failed_Test (line 121) | func Test_Single_RepeatPolitic_Broken_Failed_Test(t *testing.T) {
  function Test_Single_Broken_2 (line 139) | func Test_Single_Broken_2(t *testing.T) {
  function Test_Single_2_AllureRunner (line 163) | func Test_Single_2_AllureRunner(t *testing.T) {

FILE: examples/suite/common.go
  type ExampleSuite (line 13) | type ExampleSuite struct
    method BeforeAll (line 20) | func (i *ExampleSuite) BeforeAll(t provider.T) {
    method BeforeEach (line 31) | func (i *ExampleSuite) BeforeEach(t provider.T) {

FILE: examples/suite/main_test.go
  function TestExampleSuite (line 13) | func TestExampleSuite(t *testing.T) {

FILE: examples/suite/one_step.go
  method Test_OneStep (line 66) | func (i *ExampleSuite) Test_OneStep(t provider.T) {

FILE: examples/suite/one_step_errors.go
  method Test_OneStep_Errors (line 17) | func (i *ExampleSuite) Test_OneStep_Errors(t provider.T) {

FILE: examples/suite/simple.go
  method Test_Simple (line 21) | func (i *ExampleSuite) Test_Simple(t provider.T) {

FILE: examples/suite/two_steps.go
  method Test_TwoSteps (line 27) | func (i *ExampleSuite) Test_TwoSteps(t provider.T) {

FILE: examples/table_test/table_test.go
  function init (line 21) | func init() {
  function Test_Table (line 25) | func Test_Table(t *testing.T) {
  function Test_Table_Array (line 55) | func Test_Table_Array(t *testing.T) {
  function Test_One_Execute (line 101) | func Test_One_Execute(t *testing.T) {
  function Test_Array_Retry_OptionalFirstTries (line 116) | func Test_Array_Retry_OptionalFirstTries(t *testing.T) {
  function Test_Array_Retry_OptionalFirstTries_UltimatelyFailing (line 161) | func Test_Array_Retry_OptionalFirstTries_UltimatelyFailing(t *testing.T) {
  function Test_Array_TimeoutRetry (line 205) | func Test_Array_TimeoutRetry(t *testing.T) {
  function Test_Array (line 244) | func Test_Array(t *testing.T) {
  function Test_Array_All_Parallel (line 286) | func Test_Array_All_Parallel(t *testing.T) {
  function Test_Array_Some_Parallel (line 351) | func Test_Array_Some_Parallel(t *testing.T) {
  function Test_Array_Retry (line 420) | func Test_Array_Retry(t *testing.T) {
  function Test_Array_Timeout (line 465) | func Test_Array_Timeout(t *testing.T) {

FILE: examples/two_step_test.go
  function Test_TwoSteps_1 (line 19) | func Test_TwoSteps_1(t *testing.T) {
  function Test_TwoSteps_2_AllureRunner (line 48) | func Test_TwoSteps_2_AllureRunner(t *testing.T) {
  function Test_TwoSteps_3 (line 76) | func Test_TwoSteps_3(t *testing.T) {

FILE: examples/upload_file_test.go
  function TestUploadFile (line 14) | func TestUploadFile(t *testing.T) {

FILE: init.go
  function init (line 5) | func init() {
  function NewTestBuilder (line 11) | func NewTestBuilder() AllureBuilder {

FILE: interface.go
  type AllureBuilder (line 12) | type AllureBuilder interface
  type AllureInfoBuilder (line 25) | type AllureInfoBuilder interface
  type AllureLinksBuilder (line 37) | type AllureLinksBuilder interface
  type AllureLabelsBuilder (line 46) | type AllureLabelsBuilder interface
  type CreateBuilder (line 68) | type CreateBuilder interface
  type MiddlewareTable (line 80) | type MiddlewareTable interface
  type MiddlewareRequest (line 88) | type MiddlewareRequest interface
  type RetryPolitic (line 97) | type RetryPolitic interface
  type BeforeTest (line 112) | type BeforeTest interface
  type After (line 123) | type After interface
  type AfterTest (line 134) | type AfterTest interface
  type AfterTestExecute (line 145) | type AfterTestExecute interface
  type TableTest (line 153) | type TableTest interface
  type RequestHTTPBuilder (line 162) | type RequestHTTPBuilder interface
  type RequestParams (line 187) | type RequestParams interface
  type ExpectHTTPBuilder (line 238) | type ExpectHTTPBuilder interface
  type ControlTest (line 342) | type ControlTest interface
  type NextTestBuilder (line 350) | type NextTestBuilder interface
  type ResultsHTTPBuilder (line 357) | type ResultsHTTPBuilder interface
  type BeforeExecute (line 370) | type BeforeExecute
  type BeforeExecuteT (line 373) | type BeforeExecuteT
  type AfterExecute (line 376) | type AfterExecute
  type AfterExecuteT (line 379) | type AfterExecuteT

FILE: internal/utils/body.go
  function GetBody (line 10) | func GetBody(body io.ReadCloser) ([]byte, error) {
  function DrainBody (line 25) | func DrainBody(body io.ReadCloser) (r1, r2 io.ReadCloser, err error) {

FILE: internal/utils/json.go
  function ToJSON (line 9) | func ToJSON(v interface{}) (string, error) {
  function PrettyJSON (line 16) | func PrettyJSON(b []byte) ([]byte, error) {

FILE: json_marshaler.go
  type JSONMarshaler (line 6) | type JSONMarshaler interface
  type jsonMarshaler (line 11) | type jsonMarshaler struct
    method Marshal (line 14) | func (j jsonMarshaler) Marshal(v any) ([]byte, error) {
    method Unmarshal (line 18) | func (j jsonMarshaler) Unmarshal(data []byte, v any) error {

FILE: jsonschema.go
  method validateJSONSchema (line 12) | func (it *Test) validateJSONSchema(t internalT, body []byte) []error {
  function checkJSONSchema (line 33) | func checkJSONSchema(expect gojsonschema.JSONLoader, data []byte) []error {
  function createJSONSchemaError (line 53) | func createJSONSchemaError(err gojsonschema.ResultError) error {

FILE: jsonschema_test.go
  function TestValidateJSONSchemaEmptySchema (line 10) | func TestValidateJSONSchemaEmptySchema(t *testing.T) {
  function TestValidateJSONSchemaFromString (line 21) | func TestValidateJSONSchemaFromString(t *testing.T) {
  function TestValidateJSONSchemaFromStringWithError (line 62) | func TestValidateJSONSchemaFromStringWithError(t *testing.T) {
  function TestValidateJSONSchemaFromByteWithTwoError (line 112) | func TestValidateJSONSchemaFromByteWithTwoError(t *testing.T) {

FILE: logger.go
  type tlogger (line 7) | type tlogger interface
  method Info (line 14) | func (it *Test) Info(t tlogger, format string, args ...interface{}) {
  method Error (line 19) | func (it *Test) Error(t tlogger, format string, args ...interface{}) {
  method Debug (line 24) | func (it *Test) Debug(t tlogger, format string, args ...interface{}) {
  method logf (line 28) | func (it *Test) logf(t tlogger, level, format string, args ...interface{...
  method errorf (line 42) | func (it *Test) errorf(t tlogger, level, format string, args ...interfac...

FILE: provider.go
  type T (line 9) | type T interface
  type allureProvider (line 17) | type allureProvider interface
  type internalT (line 29) | type internalT interface
  type tProvider (line 39) | type tProvider interface
  type logProvider (line 52) | type logProvider interface
  type stepProvider (line 57) | type stepProvider interface
  type attachmentProvider (line 62) | type attachmentProvider interface
  type parametersProvider (line 67) | type parametersProvider interface
  type infoAllureProvider (line 72) | type infoAllureProvider interface
  type labelsAllureProvider (line 83) | type labelsAllureProvider interface
  type linksAllureProvider (line 102) | type linksAllureProvider interface

FILE: request.go
  type RequestBuilder (line 8) | type RequestBuilder
  type File (line 13) | type File struct
  type requestOptions (line 19) | type requestOptions struct
  function newRequestOptions (line 32) | func newRequestOptions() *requestOptions {
  function WithMethod (line 42) | func WithMethod(method string) func(o *requestOptions) {
  function WithURL (line 49) | func WithURL(url *url.URL) func(o *requestOptions) {
  function WithURI (line 56) | func WithURI(uri string) func(o *requestOptions) {
  function WithHeaders (line 63) | func WithHeaders(headers map[string][]string) func(o *requestOptions) {
  function WithHeadersKV (line 72) | func WithHeadersKV(name string, value string) func(o *requestOptions) {
  function WithQueryKV (line 79) | func WithQueryKV(name string, value string) func(o *requestOptions) {
  function WithQuery (line 86) | func WithQuery(queries map[string][]string) func(o *requestOptions) {
  function WithBody (line 95) | func WithBody(body []byte) func(o *requestOptions) {
  function WithMarshalBody (line 102) | func WithMarshalBody(body interface{}) func(o *requestOptions) {
  function WithFileFormKV (line 109) | func WithFileFormKV(name string, file *File) func(o *requestOptions) {
  function WithFileForm (line 116) | func WithFileForm(fileForms map[string]*File) func(o *requestOptions) {
  function WithFormKV (line 125) | func WithFormKV(name string, body []byte) func(o *requestOptions) {
  function WithForm (line 132) | func WithForm(forms map[string][]byte) func(o *requestOptions) {

FILE: request_test.go
  function TestRequest (line 11) | func TestRequest(t *testing.T) {

FILE: result.go
  type ResultState (line 8) | type ResultState
  constant ResultStateSuccess (line 12) | ResultStateSuccess ResultState = iota
  constant ResultStateBroken (line 13) | ResultStateBroken
  constant ResultStateFail (line 14) | ResultStateFail
  constant resultStateFailNow (line 17) | resultStateFailNow
  type testResults (line 20) | type testResults struct
    method GetHTTPResponse (line 36) | func (r *testResults) GetHTTPResponse() *http.Response {
    method GetErrors (line 40) | func (r *testResults) GetErrors() []error {
    method GetName (line 44) | func (r *testResults) GetName() string {
    method GetResultState (line 48) | func (r *testResults) GetResultState() ResultState {
  function newTestResult (line 27) | func newTestResult(name string, resp *http.Response, state ResultState, ...

FILE: result_test.go
  function TestResult (line 11) | func TestResult(t *testing.T) {

FILE: roundtripper.go
  method makeRequest (line 19) | func (it *Test) makeRequest(t internalT, req *http.Request) (*http.Respo...
  method doRequest (line 69) | func (it *Test) doRequest(t T, baseReq *http.Request) (*http.Response, e...
  method validateResponseCode (line 134) | func (it *Test) validateResponseCode(resp *http.Response) error {
  method addInformationRequest (line 146) | func (it *Test) addInformationRequest(t T, req *http.Request) error {
  function copyRequest (line 204) | func copyRequest(ctx context.Context, req *http.Request) (*http.Request,...
  method addInformationResponse (line 219) | func (it *Test) addInformationResponse(t T, response *http.Response) err...
  method createTitle (line 279) | func (it *Test) createTitle(try, countRepeat int, req *http.Request) str...

FILE: step.go
  method executeWithStep (line 11) | func (it *Test) executeWithStep(t internalT, stepName string, execute fu...
  function processStepErrors (line 28) | func processStepErrors(stepCtx provider.StepCtx, errs []error) {

FILE: test.go
  constant defaultExecuteTestTime (line 23) | defaultExecuteTestTime = 10 * time.Second
  constant defaultDelayRepeat (line 24) | defaultDelayRepeat     = 1 * time.Second
  type RequestSanitizerHook (line 34) | type RequestSanitizerHook
  type ResponseSanitizerHook (line 38) | type ResponseSanitizerHook
  type Test (line 43) | type Test struct
    method Execute (line 140) | func (it *Test) Execute(ctx context.Context, t tProvider) ResultsHTTPB...
    method clearFields (line 176) | func (it *Test) clearFields() {
    method initEmptyFields (line 185) | func (it *Test) initEmptyFields() {
    method executeInsideStep (line 232) | func (it *Test) executeInsideStep(ctx context.Context, t internalT) Re...
    method executeInsideAllure (line 242) | func (it *Test) executeInsideAllure(ctx context.Context, allureProvide...
    method startRepeatableTest (line 259) | func (it *Test) startRepeatableTest(ctx context.Context, t internalT) ...
    method startTestInsideStep (line 304) | func (it *Test) startTestInsideStep(ctx context.Context, t internalT) ...
    method processTestErrors (line 327) | func (it *Test) processTestErrors(t internalT, errs []error) ResultSta...
    method startTest (line 391) | func (it *Test) startTest(ctx context.Context, t internalT) (*http.Res...
    method afterTest (line 441) | func (it *Test) afterTest(t internalT, resp *http.Response, errs []err...
    method beforeTest (line 465) | func (it *Test) beforeTest(t internalT, req *http.Request) []error {
    method createRequest (line 490) | func (it *Test) createRequest(ctx context.Context) (*http.Request, err...
    method buildRequest (line 516) | func (it *Test) buildRequest(ctx context.Context) (*http.Request, erro...
    method validateRequest (line 654) | func (it *Test) validateRequest(req *http.Request) error {
    method validateResponse (line 666) | func (it *Test) validateResponse(t internalT, resp *http.Response) []e...
  type Retry (line 68) | type Retry struct
  type Request (line 76) | type Request struct
  type RequestRetryPolitic (line 87) | type RequestRetryPolitic struct
  type RequestRepeatPolitic (line 96) | type RequestRepeatPolitic struct
  type Middleware (line 104) | type Middleware struct
  type AllureStep (line 112) | type AllureStep struct
  type Expect (line 117) | type Expect struct
  type ExpectJSONSchema (line 133) | type ExpectJSONSchema struct
  function createFormFile (line 606) | func createFormFile(mp *multipart.Writer, fieldName string, file *File) ...
  function createFormField (line 640) | func createFormField(mp *multipart.Writer, fieldName string, body []byte...

FILE: test_test.go
  function TestCreateRequest (line 20) | func TestCreateRequest(t *testing.T) {
  function TestCreateRequestBuilder (line 35) | func TestCreateRequestBuilder(t *testing.T) {
  function TestCreateRequestBuilder_MarshalBody (line 66) | func TestCreateRequestBuilder_MarshalBody(t *testing.T) {
  function TestValidateRequestEmptyUrl (line 93) | func TestValidateRequestEmptyUrl(t *testing.T) {
  function TestValidateRequestEmptyMethod (line 99) | func TestValidateRequestEmptyMethod(t *testing.T) {
  function TestValidateResponseEmpty (line 108) | func TestValidateResponseEmpty(t *testing.T) {
  function TestValidateResponseCode (line 119) | func TestValidateResponseCode(t *testing.T) {
  function TestValidateResponseWithErrors (line 129) | func TestValidateResponseWithErrors(t *testing.T) {
  type mockRoundTripper (line 170) | type mockRoundTripper struct
    method RoundTrip (line 172) | func (m *mockRoundTripper) RoundTrip(req *http.Request) (*http.Respons...
  function TestSanitizeURLHook (line 180) | func TestSanitizeURLHook(t *testing.T) {
  function TestSanitizeURL_LastRequestURL (line 219) | func TestSanitizeURL_LastRequestURL(t *testing.T) {
  function sanitizeKeyParam (line 243) | func sanitizeKeyParam(mask string) RequestSanitizerHook {
  function TestSanitizeURL_RealRequest (line 251) | func TestSanitizeURL_RealRequest(t *testing.T) {
Condensed preview — 72 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (290K chars).
[
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "chars": 672,
    "preview": "---\nname: Bug report \\\nabout: Create a report to help us improve \\\ntitle: ' ' \\\nlabels: ' ' \\\nassignees: ' ' \n\n---\n\n**De"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "chars": 610,
    "preview": "---\nname: Feature request \\\nabout: Suggest an idea for this project \\\ntitle: '' \\\nlabels: '' \\\nassignees: ''\n\n---\n\n**Is "
  },
  {
    "path": ".github/workflows/main.yml",
    "chars": 1236,
    "preview": "name: CI\n\non:\n  push:\n    branches: [ master ]\n  pull_request:\n    branches: [ master ]\n\njobs:\n  build_and_test:\n    run"
  },
  {
    "path": ".gitignore",
    "chars": 239,
    "preview": ".idea/\ntestdata/\nallure-results/\nbin/\nvendor/\n\n# Binaries for programs and plugins\n*.exe\n*.exe~\n*.dll\n*.so\n*.dylib\n\n# Te"
  },
  {
    "path": ".golangci.yaml",
    "chars": 1586,
    "preview": "run:\n  timeout: 10m\n  issues-exit-code: 1\n  tests: true\n  skip-dirs:\n    - bin\n    - vendor\n    - var\n    - tmp\n  skip-f"
  },
  {
    "path": "LICENSE",
    "chars": 11357,
    "preview": "                                 Apache License\n                           Version 2.0, January 2004\n                   "
  },
  {
    "path": "Makefile",
    "chars": 2139,
    "preview": "export GO111MODULE=on\nexport GOSUMDB=off\nLOCAL_BIN:=$(CURDIR)/bin\n\n##################### GOLANG-CI RELATED CHECKS ######"
  },
  {
    "path": "README.MD",
    "chars": 17593,
    "preview": "<p align=\"center\">\n  <img src=\".images/cute.png\" alt=\"cute\"/>\n</p>\n\n# CUTE — create your tests easily\n\nHTTP and REST API"
  },
  {
    "path": "allure.go",
    "chars": 2152,
    "preview": "package cute\n\nfunc (qt *cute) setAllureInformation(t allureProvider) {\n\t// Log main vars to allureProvider\n\tqt.setLabels"
  },
  {
    "path": "assert.go",
    "chars": 3451,
    "preview": "package cute\n\nimport (\n\t\"net/http\"\n)\n\n// This is type of asserts, for create some assert with using custom logic.\n\n// As"
  },
  {
    "path": "assert_broken.go",
    "chars": 1278,
    "preview": "package cute\n\nimport (\n\t\"net/http\"\n\n\t\"github.com/ozontech/cute/errors\"\n)\n\nfunc brokenAssertHeaders(assert AssertHeaders)"
  },
  {
    "path": "assert_broken_test.go",
    "chars": 2190,
    "preview": "package cute\n\nimport (\n\t\"errors\"\n\t\"net/http\"\n\t\"testing\"\n\n\tcuteErrors \"github.com/ozontech/cute/errors\"\n\t\"github.com/stre"
  },
  {
    "path": "assert_optional.go",
    "chars": 1310,
    "preview": "package cute\n\nimport (\n\t\"net/http\"\n\n\t\"github.com/ozontech/cute/errors\"\n)\n\nfunc optionalAssertHeaders(assert AssertHeader"
  },
  {
    "path": "assert_optional_test.go",
    "chars": 2268,
    "preview": "package cute\n\nimport (\n\t\"errors\"\n\t\"net/http\"\n\t\"testing\"\n\n\tcuteErrors \"github.com/ozontech/cute/errors\"\n\t\"github.com/stre"
  },
  {
    "path": "assert_require.go",
    "chars": 1294,
    "preview": "package cute\n\nimport (\n\t\"net/http\"\n\n\t\"github.com/ozontech/cute/errors\"\n)\n\nfunc requireAssertHeaders(assert AssertHeaders"
  },
  {
    "path": "assert_require_test.go",
    "chars": 2228,
    "preview": "package cute\n\nimport (\n\t\"errors\"\n\t\"net/http\"\n\t\"testing\"\n\n\tcuteErrors \"github.com/ozontech/cute/errors\"\n\t\"github.com/stre"
  },
  {
    "path": "assert_trace.go",
    "chars": 2294,
    "preview": "package cute\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"runtime\"\n\n\t\"github.com/ozontech/cute/errors\"\n)\n\n// assertHeadersWithTrace is"
  },
  {
    "path": "asserts/headers/headers.go",
    "chars": 742,
    "preview": "package headers\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\n\t\"github.com/ozontech/cute\"\n\t\"github.com/ozontech/cute/errors\"\n)\n\n// Prese"
  },
  {
    "path": "asserts/headers/headers_test.go",
    "chars": 791,
    "preview": "package headers\n\nimport (\n\t\"net/http\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestPresent(t *testing."
  },
  {
    "path": "asserts/json/json.go",
    "chars": 5466,
    "preview": "package json\n\nimport (\n\t\"fmt\"\n\n\tjd \"github.com/josephburnett/jd/lib\"\n\t\"github.com/ohler55/ojg/jp\"\n\t\"github.com/ohler55/o"
  },
  {
    "path": "asserts/json/json_test.go",
    "chars": 22387,
    "preview": "package json\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/require\"\n)\n\ntype "
  },
  {
    "path": "asserts/json/util.go",
    "chars": 9336,
    "preview": "package json\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"reflect\"\n\t\"strings\"\n\n\t\"github.com/ohler55/ojg/oj\"\n\t\"github.com/ozontech/cute/er"
  },
  {
    "path": "builder.go",
    "chars": 3427,
    "preview": "package cute\n\nimport (\n\t\"net/http\"\n\t\"time\"\n)\n\nconst defaultHTTPTimeout = 30\n\nvar (\n\terrorAssertIsNil = \"assert must be n"
  },
  {
    "path": "builder_allure.go",
    "chars": 3111,
    "preview": "package cute\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/ozontech/allure-go/pkg/allure\"\n)\n\nfunc (qt *cute) Parallel() AllureBuilder {"
  },
  {
    "path": "builder_asserts.go",
    "chars": 9442,
    "preview": "package cute\n\nimport \"time\"\n\nfunc (qt *cute) AssertBody(asserts ...AssertBody) ExpectHTTPBuilder {\n\ttrace := getTrace()\n"
  },
  {
    "path": "builder_middleware.go",
    "chars": 1782,
    "preview": "package cute\n\nfunc (qt *cute) StepName(name string) MiddlewareRequest {\n\tqt.tests[qt.countTests].AllureStep.Name = name\n"
  },
  {
    "path": "builder_option.go",
    "chars": 1959,
    "preview": "package cute\n\nimport (\n\t\"net/http\"\n\t\"time\"\n)\n\ntype options struct {\n\thttpClient       *http.Client\n\thttpTimeout      tim"
  },
  {
    "path": "builder_request.go",
    "chars": 5014,
    "preview": "package cute\n\nimport (\n\t\"net/http\"\n\t\"time\"\n)\n\n// RequestRepeat is a function for set options in request\n// if response.C"
  },
  {
    "path": "builder_retry.go",
    "chars": 781,
    "preview": "package cute\n\nimport \"time\"\n\n// Retry is a function for configure test repeat\n// if response.Code != Expect.Code or any "
  },
  {
    "path": "builder_table.go",
    "chars": 1931,
    "preview": "package cute\n\nimport \"net/http\"\n\nfunc (qt *cute) CreateTableTest() MiddlewareTable {\n\tqt.isTableTest = true\n\n\treturn qt\n"
  },
  {
    "path": "builder_table_test.go",
    "chars": 4902,
    "preview": "package cute\n\nimport (\n\t\"net/http\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestFillBaseProps_WhenBase"
  },
  {
    "path": "builder_test.go",
    "chars": 12008,
    "preview": "package cute\n\nimport (\n\t\"net/http\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/ozontech/allure-go/pkg/allure\"\n\t\"github.com/stretchr"
  },
  {
    "path": "cute.go",
    "chars": 3964,
    "preview": "package cute\n\nimport (\n\t\"context\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/ozontech/allure-go/pkg/allure\"\n\t\"github.com/ozonte"
  },
  {
    "path": "errors/broken.go",
    "chars": 593,
    "preview": "package errors\n\n// BrokenError is an interface for set errors like Broken errors.\n// If the function returns an error, w"
  },
  {
    "path": "errors/error.go",
    "chars": 5591,
    "preview": "package errors\n\nimport \"fmt\"\n\nconst (\n\t// ActualField is a key for actual value in error fields\n\tActualField = \"Actual\"\n"
  },
  {
    "path": "errors/optional.go",
    "chars": 606,
    "preview": "package errors\n\n// OptionalError is an interface for set errors like Optional errors.\n// If the function returns an erro"
  },
  {
    "path": "errors/require.go",
    "chars": 720,
    "preview": "package errors\n\n// RequireError is an interface for set errors like require error.\n// If the function returns an error, "
  },
  {
    "path": "errors/trace.go",
    "chars": 363,
    "preview": "package errors\n\n// NewErrorWithTrace is a function for create error with trace\nfunc NewErrorWithTrace(err, trace string)"
  },
  {
    "path": "examples/custom_asserts.go",
    "chars": 1622,
    "preview": "package examples\n\nimport (\n\t\"errors\"\n\t\"net/http\"\n\n\t\"github.com/ozontech/allure-go/pkg/allure\"\n\t\"github.com/ozontech/cute"
  },
  {
    "path": "examples/inside_step_test.go",
    "chars": 1075,
    "preview": "//go:build example\n// +build example\n\npackage examples\n\nimport (\n\t\"context\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"testing\"\n\t\"time\"\n\n\t"
  },
  {
    "path": "examples/masked_data_test.go",
    "chars": 1608,
    "preview": "//go:build example\n// +build example\n\npackage examples\n\nimport (\n\t\"context\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"testing\"\n\t\"time\"\n\n\t"
  },
  {
    "path": "examples/parallel_test.go",
    "chars": 2085,
    "preview": "//go:build example\n// +build example\n\npackage examples\n\nimport (\n\t\"context\"\n\t\"net/http\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com"
  },
  {
    "path": "examples/single_test.go",
    "chars": 5004,
    "preview": "//go:build example\n// +build example\n\npackage examples\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/url"
  },
  {
    "path": "examples/suite/common.go",
    "chars": 659,
    "preview": "package suite\n\nimport (\n\t\"net/url\"\n\n\t\"github.com/ozontech/allure-go/pkg/framework/provider\"\n\t\"github.com/ozontech/allure"
  },
  {
    "path": "examples/suite/main_test.go",
    "chars": 294,
    "preview": "//go:build example\n// +build example\n\npackage suite\n\nimport (\n\t\"os\"\n\t\"testing\"\n\n\t\"github.com/ozontech/allure-go/pkg/fram"
  },
  {
    "path": "examples/suite/one_step.go",
    "chars": 3921,
    "preview": "package suite\n\nimport (\n\t\"context\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"path\"\n\t\"time\"\n\n\t\"github.com/ozontech/allure-go/pkg/framework"
  },
  {
    "path": "examples/suite/one_step_errors.go",
    "chars": 2171,
    "preview": "package suite\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"net/http\"\n\t\"time\"\n\n\t\"github.com/ozontech/allure-go/pkg/framework/provider"
  },
  {
    "path": "examples/suite/resources/example_valid_request.json",
    "chars": 2384,
    "preview": "{\n  \"$schema\": \"http://json-schema.org/draft-04/schema#\",\n  \"type\": \"array\",\n  \"items\": [\n    {\n      \"type\": \"object\",\n"
  },
  {
    "path": "examples/suite/simple.go",
    "chars": 864,
    "preview": "package suite\n\nimport (\n\t\"context\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"time\"\n\n\t\"github.com/ozontech/allure-go/pkg/framework/provide"
  },
  {
    "path": "examples/suite/two_steps.go",
    "chars": 1942,
    "preview": "package suite\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"path\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/o"
  },
  {
    "path": "examples/table_test/table_test.go",
    "chars": 10343,
    "preview": "//go:build example\n// +build example\n\npackage table_test\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"os\"\n\t\"strc"
  },
  {
    "path": "examples/two_step_test.go",
    "chars": 2916,
    "preview": "//go:build example\n// +build example\n\npackage examples\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"testing\"\n\t\"ti"
  },
  {
    "path": "examples/upload_file_test.go",
    "chars": 641,
    "preview": "//go:build example_upload_file\n// +build example_upload_file\n\npackage examples\n\nimport (\n\t\"context\"\n\t\"net/http\"\n\t\"testin"
  },
  {
    "path": "go.mod",
    "chars": 961,
    "preview": "module github.com/ozontech/cute\n\ngo 1.21\n\nrequire (\n\tgithub.com/josephburnett/jd v1.7.1\n\tgithub.com/ohler55/ojg v1.21.1\n"
  },
  {
    "path": "go.sum",
    "chars": 8276,
    "preview": "github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=\ngithub.com/davecgh/go-spew v1.1.0/go"
  },
  {
    "path": "init.go",
    "chars": 297,
    "preview": "package cute\n\nvar commonBuilder *HTTPTestMaker\n\nfunc init() {\n\tcommonBuilder = NewHTTPTestMaker()\n}\n\n// NewTestBuilder i"
  },
  {
    "path": "interface.go",
    "chars": 16495,
    "preview": "package cute\n\nimport (\n\t\"context\"\n\t\"net/http\"\n\t\"time\"\n\n\t\"github.com/ozontech/allure-go/pkg/allure\"\n)\n\n// AllureBuilder i"
  },
  {
    "path": "internal/utils/body.go",
    "chars": 761,
    "preview": "package utils\n\nimport (\n\t\"bytes\"\n\t\"io\"\n\t\"net/http\"\n)\n\n// GetBody get body from IO\nfunc GetBody(body io.ReadCloser) ([]by"
  },
  {
    "path": "internal/utils/json.go",
    "chars": 479,
    "preview": "package utils\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n)\n\n// ToJSON returns string Json representation of any object that can"
  },
  {
    "path": "json_marshaler.go",
    "chars": 432,
    "preview": "package cute\n\nimport \"encoding/json\"\n\n// JSONMarshaler is marshaler which use for marshal/unmarshal JSON to/from struct\n"
  },
  {
    "path": "jsonschema.go",
    "chars": 2018,
    "preview": "package cute\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/ozontech/cute/errors\"\n\t\"github.com/xeipuuv/gojsonschema\"\n)\n\n// Validate is a"
  },
  {
    "path": "jsonschema_test.go",
    "chars": 3364,
    "preview": "package cute\n\nimport (\n\t\"testing\"\n\n\tcuteErrors \"github.com/ozontech/cute/errors\"\n\t\"github.com/stretchr/testify/require\"\n"
  },
  {
    "path": "logger.go",
    "chars": 1521,
    "preview": "package cute\n\nimport (\n\t\"fmt\"\n)\n\ntype tlogger interface {\n\tName() string\n\tLogf(format string, args ...any)\n\tErrorf(forma"
  },
  {
    "path": "provider.go",
    "chars": 2239,
    "preview": "package cute\n\nimport (\n\t\"github.com/ozontech/allure-go/pkg/allure\"\n\t\"github.com/ozontech/allure-go/pkg/framework/provide"
  },
  {
    "path": "request.go",
    "chars": 3477,
    "preview": "package cute\n\nimport (\n\t\"net/url\"\n)\n\n// RequestBuilder is a function for set options in request\ntype RequestBuilder func"
  },
  {
    "path": "request_test.go",
    "chars": 991,
    "preview": "package cute\n\nimport (\n\t\"net/http\"\n\t\"net/url\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestRequest(t *"
  },
  {
    "path": "result.go",
    "chars": 942,
    "preview": "package cute\n\nimport (\n\t\"net/http\"\n)\n\n// ResultState is state of test\ntype ResultState int\n\n// ResultState is state of t"
  },
  {
    "path": "result_test.go",
    "chars": 661,
    "preview": "package cute\n\nimport (\n\t\"errors\"\n\t\"net/http\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestResult(t *te"
  },
  {
    "path": "roundtripper.go",
    "chars": 7338,
    "preview": "package cute\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/ozontech/allure-go"
  },
  {
    "path": "step.go",
    "chars": 2031,
    "preview": "package cute\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/ozontech/allure-go/pkg/allure\"\n\t\"github.com/ozontech/allure-go/pkg/framework"
  },
  {
    "path": "test.go",
    "chars": 16631,
    "preview": "package cute\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"mime/multipart\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"os\"\n\t\"testi"
  },
  {
    "path": "test_test.go",
    "chars": 5824,
    "preview": "package cute\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"errors\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"net/url\"\n\t\"strings\"\n\t\"test"
  }
]

About this extraction

This page contains the full source code of the ozontech/cute GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 72 files (255.0 KB), approximately 73.4k tokens, and a symbol index with 470 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!