feat: add product tags index
This commit is contained in:
		
							parent
							
								
									f6e936a760
								
							
						
					
					
						commit
						6e47895174
					
				| 
						 | 
				
			
			@ -0,0 +1,497 @@
 | 
			
		|||
package repository
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/entity"
 | 
			
		||||
	"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/product"
 | 
			
		||||
	"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/repository"
 | 
			
		||||
	mgo "code.30cm.net/digimon/library-go/mongo"
 | 
			
		||||
	"context"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"github.com/alicebob/miniredis/v2"
 | 
			
		||||
	"github.com/stretchr/testify/assert"
 | 
			
		||||
	"github.com/stretchr/testify/require"
 | 
			
		||||
	"github.com/zeromicro/go-zero/core/stores/cache"
 | 
			
		||||
	"github.com/zeromicro/go-zero/core/stores/mon"
 | 
			
		||||
	"github.com/zeromicro/go-zero/core/stores/redis"
 | 
			
		||||
	"go.mongodb.org/mongo-driver/bson/primitive"
 | 
			
		||||
	"testing"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func SetupTestProductTagsRepo(db string) (repository.TagRepo, func(), error) {
 | 
			
		||||
	h, p, tearDown, err := startMongoContainer()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	s, _ := miniredis.Run()
 | 
			
		||||
 | 
			
		||||
	conf := &mgo.Conf{
 | 
			
		||||
		Schema:                           Schema,
 | 
			
		||||
		Host:                             fmt.Sprintf("%s:%s", h, p),
 | 
			
		||||
		Database:                         db,
 | 
			
		||||
		MaxStaleness:                     300,
 | 
			
		||||
		MaxPoolSize:                      100,
 | 
			
		||||
		MinPoolSize:                      100,
 | 
			
		||||
		MaxConnIdleTime:                  300,
 | 
			
		||||
		Compressors:                      []string{},
 | 
			
		||||
		EnableStandardReadWriteSplitMode: false,
 | 
			
		||||
		ConnectTimeoutMs:                 3000,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cacheConf := cache.CacheConf{
 | 
			
		||||
		cache.NodeConf{
 | 
			
		||||
			RedisConf: redis.RedisConf{
 | 
			
		||||
				Host: s.Addr(),
 | 
			
		||||
				Type: redis.NodeType,
 | 
			
		||||
			},
 | 
			
		||||
			Weight: 100,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cacheOpts := []cache.Option{
 | 
			
		||||
		cache.WithExpiry(1000 * time.Microsecond),
 | 
			
		||||
		cache.WithNotFoundExpiry(1000 * time.Microsecond),
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	param := TagsRepositoryParam{
 | 
			
		||||
		Conf:      conf,
 | 
			
		||||
		CacheConf: cacheConf,
 | 
			
		||||
		CacheOpts: cacheOpts,
 | 
			
		||||
		DBOpts: []mon.Option{
 | 
			
		||||
			mgo.SetCustomDecimalType(),
 | 
			
		||||
			mgo.InitMongoOptions(*conf),
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	repo := NewTagsRepository(param)
 | 
			
		||||
	_, _ = repo.IndexTags20250317001UP(context.Background())
 | 
			
		||||
	_, _ = repo.IndexTagsBinding20250317001UP(context.Background())
 | 
			
		||||
 | 
			
		||||
	return repo, tearDown, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestCreateTags(t *testing.T) {
 | 
			
		||||
	repo, tearDown, err := SetupTestProductTagsRepo("testDB")
 | 
			
		||||
	require.NoError(t, err)
 | 
			
		||||
	defer tearDown()
 | 
			
		||||
 | 
			
		||||
	ctx := context.Background()
 | 
			
		||||
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		name      string
 | 
			
		||||
		inputTag  *entity.Tags
 | 
			
		||||
		check     func(t *testing.T, tag *entity.Tags)
 | 
			
		||||
		expectErr bool
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			name: "Insert tag with zero ID",
 | 
			
		||||
			inputTag: &entity.Tags{
 | 
			
		||||
				// ID 為零值,Create 會自動生成
 | 
			
		||||
				Types:    product.ItemTypeSkill,
 | 
			
		||||
				Name:     "Tag A",
 | 
			
		||||
				ShowType: product.ShowTypeNormal,
 | 
			
		||||
				Cover:    nil,
 | 
			
		||||
			},
 | 
			
		||||
			check: func(t *testing.T, tag *entity.Tags) {
 | 
			
		||||
				require.False(t, tag.ID.IsZero(), "ID should be generated")
 | 
			
		||||
				assert.NotZero(t, tag.CreatedAt, "CreatedAt should be set")
 | 
			
		||||
				assert.NotZero(t, tag.UpdatedAt, "UpdatedAt should be set")
 | 
			
		||||
				assert.Equal(t, "Tag A", tag.Name)
 | 
			
		||||
			},
 | 
			
		||||
			expectErr: false,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "Insert tag with preset ID",
 | 
			
		||||
			inputTag: &entity.Tags{
 | 
			
		||||
				ID:       primitive.NewObjectID(), // 預先設定 ID,不會被覆蓋
 | 
			
		||||
				Types:    product.ItemTypeSkill,
 | 
			
		||||
				Name:     "Tag B",
 | 
			
		||||
				ShowType: product.ShowTypeNormal,
 | 
			
		||||
				Cover:    nil,
 | 
			
		||||
				// 預設時間欄位
 | 
			
		||||
				CreatedAt: 123456789,
 | 
			
		||||
				UpdatedAt: 123456789,
 | 
			
		||||
			},
 | 
			
		||||
			check: func(t *testing.T, tag *entity.Tags) {
 | 
			
		||||
				assert.False(t, tag.ID.IsZero())
 | 
			
		||||
				assert.Equal(t, "Tag B", tag.Name)
 | 
			
		||||
				// 保持原有的 CreatedAt 與 UpdatedAt 值
 | 
			
		||||
				assert.Equal(t, int64(123456789), tag.CreatedAt)
 | 
			
		||||
				assert.Equal(t, int64(123456789), tag.UpdatedAt)
 | 
			
		||||
			},
 | 
			
		||||
			expectErr: false,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, tc := range tests {
 | 
			
		||||
		tc := tc // capture range variable
 | 
			
		||||
		t.Run(tc.name, func(t *testing.T) {
 | 
			
		||||
			err := repo.Create(ctx, tc.inputTag)
 | 
			
		||||
			if tc.expectErr {
 | 
			
		||||
				require.Error(t, err)
 | 
			
		||||
			} else {
 | 
			
		||||
				require.NoError(t, err)
 | 
			
		||||
				// 驗證 Create 方法對輸入資料的影響
 | 
			
		||||
				tc.check(t, tc.inputTag)
 | 
			
		||||
 | 
			
		||||
				// 可選:利用 GetByID 再從資料庫中讀取進一步驗證
 | 
			
		||||
				tagFromDB, err := repo.GetByID(ctx, tc.inputTag.ID.Hex())
 | 
			
		||||
				require.NoError(t, err)
 | 
			
		||||
				assert.Equal(t, tc.inputTag.Name, tagFromDB.Name)
 | 
			
		||||
				assert.Equal(t, tc.inputTag.Types, tagFromDB.Types)
 | 
			
		||||
				assert.Equal(t, tc.inputTag.ShowType, tagFromDB.ShowType)
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestGetTagByID(t *testing.T) {
 | 
			
		||||
	repo, tearDown, err := SetupTestProductTagsRepo("testDB")
 | 
			
		||||
	require.NoError(t, err)
 | 
			
		||||
	defer tearDown()
 | 
			
		||||
 | 
			
		||||
	ctx := context.Background()
 | 
			
		||||
 | 
			
		||||
	// 先建立一筆測試資料
 | 
			
		||||
	tag := &entity.Tags{
 | 
			
		||||
		Types:    product.ItemTypeSkill,
 | 
			
		||||
		Name:     "Sample Tag",
 | 
			
		||||
		ShowType: product.ShowTypeNormal,
 | 
			
		||||
		Cover:    nil,
 | 
			
		||||
	}
 | 
			
		||||
	err = repo.Create(ctx, tag)
 | 
			
		||||
	require.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		name         string
 | 
			
		||||
		inputID      string
 | 
			
		||||
		expectedName string
 | 
			
		||||
		expectedErr  error
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			name:         "Valid tag ID",
 | 
			
		||||
			inputID:      tag.ID.Hex(),
 | 
			
		||||
			expectedName: "Sample Tag",
 | 
			
		||||
			expectedErr:  nil,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:         "Invalid ObjectID format",
 | 
			
		||||
			inputID:      "invalid-hex",
 | 
			
		||||
			expectedName: "",
 | 
			
		||||
			// 這裡預期錯誤內容會包含 "hex" 字樣,故使用 nil 來做後續判斷
 | 
			
		||||
			expectedErr: errors.New("invalid"),
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:         "Tag not found",
 | 
			
		||||
			inputID:      primitive.NewObjectID().Hex(),
 | 
			
		||||
			expectedName: "",
 | 
			
		||||
			expectedErr:  ErrNotFound,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, tt := range tests {
 | 
			
		||||
		tt := tt // capture range variable
 | 
			
		||||
		t.Run(tt.name, func(t *testing.T) {
 | 
			
		||||
			res, err := repo.GetByID(ctx, tt.inputID)
 | 
			
		||||
			if tt.expectedErr != nil {
 | 
			
		||||
				require.Error(t, err)
 | 
			
		||||
				if tt.name == "Invalid ObjectID format" {
 | 
			
		||||
					assert.Contains(t, err.Error(), "hex")
 | 
			
		||||
				} else {
 | 
			
		||||
					assert.Equal(t, tt.expectedErr, err)
 | 
			
		||||
				}
 | 
			
		||||
				assert.Nil(t, res)
 | 
			
		||||
			} else {
 | 
			
		||||
				require.NoError(t, err)
 | 
			
		||||
				require.NotNil(t, res)
 | 
			
		||||
				assert.Equal(t, tt.expectedName, res.Name)
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestUpdateTag(t *testing.T) {
 | 
			
		||||
	repo, tearDown, err := SetupTestProductTagsRepo("testDB")
 | 
			
		||||
	require.NoError(t, err)
 | 
			
		||||
	defer tearDown()
 | 
			
		||||
 | 
			
		||||
	ctx := context.Background()
 | 
			
		||||
 | 
			
		||||
	// 先建立一筆初始的 Tag 測試資料
 | 
			
		||||
	origTag := &entity.Tags{
 | 
			
		||||
		Types:    product.ItemTypeSkill,
 | 
			
		||||
		ShowType: product.ShowTypeNormal,
 | 
			
		||||
		Name:     "Original Name",
 | 
			
		||||
	}
 | 
			
		||||
	err = repo.Create(ctx, origTag)
 | 
			
		||||
	require.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		name             string
 | 
			
		||||
		id               string
 | 
			
		||||
		params           repository.TagModifyParams
 | 
			
		||||
		expectedName     string
 | 
			
		||||
		expectedTypes    product.ItemType
 | 
			
		||||
		expectedShowType product.ShowType
 | 
			
		||||
		expectedCover    *string
 | 
			
		||||
		expectErr        bool
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			name: "Update all fields",
 | 
			
		||||
			id:   origTag.ID.Hex(),
 | 
			
		||||
			params: repository.TagModifyParams{
 | 
			
		||||
				Name:     ptr("New Name"),
 | 
			
		||||
				Types:    ptr(product.ItemTypeSkill),
 | 
			
		||||
				ShowType: ptr(product.ShowTypeNormal),
 | 
			
		||||
				Cover:    ptr("new-cover.jpg"),
 | 
			
		||||
			},
 | 
			
		||||
			expectedName:     "New Name",
 | 
			
		||||
			expectedTypes:    product.ItemTypeSkill,
 | 
			
		||||
			expectedShowType: product.ShowTypeNormal,
 | 
			
		||||
			expectedCover:    ptr("new-cover.jpg"),
 | 
			
		||||
			expectErr:        false,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "Update only name",
 | 
			
		||||
			id:   origTag.ID.Hex(),
 | 
			
		||||
			params: repository.TagModifyParams{
 | 
			
		||||
				Name: ptr("Another Name"),
 | 
			
		||||
			},
 | 
			
		||||
			// 其他欄位保持原值
 | 
			
		||||
			expectedName:     "Another Name",
 | 
			
		||||
			expectedTypes:    origTag.Types,
 | 
			
		||||
			expectedShowType: origTag.ShowType,
 | 
			
		||||
			expectedCover:    ptr("new-cover.jpg"),
 | 
			
		||||
			expectErr:        false,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "Invalid ObjectID",
 | 
			
		||||
			id:   "invalid-id",
 | 
			
		||||
			params: repository.TagModifyParams{
 | 
			
		||||
				Name: ptr("Should Not Update"),
 | 
			
		||||
			},
 | 
			
		||||
			expectErr: true,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, tt := range tests {
 | 
			
		||||
		tt := tt // capture range variable
 | 
			
		||||
		t.Run(tt.name, func(t *testing.T) {
 | 
			
		||||
			err := repo.Update(ctx, tt.id, tt.params)
 | 
			
		||||
			if tt.expectErr {
 | 
			
		||||
				require.Error(t, err)
 | 
			
		||||
			} else {
 | 
			
		||||
				require.NoError(t, err)
 | 
			
		||||
				// 讀取更新後的資料
 | 
			
		||||
				updated, err := repo.GetByID(ctx, tt.id)
 | 
			
		||||
				require.NoError(t, err)
 | 
			
		||||
				assert.Equal(t, tt.expectedName, updated.Name)
 | 
			
		||||
				assert.Equal(t, tt.expectedTypes, updated.Types)
 | 
			
		||||
				assert.Equal(t, tt.expectedShowType, updated.ShowType)
 | 
			
		||||
				if tt.expectedCover == nil {
 | 
			
		||||
					assert.Nil(t, updated.Cover)
 | 
			
		||||
				} else {
 | 
			
		||||
					assert.Equal(t, *tt.expectedCover, *updated.Cover)
 | 
			
		||||
				}
 | 
			
		||||
				// 驗證 updated_at 一定被更新(大於 0)
 | 
			
		||||
				assert.NotZero(t, updated.UpdatedAt)
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestDeleteTag(t *testing.T) {
 | 
			
		||||
	repo, tearDown, err := SetupTestProductTagsRepo("testDB")
 | 
			
		||||
	require.NoError(t, err)
 | 
			
		||||
	defer tearDown()
 | 
			
		||||
 | 
			
		||||
	ctx := context.Background()
 | 
			
		||||
 | 
			
		||||
	// 插入一筆測試資料
 | 
			
		||||
	tag := &entity.Tags{
 | 
			
		||||
		Types:    product.ItemTypeSkill,
 | 
			
		||||
		ShowType: product.ShowTypeNormal,
 | 
			
		||||
		Name:     "Test Tag",
 | 
			
		||||
		// Cover 為 nil
 | 
			
		||||
	}
 | 
			
		||||
	err = repo.Create(ctx, tag)
 | 
			
		||||
	require.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		name        string
 | 
			
		||||
		id          string
 | 
			
		||||
		expectErr   error // 預期的錯誤,若為 nil 表示預期成功
 | 
			
		||||
		checkDelete bool  // 若為 true,表示刪除後需驗證資料不存在
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			name:        "Delete existing tag",
 | 
			
		||||
			id:          tag.ID.Hex(),
 | 
			
		||||
			expectErr:   nil,
 | 
			
		||||
			checkDelete: true,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:        "Invalid ObjectID format",
 | 
			
		||||
			id:          "invalid-id",
 | 
			
		||||
			expectErr:   ErrInvalidObjectID,
 | 
			
		||||
			checkDelete: false,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:        "Delete non-existent tag",
 | 
			
		||||
			id:          primitive.NewObjectID().Hex(),
 | 
			
		||||
			expectErr:   nil,
 | 
			
		||||
			checkDelete: false,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, tt := range tests {
 | 
			
		||||
		tt := tt // capture range variable
 | 
			
		||||
		t.Run(tt.name, func(t *testing.T) {
 | 
			
		||||
			err := repo.Delete(ctx, tt.id)
 | 
			
		||||
			if tt.expectErr != nil {
 | 
			
		||||
				require.Error(t, err)
 | 
			
		||||
				assert.Equal(t, tt.expectErr, err)
 | 
			
		||||
			} else {
 | 
			
		||||
				require.NoError(t, err)
 | 
			
		||||
				if tt.checkDelete {
 | 
			
		||||
					// 刪除成功後,透過 GetByID 應查無資料
 | 
			
		||||
					_, err := repo.GetByID(ctx, tt.id)
 | 
			
		||||
					require.Error(t, err)
 | 
			
		||||
					assert.Equal(t, ErrNotFound, err)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestListTags(t *testing.T) {
 | 
			
		||||
	repo, tearDown, err := SetupTestProductTagsRepo("testDB")
 | 
			
		||||
	require.NoError(t, err)
 | 
			
		||||
	defer tearDown()
 | 
			
		||||
 | 
			
		||||
	ctx := context.Background()
 | 
			
		||||
	now := time.Now().UnixNano()
 | 
			
		||||
 | 
			
		||||
	// 建立測試資料,手動指定 ID 與時間(不讓 Create 自動覆蓋)
 | 
			
		||||
	tag1 := &entity.Tags{
 | 
			
		||||
		ID:        primitive.NewObjectID(),
 | 
			
		||||
		Name:      "Tag A",
 | 
			
		||||
		Types:     product.ItemTypeSkill,
 | 
			
		||||
		ShowType:  product.ShowTypeNormal,
 | 
			
		||||
		CreatedAt: now + 300,
 | 
			
		||||
		UpdatedAt: now + 300,
 | 
			
		||||
	}
 | 
			
		||||
	tag2 := &entity.Tags{
 | 
			
		||||
		ID:        primitive.NewObjectID(),
 | 
			
		||||
		Name:      "Tag B",
 | 
			
		||||
		Types:     product.ItemTypeProduct,
 | 
			
		||||
		ShowType:  product.ShowTypeNormal,
 | 
			
		||||
		CreatedAt: now + 200,
 | 
			
		||||
		UpdatedAt: now + 200,
 | 
			
		||||
	}
 | 
			
		||||
	tag3 := &entity.Tags{
 | 
			
		||||
		ID:        primitive.NewObjectID(),
 | 
			
		||||
		Types:     product.ItemTypeProduct,
 | 
			
		||||
		Name:      "Tag C",
 | 
			
		||||
		ShowType:  product.ShowTypeNormal,
 | 
			
		||||
		CreatedAt: now + 100,
 | 
			
		||||
		UpdatedAt: now + 100,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 插入測試資料
 | 
			
		||||
	err = repo.Create(ctx, tag1)
 | 
			
		||||
	require.NoError(t, err)
 | 
			
		||||
	err = repo.Create(ctx, tag2)
 | 
			
		||||
	require.NoError(t, err)
 | 
			
		||||
	err = repo.Create(ctx, tag3)
 | 
			
		||||
	require.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		name           string
 | 
			
		||||
		params         repository.TagQueryParams
 | 
			
		||||
		expectCount    int64
 | 
			
		||||
		expectIDsOrder []primitive.ObjectID
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			name: "Filter by Name",
 | 
			
		||||
			params: repository.TagQueryParams{
 | 
			
		||||
				Name:      ptr("Tag A"),
 | 
			
		||||
				PageSize:  10,
 | 
			
		||||
				PageIndex: 1,
 | 
			
		||||
			},
 | 
			
		||||
			expectCount:    1,
 | 
			
		||||
			expectIDsOrder: []primitive.ObjectID{tag1.ID},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "Filter by Types = type1",
 | 
			
		||||
			params: repository.TagQueryParams{
 | 
			
		||||
				Types:     ptr(product.ItemTypeProduct),
 | 
			
		||||
				PageSize:  10,
 | 
			
		||||
				PageIndex: 1,
 | 
			
		||||
			},
 | 
			
		||||
			// tag1與 tag2 符合條件
 | 
			
		||||
			expectCount: 2,
 | 
			
		||||
			// 排序依 updated_at 由大到小,故 tag1 (now+300) 在前,接著 tag2 (now+200)
 | 
			
		||||
			expectIDsOrder: []primitive.ObjectID{tag1.ID, tag2.ID},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "Filter by ShowType = show1",
 | 
			
		||||
			params: repository.TagQueryParams{
 | 
			
		||||
				ShowType:  ptr(product.ShowTypeNormal),
 | 
			
		||||
				PageSize:  10,
 | 
			
		||||
				PageIndex: 1,
 | 
			
		||||
			},
 | 
			
		||||
			// tag1與 tag3 符合條件
 | 
			
		||||
			expectCount: 3,
 | 
			
		||||
			// 排序:tag1 (now+300) 在前,tag3 (now+100) 在後
 | 
			
		||||
			expectIDsOrder: []primitive.ObjectID{tag1.ID, tag2.ID, tag3.ID},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "Filter by Types=type1 and ShowType=show1",
 | 
			
		||||
			params: repository.TagQueryParams{
 | 
			
		||||
				Types:     ptr(product.ItemTypeProduct),
 | 
			
		||||
				ShowType:  ptr(product.ShowTypeNormal),
 | 
			
		||||
				PageSize:  10,
 | 
			
		||||
				PageIndex: 1,
 | 
			
		||||
			},
 | 
			
		||||
			// 只有 tag1 同時符合兩個條件
 | 
			
		||||
			expectCount:    2,
 | 
			
		||||
			expectIDsOrder: []primitive.ObjectID{tag1.ID, tag3.ID},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "Pagination works: PageIndex 1",
 | 
			
		||||
			params: repository.TagQueryParams{
 | 
			
		||||
				PageSize:  2,
 | 
			
		||||
				PageIndex: 1,
 | 
			
		||||
			},
 | 
			
		||||
			// 全部 3 筆資料符合查詢條件,但分頁僅返回前 2 筆,排序依 updated_at 由大到小:tag1, tag2, tag3
 | 
			
		||||
			expectCount:    3,
 | 
			
		||||
			expectIDsOrder: []primitive.ObjectID{tag1.ID, tag2.ID},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "Pagination works: PageIndex 2",
 | 
			
		||||
			params: repository.TagQueryParams{
 | 
			
		||||
				PageSize:  2,
 | 
			
		||||
				PageIndex: 2,
 | 
			
		||||
			},
 | 
			
		||||
			// 第二頁應返回剩下的 1 筆:tag3
 | 
			
		||||
			expectCount:    3,
 | 
			
		||||
			expectIDsOrder: []primitive.ObjectID{tag3.ID},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, tt := range tests {
 | 
			
		||||
		tt := tt // capture range variable
 | 
			
		||||
		t.Run(tt.name, func(t *testing.T) {
 | 
			
		||||
			result, count, err := repo.List(ctx, tt.params)
 | 
			
		||||
			require.NoError(t, err)
 | 
			
		||||
			assert.Equal(t, tt.expectCount, count)
 | 
			
		||||
 | 
			
		||||
			var gotIDs []primitive.ObjectID
 | 
			
		||||
			for _, tag := range result {
 | 
			
		||||
				gotIDs = append(gotIDs, tag.ID)
 | 
			
		||||
			}
 | 
			
		||||
			assert.Equal(t, tt.expectIDsOrder, gotIDs)
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue