goyave.dev/goyave/v5@v5.0.0-rc9.0.20240517145003-d3f977d0b9f3/database/paginator_test.go (about)

     1  package database
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/stretchr/testify/assert"
     7  	"github.com/stretchr/testify/require"
     8  	"gorm.io/driver/sqlite"
     9  	"gorm.io/gorm"
    10  	"goyave.dev/goyave/v5/config"
    11  )
    12  
    13  type TestArticle struct {
    14  	Author *TestUser `gorm:"foreignKey:AuthorID"`
    15  
    16  	Title    string `gorm:"type:varchar(255)"`
    17  	Content  string `gorm:"type:text"`
    18  	ID       uint   `gorm:"primaryKey"`
    19  	AuthorID uint
    20  }
    21  
    22  func articleGenerator() *TestArticle {
    23  	return &TestArticle{
    24  		Title:   "lorem ipsum",
    25  		Content: "lorem ipsum sit dolor amet",
    26  	}
    27  }
    28  
    29  func preparePaginatorTestDB() (*gorm.DB, []*TestArticle) {
    30  	cfg := config.LoadDefault()
    31  	cfg.Set("app.debug", false)
    32  	cfg.Set("database.connection", "sqlite3_paginator_test")
    33  	cfg.Set("database.name", "paginator_test.db")
    34  	cfg.Set("database.options", "mode=memory")
    35  	db, err := New(cfg, nil)
    36  	if err != nil {
    37  		panic(err)
    38  	}
    39  
    40  	if err := db.AutoMigrate(&TestUser{}, &TestArticle{}); err != nil {
    41  		panic(err)
    42  	}
    43  
    44  	author := userGenerator()
    45  	if err := db.Create(author).Error; err != nil {
    46  		panic(err)
    47  	}
    48  
    49  	factory := NewFactory(articleGenerator)
    50  	factory.Override(&TestArticle{AuthorID: author.ID})
    51  
    52  	articles := factory.Save(db, 11)
    53  	return db, articles
    54  }
    55  
    56  func TestPaginator(t *testing.T) {
    57  	RegisterDialect("sqlite3_paginator_test", "file:{name}?{options}", sqlite.Open)
    58  	t.Cleanup(func() {
    59  		mu.Lock()
    60  		delete(dialects, "sqlite3_paginator_test")
    61  		mu.Unlock()
    62  	})
    63  
    64  	t.Run("UpdatePageInfo", func(t *testing.T) {
    65  		db, _ := preparePaginatorTestDB()
    66  		articles := []*TestArticle{}
    67  		p := NewPaginator(db, 2, 5, &articles)
    68  
    69  		assert.Equal(t, db, p.DB)
    70  		assert.Equal(t, 2, p.CurrentPage)
    71  		assert.Equal(t, 5, p.PageSize)
    72  		assert.Equal(t, &articles, p.Records)
    73  
    74  		err := p.UpdatePageInfo()
    75  		require.NoError(t, err)
    76  
    77  		assert.Equal(t, int64(11), p.Total)
    78  		assert.Equal(t, int64(3), p.MaxPage)
    79  		assert.True(t, p.loadedPageInfo)
    80  	})
    81  
    82  	t.Run("Find", func(t *testing.T) {
    83  		db, srcArticles := preparePaginatorTestDB()
    84  		articles := []*TestArticle{}
    85  		p := NewPaginator(db, 2, 5, &articles)
    86  
    87  		assert.Equal(t, db, p.DB)
    88  		assert.Equal(t, 2, p.CurrentPage)
    89  		assert.Equal(t, 5, p.PageSize)
    90  		assert.Equal(t, &articles, p.Records)
    91  
    92  		err := p.Find()
    93  		require.NoError(t, err)
    94  
    95  		assert.Equal(t, int64(11), p.Total)
    96  		assert.Equal(t, int64(3), p.MaxPage)
    97  		assert.True(t, p.loadedPageInfo)
    98  		assert.Equal(t, srcArticles[5:10], *p.Records)
    99  	})
   100  
   101  	t.Run("Find_no_record", func(t *testing.T) {
   102  		cfg := config.LoadDefault()
   103  		cfg.Set("app.debug", false)
   104  		cfg.Set("database.connection", "sqlite3_paginator_test")
   105  		cfg.Set("database.name", "paginator_test.db")
   106  		cfg.Set("database.options", "mode=memory")
   107  		db, err := New(cfg, nil)
   108  		if err != nil {
   109  			panic(err)
   110  		}
   111  
   112  		if err := db.AutoMigrate(&TestUser{}, &TestArticle{}); err != nil {
   113  			panic(err)
   114  		}
   115  
   116  		articles := []*TestArticle{}
   117  		p := NewPaginator(db, 2, 5, &articles)
   118  
   119  		err = p.Find()
   120  		require.NoError(t, err)
   121  
   122  		assert.Equal(t, int64(0), p.Total)
   123  		assert.Equal(t, int64(1), p.MaxPage)
   124  		assert.True(t, p.loadedPageInfo)
   125  		assert.Empty(t, *p.Records)
   126  	})
   127  
   128  	t.Run("UpdatePageInfo_error", func(t *testing.T) {
   129  		db, _ := preparePaginatorTestDB()
   130  		articles := []*TestArticle{}
   131  
   132  		db = db.Where("not_a_column", 1)
   133  		p := NewPaginator(db, 2, 5, &articles)
   134  
   135  		err := p.Find() // updatePageInfo is called because the page info is not called yet
   136  		require.Error(t, err)
   137  		assert.False(t, p.loadedPageInfo)
   138  	})
   139  
   140  	t.Run("Find_error", func(t *testing.T) {
   141  		db, _ := preparePaginatorTestDB()
   142  		articles := []*TestArticle{}
   143  
   144  		db = db.Where("not_a_column", 1)
   145  		p := NewPaginator(db, 2, 5, &articles)
   146  		p.loadedPageInfo = true // Let's assume the page info has already been loaded
   147  
   148  		err := p.Find()
   149  		require.Error(t, err)
   150  		assert.False(t, p.loadedPageInfo) // Page info invalidated
   151  	})
   152  
   153  	t.Run("select_where_preload", func(t *testing.T) {
   154  		db, _ := preparePaginatorTestDB()
   155  		articles := []*TestArticle{}
   156  
   157  		db = db.Select("id", "title", "author_id").Where("id > ?", 9).Preload("Author")
   158  		p := NewPaginator(db, 1, 5, &articles)
   159  
   160  		err := p.Find()
   161  		require.NoError(t, err)
   162  
   163  		assert.Equal(t, int64(2), p.Total)
   164  		assert.Equal(t, int64(1), p.MaxPage)
   165  		assert.True(t, p.loadedPageInfo)
   166  
   167  		author := userGenerator()
   168  		author.ID = 1
   169  		expected := []*TestArticle{
   170  			{ID: 10, Title: "lorem ipsum", AuthorID: 1, Author: author},
   171  			{ID: 11, Title: "lorem ipsum", AuthorID: 1, Author: author},
   172  		}
   173  		assert.Equal(t, expected, *p.Records)
   174  	})
   175  
   176  	t.Run("Raw", func(t *testing.T) {
   177  		db, _ := preparePaginatorTestDB()
   178  		articles := []*TestArticle{}
   179  		p := NewPaginator(db, 1, 5, &articles)
   180  
   181  		query := `SELECT id, title FROM test_articles WHERE id > ?`
   182  		queryVars := []any{9}
   183  		countQuery := `SELECT COUNT(*) FROM test_articles WHERE id > ?`
   184  		assert.Equal(t, p, p.Raw(query, queryVars, countQuery, queryVars))
   185  
   186  		err := p.Find()
   187  		require.NoError(t, err)
   188  
   189  		assert.Equal(t, int64(2), p.Total)
   190  		assert.Equal(t, int64(1), p.MaxPage)
   191  		assert.True(t, p.loadedPageInfo)
   192  
   193  		expected := []*TestArticle{
   194  			{ID: 10, Title: "lorem ipsum"},
   195  			{ID: 11, Title: "lorem ipsum"},
   196  		}
   197  		assert.Equal(t, expected, *p.Records)
   198  
   199  		// Get page 2 (no results expected)
   200  		articles = []*TestArticle{}
   201  		p = NewPaginator(db, 2, 5, &articles)
   202  		p.Raw(query, queryVars, countQuery, queryVars)
   203  		err = p.Find()
   204  		require.NoError(t, err)
   205  		assert.Equal(t, int64(2), p.Total)
   206  		assert.Equal(t, int64(1), p.MaxPage)
   207  		assert.True(t, p.loadedPageInfo)
   208  		assert.Empty(t, *p.Records)
   209  	})
   210  }