setting_repo_integration_test.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. //go:build integration
  2. package repository
  3. import (
  4. "context"
  5. "testing"
  6. "github.com/Wei-Shaw/sub2api/internal/service"
  7. "github.com/stretchr/testify/suite"
  8. )
  9. type SettingRepoSuite struct {
  10. suite.Suite
  11. ctx context.Context
  12. repo *settingRepository
  13. }
  14. func (s *SettingRepoSuite) SetupTest() {
  15. s.ctx = context.Background()
  16. tx := testEntTx(s.T())
  17. s.repo = NewSettingRepository(tx.Client()).(*settingRepository)
  18. }
  19. func TestSettingRepoSuite(t *testing.T) {
  20. suite.Run(t, new(SettingRepoSuite))
  21. }
  22. func (s *SettingRepoSuite) TestSetAndGetValue() {
  23. s.Require().NoError(s.repo.Set(s.ctx, "k1", "v1"), "Set")
  24. got, err := s.repo.GetValue(s.ctx, "k1")
  25. s.Require().NoError(err, "GetValue")
  26. s.Require().Equal("v1", got, "GetValue mismatch")
  27. }
  28. func (s *SettingRepoSuite) TestSet_Upsert() {
  29. s.Require().NoError(s.repo.Set(s.ctx, "k1", "v1"), "Set")
  30. s.Require().NoError(s.repo.Set(s.ctx, "k1", "v2"), "Set upsert")
  31. got, err := s.repo.GetValue(s.ctx, "k1")
  32. s.Require().NoError(err, "GetValue after upsert")
  33. s.Require().Equal("v2", got, "upsert mismatch")
  34. }
  35. func (s *SettingRepoSuite) TestGetValue_Missing() {
  36. _, err := s.repo.GetValue(s.ctx, "nonexistent")
  37. s.Require().Error(err, "expected error for missing key")
  38. s.Require().ErrorIs(err, service.ErrSettingNotFound)
  39. }
  40. func (s *SettingRepoSuite) TestSetMultiple_AndGetMultiple() {
  41. s.Require().NoError(s.repo.SetMultiple(s.ctx, map[string]string{"k2": "v2", "k3": "v3"}), "SetMultiple")
  42. m, err := s.repo.GetMultiple(s.ctx, []string{"k2", "k3"})
  43. s.Require().NoError(err, "GetMultiple")
  44. s.Require().Equal("v2", m["k2"])
  45. s.Require().Equal("v3", m["k3"])
  46. }
  47. func (s *SettingRepoSuite) TestGetMultiple_EmptyKeys() {
  48. m, err := s.repo.GetMultiple(s.ctx, []string{})
  49. s.Require().NoError(err, "GetMultiple with empty keys")
  50. s.Require().Empty(m, "expected empty map")
  51. }
  52. func (s *SettingRepoSuite) TestGetMultiple_Subset() {
  53. s.Require().NoError(s.repo.SetMultiple(s.ctx, map[string]string{"a": "1", "b": "2", "c": "3"}))
  54. m, err := s.repo.GetMultiple(s.ctx, []string{"a", "c", "nonexistent"})
  55. s.Require().NoError(err, "GetMultiple subset")
  56. s.Require().Equal("1", m["a"])
  57. s.Require().Equal("3", m["c"])
  58. _, exists := m["nonexistent"]
  59. s.Require().False(exists, "nonexistent key should not be in map")
  60. }
  61. func (s *SettingRepoSuite) TestGetAll() {
  62. s.Require().NoError(s.repo.SetMultiple(s.ctx, map[string]string{"x": "1", "y": "2"}))
  63. all, err := s.repo.GetAll(s.ctx)
  64. s.Require().NoError(err, "GetAll")
  65. s.Require().GreaterOrEqual(len(all), 2, "expected at least 2 settings")
  66. s.Require().Equal("1", all["x"])
  67. s.Require().Equal("2", all["y"])
  68. }
  69. func (s *SettingRepoSuite) TestDelete() {
  70. s.Require().NoError(s.repo.Set(s.ctx, "todelete", "val"))
  71. s.Require().NoError(s.repo.Delete(s.ctx, "todelete"), "Delete")
  72. _, err := s.repo.GetValue(s.ctx, "todelete")
  73. s.Require().Error(err, "expected missing key error after Delete")
  74. s.Require().ErrorIs(err, service.ErrSettingNotFound)
  75. }
  76. func (s *SettingRepoSuite) TestDelete_Idempotent() {
  77. // Delete a key that doesn't exist should not error
  78. s.Require().NoError(s.repo.Delete(s.ctx, "nonexistent_delete"), "Delete nonexistent should be idempotent")
  79. }
  80. func (s *SettingRepoSuite) TestSetMultiple_Upsert() {
  81. s.Require().NoError(s.repo.Set(s.ctx, "upsert_key", "old_value"))
  82. s.Require().NoError(s.repo.SetMultiple(s.ctx, map[string]string{"upsert_key": "new_value", "new_key": "new_val"}))
  83. got, err := s.repo.GetValue(s.ctx, "upsert_key")
  84. s.Require().NoError(err)
  85. s.Require().Equal("new_value", got, "SetMultiple should upsert existing key")
  86. got2, err := s.repo.GetValue(s.ctx, "new_key")
  87. s.Require().NoError(err)
  88. s.Require().Equal("new_val", got2)
  89. }
  90. // TestSet_EmptyValue 测试保存空字符串值
  91. // 这是一个回归测试,确保可选设置(如站点Logo、API端点地址等)可以保存为空字符串
  92. func (s *SettingRepoSuite) TestSet_EmptyValue() {
  93. // 测试 Set 方法保存空值
  94. s.Require().NoError(s.repo.Set(s.ctx, "empty_key", ""), "Set with empty value should succeed")
  95. got, err := s.repo.GetValue(s.ctx, "empty_key")
  96. s.Require().NoError(err, "GetValue for empty value")
  97. s.Require().Equal("", got, "empty value should be preserved")
  98. }
  99. // TestSetMultiple_WithEmptyValues 测试批量保存包含空字符串的设置
  100. // 模拟用户保存站点设置时部分字段为空的场景
  101. func (s *SettingRepoSuite) TestSetMultiple_WithEmptyValues() {
  102. // 模拟保存站点设置,部分字段有值,部分字段为空
  103. settings := map[string]string{
  104. "site_name": "Sub2api",
  105. "site_subtitle": "Subscription to API",
  106. "site_logo": "", // 用户未上传Logo
  107. "api_base_url": "", // 用户未设置API地址
  108. "contact_info": "", // 用户未设置联系方式
  109. "doc_url": "", // 用户未设置文档链接
  110. }
  111. s.Require().NoError(s.repo.SetMultiple(s.ctx, settings), "SetMultiple with empty values should succeed")
  112. // 验证所有值都正确保存
  113. result, err := s.repo.GetMultiple(s.ctx, []string{"site_name", "site_subtitle", "site_logo", "api_base_url", "contact_info", "doc_url"})
  114. s.Require().NoError(err, "GetMultiple after SetMultiple with empty values")
  115. s.Require().Equal("Sub2api", result["site_name"])
  116. s.Require().Equal("Subscription to API", result["site_subtitle"])
  117. s.Require().Equal("", result["site_logo"], "empty site_logo should be preserved")
  118. s.Require().Equal("", result["api_base_url"], "empty api_base_url should be preserved")
  119. s.Require().Equal("", result["contact_info"], "empty contact_info should be preserved")
  120. s.Require().Equal("", result["doc_url"], "empty doc_url should be preserved")
  121. }
  122. // TestSetMultiple_UpdateToEmpty 测试将已有值更新为空字符串
  123. // 确保用户可以清空之前设置的值
  124. func (s *SettingRepoSuite) TestSetMultiple_UpdateToEmpty() {
  125. // 先设置非空值
  126. s.Require().NoError(s.repo.Set(s.ctx, "clearable_key", "initial_value"))
  127. got, err := s.repo.GetValue(s.ctx, "clearable_key")
  128. s.Require().NoError(err)
  129. s.Require().Equal("initial_value", got)
  130. // 更新为空值
  131. s.Require().NoError(s.repo.SetMultiple(s.ctx, map[string]string{"clearable_key": ""}), "Update to empty should succeed")
  132. got, err = s.repo.GetValue(s.ctx, "clearable_key")
  133. s.Require().NoError(err)
  134. s.Require().Equal("", got, "value should be updated to empty string")
  135. }