github.com/kyma-incubator/compass/components/director@v0.0.0-20230623144113-d764f56ff805/pkg/pagination/pagination_test.go (about)

     1  package pagination
     2  
     3  import (
     4  	"encoding/base64"
     5  	"strconv"
     6  	"testing"
     7  
     8  	"github.com/pkg/errors"
     9  	"github.com/stretchr/testify/assert"
    10  	"github.com/stretchr/testify/require"
    11  )
    12  
    13  func TestComputeOffset(t *testing.T) {
    14  	//GIVEN
    15  	offset := 2000
    16  	testCases := []struct {
    17  		Name            string
    18  		InputCursor     string
    19  		ExptectedOffset int
    20  		ExpectedErr     error
    21  	}{
    22  		{
    23  			Name:            "Success",
    24  			InputCursor:     convertIntToBase64String(offset),
    25  			ExptectedOffset: offset,
    26  			ExpectedErr:     nil,
    27  		},
    28  		{
    29  			Name:            "Success with easter egg",
    30  			InputCursor:     base64.StdEncoding.EncodeToString([]byte("DpKtJ4j9jDq" + strconv.Itoa(offset))),
    31  			ExptectedOffset: offset,
    32  			ExpectedErr:     nil,
    33  		},
    34  		{
    35  			Name:            "Success when cursor is empty",
    36  			InputCursor:     "",
    37  			ExptectedOffset: 0,
    38  			ExpectedErr:     nil,
    39  		},
    40  		{
    41  			Name:            "Return error when cursor is negative",
    42  			InputCursor:     convertIntToBase64String(-offset),
    43  			ExptectedOffset: 0,
    44  			ExpectedErr:     errors.New("cursor is not correct"),
    45  		},
    46  		{
    47  			Name:            "Return error when input is not integer",
    48  			InputCursor:     base64.StdEncoding.EncodeToString([]byte("foo-bar")),
    49  			ExptectedOffset: 0,
    50  			ExpectedErr:     errors.New("cursor is not correct"),
    51  		},
    52  		{
    53  			Name:            "Return error when input is not valid BASE64 string",
    54  			InputCursor:     "Zm9vLWJh-1cg==",
    55  			ExptectedOffset: 0,
    56  			ExpectedErr:     errors.New("cursor is not correct"),
    57  		},
    58  	}
    59  
    60  	for _, testCase := range testCases {
    61  		t.Run(testCase.Name, func(t *testing.T) {
    62  			// WHEN
    63  			offset, err := DecodeOffsetCursor(testCase.InputCursor)
    64  
    65  			// THEN
    66  			if testCase.ExpectedErr != nil {
    67  				require.Error(t, err)
    68  			} else {
    69  				require.NoError(t, err)
    70  				assert.Equal(t, testCase.ExptectedOffset, offset)
    71  			}
    72  		})
    73  	}
    74  }
    75  
    76  func TestConvertOffsetToPageCursor(t *testing.T) {
    77  	// GIVEN
    78  	pageSize := 50
    79  	offset := 50
    80  
    81  	// WHEN
    82  	nextPageCursor := EncodeNextOffsetCursor(pageSize, offset)
    83  
    84  	// THEN
    85  	require.Equal(t, "RHBLdEo0ajlqRHExMDA=", nextPageCursor)
    86  }
    87  
    88  func TestConvertOffsetLimitAndOrderedColumnToSQL(t *testing.T) {
    89  	t.Run("Success converting Offset and Limit to SQL ", func(t *testing.T) {
    90  		// WHEN
    91  		sql, err := ConvertOffsetLimitAndOrderedColumnToSQL(5, 5, "id")
    92  
    93  		// THEN
    94  		require.NoError(t, err)
    95  		assert.Equal(t, sql, `ORDER BY id LIMIT 5 OFFSET 5`)
    96  	})
    97  
    98  	t.Run("Return error when column to order by is empty", func(t *testing.T) {
    99  		// WHEN
   100  		_, err := ConvertOffsetLimitAndOrderedColumnToSQL(5, 10, "")
   101  
   102  		// THEN
   103  		require.Error(t, err)
   104  		assert.Contains(t, err.Error(), `to use pagination you must provide column to order by`)
   105  	})
   106  
   107  	t.Run("Return error when page size is smaller than 1", func(t *testing.T) {
   108  		// WHEN
   109  		_, err := ConvertOffsetLimitAndOrderedColumnToSQL(-1, 5, "id")
   110  
   111  		// THEN
   112  		require.Error(t, err)
   113  		assert.Contains(t, err.Error(), `page size cannot be smaller than 1`)
   114  	})
   115  
   116  	t.Run("Return error when offset is smaller than 0", func(t *testing.T) {
   117  		// WHEN
   118  		_, err := ConvertOffsetLimitAndOrderedColumnToSQL(5, -1, "id")
   119  
   120  		// THEN
   121  		require.Error(t, err)
   122  		assert.Contains(t, err.Error(), `offset cannot be smaller than 0`)
   123  	})
   124  }
   125  
   126  func TestDecodeAndEncodeCursorTogether(t *testing.T) {
   127  	t.Run("Success encoding and then decoding cursor", func(t *testing.T) {
   128  		//GIVEN
   129  		offset := 4
   130  
   131  		// WHEN
   132  		cursor := EncodeNextOffsetCursor(offset, 0)
   133  		decodedOffset, err := DecodeOffsetCursor(cursor)
   134  
   135  		// THEN
   136  		require.NoError(t, err)
   137  		assert.Equal(t, offset, decodedOffset)
   138  	})
   139  
   140  	t.Run("Success encoding and then decoding next page cursor", func(t *testing.T) {
   141  		//GIVEN
   142  		offset := 4
   143  		pageSize := 5
   144  
   145  		// WHEN
   146  		cursor := EncodeNextOffsetCursor(offset, pageSize)
   147  		decodedOffset, err := DecodeOffsetCursor(cursor)
   148  		// THEN
   149  		require.NoError(t, err)
   150  		assert.Equal(t, offset+pageSize, decodedOffset)
   151  	})
   152  
   153  	t.Run("Success decoding and then encoding cursor", func(t *testing.T) {
   154  		//GIVEN
   155  		cursor := "RHBLdEo0ajlqRHExMDA="
   156  
   157  		// WHEN
   158  		offset, err := DecodeOffsetCursor(cursor)
   159  		encodedCusor := EncodeNextOffsetCursor(offset, 0)
   160  
   161  		// THEN
   162  		require.NoError(t, err)
   163  		assert.Equal(t, cursor, encodedCusor)
   164  	})
   165  
   166  	t.Run("Success decoding and then encoding incremented cursor", func(t *testing.T) {
   167  		//GIVEN
   168  		cursor := "RHBLdEo0ajlqRHExMDA="
   169  		nextCursor := "RHBLdEo0ajlqRHExMDU="
   170  
   171  		// WHEN
   172  		offset, err := DecodeOffsetCursor(cursor)
   173  		encodedCusor := EncodeNextOffsetCursor(offset, 5)
   174  
   175  		// THEN
   176  		require.NoError(t, err)
   177  		assert.Equal(t, nextCursor, encodedCusor)
   178  	})
   179  }
   180  
   181  func convertIntToBase64String(number int) string {
   182  	return base64.StdEncoding.EncodeToString([]byte(strconv.Itoa(number)))
   183  }