github.com/kaptinlin/jsonschema@v0.4.6/result_test.go (about)

     1  package jsonschema
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/stretchr/testify/assert"
     7  
     8  	"github.com/goccy/go-json"
     9  )
    10  
    11  // Define the JSON schema
    12  const schemaJSON = `{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"example-schema","type":"object","title":"foo object schema","properties":{"foo":{"title":"foo's title","description":"foo's description","type":"string","pattern":"^foo ","minLength":10}},"required":["foo"],"additionalProperties":false}`
    13  
    14  func TestValidationOutputs(t *testing.T) {
    15  	compiler := NewCompiler()
    16  	schema, err := compiler.Compile([]byte(schemaJSON))
    17  	if err != nil {
    18  		t.Fatalf("Failed to compile schema: %v", err)
    19  	}
    20  
    21  	testCases := []struct {
    22  		description   string
    23  		instance      interface{}
    24  		expectedValid bool
    25  	}{
    26  		{
    27  			description: "Valid input matching schema requirements",
    28  			instance: map[string]interface{}{
    29  				"foo": "foo bar baz baz",
    30  			},
    31  			expectedValid: true,
    32  		},
    33  		{
    34  			description:   "Input missing required property 'foo'",
    35  			instance:      map[string]interface{}{},
    36  			expectedValid: false,
    37  		},
    38  		{
    39  			description: "Invalid additional property",
    40  			instance: map[string]interface{}{
    41  				"foo": "foo valid", "extra": "data",
    42  			},
    43  			expectedValid: false,
    44  		},
    45  	}
    46  
    47  	for _, tc := range testCases {
    48  		t.Run(tc.description, func(t *testing.T) {
    49  			result := schema.Validate(tc.instance)
    50  
    51  			if result.Valid != tc.expectedValid {
    52  				t.Errorf("FlagOutput validity mismatch: expected %v, got %v", tc.expectedValid, result.Valid)
    53  			}
    54  		})
    55  	}
    56  }
    57  
    58  func TestToLocalizeList(t *testing.T) {
    59  	// Initialize localizer for Simplified Chinese
    60  	i18n, err := GetI18n()
    61  	assert.Nil(t, err, "Failed to initialize i18n")
    62  	localizer := i18n.NewLocalizer("zh-Hans")
    63  
    64  	// Define a schema JSON with multiple constraints
    65  	schemaJSON := `{
    66          "type": "object",
    67          "properties": {
    68              "name": {"type": "string", "minLength": 3},
    69              "age": {"type": "integer", "minimum": 20},
    70              "email": {"type": "string", "format": "email"}
    71          },
    72          "required": ["name", "age", "email"]
    73      }`
    74  
    75  	compiler := NewCompiler()
    76  	schema, err := compiler.Compile([]byte(schemaJSON))
    77  	assert.Nil(t, err, "Schema compilation should not fail")
    78  
    79  	// Test instance with multiple validation errors
    80  	instance := map[string]interface{}{
    81  		"name":  "Jo",
    82  		"age":   18,
    83  		"email": "not-an-email",
    84  	}
    85  	result := schema.Validate(instance)
    86  
    87  	// Check if the validation result is as expected
    88  	assert.False(t, result.IsValid(), "Schema validation should fail for the given instance")
    89  
    90  	// Localize and output the validation errors
    91  	details, err := json.MarshalIndent(result.ToLocalizeList(localizer), "", "  ")
    92  	assert.Nil(t, err, "Marshaling the localized list should not fail")
    93  
    94  	// Check if the error message for "minLength" is correctly localized
    95  	assert.Contains(t, string(details), "值应至少为 3 个字符", "The error message for 'minLength' should be correctly localized and contain the expected substring")
    96  }
    97  
    98  func TestToList(t *testing.T) {
    99  	// Create a sample EvaluationResult instance
   100  	evaluationResult := &EvaluationResult{
   101  		Valid:            true,
   102  		EvaluationPath:   "/",
   103  		SchemaLocation:   "http://example.com/schema",
   104  		InstanceLocation: "http://example.com/instance",
   105  		Annotations: map[string]interface{}{
   106  			"key1": "value1",
   107  			"key2": "value2",
   108  		},
   109  		Errors: map[string]*EvaluationError{
   110  			"required": {
   111  				Keyword: "required",
   112  				Code:    "missing_required_property",
   113  				Message: "Required property {property} is missing",
   114  				Params: map[string]interface{}{
   115  					"property": "fieldName1",
   116  				},
   117  			},
   118  			"minLength": {
   119  				Keyword: "minLength",
   120  				Code:    "string_too_short",
   121  				Message: "Value should be at least {min_length} characters",
   122  				Params: map[string]interface{}{
   123  					"minLength": 5,
   124  				},
   125  			},
   126  		},
   127  		Details: []*EvaluationResult{
   128  			{
   129  				Valid:          false,
   130  				EvaluationPath: "/property",
   131  				Errors: map[string]*EvaluationError{
   132  					"format": {
   133  						Keyword: "format",
   134  						Code:    "format_mismatch",
   135  						Message: "Value does not match format {format}",
   136  						Params: map[string]interface{}{
   137  							"format": "email",
   138  						},
   139  					},
   140  				},
   141  			},
   142  		},
   143  	}
   144  
   145  	// Test case 1: Call ToList with default parameters
   146  	list1 := evaluationResult.ToList()
   147  
   148  	// Verify that the returned list is not nil
   149  	assert.NotNil(t, list1, "ToList should return a non-nil list")
   150  
   151  	// Verify the length of the returned list
   152  	assert.Equal(t, 1, len(list1.Details), "Expected length of list.Details is 1")
   153  
   154  	// Verify the validity of each list item
   155  	for _, item := range list1.Details {
   156  		assert.Equal(t, false, item.Valid, "Expected validity of list item to match EvaluationResult validity")
   157  	}
   158  
   159  	// Test case 2: Call ToList with includeHierarchy set to false
   160  	list2 := evaluationResult.ToList(false)
   161  
   162  	// Verify that the returned list is not nil
   163  	assert.NotNil(t, list2, "ToList with includeHierarchy=false should return a non-nil list")
   164  
   165  	// Verify the length of the returned list
   166  	assert.Equal(t, 1, len(list2.Details), "Expected length of list.Details is 1")
   167  
   168  	// Verify the validity of each list item
   169  	for _, item := range list2.Details {
   170  		assert.Equal(t, false, item.Valid, "Expected validity of list item to match EvaluationResult validity")
   171  	}
   172  }
   173  
   174  // TestToFlag tests the ToFlag method of the EvaluationResult struct.
   175  func TestToFlag(t *testing.T) {
   176  	// Test case 1: Valid result
   177  	evaluationResultValid := &EvaluationResult{
   178  		Valid: true,
   179  	}
   180  
   181  	// Call ToFlag method for valid result
   182  	flagValid := evaluationResultValid.ToFlag()
   183  
   184  	// Verify that the returned flag is not nil
   185  	assert.NotNil(t, flagValid, "ToFlag should return a non-nil flag for a valid result")
   186  
   187  	// Verify the validity of the returned flag
   188  	assert.Equal(t, true, flagValid.Valid, "Expected validity of flag to match EvaluationResult validity for a valid result")
   189  
   190  	// Test case 2: Invalid result
   191  	evaluationResultInvalid := &EvaluationResult{
   192  		Valid: false,
   193  	}
   194  
   195  	// Call ToFlag method for invalid result
   196  	flagInvalid := evaluationResultInvalid.ToFlag()
   197  
   198  	// Verify that the returned flag is not nil
   199  	assert.NotNil(t, flagInvalid, "ToFlag should return a non-nil flag for an invalid result")
   200  
   201  	// Verify the validity of the returned flag
   202  	assert.Equal(t, false, flagInvalid.Valid, "Expected validity of flag to match EvaluationResult validity for an invalid result")
   203  }