github.com/akamai/AkamaiOPEN-edgegrid-golang/v8@v8.1.0/pkg/papi/errors_test.go (about)

     1  package papi
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"net/http"
     8  	"strings"
     9  	"testing"
    10  
    11  	"github.com/akamai/AkamaiOPEN-edgegrid-golang/v8/pkg/session"
    12  	"github.com/akamai/AkamaiOPEN-edgegrid-golang/v8/pkg/tools"
    13  	"github.com/stretchr/testify/require"
    14  	"github.com/tj/assert"
    15  )
    16  
    17  func TestNewError(t *testing.T) {
    18  	sess, err := session.New()
    19  	require.NoError(t, err)
    20  
    21  	req, err := http.NewRequestWithContext(
    22  		context.TODO(),
    23  		http.MethodHead,
    24  		"/",
    25  		nil)
    26  	require.NoError(t, err)
    27  
    28  	tests := map[string]struct {
    29  		response *http.Response
    30  		expected *Error
    31  	}{
    32  		"valid response, status code 500": {
    33  			response: &http.Response{
    34  				Status:     "Internal Server Error",
    35  				StatusCode: http.StatusInternalServerError,
    36  				Body: ioutil.NopCloser(strings.NewReader(
    37  					`{"type":"a","title":"b","detail":"c"}`),
    38  				),
    39  				Request: req,
    40  			},
    41  			expected: &Error{
    42  				Type:       "a",
    43  				Title:      "b",
    44  				Detail:     "c",
    45  				StatusCode: http.StatusInternalServerError,
    46  			},
    47  		},
    48  		"invalid response body, assign status code": {
    49  			response: &http.Response{
    50  				Status:     "Internal Server Error",
    51  				StatusCode: http.StatusInternalServerError,
    52  				Body: ioutil.NopCloser(strings.NewReader(
    53  					`test`),
    54  				),
    55  				Request: req,
    56  			},
    57  			expected: &Error{
    58  				Title:      "Failed to unmarshal error body. PAPI API failed. Check details for more information.",
    59  				Detail:     "test",
    60  				StatusCode: http.StatusInternalServerError,
    61  			},
    62  		},
    63  	}
    64  	for name, test := range tests {
    65  		t.Run(name, func(t *testing.T) {
    66  			res := Client(sess).(*papi).Error(test.response)
    67  			assert.Equal(t, test.expected, res)
    68  		})
    69  	}
    70  }
    71  
    72  func TestErrorIs(t *testing.T) {
    73  	tests := map[string]struct {
    74  		err      Error
    75  		given    error
    76  		expected bool
    77  	}{
    78  		"is ErrSBDNotEnabled": {
    79  			err: Error{
    80  				StatusCode: http.StatusForbidden,
    81  				Type:       "https://problems.luna.akamaiapis.net/papi/v0/property-version-hostname/default-cert-provisioning-unavailable",
    82  			},
    83  			given:    ErrSBDNotEnabled,
    84  			expected: true,
    85  		},
    86  		"is wrapped ErrSBDNotEnabled": {
    87  			err: Error{
    88  				StatusCode: http.StatusForbidden,
    89  				Type:       "https://problems.luna.akamaiapis.net/papi/v0/property-version-hostname/default-cert-provisioning-unavailable",
    90  			},
    91  			given:    fmt.Errorf("oops: %w", ErrSBDNotEnabled),
    92  			expected: true,
    93  		},
    94  		"is ErrDefaultCertLimitReached": {
    95  			err: Error{
    96  				StatusCode: http.StatusTooManyRequests,
    97  				LimitKey:   "DEFAULT_CERTS_PER_CONTRACT",
    98  				Remaining:  tools.IntPtr(0),
    99  			},
   100  			given:    ErrDefaultCertLimitReached,
   101  			expected: true,
   102  		},
   103  		"is not ErrSBDNotEnabled": {
   104  			err: Error{
   105  				StatusCode: http.StatusTooManyRequests,
   106  				LimitKey:   "DEFAULT_CERTS_PER_CONTRACT",
   107  				Remaining:  tools.IntPtr(0),
   108  			},
   109  			given:    ErrSBDNotEnabled,
   110  			expected: false,
   111  		},
   112  		"is not ErrDefaultCertLimitReached": {
   113  			err: Error{
   114  				StatusCode: http.StatusForbidden,
   115  				Type:       "https://problems.luna.akamaiapis.net/papi/v0/property-version-hostname/default-cert-provisioning-unavailable",
   116  			},
   117  			given:    ErrDefaultCertLimitReached,
   118  			expected: false,
   119  		},
   120  	}
   121  
   122  	for name, test := range tests {
   123  		t.Run(name, func(t *testing.T) {
   124  			res := test.err.Is(test.given)
   125  			assert.Equal(t, test.expected, res)
   126  		})
   127  	}
   128  }
   129  
   130  func TestJsonErrorUnmarshalling(t *testing.T) {
   131  	req, err := http.NewRequestWithContext(
   132  		context.TODO(),
   133  		http.MethodHead,
   134  		"/",
   135  		nil)
   136  	require.NoError(t, err)
   137  	tests := map[string]struct {
   138  		input    *http.Response
   139  		expected *Error
   140  	}{
   141  		"API failure with HTML response": {
   142  			input: &http.Response{
   143  				Request:    req,
   144  				Status:     "OK",
   145  				StatusCode: http.StatusServiceUnavailable,
   146  				Body:       ioutil.NopCloser(strings.NewReader(`<HTML><HEAD>...</HEAD><BODY>...</BODY></HTML>`))},
   147  			expected: &Error{
   148  				Type:       "",
   149  				Title:      "Failed to unmarshal error body. PAPI API failed. Check details for more information.",
   150  				Detail:     "<HTML><HEAD>...</HEAD><BODY>...</BODY></HTML>",
   151  				StatusCode: http.StatusServiceUnavailable,
   152  			},
   153  		},
   154  		"API failure with plain text response": {
   155  			input: &http.Response{
   156  				Request:    req,
   157  				Status:     "OK",
   158  				StatusCode: http.StatusServiceUnavailable,
   159  				Body:       ioutil.NopCloser(strings.NewReader("Your request did not succeed as this operation has reached  the limit for your account. Please try after 2024-01-16T15:20:55.945Z"))},
   160  			expected: &Error{
   161  				Type:       "",
   162  				StatusCode: http.StatusServiceUnavailable,
   163  				Title:      "Failed to unmarshal error body. PAPI API failed. Check details for more information.",
   164  				Detail:     "Your request did not succeed as this operation has reached  the limit for your account. Please try after 2024-01-16T15:20:55.945Z",
   165  			},
   166  		},
   167  		"API failure with XML response": {
   168  			input: &http.Response{
   169  				Request:    req,
   170  				Status:     "OK",
   171  				StatusCode: http.StatusServiceUnavailable,
   172  				Body:       ioutil.NopCloser(strings.NewReader(`<Root><Item id="1" name="Example" /></Root>`))},
   173  			expected: &Error{
   174  				Type:       "",
   175  				StatusCode: http.StatusServiceUnavailable,
   176  				Title:      "Failed to unmarshal error body. PAPI API failed. Check details for more information.",
   177  				Detail:     "<Root><Item id=\"1\" name=\"Example\" /></Root>",
   178  			},
   179  		},
   180  	}
   181  
   182  	for name, test := range tests {
   183  		t.Run(name, func(t *testing.T) {
   184  			sess, _ := session.New()
   185  			p := papi{
   186  				Session: sess,
   187  			}
   188  			assert.Equal(t, test.expected, p.Error(test.input))
   189  		})
   190  	}
   191  }