github.com/yandex/pandora@v0.5.32/components/providers/scenario/http/templater/templater_text_test.go (about)

     1  package templater
     2  
     3  import (
     4  	"strconv"
     5  	"testing"
     6  
     7  	"github.com/stretchr/testify/assert"
     8  	"github.com/stretchr/testify/require"
     9  	gun "github.com/yandex/pandora/components/guns/http_scenario"
    10  )
    11  
    12  func TestTextTemplater_Apply(t *testing.T) {
    13  	tests := []struct {
    14  		name            string
    15  		scenarioName    string
    16  		stepName        string
    17  		parts           *gun.RequestParts
    18  		vs              map[string]interface{}
    19  		expectedURL     string
    20  		expectedHeaders map[string]string
    21  		expectedBody    string
    22  		expectError     bool
    23  	}{
    24  		{
    25  			name:         "Test Scenario 1",
    26  			scenarioName: "TestScenario",
    27  			stepName:     "TestStep",
    28  			parts: &gun.RequestParts{
    29  				URL: "http://example.com/{{.endpoint}}",
    30  				Headers: map[string]string{
    31  					"Authorization": "Bearer {{.token}}",
    32  					"Content-Type":  "application/json",
    33  				},
    34  				Body: []byte(`{"name": "{{.name}}", "age": {{.age}}}`),
    35  			},
    36  			vs: map[string]interface{}{
    37  				"endpoint": "users",
    38  				"token":    "abc123",
    39  				"name":     "John",
    40  				"age":      30,
    41  			},
    42  			expectedURL: "http://example.com/users",
    43  			expectedHeaders: map[string]string{
    44  				"Authorization": "Bearer abc123",
    45  				"Content-Type":  "application/json",
    46  			},
    47  			expectedBody: `{"name": "John", "age": 30}`,
    48  			expectError:  false,
    49  		},
    50  		{
    51  			name:         "Test Scenario 2 (Invalid Template)",
    52  			scenarioName: "TestScenario",
    53  			stepName:     "TestStep",
    54  			parts: &gun.RequestParts{
    55  				URL: "http://example.com/{{.endpoint",
    56  			},
    57  			vs: map[string]interface{}{
    58  				"endpoint": "users",
    59  			},
    60  			expectedURL:     "",
    61  			expectedHeaders: nil,
    62  			expectedBody:    "",
    63  			expectError:     true,
    64  		},
    65  		{
    66  			name:            "Test Scenario 3 (Empty RequestParts)",
    67  			scenarioName:    "EmptyScenario",
    68  			stepName:        "EmptyStep",
    69  			parts:           &gun.RequestParts{},
    70  			vs:              map[string]interface{}{},
    71  			expectedURL:     "",
    72  			expectedHeaders: nil,
    73  			expectedBody:    "",
    74  			expectError:     false,
    75  		},
    76  		{
    77  			name:         "Test Scenario 4 (No Variables)",
    78  			scenarioName: "NoVarsScenario",
    79  			stepName:     "NoVarsStep",
    80  			parts: &gun.RequestParts{
    81  				URL: "http://example.com",
    82  				Headers: map[string]string{
    83  					"Authorization": "Bearer abc123",
    84  				},
    85  				Body: []byte(`{"name": "John", "age": 30}`),
    86  			},
    87  			vs:          map[string]interface{}{},
    88  			expectedURL: "http://example.com",
    89  			expectedHeaders: map[string]string{
    90  				"Authorization": "Bearer abc123",
    91  			},
    92  			expectedBody: `{"name": "John", "age": 30}`,
    93  			expectError:  false,
    94  		},
    95  		{
    96  			name:         "Test Scenario 5 (URL Only)",
    97  			scenarioName: "URLScenario",
    98  			stepName:     "URLStep",
    99  			parts: &gun.RequestParts{
   100  				URL: "http://example.com/{{.endpoint}}",
   101  			},
   102  			vs: map[string]interface{}{
   103  				"endpoint": "users",
   104  			},
   105  			expectedURL:     "http://example.com/users",
   106  			expectedHeaders: nil,
   107  			expectedBody:    "",
   108  			expectError:     false,
   109  		},
   110  		{
   111  			name:         "Test Scenario 6 (Headers Only)",
   112  			scenarioName: "HeaderScenario",
   113  			stepName:     "HeaderStep",
   114  			parts: &gun.RequestParts{
   115  				Headers: map[string]string{
   116  					"Authorization": "Bearer {{.token}}",
   117  					"Content-Type":  "application/json",
   118  				},
   119  			},
   120  			vs: map[string]interface{}{
   121  				"token": "xyz456",
   122  			},
   123  			expectedURL: "",
   124  			expectedHeaders: map[string]string{
   125  				"Authorization": "Bearer xyz456",
   126  				"Content-Type":  "application/json",
   127  			},
   128  			expectedBody: "",
   129  			expectError:  false,
   130  		},
   131  		{
   132  			name:         "Test Scenario 7 (Body Only)",
   133  			scenarioName: "BodyScenario",
   134  			stepName:     "BodyStep",
   135  			parts: &gun.RequestParts{
   136  				Body: []byte(`{"name": "{{.name}}", "age": {{.age}}}`),
   137  			},
   138  			vs: map[string]interface{}{
   139  				"name": "Alice",
   140  				"age":  25,
   141  			},
   142  			expectedURL:     "",
   143  			expectedHeaders: nil,
   144  			expectedBody:    `{"name": "Alice", "age": 25}`,
   145  			expectError:     false,
   146  		},
   147  		{
   148  			name:         "Test Scenario 8 (Invalid Template in Headers)",
   149  			scenarioName: "InvalidHeaderScenario",
   150  			stepName:     "InvalidHeaderStep",
   151  			parts: &gun.RequestParts{
   152  				Headers: map[string]string{
   153  					"Authorization": "Bearer {{.token",
   154  				},
   155  			},
   156  			vs:              map[string]interface{}{},
   157  			expectedURL:     "",
   158  			expectedHeaders: nil,
   159  			expectedBody:    "",
   160  			expectError:     true,
   161  		},
   162  		{
   163  			name:         "Test Scenario 9 (Invalid Template in URL)",
   164  			scenarioName: "InvalidURLScenario",
   165  			stepName:     "InvalidURLStep",
   166  			parts: &gun.RequestParts{
   167  				URL: "http://example.com/{{.endpoint",
   168  			},
   169  			vs:              map[string]interface{}{},
   170  			expectedURL:     "",
   171  			expectedHeaders: nil,
   172  			expectedBody:    "",
   173  			expectError:     true,
   174  		},
   175  		{
   176  			name:         "Test Scenario 10 (Invalid Template in Body)",
   177  			scenarioName: "InvalidBodyScenario",
   178  			stepName:     "InvalidBodyStep",
   179  			parts: &gun.RequestParts{
   180  				Body: []byte(`{"name": "{{.name}"}`),
   181  			},
   182  			vs:              map[string]interface{}{},
   183  			expectedURL:     "",
   184  			expectedHeaders: nil,
   185  			expectedBody:    "",
   186  			expectError:     true,
   187  		},
   188  	}
   189  
   190  	for _, test := range tests {
   191  		t.Run(test.name, func(t *testing.T) {
   192  			templater := &TextTemplater{}
   193  			err := templater.Apply(test.parts, test.vs, test.scenarioName, test.stepName)
   194  
   195  			if test.expectError {
   196  				require.Error(t, err)
   197  			} else {
   198  				require.NoError(t, err)
   199  				assert.Equal(t, test.expectedURL, test.parts.URL)
   200  				assert.Equal(t, test.expectedHeaders, test.parts.Headers)
   201  				assert.Equal(t, test.expectedBody, string(test.parts.Body))
   202  			}
   203  		})
   204  	}
   205  }
   206  
   207  func TestTextTemplater_Apply_WithRandFunct(t *testing.T) {
   208  	tests := []struct {
   209  		name        string
   210  		parts       *gun.RequestParts
   211  		vs          map[string]interface{}
   212  		assertBody  func(t *testing.T, body string)
   213  		expectError bool
   214  	}{
   215  		{
   216  			name:  "randInt with vars",
   217  			parts: &gun.RequestParts{Body: []byte(`{{ randInt .from .to }}`)},
   218  			vs: map[string]interface{}{
   219  				"from": int64(10),
   220  				"to":   30,
   221  			},
   222  			assertBody: func(t *testing.T, body string) {
   223  				v, err := strconv.ParseInt(body, 10, 64)
   224  				require.NoError(t, err)
   225  				require.InDelta(t, 20, v, 10)
   226  			},
   227  			expectError: false,
   228  		},
   229  		{
   230  			name:  "randInt with literals",
   231  			parts: &gun.RequestParts{Body: []byte(`{{ randInt 10 30 }}`)},
   232  			vs:    map[string]interface{}{},
   233  			assertBody: func(t *testing.T, body string) {
   234  				v, err := strconv.ParseInt(body, 10, 64)
   235  				require.NoError(t, err)
   236  				require.InDelta(t, 20, v, 10)
   237  			},
   238  			expectError: false,
   239  		},
   240  		{
   241  			name:  "randInt with no args",
   242  			parts: &gun.RequestParts{Body: []byte(`{{ randInt }}`)},
   243  			vs:    map[string]interface{}{},
   244  			assertBody: func(t *testing.T, body string) {
   245  				v, err := strconv.ParseInt(body, 10, 64)
   246  				require.NoError(t, err)
   247  				require.InDelta(t, 5, v, 5)
   248  			},
   249  			expectError: false,
   250  		},
   251  		{
   252  			name:  "randInt with literals",
   253  			parts: &gun.RequestParts{Body: []byte(`{{ randInt -10 }}`)},
   254  			vs:    map[string]interface{}{},
   255  			assertBody: func(t *testing.T, body string) {
   256  				v, err := strconv.ParseInt(body, 10, 64)
   257  				require.NoError(t, err)
   258  				require.InDelta(t, -5, v, 5)
   259  			},
   260  			expectError: false,
   261  		},
   262  		{
   263  			name:        "randInt with invalid args",
   264  			parts:       &gun.RequestParts{Body: []byte(`{{ randInt 10 "asdf" }}`)},
   265  			vs:          map[string]interface{}{},
   266  			assertBody:  nil,
   267  			expectError: true,
   268  		},
   269  		{
   270  			name:  "randString with 2 arg",
   271  			parts: &gun.RequestParts{Body: []byte(`{{ randString 10 "asdfgzxcv" }}`)},
   272  			vs:    map[string]interface{}{},
   273  			assertBody: func(t *testing.T, body string) {
   274  				require.Len(t, body, 10)
   275  			},
   276  			expectError: false,
   277  		},
   278  		{
   279  			name:  "randString with 1 arg",
   280  			parts: &gun.RequestParts{Body: []byte(`{{ randString 10 }}`)},
   281  			vs:    map[string]interface{}{},
   282  			assertBody: func(t *testing.T, body string) {
   283  				require.Len(t, body, 10)
   284  			},
   285  			expectError: false,
   286  		},
   287  		{
   288  			name:  "randString with 0 arg",
   289  			parts: &gun.RequestParts{Body: []byte(`{{ randString }}`)},
   290  			vs:    map[string]interface{}{},
   291  			assertBody: func(t *testing.T, body string) {
   292  				require.Len(t, body, 1)
   293  			},
   294  			expectError: false,
   295  		},
   296  		{
   297  			name:        "randString with invalid arg",
   298  			parts:       &gun.RequestParts{Body: []byte(`{{ randString "asdf" }}`)},
   299  			vs:          map[string]interface{}{},
   300  			assertBody:  nil,
   301  			expectError: true,
   302  		},
   303  		{
   304  			name:  "uuid",
   305  			parts: &gun.RequestParts{Body: []byte(`{{ uuid }}`)},
   306  			vs:    map[string]interface{}{},
   307  			assertBody: func(t *testing.T, body string) {
   308  				require.Len(t, body, 36)
   309  			},
   310  			expectError: false,
   311  		},
   312  	}
   313  	for _, tt := range tests {
   314  		t.Run(tt.name, func(t *testing.T) {
   315  			templater := &TextTemplater{}
   316  			err := templater.Apply(tt.parts, tt.vs, "scenarioName", "stepName")
   317  
   318  			if tt.expectError {
   319  				require.Error(t, err)
   320  			} else {
   321  				require.NoError(t, err)
   322  				tt.assertBody(t, string(tt.parts.Body))
   323  			}
   324  		})
   325  	}
   326  }