github.com/goplus/yap@v0.8.1/ytest/response.go (about)

     1  /*
     2   * Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package ytest
    18  
    19  import (
    20  	"encoding/json"
    21  	"io"
    22  	"net/http"
    23  	"net/url"
    24  
    25  	"github.com/goplus/yap/test"
    26  )
    27  
    28  type Response struct {
    29  	code   int
    30  	header http.Header
    31  	raw    []byte
    32  	mime   string
    33  	body   any
    34  }
    35  
    36  func newResponse(resp *http.Response) *Response {
    37  	raw, err := io.ReadAll(resp.Body)
    38  	if err != nil {
    39  		test.Fatal("ReadAll resp.Body:", err)
    40  	}
    41  	return &Response{
    42  		code:   resp.StatusCode,
    43  		header: resp.Header,
    44  		raw:    raw,
    45  	}
    46  }
    47  
    48  // Code returns the status code of this response.
    49  func (p *Response) Code() int {
    50  	return p.code
    51  }
    52  
    53  func (p *Response) matchCode(t CaseT, code any) {
    54  	t.Helper()
    55  	switch v := code.(type) {
    56  	case int:
    57  		test.Gopt_Case_MatchTBase(t, p.code, v)
    58  	case *test.Var__0[int]:
    59  		v.Match(t, p.code)
    60  	default:
    61  		t.Fatalf("match status code failed - unexpected type: %T\n", code)
    62  	}
    63  }
    64  
    65  // Header returns header of this response.
    66  func (p *Response) Header() http.Header {
    67  	return p.header
    68  }
    69  
    70  func (p *Response) matchHeader(t CaseT, key string, value any) {
    71  	t.Helper()
    72  	switch v := value.(type) {
    73  	case string:
    74  		test.Gopt_Case_MatchTBase(t, v, p.header.Get(key))
    75  	case []string:
    76  		test.Gopt_Case_MatchBaseSlice(t, v, p.header[key])
    77  	case test.TySet[string]:
    78  		test.Gopt_Case_MatchSet(t, v, p.header[key])
    79  	case *test.Var__0[string]:
    80  		v.Match(t, p.header.Get(key))
    81  	case *test.Var__3[[]string]:
    82  		v.Match(t, p.header[key])
    83  	default:
    84  		t.Fatalf("match header failed! unexpected value type: %T\n", value)
    85  	}
    86  }
    87  
    88  // RawBody returns raw response body as []byte (byte slice).
    89  func (p *Response) RawBody() []byte {
    90  	return p.raw
    91  }
    92  
    93  // Body returns response body decoded according Content-Type.
    94  func (p *Response) Body() (ret any) {
    95  	if p.mime == mimeNone {
    96  		mime := p.header.Get("Content-Type")
    97  		switch mime {
    98  		case mimeJson:
    99  			if err := json.Unmarshal(p.raw, &ret); err != nil {
   100  				test.Fatal("json.Unmarshal resp.Body:", err)
   101  			}
   102  		case mimeForm:
   103  			form, err := url.ParseQuery(string(p.raw))
   104  			if err != nil {
   105  				test.Fatal("url.ParseQuery resp.Body:", err)
   106  			}
   107  			ret = form
   108  		case mimeNone:
   109  			mime = mimeBinary
   110  			fallthrough
   111  		default:
   112  			ret = p.raw
   113  		}
   114  		p.mime, p.body = mime, ret
   115  	}
   116  	return p.body
   117  }
   118  
   119  func (p *Response) matchBody(t CaseT, bodyType string, body any) {
   120  	t.Helper()
   121  	mime := p.header.Get("Content-Type")
   122  	if mime != bodyType {
   123  		t.Fatalf("resp.MatchBody: unmatched mime type - got: %s, expected: %s\n", mime, bodyType)
   124  	}
   125  	test.Gopt_Case_MatchAny(t, body, p.Body())
   126  }