|  | @@ -0,0 +1,80 @@
 | 
	
		
			
				|  |  | +package rest
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +import (
 | 
	
		
			
				|  |  | +	"errors"
 | 
	
		
			
				|  |  | +	"io"
 | 
	
		
			
				|  |  | +	"net/http/httptest"
 | 
	
		
			
				|  |  | +	"testing"
 | 
	
		
			
				|  |  | +)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +func TestErrorWriteJSON(t *testing.T) {
 | 
	
		
			
				|  |  | +	type TestCase struct {
 | 
	
		
			
				|  |  | +		Input  Error
 | 
	
		
			
				|  |  | +		C      int
 | 
	
		
			
				|  |  | +		Output string
 | 
	
		
			
				|  |  | +		Err    error
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	testCases := []TestCase{
 | 
	
		
			
				|  |  | +		// Empty error
 | 
	
		
			
				|  |  | +		{Input: Err, C: 200, Output: `{"message":""}`},
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		// Standard errors
 | 
	
		
			
				|  |  | +		{Input: ErrPermanentRedirect, C: 308, Output: `{"message":"Permanent Redirect"}`},
 | 
	
		
			
				|  |  | +		{Input: ErrNotFound, C: 404, Output: `{"message":"Not Found"}`},
 | 
	
		
			
				|  |  | +		{Input: ErrInternalServerError, C: 500, Output: `{"message":"Internal Server Error"}`},
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		// Error with changed message
 | 
	
		
			
				|  |  | +		{Input: ErrBadRequest.WithMessage("Invalid Recipe"), C: 400, Output: `{"message":"Invalid Recipe"}`},
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		// Error with data
 | 
	
		
			
				|  |  | +		{
 | 
	
		
			
				|  |  | +			Input:  ErrGatewayTimeout.WithData(map[string]any{"service": "RecipeDatabase"}),
 | 
	
		
			
				|  |  | +			C:      504,
 | 
	
		
			
				|  |  | +			Output: `{"message":"Gateway Timeout","data":{"service":"RecipeDatabase"}}`,
 | 
	
		
			
				|  |  | +		},
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		// Error with value
 | 
	
		
			
				|  |  | +		{
 | 
	
		
			
				|  |  | +			Input:  ErrGatewayTimeout.WithValue("service", "RecipeDatabase"),
 | 
	
		
			
				|  |  | +			C:      504,
 | 
	
		
			
				|  |  | +			Output: `{"message":"Gateway Timeout","data":{"service":"RecipeDatabase"}}`,
 | 
	
		
			
				|  |  | +		},
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		// Error with error
 | 
	
		
			
				|  |  | +		{
 | 
	
		
			
				|  |  | +			Input:  ErrInternalServerError.WithError(errors.New("recipe is too delicious")),
 | 
	
		
			
				|  |  | +			C:      500,
 | 
	
		
			
				|  |  | +			Output: `{"message":"Internal Server Error","data":{"error":"recipe is too delicious"}}`,
 | 
	
		
			
				|  |  | +		},
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	for i, tc := range testCases {
 | 
	
		
			
				|  |  | +		t.Logf("(%d) Testing %v", i, tc.Input)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		rec := httptest.NewRecorder()
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		err := tc.Input.WriteJSON(rec)
 | 
	
		
			
				|  |  | +		if err != tc.Err {
 | 
	
		
			
				|  |  | +			t.Errorf("Expected error %v, got %v", tc.Err, err)
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +		if err != nil {
 | 
	
		
			
				|  |  | +			continue
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		res := rec.Result()
 | 
	
		
			
				|  |  | +		if res.StatusCode != tc.C {
 | 
	
		
			
				|  |  | +			t.Errorf("Expected status code %d, got %d", tc.C, res.StatusCode)
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		body, err := io.ReadAll(res.Body)
 | 
	
		
			
				|  |  | +		if err != nil {
 | 
	
		
			
				|  |  | +			t.Errorf("Unexpected error reading response body: %v", err)
 | 
	
		
			
				|  |  | +			continue
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		if string(body) != tc.Output {
 | 
	
		
			
				|  |  | +			t.Errorf("Expected body %q, got %q", tc.Output, string(body))
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +}
 |