mirror of
				https://github.com/NginxProxyManager/nginx-proxy-manager.git
				synced 2025-10-30 23:33:34 +00:00 
			
		
		
		
	Add more backend unit tests
This commit is contained in:
		
							
								
								
									
										156
									
								
								backend/internal/tags/filters_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										156
									
								
								backend/internal/tags/filters_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,156 @@ | |||||||
|  | package tags | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"npm/internal/util" | ||||||
|  | 	"testing" | ||||||
|  |  | ||||||
|  | 	"github.com/stretchr/testify/assert" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func TestGetFilterSchema(t *testing.T) { | ||||||
|  | 	m := struct { | ||||||
|  | 		ID   int    `filter:"id"` | ||||||
|  | 		Name string `filter:"name"` | ||||||
|  | 	}{ | ||||||
|  | 		ID:   1, | ||||||
|  | 		Name: "John", | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	filterSchema := util.PrettyPrintJSON(GetFilterSchema(m)) | ||||||
|  |  | ||||||
|  | 	expectedSchema := `{ | ||||||
|  |   "type": "array", | ||||||
|  |   "items": { | ||||||
|  |     "oneOf": [ | ||||||
|  |       { | ||||||
|  |         "type": "object", | ||||||
|  |         "properties": { | ||||||
|  |           "field": { | ||||||
|  |             "type": "string", | ||||||
|  |             "pattern": "^id$" | ||||||
|  |           }, | ||||||
|  |           "modifier": { | ||||||
|  |             "type": "string", | ||||||
|  |             "pattern": "^(equals|not|contains|starts|ends|in|notin)$" | ||||||
|  |           }, | ||||||
|  |           "value": { | ||||||
|  |             "oneOf": [ | ||||||
|  |               { | ||||||
|  |                 "type": "string", | ||||||
|  |                 "minLength": 1 | ||||||
|  |               }, | ||||||
|  |               { | ||||||
|  |                 "type": "array", | ||||||
|  |                 "items": { | ||||||
|  |                   "type": "string", | ||||||
|  |                   "minLength": 1 | ||||||
|  |                 } | ||||||
|  |               } | ||||||
|  |             ] | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |       { | ||||||
|  |         "type": "object", | ||||||
|  |         "properties": { | ||||||
|  |           "field": { | ||||||
|  |             "type": "string", | ||||||
|  |             "pattern": "^name$" | ||||||
|  |           }, | ||||||
|  |           "modifier": { | ||||||
|  |             "type": "string", | ||||||
|  |             "pattern": "^(equals|not|contains|starts|ends|in|notin)$" | ||||||
|  |           }, | ||||||
|  |           "value": { | ||||||
|  |             "oneOf": [ | ||||||
|  |               { | ||||||
|  |                 "type": "string", | ||||||
|  |                 "minLength": 1 | ||||||
|  |               }, | ||||||
|  |               { | ||||||
|  |                 "type": "array", | ||||||
|  |                 "items": { | ||||||
|  |                   "type": "string", | ||||||
|  |                   "minLength": 1 | ||||||
|  |                 } | ||||||
|  |               } | ||||||
|  |             ] | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     ] | ||||||
|  |   } | ||||||
|  | }` | ||||||
|  |  | ||||||
|  | 	assert.Equal(t, expectedSchema, filterSchema) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestGetFilterTagSchema(t *testing.T) { | ||||||
|  | 	schema := util.PrettyPrintJSON(getFilterTagSchema("id,integer")) | ||||||
|  |  | ||||||
|  | 	expectedSchema := `{ | ||||||
|  |   "type": "object", | ||||||
|  |   "properties": { | ||||||
|  |     "field": { | ||||||
|  |       "type": "string", | ||||||
|  |       "pattern": "^id$" | ||||||
|  |     }, | ||||||
|  |     "modifier": { | ||||||
|  |       "type": "string", | ||||||
|  |       "pattern": "^(equals|not|contains|starts|ends|in|notin|min|max|greater|less)$" | ||||||
|  |     }, | ||||||
|  |     "value": { | ||||||
|  |       "oneOf": [ | ||||||
|  |         { | ||||||
|  |           "type": "string", | ||||||
|  |           "pattern": "^[0-9]+$" | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |           "type": "array", | ||||||
|  |           "items": { | ||||||
|  |             "type": "string", | ||||||
|  |             "pattern": "^[0-9]+$" | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       ] | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | }` | ||||||
|  |  | ||||||
|  | 	assert.Equal(t, expectedSchema, schema) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestBoolFieldSchema(t *testing.T) { | ||||||
|  | 	schema := util.PrettyPrintJSON(boolFieldSchema("active")) | ||||||
|  |  | ||||||
|  | 	expectedSchema := `{ | ||||||
|  |   "type": "object", | ||||||
|  |   "properties": { | ||||||
|  |     "field": { | ||||||
|  |       "type": "string", | ||||||
|  |       "pattern": "^active$" | ||||||
|  |     }, | ||||||
|  |     "modifier": { | ||||||
|  |       "type": "string", | ||||||
|  |       "pattern": "^(equals|not)$" | ||||||
|  |     }, | ||||||
|  |     "value": { | ||||||
|  |       "oneOf": [ | ||||||
|  |         { | ||||||
|  |           "type": "string", | ||||||
|  |           "pattern": "^(TRUE|true|t|yes|y|on|1|FALSE|f|false|n|no|off|0)$" | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |           "type": "array", | ||||||
|  |           "items": { | ||||||
|  |             "type": "string", | ||||||
|  |             "pattern": "^(TRUE|true|t|yes|y|on|1|FALSE|f|false|n|no|off|0)$" | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       ] | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | }` | ||||||
|  |  | ||||||
|  | 	assert.Equal(t, expectedSchema, schema) | ||||||
|  | } | ||||||
							
								
								
									
										110
									
								
								backend/internal/types/db_date_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								backend/internal/types/db_date_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,110 @@ | |||||||
|  | package types | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"encoding/json" | ||||||
|  | 	"testing" | ||||||
|  | 	"time" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func TestDBDate_Value(t *testing.T) { | ||||||
|  | 	// Create a DBDate instance with a specific time | ||||||
|  | 	expectedTime := time.Date(2022, time.January, 1, 0, 0, 0, 0, time.UTC) | ||||||
|  | 	dbDate := DBDate{Time: expectedTime} | ||||||
|  |  | ||||||
|  | 	// Call the Value method | ||||||
|  | 	value, err := dbDate.Value() | ||||||
|  |  | ||||||
|  | 	// Assert the value and error | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Errorf("Unexpected error: %v", err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Convert the value to int64 | ||||||
|  | 	unixTime := value.(int64) | ||||||
|  |  | ||||||
|  | 	// Convert the unix time back to time.Time | ||||||
|  | 	actualTime := time.Unix(unixTime, 0) | ||||||
|  |  | ||||||
|  | 	// Compare the actual time with the expected time | ||||||
|  | 	if !actualTime.Equal(expectedTime) { | ||||||
|  | 		t.Errorf("Expected time '%v', got '%v'", expectedTime, actualTime) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestDBDate_Scan(t *testing.T) { | ||||||
|  | 	// Simulate a value from the database (unix timestamp) | ||||||
|  | 	unixTime := int64(1640995200) | ||||||
|  |  | ||||||
|  | 	// Create a DBDate instance | ||||||
|  | 	dbDate := DBDate{} | ||||||
|  |  | ||||||
|  | 	// Call the Scan method | ||||||
|  | 	err := dbDate.Scan(unixTime) | ||||||
|  |  | ||||||
|  | 	// Assert the error | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Errorf("Unexpected error: %v", err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Convert the DBDate's time to unix timestamp for comparison | ||||||
|  | 	actualUnixTime := dbDate.Time.Unix() | ||||||
|  |  | ||||||
|  | 	// Compare the actual unix time with the expected unix time | ||||||
|  | 	if actualUnixTime != unixTime { | ||||||
|  | 		t.Errorf("Expected unix time '%v', got '%v'", unixTime, actualUnixTime) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestDBDate_UnmarshalJSON(t *testing.T) { | ||||||
|  | 	// Simulate a JSON input representing a unix timestamp | ||||||
|  | 	jsonData := []byte("1640995200") | ||||||
|  |  | ||||||
|  | 	// Create a DBDate instance | ||||||
|  | 	dbDate := DBDate{} | ||||||
|  |  | ||||||
|  | 	// Call the UnmarshalJSON method | ||||||
|  | 	err := dbDate.UnmarshalJSON(jsonData) | ||||||
|  |  | ||||||
|  | 	// Assert the error | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Errorf("Unexpected error: %v", err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Convert the DBDate's time to unix timestamp for comparison | ||||||
|  | 	actualUnixTime := dbDate.Time.Unix() | ||||||
|  |  | ||||||
|  | 	// Compare the actual unix time with the expected unix time | ||||||
|  | 	expectedUnixTime := int64(1640995200) | ||||||
|  | 	if actualUnixTime != expectedUnixTime { | ||||||
|  | 		t.Errorf("Expected unix time '%v', got '%v'", expectedUnixTime, actualUnixTime) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestDBDate_MarshalJSON(t *testing.T) { | ||||||
|  | 	// Create a DBDate instance with a specific time | ||||||
|  | 	expectedTime := time.Date(2022, time.January, 1, 0, 0, 0, 0, time.UTC) | ||||||
|  | 	dbDate := DBDate{Time: expectedTime} | ||||||
|  |  | ||||||
|  | 	// Call the MarshalJSON method | ||||||
|  | 	jsonData, err := dbDate.MarshalJSON() | ||||||
|  |  | ||||||
|  | 	// Assert the value and error | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Errorf("Unexpected error: %v", err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Convert the JSON data to an integer | ||||||
|  | 	var actualUnixTime int64 | ||||||
|  | 	err = json.Unmarshal(jsonData, &actualUnixTime) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Errorf("Failed to unmarshal JSON data: %v", err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Convert the unix time back to time.Time | ||||||
|  | 	actualTime := time.Unix(actualUnixTime, 0) | ||||||
|  |  | ||||||
|  | 	// Compare the actual time with the expected time | ||||||
|  | 	if !actualTime.Equal(expectedTime) { | ||||||
|  | 		t.Errorf("Expected time '%v', got '%v'", expectedTime, actualTime) | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										91
									
								
								backend/internal/types/db_nullable_int_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								backend/internal/types/db_nullable_int_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,91 @@ | |||||||
|  | package types | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"testing" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func TestNullableDBIntValue(t *testing.T) { | ||||||
|  | 	var d NullableDBInt | ||||||
|  |  | ||||||
|  | 	// Test when Int is 0 (null) | ||||||
|  | 	d.Int = 0 | ||||||
|  | 	value, err := d.Value() | ||||||
|  | 	if value != nil || err != nil { | ||||||
|  | 		t.Errorf("Expected Value() to return nil, nil but got %v, %v", value, err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Test when Int is not null | ||||||
|  | 	d.Int = 10 | ||||||
|  | 	value, err = d.Value() | ||||||
|  | 	if value != int64(10) || err != nil { | ||||||
|  | 		t.Errorf("Expected Value() to return 10, nil but got %v, %v", value, err) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestNullableDBIntScan(t *testing.T) { | ||||||
|  | 	var d NullableDBInt | ||||||
|  |  | ||||||
|  | 	// Test when src is an int | ||||||
|  | 	err := d.Scan(20) | ||||||
|  | 	if d.Int != 20 || err != nil { | ||||||
|  | 		t.Errorf("Expected Scan(20) to set d.Int to 20 and return nil but got d.Int = %d, err = %v", d.Int, err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Test when src is an int64 | ||||||
|  | 	err = d.Scan(int64(30)) | ||||||
|  | 	if d.Int != 30 || err != nil { | ||||||
|  | 		t.Errorf("Expected Scan(int64(30)) to set d.Int to 30 and return nil but got d.Int = %d, err = %v", d.Int, err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Test when src is a float32 | ||||||
|  | 	err = d.Scan(float32(40)) | ||||||
|  | 	if d.Int != 40 || err != nil { | ||||||
|  | 		t.Errorf("Expected Scan(float32(40)) to set d.Int to 40 and return nil but got d.Int = %d, err = %v", d.Int, err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Test when src is a float64 | ||||||
|  | 	err = d.Scan(float64(50)) | ||||||
|  | 	if d.Int != 50 || err != nil { | ||||||
|  | 		t.Errorf("Expected Scan(float64(50)) to set d.Int to 50 and return nil but got d.Int = %d, err = %v", d.Int, err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Test when src is a string | ||||||
|  | 	err = d.Scan("60") | ||||||
|  | 	if d.Int != 60 || err != nil { | ||||||
|  | 		t.Errorf("Expected Scan(\"60\") to set d.Int to 60 and return nil but got d.Int = %d, err = %v", d.Int, err) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestNullableDBIntUnmarshalJSON(t *testing.T) { | ||||||
|  | 	var d NullableDBInt | ||||||
|  |  | ||||||
|  | 	// Test when data is an integer value | ||||||
|  | 	err := d.UnmarshalJSON([]byte("10")) | ||||||
|  | 	if d.Int != 10 || err != nil { | ||||||
|  | 		t.Errorf("Expected UnmarshalJSON([]byte(\"10\")) to set d.Int to 10 and return nil but got d.Int = %d, err = %v", d.Int, err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Test when data is null | ||||||
|  | 	err = d.UnmarshalJSON([]byte("null")) | ||||||
|  | 	if d.Int != 0 || err != nil { | ||||||
|  | 		t.Errorf("Expected UnmarshalJSON([]byte(\"null\")) to set d.Int to 0 and return nil but got d.Int = %d, err = %v", d.Int, err) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestNullableDBIntMarshalJSON(t *testing.T) { | ||||||
|  | 	var d NullableDBInt | ||||||
|  |  | ||||||
|  | 	// Test when Int is 0 (null) | ||||||
|  | 	d.Int = 0 | ||||||
|  | 	result, err := d.MarshalJSON() | ||||||
|  | 	if string(result) != "null" || err != nil { | ||||||
|  | 		t.Errorf("Expected MarshalJSON() to return \"null\", nil but got %s, %v", result, err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Test when Int is not null | ||||||
|  | 	d.Int = 10 | ||||||
|  | 	result, err = d.MarshalJSON() | ||||||
|  | 	if string(result) != "10" || err != nil { | ||||||
|  | 		t.Errorf("Expected MarshalJSON() to return \"10\", nil but got %s, %v", result, err) | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										146
									
								
								backend/internal/types/db_nullable_uint_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										146
									
								
								backend/internal/types/db_nullable_uint_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,146 @@ | |||||||
|  | package types | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"database/sql/driver" | ||||||
|  | 	"testing" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func TestNullableDBUint_Value(t *testing.T) { | ||||||
|  | 	tests := []struct { | ||||||
|  | 		name      string | ||||||
|  | 		input     NullableDBUint | ||||||
|  | 		wantValue driver.Value | ||||||
|  | 		wantErr   bool | ||||||
|  | 	}{ | ||||||
|  | 		{ | ||||||
|  | 			name:      "Value should return nil when Uint is 0", | ||||||
|  | 			input:     NullableDBUint{Uint: 0}, | ||||||
|  | 			wantValue: nil, | ||||||
|  | 			wantErr:   false, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name:      "Value should return int64 value of Uint", | ||||||
|  | 			input:     NullableDBUint{Uint: 10}, | ||||||
|  | 			wantValue: int64(10), | ||||||
|  | 			wantErr:   false, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for _, tt := range tests { | ||||||
|  | 		t.Run(tt.name, func(t *testing.T) { | ||||||
|  | 			gotValue, gotErr := tt.input.Value() | ||||||
|  | 			if gotValue != tt.wantValue { | ||||||
|  | 				t.Errorf("Value() = %v, want %v", gotValue, tt.wantValue) | ||||||
|  | 			} | ||||||
|  | 			if (gotErr != nil) != tt.wantErr { | ||||||
|  | 				t.Errorf("Value() error = %v, wantErr %v", gotErr, tt.wantErr) | ||||||
|  | 			} | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestNullableDBUint_Scan(t *testing.T) { | ||||||
|  | 	tests := []struct { | ||||||
|  | 		name     string | ||||||
|  | 		input    interface{} | ||||||
|  | 		wantUint uint | ||||||
|  | 		wantErr  bool | ||||||
|  | 	}{ | ||||||
|  | 		{ | ||||||
|  | 			name:     "Scan should convert int to uint", | ||||||
|  | 			input:    int(10), | ||||||
|  | 			wantUint: uint(10), | ||||||
|  | 			wantErr:  false, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name:     "Scan should convert int64 to uint", | ||||||
|  | 			input:    int64(10), | ||||||
|  | 			wantUint: uint(10), | ||||||
|  | 			wantErr:  false, | ||||||
|  | 		}, | ||||||
|  | 		// Add more tests for other supported types | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for _, tt := range tests { | ||||||
|  | 		t.Run(tt.name, func(t *testing.T) { | ||||||
|  | 			var d NullableDBUint | ||||||
|  | 			err := d.Scan(tt.input) | ||||||
|  | 			if err != nil && !tt.wantErr { | ||||||
|  | 				t.Errorf("Scan() error = %v, wantErr %v", err, tt.wantErr) | ||||||
|  | 			} | ||||||
|  | 			if d.Uint != tt.wantUint { | ||||||
|  | 				t.Errorf("Scan() Uint = %v, want %v", d.Uint, tt.wantUint) | ||||||
|  | 			} | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestNullableDBUint_UnmarshalJSON(t *testing.T) { | ||||||
|  | 	tests := []struct { | ||||||
|  | 		name     string | ||||||
|  | 		input    []byte | ||||||
|  | 		wantUint uint | ||||||
|  | 		wantErr  bool | ||||||
|  | 	}{ | ||||||
|  | 		{ | ||||||
|  | 			name:     "UnmarshalJSON should unmarshal integer value", | ||||||
|  | 			input:    []byte("10"), | ||||||
|  | 			wantUint: uint(10), | ||||||
|  | 			wantErr:  false, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name:     "UnmarshalJSON should return zero Uint when data is invalid", | ||||||
|  | 			input:    []byte(`"invalid"`), | ||||||
|  | 			wantUint: uint(0), | ||||||
|  | 			wantErr:  false, | ||||||
|  | 		}, | ||||||
|  | 		// Add more tests for other scenarios | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for _, tt := range tests { | ||||||
|  | 		t.Run(tt.name, func(t *testing.T) { | ||||||
|  | 			var d NullableDBUint | ||||||
|  | 			err := d.UnmarshalJSON(tt.input) | ||||||
|  | 			if err != nil && !tt.wantErr { | ||||||
|  | 				t.Errorf("UnmarshalJSON() error = %v, wantErr %v", err, tt.wantErr) | ||||||
|  | 			} | ||||||
|  | 			if d.Uint != tt.wantUint { | ||||||
|  | 				t.Errorf("UnmarshalJSON() Uint = %v, want %v", d.Uint, tt.wantUint) | ||||||
|  | 			} | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestNullableDBUint_MarshalJSON(t *testing.T) { | ||||||
|  | 	tests := []struct { | ||||||
|  | 		name       string | ||||||
|  | 		input      NullableDBUint | ||||||
|  | 		wantOutput []byte | ||||||
|  | 		wantErr    bool | ||||||
|  | 	}{ | ||||||
|  | 		{ | ||||||
|  | 			name:       "MarshalJSON should marshal nil when Uint is 0", | ||||||
|  | 			input:      NullableDBUint{Uint: 0}, | ||||||
|  | 			wantOutput: []byte("null"), | ||||||
|  | 			wantErr:    false, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name:       "MarshalJSON should marshal Uint as JSON value", | ||||||
|  | 			input:      NullableDBUint{Uint: 10}, | ||||||
|  | 			wantOutput: []byte("10"), | ||||||
|  | 			wantErr:    false, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for _, tt := range tests { | ||||||
|  | 		t.Run(tt.name, func(t *testing.T) { | ||||||
|  | 			gotOutput, gotErr := tt.input.MarshalJSON() | ||||||
|  | 			if (gotErr != nil) != tt.wantErr { | ||||||
|  | 				t.Errorf("MarshalJSON() error = %v, wantErr %v", gotErr, tt.wantErr) | ||||||
|  | 			} | ||||||
|  | 			if string(gotOutput) != string(tt.wantOutput) { | ||||||
|  | 				t.Errorf("MarshalJSON() output = %s, want %s", gotOutput, tt.wantOutput) | ||||||
|  | 			} | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										133
									
								
								backend/internal/types/jsonb_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								backend/internal/types/jsonb_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,133 @@ | |||||||
|  | package types | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"encoding/json" | ||||||
|  | 	"testing" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // TestJSONBValue tests the Value method of the JSONB type | ||||||
|  | func TestJSONBValue(t *testing.T) { | ||||||
|  | 	j := JSONB{ | ||||||
|  | 		Decoded: map[string]interface{}{ | ||||||
|  | 			"name": "John", | ||||||
|  | 			"age":  30, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	value, err := j.Value() | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Errorf("Unexpected error: %v", err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// nolint: goconst | ||||||
|  | 	if value != `{"age":30,"name":"John"}` { | ||||||
|  | 		t.Errorf("Incorrect value. Expected: %s, Got: %s", `{"name":"John","age":30}`, value) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // TestJSONBScan tests the Scan method of the JSONB type | ||||||
|  | func TestJSONBScan(t *testing.T) { | ||||||
|  | 	src := `{"name":"John","age":30}` | ||||||
|  | 	var j JSONB | ||||||
|  |  | ||||||
|  | 	err := j.Scan(src) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Errorf("Unexpected error: %v", err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	expectedDecoded := map[string]interface{}{ | ||||||
|  | 		"name": "John", | ||||||
|  | 		"age":  30, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if !jsonEqual(j.Decoded, expectedDecoded) { | ||||||
|  | 		t.Errorf("Incorrect decoded value. Expected: %v, Got: %v", expectedDecoded, j.Decoded) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if j.Encoded != src { | ||||||
|  | 		t.Errorf("Incorrect encoded value. Expected: %s, Got: %s", src, j.Encoded) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // TestJSONBUnmarshalJSON tests the UnmarshalJSON method of the JSONB type | ||||||
|  | func TestJSONBUnmarshalJSON(t *testing.T) { | ||||||
|  | 	data := []byte(`{"name":"John","age":30}`) | ||||||
|  | 	var j JSONB | ||||||
|  |  | ||||||
|  | 	err := j.UnmarshalJSON(data) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Errorf("Unexpected error: %v", err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	expectedDecoded := map[string]interface{}{ | ||||||
|  | 		"name": "John", | ||||||
|  | 		"age":  30, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if !jsonEqual(j.Decoded, expectedDecoded) { | ||||||
|  | 		t.Errorf("Incorrect decoded value. Expected: %v, Got: %v", expectedDecoded, j.Decoded) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if j.Encoded != string(data) { | ||||||
|  | 		t.Errorf("Incorrect encoded value. Expected: %s, Got: %s", string(data), j.Encoded) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // TestJSONBMarshalJSON tests the MarshalJSON method of the JSONB type | ||||||
|  | func TestJSONBMarshalJSON(t *testing.T) { | ||||||
|  | 	j := JSONB{ | ||||||
|  | 		Decoded: map[string]interface{}{ | ||||||
|  | 			"name": "John", | ||||||
|  | 			"age":  30, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	result, err := j.MarshalJSON() | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Errorf("Unexpected error: %v", err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	expectedResult := `{"age":30,"name":"John"}` | ||||||
|  |  | ||||||
|  | 	if string(result) != expectedResult { | ||||||
|  | 		t.Errorf("Incorrect result. Expected: %s, Got: %s", expectedResult, string(result)) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // TestJSONBAsStringArray tests the AsStringArray method of the JSONB type | ||||||
|  | func TestJSONBAsStringArray(t *testing.T) { | ||||||
|  | 	j := JSONB{ | ||||||
|  | 		Decoded: []string{"apple", "banana", "orange"}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	strs, err := j.AsStringArray() | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Errorf("Unexpected error: %v", err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	expectedStrs := []string{"apple", "banana", "orange"} | ||||||
|  |  | ||||||
|  | 	if !stringSliceEqual(strs, expectedStrs) { | ||||||
|  | 		t.Errorf("Incorrect result. Expected: %v, Got: %v", expectedStrs, strs) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Helper function to compare JSON objects | ||||||
|  | func jsonEqual(a, b interface{}) bool { | ||||||
|  | 	aJSON, _ := json.Marshal(a) | ||||||
|  | 	bJSON, _ := json.Marshal(b) | ||||||
|  | 	return string(aJSON) == string(bJSON) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Helper function to compare string slices | ||||||
|  | func stringSliceEqual(a, b []string) bool { | ||||||
|  | 	if len(a) != len(b) { | ||||||
|  | 		return false | ||||||
|  | 	} | ||||||
|  | 	for i := range a { | ||||||
|  | 		if a[i] != b[i] { | ||||||
|  | 			return false | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return true | ||||||
|  | } | ||||||
							
								
								
									
										107
									
								
								backend/internal/types/nullable_db_date_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								backend/internal/types/nullable_db_date_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,107 @@ | |||||||
|  | package types | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"testing" | ||||||
|  | 	"time" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // TestNullableDBDateValue tests the Value method of the NullableDBDate type | ||||||
|  | func TestNullableDBDateValue(t *testing.T) { | ||||||
|  | 	tme := time.Date(2022, time.January, 1, 0, 0, 0, 0, time.UTC) | ||||||
|  | 	d := NullableDBDate{ | ||||||
|  | 		Time: &tme, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	value, err := d.Value() | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Errorf("Unexpected error: %v", err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	expectedValue := tme.Unix() | ||||||
|  |  | ||||||
|  | 	if value != expectedValue { | ||||||
|  | 		t.Errorf("Incorrect value. Expected: %d, Got: %v", expectedValue, value) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // TestNullableDBDateScan tests the Scan method of the NullableDBDate type | ||||||
|  | func TestNullableDBDateScan(t *testing.T) { | ||||||
|  | 	var d NullableDBDate | ||||||
|  |  | ||||||
|  | 	err := d.Scan(int64(1640995200)) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Errorf("Unexpected error: %v", err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	expectedTime := time.Date(2022, time.January, 1, 0, 0, 0, 0, time.UTC) | ||||||
|  |  | ||||||
|  | 	if !expectedTime.Equal(*d.Time) { | ||||||
|  | 		t.Errorf("Incorrect time. Expected: %v, Got: %v", expectedTime, *d.Time) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // TestNullableDBDateUnmarshalJSON tests the UnmarshalJSON method of the NullableDBDate type | ||||||
|  | func TestNullableDBDateUnmarshalJSON(t *testing.T) { | ||||||
|  | 	data := []byte(`1640995200`) | ||||||
|  | 	var d NullableDBDate | ||||||
|  |  | ||||||
|  | 	err := d.UnmarshalJSON(data) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Errorf("Unexpected error: %v", err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	expectedTime := time.Date(2022, time.January, 1, 0, 0, 0, 0, time.UTC) | ||||||
|  |  | ||||||
|  | 	if !expectedTime.Equal(*d.Time) { | ||||||
|  | 		t.Errorf("Incorrect time. Expected: %v, Got: %v", expectedTime, *d.Time) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // TestNullableDBDateMarshalJSON tests the MarshalJSON method of the NullableDBDate type | ||||||
|  | func TestNullableDBDateMarshalJSON(t *testing.T) { | ||||||
|  | 	tme := time.Date(2022, time.January, 1, 0, 0, 0, 0, time.UTC) | ||||||
|  | 	d := NullableDBDate{ | ||||||
|  | 		Time: &tme, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	result, err := d.MarshalJSON() | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Errorf("Unexpected error: %v", err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	expectedResult := []byte(`1640995200`) | ||||||
|  |  | ||||||
|  | 	if string(result) != string(expectedResult) { | ||||||
|  | 		t.Errorf("Incorrect result. Expected: %s, Got: %s", expectedResult, result) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // TestNullableDBDateAsInt64 tests the AsInt64 method of the NullableDBDate type | ||||||
|  | func TestNullableDBDateAsInt64(t *testing.T) { | ||||||
|  | 	tme := time.Date(2022, time.January, 1, 0, 0, 0, 0, time.UTC) | ||||||
|  | 	d := NullableDBDate{ | ||||||
|  | 		Time: &tme, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	unixtime := d.AsInt64() | ||||||
|  | 	expectedUnixtime := tme.Unix() | ||||||
|  |  | ||||||
|  | 	if unixtime != expectedUnixtime { | ||||||
|  | 		t.Errorf("Incorrect unixtime. Expected: %d, Got: %d", expectedUnixtime, unixtime) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // TestNullableDBDateAsString tests the AsString method of the NullableDBDate type | ||||||
|  | func TestNullableDBDateAsString(t *testing.T) { | ||||||
|  | 	tme := time.Date(2022, time.January, 1, 0, 0, 0, 0, time.UTC) | ||||||
|  | 	d := NullableDBDate{ | ||||||
|  | 		Time: &tme, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	str := d.AsString() | ||||||
|  | 	expectedStr := tme.String() | ||||||
|  |  | ||||||
|  | 	if str != expectedStr { | ||||||
|  | 		t.Errorf("Incorrect string. Expected: %s, Got: %s", expectedStr, str) | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										33
									
								
								backend/internal/util/interfaces_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								backend/internal/util/interfaces_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | |||||||
|  | package util | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"testing" | ||||||
|  |  | ||||||
|  | 	"github.com/stretchr/testify/assert" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func TestFindItemInInterface(t *testing.T) { | ||||||
|  | 	obj := map[string]interface{}{ | ||||||
|  | 		"key1": "value1", | ||||||
|  | 		"key2": 10, | ||||||
|  | 		"key3": map[string]interface{}{ | ||||||
|  | 			"nestedKey": "nestedValue", | ||||||
|  | 		}, | ||||||
|  | 		"key4": []interface{}{"item1", "item2"}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Test case 1: Key exists at the top level | ||||||
|  | 	result, found := FindItemInInterface("key1", obj) | ||||||
|  | 	assert.Equal(t, true, found) | ||||||
|  | 	assert.Equal(t, "value1", result) | ||||||
|  |  | ||||||
|  | 	// Test case 2: Key exists at a nested level | ||||||
|  | 	result, found = FindItemInInterface("nestedKey", obj) | ||||||
|  | 	assert.Equal(t, true, found) | ||||||
|  | 	assert.Equal(t, "nestedValue", result) | ||||||
|  |  | ||||||
|  | 	// Test case 3: Key does not exist | ||||||
|  | 	result, found = FindItemInInterface("nonExistentKey", obj) | ||||||
|  | 	assert.Equal(t, false, found) | ||||||
|  | 	assert.Equal(t, nil, result) | ||||||
|  | } | ||||||
| @@ -1,6 +1,7 @@ | |||||||
| package util | package util | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
|  | 	"reflect" | ||||||
| 	"testing" | 	"testing" | ||||||
|  |  | ||||||
| 	"github.com/stretchr/testify/assert" | 	"github.com/stretchr/testify/assert" | ||||||
| @@ -90,3 +91,21 @@ func TestConvertIntSliceToString(t *testing.T) { | |||||||
| 	str := ConvertIntSliceToString(items) | 	str := ConvertIntSliceToString(items) | ||||||
| 	assert.Equal(t, expectedStr, str) | 	assert.Equal(t, expectedStr, str) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func TestConvertStringSliceToInterface(t *testing.T) { | ||||||
|  | 	testCases := []struct { | ||||||
|  | 		input    []string | ||||||
|  | 		expected []interface{} | ||||||
|  | 	}{ | ||||||
|  | 		{[]string{"hello", "world"}, []interface{}{"hello", "world"}}, | ||||||
|  | 		{[]string{"apple", "banana", "cherry"}, []interface{}{"apple", "banana", "cherry"}}, | ||||||
|  | 		{[]string{}, []interface{}{}}, // Empty slice should return an empty slice | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for _, tc := range testCases { | ||||||
|  | 		result := ConvertStringSliceToInterface(tc.input) | ||||||
|  | 		if !reflect.DeepEqual(result, tc.expected) { | ||||||
|  | 			t.Errorf("Expected: %v, Got: %v", tc.expected, result) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|   | |||||||
| @@ -49,3 +49,19 @@ upstream npm_upstream_5 { | |||||||
| 		}) | 		}) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func TestPrettyPrintJSON(t *testing.T) { | ||||||
|  | 	testCases := []struct { | ||||||
|  | 		input    string | ||||||
|  | 		expected string | ||||||
|  | 	}{ | ||||||
|  | 		{`{"name":"John","age":30,"city":"New York"}`, "{\n  \"name\": \"John\",\n  \"age\": 30,\n  \"city\": \"New York\"\n}"}, | ||||||
|  | 		{`{"fruit":"apple","color":"red"}`, "{\n  \"fruit\": \"apple\",\n  \"color\": \"red\"\n}"}, | ||||||
|  | 		{"invalid-json", "invalid-json"}, // non-JSON input should return the original string unchanged | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for _, tc := range testCases { | ||||||
|  | 		result := PrettyPrintJSON(tc.input) | ||||||
|  | 		assert.Equal(t, tc.expected, result) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|   | |||||||
							
								
								
									
										25
									
								
								backend/internal/util/time_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								backend/internal/util/time_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | |||||||
|  | package util | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"testing" | ||||||
|  |  | ||||||
|  | 	"github.com/stretchr/testify/assert" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func TestUnixMilliToNiceFormat(t *testing.T) { | ||||||
|  | 	tests := []struct { | ||||||
|  | 		input    int64 | ||||||
|  | 		expected string | ||||||
|  | 	}{ | ||||||
|  | 		{0, "1970-01-01 10:00:00"},                   // Unix epoch time | ||||||
|  | 		{1568000000000, "2019-09-09 13:33:20"},       // Arbitrary millisecond timestamp | ||||||
|  | 		{1636598400000, "2021-11-11 12:40:00"},       // Another arbitrary millisecond timestamp | ||||||
|  | 		{-1000000000000, "1938-04-25 08:13:20"},      // Negative millisecond timestamp | ||||||
|  | 		{9223372036854775807, "1970-01-01 09:59:59"}, // Maximum representable millisecond timestamp | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for _, test := range tests { | ||||||
|  | 		output := UnixMilliToNiceFormat(test.input) | ||||||
|  | 		assert.Equal(t, test.expected, output) | ||||||
|  | 	} | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user