From cb45b89ece7629778916c0bf2e3bd31b575e8ede Mon Sep 17 00:00:00 2001 From: eynopv Date: Wed, 16 Apr 2025 19:16:30 +0300 Subject: [PATCH 1/3] WIP --- pkg/printer/outputter.go | 26 ++++++++++++++++ pkg/printer/printer.go | 65 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 pkg/printer/outputter.go diff --git a/pkg/printer/outputter.go b/pkg/printer/outputter.go new file mode 100644 index 0000000..346e31e --- /dev/null +++ b/pkg/printer/outputter.go @@ -0,0 +1,26 @@ +package printer + +import ( + "io" + + "github.com/eynopv/lac/pkg/result" +) + +type Includes struct { + ResponseBody bool + ResponseHeaders bool + ResponseMeta bool + RequestBody bool + RequestHeaders bool + RequestMeta bool +} + +type Outputter struct { + includes Includes + destination io.Writer + formatter Formatter +} + +func (o *Outputter) Write(res *result.Result) error { + +} diff --git a/pkg/printer/printer.go b/pkg/printer/printer.go index 5dd3f65..5d7125b 100644 --- a/pkg/printer/printer.go +++ b/pkg/printer/printer.go @@ -1,6 +1,7 @@ package printer import ( + "encoding/json" "fmt" "io" "os" @@ -28,7 +29,7 @@ type Printer struct { func NewPrinter(config PrinterConfig) Printer { formatter := Formatter{ - colored: IsTerminal(int(os.Stdout.Fd())), + colored: true, } return Printer{ @@ -39,11 +40,23 @@ func NewPrinter(config PrinterConfig) Printer { } func (p *Printer) Print(res *result.Result) { + var output string + if res.Response == nil { fmt.Fprint(p.destination, "No HTTP response available\n") return } + if IsTerminal(int(os.Stdout.Fd())) { + output = p.makeTerminalOutput(res) + } else { + output = p.makeNonTerminalOutput(res) + } + + fmt.Fprint(p.destination, output) +} + +func (p *Printer) makeTerminalOutput(res *result.Result) string { sections := []string{} if p.config.PrintRequestHeaders { @@ -62,7 +75,55 @@ func (p *Printer) Print(res *result.Result) { sections = append(sections, p.printBody(&res.ResponseBody)) } - fmt.Fprint(p.destination, strings.Join(sections, "\n")) + return strings.Join(sections, "\n") +} + +func (p *Printer) makeNonTerminalOutput(res *result.Result) string { + m := map[string]any{} + + if p.config.PrintRequestHeaders || p.config.PrintRequestBody { + rm := map[string]any{} + + if p.config.PrintRequestHeaders { + rm["headers"] = res.Response.Request.Header + } + + if p.config.PrintRequestBody { + if jsonBody := res.RequestBody.Json(); jsonBody != nil { + rm["body"] = jsonBody + } else if textBody := res.RequestBody.Text(); textBody != "" { + rm["body"] = textBody + } + } + + m["request"] = rm + } + + if p.config.PrintResponseHeaders || p.config.PrintResponseBody { + rm := map[string]any{} + + if p.config.PrintResponseHeaders { + rm["headers"] = res.Response.Header + } + + if p.config.PrintResponseBody { + if jsonBody := res.ResponseBody.Json(); jsonBody != nil { + rm["body"] = jsonBody + } else if textBody := res.ResponseBody.Text(); textBody != "" { + rm["body"] = textBody + } + } + + m["response"] = rm + } + + b, err := json.MarshalIndent(m, "", " ") + + if err != nil { + return err.Error() + } + + return string(b) } func (p *Printer) printRequestHeaders(res *result.Result) string { From bf5c89b80825792ab79147b6e61e96a11c35f8bd Mon Sep 17 00:00:00 2001 From: eynopv Date: Mon, 16 Jun 2025 18:43:55 +0300 Subject: [PATCH 2/3] i just push this stuff so i can continue work --- cmd/run.go | 7 +- pkg/builder/builder.go | 5 + pkg/printer/formatter.go | 129 ++++++++++++-- pkg/printer/formatter_test.go | 322 ---------------------------------- pkg/printer/outputter.go | 39 +++- pkg/printer/printer.go | 18 +- pkg/result/result.go | 24 ++- 7 files changed, 194 insertions(+), 350 deletions(-) delete mode 100644 pkg/printer/formatter_test.go diff --git a/cmd/run.go b/cmd/run.go index b5028bf..3a9882d 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -28,6 +28,9 @@ func runCommandFunction(bldr *builder.Builder) { os.Exit(1) } - prntr := bldr.BuildPrinter() - prntr.Print(result) + outputter := bldr.BuildOutputter() + if err := outputter.Write(result); err != nil { + fmt.Println(err) + os.Exit(1) + } } diff --git a/pkg/builder/builder.go b/pkg/builder/builder.go index 8d35cef..af2560f 100644 --- a/pkg/builder/builder.go +++ b/pkg/builder/builder.go @@ -58,3 +58,8 @@ func (b *Builder) BuildPrinter() *printer.Printer { p := printer.NewPrinter(b.ClientConfig.PrinterConfig) return &p } + +func (b *Builder) BuildOutputter() *printer.Outputter { + o := printer.NewOutputter(b.ClientConfig.PrinterConfig) + return o +} diff --git a/pkg/printer/formatter.go b/pkg/printer/formatter.go index 1db3a2b..9f6b361 100644 --- a/pkg/printer/formatter.go +++ b/pkg/printer/formatter.go @@ -1,6 +1,7 @@ package printer import ( + "encoding/json" "fmt" "net/http" "sort" @@ -11,24 +12,132 @@ import ( "github.com/eynopv/lac/pkg/result" ) -type Formatter struct { - colored bool +type Formatter interface { + Format(res *result.Result) (string, error) } -func (f Formatter) Headers(headers http.Header) string { - return formatHeaders(headers, f.colored) +type JsonFormatter struct { + includes Includes } -func (f Formatter) StatusLine(line result.StatusLine) string { - return formatStatusLine(line, f.colored) +func (f *JsonFormatter) Format(res *result.Result) (string, error) { + m := map[string]any{} + + if f.includes.RequestHeaders || f.includes.RequestBody || f.includes.RequestMeta { + rm := map[string]any{} + + if f.includes.RequestMeta { + rm["meta"] = res.RequestLine() + } + + if f.includes.RequestHeaders { + rm["headers"] = res.Response.Request.Header + } + + if f.includes.RequestBody { + rm["body"] = res.RequestBody.Data() + } + + m["request"] = rm + } + + if f.includes.ResponseHeaders || f.includes.ResponseBody || f.includes.ResponseMeta { + rm := map[string]any{} + + if f.includes.ResponseMeta { + rm["meta"] = res.StatusLine() + } + + if f.includes.ResponseHeaders { + rm["headers"] = res.Response.Header + } + + if f.includes.ResponseBody { + rm["body"] = res.ResponseBody.Data() + } + + m["response"] = rm + } + + b, err := json.MarshalIndent(m, "", " ") + + if err != nil { + return "", err + } + + return string(b), nil +} + +type PrettyFormatter struct { + includes Includes +} + +func (f *PrettyFormatter) Format(res *result.Result) (string, error) { + sections := []string{} + + if f.includes.RequestHeaders { + sections = append(sections, f.printRequestHeaders(res)) + } + + if f.includes.RequestBody { + sections = append(sections, f.printBody(&res.RequestBody)) + } + + if f.includes.ResponseHeaders { + sections = append(sections, f.printResponseHeaders(res)) + } + + if f.includes.ResponseBody { + sections = append(sections, f.printBody(&res.ResponseBody)) + } + + return strings.Join(sections, "\n"), nil +} + +func (f *PrettyFormatter) printRequestHeaders(res *result.Result) string { + req := *res.Response.Request + + if f.includes.RequestMeta { + return f.requestLine(*res.RequestLine()) + f.headers(req.Header) + } + + return f.headers(req.Header) +} + +func (f *PrettyFormatter) printResponseHeaders(res *result.Result) string { + if f.includes.ResponseMeta { + return f.statusLine(*res.StatusLine()) + f.headers(res.Response.Header) + } + + return f.headers(res.Response.Header) +} + +func (f *PrettyFormatter) printBody(body *result.Body) string { + if jsonBody := body.Json(); jsonBody != nil { + return fmt.Sprintf("%v\n", f.json(jsonBody)) + } + + if textBody := body.Text(); textBody != "" { + return fmt.Sprintf("%v\n", textBody) + } + + return "" +} + +func (f *PrettyFormatter) headers(headers http.Header) string { + return formatHeaders(headers, true) +} + +func (f *PrettyFormatter) statusLine(line result.StatusLine) string { + return formatStatusLine(line, true) } -func (f Formatter) RequestLine(line result.RequestLine) string { - return formatRequestLine(line, f.colored) +func (f *PrettyFormatter) requestLine(line result.RequestLine) string { + return formatRequestLine(line, true) } -func (f Formatter) Json(j map[string]any) string { - return formatJson(j, f.colored) +func (f *PrettyFormatter) json(j map[string]any) string { + return formatJson(j, true) } func formatHeaders(headers http.Header, colorized bool) string { diff --git a/pkg/printer/formatter_test.go b/pkg/printer/formatter_test.go deleted file mode 100644 index a4feee4..0000000 --- a/pkg/printer/formatter_test.go +++ /dev/null @@ -1,322 +0,0 @@ -package printer - -import ( - "fmt" - "net/http" - "testing" - "time" - - "github.com/eynopv/lac/internal/assert" - "github.com/eynopv/lac/pkg/result" -) - -func Test_formatStatusLine(t *testing.T) { - tests := []struct { - name string - line result.StatusLine - useColor bool - want string - }{ - { - name: "non-colorized 200", - line: result.StatusLine{ - Protocol: "HTTP/1.1", - Status: "200 OK", - Time: 300 * time.Millisecond, - }, - useColor: false, - want: "HTTP/1.1 200 OK [300ms]\n", - }, - { - name: "colorized 200 fast response", - line: result.StatusLine{ - Protocol: "HTTP/2", - Status: "200 OK", - Time: 300 * time.Millisecond, - }, - useColor: true, - want: fmt.Sprintf( - "%v %v [%v]\n", - "HTTP/2", - Colorize("200 OK", ColorGreen), - Colorize("300ms", ColorReset), - ), - }, - { - name: "colorized 301 medium response", - line: result.StatusLine{ - Protocol: "HTTP/1.1", - Status: "301 Moved Permanently", - Time: 800 * time.Millisecond, - }, - useColor: true, - want: fmt.Sprintf( - "%v %v [%v]\n", - "HTTP/1.1", - Colorize("301 Moved Permanently", ColorCyan), - Colorize("800ms", ColorYellow), - ), - }, - { - name: "colorized 500 slow response", - line: result.StatusLine{ - Protocol: "HTTP/1.1", - Status: "500 Internal Server Error", - Time: 1500 * time.Millisecond, - }, - useColor: true, - want: fmt.Sprintf( - "%v %v [%v]\n", - "HTTP/1.1", - Colorize("500 Internal Server Error", ColorRed), - Colorize("1.5s", ColorRed), - ), - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - formatter := Formatter{colored: tt.useColor} - got := formatter.StatusLine(tt.line) - assert.Equal(t, tt.want, got) - }) - } -} - -func Test_formatRequestLine(t *testing.T) { - testUrl := "https://example.com/dogs" - tests := []struct { - name string - line result.RequestLine - useColor bool - want string - }{ - { - name: "non-colorized GET", - line: result.RequestLine{ - Method: "GET", - Url: testUrl, - Protocol: "HTTP/1.1", - }, - useColor: false, - want: fmt.Sprintf("GET %v HTTP/1.1\n", testUrl), - }, - { - name: "colorized GET", - line: result.RequestLine{ - Method: "GET", - Url: testUrl, - Protocol: "HTTP/1.1", - }, - useColor: true, - want: fmt.Sprintf( - "%v %v %v\n", - Colorize("GET", ColorGreen), - testUrl, - "HTTP/1.1", - ), - }, - { - name: "colorized POST", - line: result.RequestLine{ - Method: "POST", - Url: testUrl, - Protocol: "HTTP/2", - }, - useColor: true, - want: fmt.Sprintf( - "%v %v %v\n", - Colorize("POST", ColorYellow), - testUrl, - "HTTP/2", - ), - }, - { - name: "colorized DELETE", - line: result.RequestLine{ - Method: "DELETE", - Url: testUrl, - Protocol: "HTTP/1.1", - }, - useColor: true, - want: fmt.Sprintf( - "%v %v %v\n", - Colorize("DELETE", ColorRed), - testUrl, - "HTTP/1.1", - ), - }, - { - name: "colorized default", - line: result.RequestLine{ - Method: "OPTIONS", - Url: testUrl, - Protocol: "HTTP/1.0", - }, - useColor: true, - want: fmt.Sprintf( - "%v %v %v\n", - Colorize("OPTIONS", ColorMagenta), - testUrl, - "HTTP/1.0", - ), - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - formatter := Formatter{colored: tt.useColor} - got := formatter.RequestLine(tt.line) - assert.Equal(t, tt.want, got) - }) - } -} - -func Test_formatJson(t *testing.T) { - tests := []struct { - name string - json map[string]any - useColor bool - want string - }{ - { - name: "simple", - json: map[string]any{ - "name": "Alice", - "age": 30, - }, - useColor: false, - want: "{\n \"age\": 30,\n \"name\": \"Alice\"\n}", - }, - { - name: "nested", - json: map[string]any{ - "user": map[string]any{ - "id": 1, - "name": "Bob", - }, - }, - useColor: false, - want: "{\n \"user\": {\n \"id\": 1,\n \"name\": \"Bob\"\n }\n}", - }, - { - name: "empty", - json: map[string]any{}, - useColor: false, - want: "{}", - }, - { - name: "colored int", - json: map[string]any{ - "int": 1, - }, - useColor: true, - want: fmt.Sprintf("{\n %v: %v\n}", Yellow(`"int"`), Cyan("1")), - }, - { - name: "colored string", - json: map[string]any{ - "string": "Hello, World", - }, - useColor: true, - want: fmt.Sprintf("{\n %v: %v\n}", Yellow(`"string"`), Green(`"Hello, World"`)), - }, - { - name: "colored boolean", - json: map[string]any{ - "boolean": true, - }, - useColor: true, - want: fmt.Sprintf("{\n %v: %v\n}", Yellow(`"boolean"`), Magenta("true")), - }, - { - name: "colored float", - json: map[string]any{ - "float": 1.23, - }, - useColor: true, - want: fmt.Sprintf("{\n %v: %v\n}", Yellow(`"float"`), Cyan("1.23")), - }, - { - name: "colored nil", - json: map[string]any{ - "nil": nil, - }, - useColor: true, - want: fmt.Sprintf("{\n %v: %v\n}", Yellow(`"nil"`), Red("null")), - }, - { - name: "colored list", - json: map[string]any{ - "list": []any{1, "string", false, nil, map[string]any{"one": 1}}, - }, - useColor: true, - want: fmt.Sprintf("{\n %v: [%v, %v, %v, %v, {\n %v: %v\n }]\n}", - Yellow(`"list"`), - Cyan("1"), - Green(`"string"`), - Magenta("false"), - Red("null"), - Yellow(`"one"`), - Cyan("1"), - ), - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - formatter := Formatter{colored: tt.useColor} - got := formatter.Json(tt.json) - assert.Equal(t, tt.want, got) - }) - } -} - -func Test_formatHeaders(t *testing.T) { - tests := []struct { - name string - headers http.Header - useColor bool - want string - }{ - { - name: "no headers", - headers: http.Header{}, - useColor: false, - want: "", - }, - { - name: "single header non-colorized", - headers: http.Header{ - "Content-Type": {"application/json"}, - }, - useColor: false, - want: "Content-Type: application/json\n", - }, - { - name: "single header colorized", - headers: http.Header{ - "Content-Type": {"application/json"}, - }, - useColor: true, - want: fmt.Sprintf("%v: %v\n", Cyan("Content-Type"), "application/json"), - }, - { - name: "multiple headers", - headers: http.Header{ - "Content-Type": {"application/json"}, - "X-Custom": {"value1", "value2"}, - }, - useColor: false, - want: "Content-Type: application/json\nX-Custom: value1, value2\n", - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - formatter := Formatter{colored: tt.useColor} - got := formatter.Headers(tt.headers) - assert.Equal(t, tt.want, got) - }) - } -} diff --git a/pkg/printer/outputter.go b/pkg/printer/outputter.go index 346e31e..b64d10a 100644 --- a/pkg/printer/outputter.go +++ b/pkg/printer/outputter.go @@ -1,7 +1,9 @@ package printer import ( + "fmt" "io" + "os" "github.com/eynopv/lac/pkg/result" ) @@ -21,6 +23,41 @@ type Outputter struct { formatter Formatter } +func NewOutputter(config PrinterConfig) *Outputter { + includes := Includes{ + ResponseBody: config.PrintRequestBody, + ResponseHeaders: config.PrintResponseHeaders, + ResponseMeta: config.PrintResponseMeta, + RequestBody: config.PrintRequestBody, + RequestHeaders: config.PrintRequestHeaders, + RequestMeta: config.PrintRequestMeta, + } + + var formatter Formatter + if IsTerminal(int(os.Stdout.Fd())) { + formatter = &PrettyFormatter{ + includes: includes, + } + } else { + formatter = &JsonFormatter{ + includes: includes, + } + } + + return &Outputter{ + includes: includes, + destination: os.Stdout, + formatter: formatter, + } +} + func (o *Outputter) Write(res *result.Result) error { - + formatted, err := o.formatter.Format(res) + if err != nil { + return err + } + + _, err = fmt.Fprint(o.destination, formatted) + + return err } diff --git a/pkg/printer/printer.go b/pkg/printer/printer.go index b551b18..7b4806b 100644 --- a/pkg/printer/printer.go +++ b/pkg/printer/printer.go @@ -1,15 +1,10 @@ package printer import ( - "encoding/json" - "fmt" "io" "os" - "strings" "golang.org/x/term" - - "github.com/eynopv/lac/pkg/result" ) var IsTerminal = term.IsTerminal @@ -30,17 +25,20 @@ type Printer struct { } func NewPrinter(config PrinterConfig) Printer { - formatter := Formatter{ - colored: true, - } + /* + formatter := Formatter{ + colored: true, + } + */ return Printer{ config: config, destination: os.Stdout, - formatter: formatter, } } +/* + func (p *Printer) Print(res *result.Result) { var output string @@ -128,6 +126,7 @@ func (p *Printer) makeNonTerminalOutput(res *result.Result) string { return string(b) } +/* func (p *Printer) printRequestHeaders(res *result.Result) string { req := *res.Response.Request @@ -157,3 +156,4 @@ func (p *Printer) printBody(body *result.Body) string { return "" } +*/ diff --git a/pkg/result/result.go b/pkg/result/result.go index c14daa5..47596e3 100644 --- a/pkg/result/result.go +++ b/pkg/result/result.go @@ -18,15 +18,15 @@ type Metadata struct { } type StatusLine struct { - Protocol string - Status string - Time time.Duration + Protocol string `json:"protocol"` + Status string `json:"status"` + Time time.Duration `json:"time"` } type RequestLine struct { - Protocol string - Url string - Method string + Protocol string `json:"protocol"` + Url string `json:"url"` + Method string `json:"method"` } type Body []byte @@ -39,6 +39,10 @@ func (r Result) StatusLine() *StatusLine { } } +func (r Result) ResponseLine() *StatusLine { + return r.StatusLine() +} + func (r Result) RequestLine() *RequestLine { return &RequestLine{ Protocol: r.Response.Request.Proto, @@ -47,6 +51,14 @@ func (r Result) RequestLine() *RequestLine { } } +func (b Body) Data() any { + if body := b.Json(); body != nil { + return body + } + + return b.Text() +} + func (b Body) Json() map[string]any { if len(b) == 0 { return nil From cdbcf81e238ff3489095268ed1788ac806c98517 Mon Sep 17 00:00:00 2001 From: eynopv Date: Mon, 16 Jun 2025 18:47:10 +0300 Subject: [PATCH 3/3] cleanup --- pkg/printer/printer.go | 127 ------------------------------------ pkg/printer/printer_test.go | 120 ---------------------------------- 2 files changed, 247 deletions(-) delete mode 100644 pkg/printer/printer_test.go diff --git a/pkg/printer/printer.go b/pkg/printer/printer.go index 7b4806b..4ad2a8e 100644 --- a/pkg/printer/printer.go +++ b/pkg/printer/printer.go @@ -25,135 +25,8 @@ type Printer struct { } func NewPrinter(config PrinterConfig) Printer { - /* - formatter := Formatter{ - colored: true, - } - */ - return Printer{ config: config, destination: os.Stdout, } } - -/* - -func (p *Printer) Print(res *result.Result) { - var output string - - if res.Response == nil { - fmt.Fprint(p.destination, "No HTTP response available\n") - return - } - - if IsTerminal(int(os.Stdout.Fd())) { - output = p.makeTerminalOutput(res) - } else { - output = p.makeNonTerminalOutput(res) - } - - fmt.Fprint(p.destination, output) -} - -func (p *Printer) makeTerminalOutput(res *result.Result) string { - sections := []string{} - - if p.config.PrintRequestHeaders { - sections = append(sections, p.printRequestHeaders(res)) - } - - if p.config.PrintRequestBody { - sections = append(sections, p.printBody(&res.RequestBody)) - } - - if p.config.PrintResponseHeaders { - sections = append(sections, p.printResponseHeaders(res)) - } - - if p.config.PrintResponseBody { - sections = append(sections, p.printBody(&res.ResponseBody)) - } - - return strings.Join(sections, "\n") -} - -func (p *Printer) makeNonTerminalOutput(res *result.Result) string { - m := map[string]any{} - - if p.config.PrintRequestHeaders || p.config.PrintRequestBody { - rm := map[string]any{} - - if p.config.PrintRequestHeaders { - rm["headers"] = res.Response.Request.Header - } - - if p.config.PrintRequestBody { - if jsonBody := res.RequestBody.Json(); jsonBody != nil { - rm["body"] = jsonBody - } else if textBody := res.RequestBody.Text(); textBody != "" { - rm["body"] = textBody - } - } - - m["request"] = rm - } - - if p.config.PrintResponseHeaders || p.config.PrintResponseBody { - rm := map[string]any{} - - if p.config.PrintResponseHeaders { - rm["headers"] = res.Response.Header - } - - if p.config.PrintResponseBody { - if jsonBody := res.ResponseBody.Json(); jsonBody != nil { - rm["body"] = jsonBody - } else if textBody := res.ResponseBody.Text(); textBody != "" { - rm["body"] = textBody - } - } - - m["response"] = rm - } - - b, err := json.MarshalIndent(m, "", " ") - - if err != nil { - return err.Error() - } - - return string(b) -} - -/* -func (p *Printer) printRequestHeaders(res *result.Result) string { - req := *res.Response.Request - - if p.config.PrintRequestMeta { - return p.formatter.RequestLine(*res.RequestLine()) + p.formatter.Headers(req.Header) - } - - return p.formatter.Headers(req.Header) -} - -func (p *Printer) printResponseHeaders(res *result.Result) string { - if p.config.PrintResponseMeta { - return p.formatter.StatusLine(*res.StatusLine()) + p.formatter.Headers(res.Response.Header) - } - - return p.formatter.Headers(res.Response.Header) -} - -func (p *Printer) printBody(body *result.Body) string { - if jsonBody := body.Json(); jsonBody != nil { - return fmt.Sprintf("%v\n", p.formatter.Json(jsonBody)) - } - - if textBody := body.Text(); textBody != "" { - return fmt.Sprintf("%v\n", textBody) - } - - return "" -} -*/ diff --git a/pkg/printer/printer_test.go b/pkg/printer/printer_test.go deleted file mode 100644 index 6c96cad..0000000 --- a/pkg/printer/printer_test.go +++ /dev/null @@ -1,120 +0,0 @@ -package printer - -import ( - "bytes" - "net/http" - "net/url" - "strings" - "testing" - "time" - - "github.com/eynopv/lac/internal/assert" - "github.com/eynopv/lac/pkg/result" -) - -func TestNewPrinter(t *testing.T) { - tests := []struct { - name string - isTerminal bool - expectColor bool - }{ - {"TerminalOutput", true, true}, - {"NonTerminalOutput", false, false}, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - originalIsTerminal := IsTerminal - defer func() { IsTerminal = originalIsTerminal }() - - IsTerminal = func(fd int) bool { return tt.isTerminal } - - p := NewPrinter(PrinterConfig{}) - - assert.Equal(t, p.formatter.colored, tt.isTerminal) - }) - } -} - -func TestPrinter_Print(t *testing.T) { - var buf bytes.Buffer - - res := result.Result{ - Response: &http.Response{ - Status: "200 OK", - Proto: "HTTP/1.1", - Request: &http.Request{ - Method: "GET", - Proto: "HTTP/1.1", - URL: &url.URL{Scheme: "https", Host: "example.com", Path: "/"}, - Header: http.Header{"Req-H": []string{"v"}}, - }, - Header: http.Header{"Res-H": []string{"x"}}, - }, - RequestBody: []byte(`request body`), - ResponseBody: []byte(`response body`), - Metadata: result.Metadata{ElapsedTime: 123 * time.Millisecond}, - } - - cases := []struct { - name string - config PrinterConfig - expect []string - }{ - { - "OnlyResponseBody", - PrinterConfig{PrintResponseBody: true}, - []string{`response body`}, - }, - { - "RequestHeadersAndBody", - PrinterConfig{PrintRequestHeaders: true, PrintRequestBody: true}, - []string{`request body`, "Req-H"}, - }, - { - "RequestAllSections", - PrinterConfig{PrintRequestHeaders: true, PrintRequestBody: true, PrintRequestMeta: true}, - []string{"GET https://example.com/", `request body`, "Req-H"}, - }, - { - "AllSections", - PrinterConfig{ - PrintRequestHeaders: true, - PrintRequestBody: true, - PrintRequestMeta: true, - PrintResponseHeaders: true, - PrintResponseBody: true, - PrintResponseMeta: true, - }, - []string{ - "GET https://example.com/ HTTP/1.1", - "Req-H", - "request body", - "HTTP/1.1 200 OK [123ms]", - "Res-H", - "response body", - }, - }, - } - - for _, tt := range cases { - t.Run(tt.name, func(t *testing.T) { - buf.Reset() - - p := Printer{ - config: tt.config, - destination: &buf, - formatter: Formatter{}, - } - - p.Print(&res) - - out := buf.String() - for _, expect := range tt.expect { - if !strings.Contains(out, expect) { - t.Errorf("expected output to contain %q: %v", expect, out) - } - } - }) - } -}