error_test.go 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. // SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
  2. // SPDX-License-Identifier: Apache-2.0
  3. package locale // import "miniflux.app/v2/internal/locale"
  4. import (
  5. "errors"
  6. "testing"
  7. )
  8. func TestNewLocalizedErrorWrapper(t *testing.T) {
  9. originalErr := errors.New("original error message")
  10. translationKey := "error.test_key"
  11. args := []any{"arg1", 42}
  12. wrapper := NewLocalizedErrorWrapper(originalErr, translationKey, args...)
  13. if wrapper.originalErr != originalErr {
  14. t.Errorf("Expected original error to be %v, got %v", originalErr, wrapper.originalErr)
  15. }
  16. if wrapper.translationKey != translationKey {
  17. t.Errorf("Expected translation key to be %q, got %q", translationKey, wrapper.translationKey)
  18. }
  19. if len(wrapper.translationArgs) != 2 {
  20. t.Errorf("Expected 2 translation args, got %d", len(wrapper.translationArgs))
  21. }
  22. if wrapper.translationArgs[0] != "arg1" || wrapper.translationArgs[1] != 42 {
  23. t.Errorf("Expected translation args [arg1, 42], got %v", wrapper.translationArgs)
  24. }
  25. }
  26. func TestLocalizedErrorWrapper_Error(t *testing.T) {
  27. originalErr := errors.New("original error message")
  28. wrapper := NewLocalizedErrorWrapper(originalErr, "error.test_key")
  29. result := wrapper.Error()
  30. if result != originalErr {
  31. t.Errorf("Expected Error() to return original error %v, got %v", originalErr, result)
  32. }
  33. }
  34. func TestLocalizedErrorWrapper_Translate(t *testing.T) {
  35. // Set up test catalog
  36. defaultCatalog = catalog{
  37. "en_US": translationDict{
  38. singulars: map[string]string{
  39. "error.test_key": "Error: %s (code: %d)",
  40. },
  41. },
  42. "fr_FR": translationDict{
  43. singulars: map[string]string{
  44. "error.test_key": "Erreur : %s (code : %d)",
  45. },
  46. },
  47. }
  48. originalErr := errors.New("original error")
  49. wrapper := NewLocalizedErrorWrapper(originalErr, "error.test_key", "test message", 404)
  50. // Test English translation
  51. result := wrapper.Translate("en_US")
  52. expected := "Error: test message (code: 404)"
  53. if result != expected {
  54. t.Errorf("Expected English translation %q, got %q", expected, result)
  55. }
  56. // Test French translation
  57. result = wrapper.Translate("fr_FR")
  58. expected = "Erreur : test message (code : 404)"
  59. if result != expected {
  60. t.Errorf("Expected French translation %q, got %q", expected, result)
  61. }
  62. // Test with missing language (should use key as fallback with args applied)
  63. result = wrapper.Translate("invalid_lang")
  64. expected = "error.test_key%!(EXTRA string=test message, int=404)"
  65. if result != expected {
  66. t.Errorf("Expected fallback translation %q, got %q", expected, result)
  67. }
  68. }
  69. func TestLocalizedErrorWrapper_TranslateWithEmptyKey(t *testing.T) {
  70. originalErr := errors.New("original error message")
  71. wrapper := NewLocalizedErrorWrapper(originalErr, "")
  72. result := wrapper.Translate("en_US")
  73. expected := "original error message"
  74. if result != expected {
  75. t.Errorf("Expected original error message %q, got %q", expected, result)
  76. }
  77. }
  78. func TestLocalizedErrorWrapper_TranslateWithNoArgs(t *testing.T) {
  79. defaultCatalog = catalog{
  80. "en_US": translationDict{
  81. singulars: map[string]string{
  82. "error.simple": "Simple error message",
  83. },
  84. },
  85. }
  86. originalErr := errors.New("original error")
  87. wrapper := NewLocalizedErrorWrapper(originalErr, "error.simple")
  88. result := wrapper.Translate("en_US")
  89. expected := "Simple error message"
  90. if result != expected {
  91. t.Errorf("Expected translation %q, got %q", expected, result)
  92. }
  93. }
  94. func TestNewLocalizedError(t *testing.T) {
  95. translationKey := "error.validation"
  96. args := []any{"field1", "invalid"}
  97. localizedErr := NewLocalizedError(translationKey, args...)
  98. if localizedErr.translationKey != translationKey {
  99. t.Errorf("Expected translation key to be %q, got %q", translationKey, localizedErr.translationKey)
  100. }
  101. if len(localizedErr.translationArgs) != 2 {
  102. t.Errorf("Expected 2 translation args, got %d", len(localizedErr.translationArgs))
  103. }
  104. if localizedErr.translationArgs[0] != "field1" || localizedErr.translationArgs[1] != "invalid" {
  105. t.Errorf("Expected translation args [field1, invalid], got %v", localizedErr.translationArgs)
  106. }
  107. }
  108. func TestLocalizedError_String(t *testing.T) {
  109. defaultCatalog = catalog{
  110. "en_US": translationDict{
  111. singulars: map[string]string{
  112. "error.validation": "Validation failed for %s: %s",
  113. },
  114. },
  115. }
  116. localizedErr := NewLocalizedError("error.validation", "username", "too short")
  117. result := localizedErr.String()
  118. expected := "Validation failed for username: too short"
  119. if result != expected {
  120. t.Errorf("Expected String() result %q, got %q", expected, result)
  121. }
  122. }
  123. func TestLocalizedError_StringWithMissingTranslation(t *testing.T) {
  124. defaultCatalog = catalog{
  125. "en_US": translationDict{},
  126. }
  127. localizedErr := NewLocalizedError("error.missing", "arg1")
  128. result := localizedErr.String()
  129. expected := "error.missing%!(EXTRA string=arg1)"
  130. if result != expected {
  131. t.Errorf("Expected String() result %q, got %q", expected, result)
  132. }
  133. }
  134. func TestLocalizedError_Error(t *testing.T) {
  135. defaultCatalog = catalog{
  136. "en_US": translationDict{
  137. singulars: map[string]string{
  138. "error.database": "Database connection failed: %s",
  139. },
  140. },
  141. }
  142. localizedErr := NewLocalizedError("error.database", "timeout")
  143. result := localizedErr.Error()
  144. if result == nil {
  145. t.Error("Expected Error() to return a non-nil error")
  146. }
  147. expected := "Database connection failed: timeout"
  148. if result.Error() != expected {
  149. t.Errorf("Expected Error() message %q, got %q", expected, result.Error())
  150. }
  151. }
  152. func TestLocalizedError_Translate(t *testing.T) {
  153. defaultCatalog = catalog{
  154. "en_US": translationDict{
  155. singulars: map[string]string{
  156. "error.permission": "Permission denied for %s",
  157. },
  158. },
  159. "es_ES": translationDict{
  160. singulars: map[string]string{
  161. "error.permission": "Permiso denegado para %s",
  162. },
  163. },
  164. }
  165. localizedErr := NewLocalizedError("error.permission", "admin panel")
  166. // Test English translation
  167. result := localizedErr.Translate("en_US")
  168. expected := "Permission denied for admin panel"
  169. if result != expected {
  170. t.Errorf("Expected English translation %q, got %q", expected, result)
  171. }
  172. // Test Spanish translation
  173. result = localizedErr.Translate("es_ES")
  174. expected = "Permiso denegado para admin panel"
  175. if result != expected {
  176. t.Errorf("Expected Spanish translation %q, got %q", expected, result)
  177. }
  178. // Test with missing language
  179. result = localizedErr.Translate("invalid_lang")
  180. expected = "error.permission%!(EXTRA string=admin panel)"
  181. if result != expected {
  182. t.Errorf("Expected fallback translation %q, got %q", expected, result)
  183. }
  184. }
  185. func TestLocalizedError_TranslateWithNoArgs(t *testing.T) {
  186. defaultCatalog = catalog{
  187. "en_US": translationDict{
  188. singulars: map[string]string{
  189. "error.generic": "An error occurred",
  190. },
  191. },
  192. "de_DE": translationDict{
  193. singulars: map[string]string{
  194. "error.generic": "Ein Fehler ist aufgetreten",
  195. },
  196. },
  197. }
  198. localizedErr := NewLocalizedError("error.generic")
  199. // Test English
  200. result := localizedErr.Translate("en_US")
  201. expected := "An error occurred"
  202. if result != expected {
  203. t.Errorf("Expected English translation %q, got %q", expected, result)
  204. }
  205. // Test German
  206. result = localizedErr.Translate("de_DE")
  207. expected = "Ein Fehler ist aufgetreten"
  208. if result != expected {
  209. t.Errorf("Expected German translation %q, got %q", expected, result)
  210. }
  211. }
  212. func TestLocalizedError_TranslateWithComplexArgs(t *testing.T) {
  213. defaultCatalog = catalog{
  214. "en_US": translationDict{
  215. singulars: map[string]string{
  216. "error.complex": "Error %d: %s occurred at %s with severity %s",
  217. },
  218. },
  219. }
  220. localizedErr := NewLocalizedError("error.complex", 500, "Internal Server Error", "2024-01-01", "high")
  221. result := localizedErr.Translate("en_US")
  222. expected := "Error 500: Internal Server Error occurred at 2024-01-01 with severity high"
  223. if result != expected {
  224. t.Errorf("Expected complex translation %q, got %q", expected, result)
  225. }
  226. }
  227. func TestLocalizedErrorWrapper_WithNilError(t *testing.T) {
  228. // This tests edge case behavior - what happens with nil error
  229. wrapper := NewLocalizedErrorWrapper(nil, "error.test")
  230. // Error() should return nil
  231. result := wrapper.Error()
  232. if result != nil {
  233. t.Errorf("Expected Error() to return nil, got %v", result)
  234. }
  235. }
  236. func TestLocalizedErrorWrapper_TranslateWithEmptyKeyAndNilError(t *testing.T) {
  237. wrapper := NewLocalizedErrorWrapper(nil, "")
  238. result := wrapper.Translate("en_US")
  239. expected := ""
  240. if result != expected {
  241. t.Errorf("Expected empty string for nil wrapped error, got %q", result)
  242. }
  243. }
  244. func TestLocalizedError_EmptyKey(t *testing.T) {
  245. localizedErr := NewLocalizedError("")
  246. result := localizedErr.String()
  247. expected := ""
  248. if result != expected {
  249. t.Errorf("Expected empty string for empty key, got %q", result)
  250. }
  251. result = localizedErr.Translate("en_US")
  252. if result != expected {
  253. t.Errorf("Expected empty string for empty key translation, got %q", result)
  254. }
  255. }