1 package com.atlassian.refapp.sal.message;
2
3 import com.atlassian.plugin.Plugin;
4 import com.atlassian.plugin.PluginAccessor;
5 import com.atlassian.plugin.elements.ResourceDescriptor;
6 import com.atlassian.plugin.event.PluginEventManager;
7 import com.atlassian.plugin.event.events.PluginEnabledEvent;
8 import org.junit.Assert;
9 import org.junit.Test;
10 import org.mockito.Mockito;
11
12 import java.io.Serializable;
13 import java.util.Arrays;
14 import java.util.HashMap;
15 import java.util.ListResourceBundle;
16 import java.util.Locale;
17 import java.util.Map;
18 import java.util.MissingResourceException;
19 import java.util.ResourceBundle;
20
21 import static org.junit.Assert.assertEquals;
22
23 public class RefimplI18nResolverTest {
24 private static final String PREFIX = "com.atlassian.sal.com.atlassian.refapp.sal.message.test.";
25
26 private static final String KEY_WITH_PREFIX_AT_START_1 = PREFIX + "key1";
27 private static final String KEY_WITHOUT_PREFIX_1 = "noprefix.key";
28 private static final String KEY_WITH_PREFIX_NOT_AT_START_1 = "notatstart." + PREFIX + "key";
29 private static final String KEY_WITH_PREFIX_AT_START_ONLY_IN_FRENCH_1 = PREFIX + "onlyinfrench.key";
30
31 private static final String US_VALUE_FOR_KEY_WITH_PREFIX_AT_START_1 = "Hello, world";
32 private static final String FR_VALUE_FOR_KEY_WITH_PREFIX_AT_START_1 = "Bonjour tout le monde";
33 private static final String US_VALUE_FOR_KEY_WITHOUT_PREFIX_1 = "Hello, Atlassian";
34 private static final String FR_VALUE_FOR_KEY_WITHOUT_PREFIX_1 = "Bonjour, Atlassian";
35 private static final String US_VALUE_FOR_KEY_WITH_PREFIX_NOT_AT_START_1 = "Hello, San Francisco";
36 private static final String FR_VALUE_FOR_KEY_WITH_PREFIX_NOT_AT_START_1 = "Bonjour, San Francisco";
37 private static final String FR_VALUE_FOR_KEY_WITH_PREFIX_AT_START_ONLY_IN_FRENCH_1 = "Bonjour, France!";
38
39 private static final String KEY_WITHOUT_PREFIX_2 = "another." + KEY_WITHOUT_PREFIX_1;
40 private static final String KEY_WITH_PREFIX_NOT_AT_START_2 = "another.notatstart." + PREFIX + "key";
41 private static final String KEY_WITH_PREFIX_AT_START_2 = PREFIX + "key2";
42
43 private static final String US_VALUE_FOR_KEY_WITHOUT_PREFIX_2 = "Hello, universe";
44 private static final String US_VALUE_FOR_KEY_WITH_PREFIX_NOT_AT_START_2 = "Hello, Sydney";
45 private static final String US_VALUE_FOR_KEY_WITH_PREFIX_AT_START_2 = "Hello, everyone";
46
47 private static final String KEY_3 = "key3";
48 private static final String VALUE_FOR_KEY_3 = "Hello {0}";
49
50 private static final ResourceBundle bundle1_en_US = new ListResourceBundle() {
51 @Override
52 public Locale getLocale() {
53 return Locale.US;
54 }
55
56 protected Object[][] getContents() {
57 return new Object[][]
58 {
59 {KEY_WITH_PREFIX_AT_START_1, US_VALUE_FOR_KEY_WITH_PREFIX_AT_START_1},
60 {KEY_WITHOUT_PREFIX_1, US_VALUE_FOR_KEY_WITHOUT_PREFIX_1},
61 {KEY_WITH_PREFIX_NOT_AT_START_1, US_VALUE_FOR_KEY_WITH_PREFIX_NOT_AT_START_1}
62 };
63 }
64 };
65
66 private static final ResourceBundle bundle2_en_US = new ListResourceBundle() {
67 @Override
68 public Locale getLocale() {
69 return Locale.US;
70 }
71
72 protected Object[][] getContents() {
73 return new Object[][]
74 {
75 {KEY_WITHOUT_PREFIX_2, US_VALUE_FOR_KEY_WITHOUT_PREFIX_2},
76 {KEY_WITH_PREFIX_NOT_AT_START_2, US_VALUE_FOR_KEY_WITH_PREFIX_NOT_AT_START_2},
77 {KEY_WITH_PREFIX_AT_START_2, US_VALUE_FOR_KEY_WITH_PREFIX_AT_START_2}
78 };
79 }
80 };
81
82 private static final ResourceBundle bundle1_fr_FR = new ListResourceBundle() {
83 @Override
84 public Locale getLocale() {
85 return Locale.FRANCE;
86 }
87
88 protected Object[][] getContents() {
89 return new Object[][]
90 {
91 {KEY_WITH_PREFIX_AT_START_1, FR_VALUE_FOR_KEY_WITH_PREFIX_AT_START_1},
92 {KEY_WITHOUT_PREFIX_1, FR_VALUE_FOR_KEY_WITHOUT_PREFIX_1},
93 {KEY_WITH_PREFIX_NOT_AT_START_1, FR_VALUE_FOR_KEY_WITH_PREFIX_NOT_AT_START_1},
94 {KEY_WITH_PREFIX_AT_START_ONLY_IN_FRENCH_1, FR_VALUE_FOR_KEY_WITH_PREFIX_AT_START_ONLY_IN_FRENCH_1}
95 };
96 }
97 };
98
99 private static final ResourceBundle bundle3_currentLocale = new ListResourceBundle() {
100 @Override
101 public Locale getLocale() {
102 return Locale.getDefault();
103 }
104
105 protected Object[][] getContents() {
106 return new Object[][]
107 {
108 {KEY_3, VALUE_FOR_KEY_3}
109 };
110 }
111 };
112
113 private static final ResourceBundleResolver resourceBundleResolver = new ResourceBundleResolver() {
114 public ResourceBundle getBundle(String baseName, Locale locale, ClassLoader classLoader) {
115 if (baseName.equals("bundle1")) {
116 if (locale.equals(bundle1_en_US.getLocale())) {
117 return bundle1_en_US;
118 } else if (locale.equals(bundle1_fr_FR.getLocale())) {
119 return bundle1_fr_FR;
120 }
121 } else if (baseName.equals("bundle2")) {
122 if (locale.equals(bundle2_en_US.getLocale())) {
123 return bundle2_en_US;
124 }
125 } else if (baseName.equals("bundle3")) {
126 if (locale.equals(bundle3_currentLocale.getLocale())) {
127 return bundle3_currentLocale;
128 }
129 }
130 throw new MissingResourceException("Can't find bundle for base name " + baseName + ", locale " + locale,
131 baseName + "_" + locale, "");
132 }
133 };
134
135 private final PluginAccessor pluginAccessor = Mockito.mock(PluginAccessor.class);
136 private final PluginEventManager pluginEventManager = Mockito.mock(PluginEventManager.class);
137 private final Plugin plugin = Mockito.mock(Plugin.class);
138 private final ResourceDescriptor bundleResourceDescriptor1 = mockResourceDescriptor("bundle1");
139 private final ResourceDescriptor bundleResourceDescriptor2 = mockResourceDescriptor("bundle2");
140 private final ResourceDescriptor bundleResourceDescriptor3 = mockResourceDescriptor("bundle3");
141
142 private RefimplI18nResolver resolver =
143 new RefimplI18nResolver(pluginAccessor, pluginEventManager, resourceBundleResolver);
144
145 @Test
146 public void getAllTranslationsForPrefixWithNoResourceBundlesAvailableReturnsEmptyMap() {
147 Assert.assertTrue(resolver.getAllTranslationsForPrefix(PREFIX, Locale.US).isEmpty());
148 }
149
150 @Test
151 public void getAllTranslationsForPrefixWithMatchingPrefixAndLocaleReturnsMatches() {
152 Mockito.when(plugin.getResourceDescriptors("i18n")).thenReturn(Arrays.asList(bundleResourceDescriptor1));
153 resolver.pluginEnabled(new PluginEnabledEvent(plugin));
154
155 Map<String, String> expectations = new HashMap<String, String>();
156 expectations.put(KEY_WITH_PREFIX_AT_START_1, US_VALUE_FOR_KEY_WITH_PREFIX_AT_START_1);
157
158 assertEquals(expectations, resolver.getAllTranslationsForPrefix(PREFIX, Locale.US));
159 }
160
161 @Test
162 public void getAllTranslationsForPrefixWithMatchingPrefixAndNonMatchingLocaleReturnsEmptyMap() {
163 Mockito.when(plugin.getResourceDescriptors("i18n")).thenReturn(Arrays.asList(bundleResourceDescriptor1));
164 resolver.pluginEnabled(new PluginEnabledEvent(plugin));
165
166 Assert.assertTrue(resolver.getAllTranslationsForPrefix(PREFIX, Locale.GERMANY).isEmpty());
167 }
168
169 @Test
170 public void getAllTranslationsForPrefixWithNonMatchingPrefixAndMatchingLocaleReturnsEmptyMap() {
171 Mockito.when(plugin.getResourceDescriptors("i18n")).thenReturn(Arrays.asList(bundleResourceDescriptor1));
172 resolver.pluginEnabled(new PluginEnabledEvent(plugin));
173
174 Assert.assertTrue(resolver.getAllTranslationsForPrefix(PREFIX + "nomatch", Locale.US).isEmpty());
175 }
176
177 @Test
178 public void getAllTranslationsForPrefixWithMultipleMatchingBundlesInOnePluginReturnsAllMatches() {
179 Mockito.when(plugin.getResourceDescriptors("i18n"))
180 .thenReturn(Arrays.asList(bundleResourceDescriptor1, bundleResourceDescriptor2));
181 resolver.pluginEnabled(new PluginEnabledEvent(plugin));
182
183 Map<String, String> expectations = new HashMap<String, String>();
184 expectations.put(KEY_WITH_PREFIX_AT_START_1, US_VALUE_FOR_KEY_WITH_PREFIX_AT_START_1);
185 expectations.put(KEY_WITH_PREFIX_AT_START_2, US_VALUE_FOR_KEY_WITH_PREFIX_AT_START_2);
186
187 assertEquals(expectations, resolver.getAllTranslationsForPrefix(PREFIX, Locale.US));
188 }
189
190 @Test
191 public void getAllTranslationsForPrefixWithMultipleMatchingBundlesInDifferentPluginsReturnsAllMatches() {
192 Mockito.when(plugin.getResourceDescriptors("i18n")).thenReturn(Arrays.asList(bundleResourceDescriptor1));
193 Plugin plugin2 = Mockito.mock(Plugin.class);
194 Mockito.when(plugin2.getResourceDescriptors("i18n")).thenReturn(Arrays.asList(bundleResourceDescriptor2));
195
196 resolver.pluginEnabled(new PluginEnabledEvent(plugin));
197 resolver.pluginEnabled(new PluginEnabledEvent(plugin2));
198
199 Map<String, String> expectations = new HashMap<String, String>();
200 expectations.put(KEY_WITH_PREFIX_AT_START_1, US_VALUE_FOR_KEY_WITH_PREFIX_AT_START_1);
201 expectations.put(KEY_WITH_PREFIX_AT_START_2, US_VALUE_FOR_KEY_WITH_PREFIX_AT_START_2);
202
203 assertEquals(expectations, resolver.getAllTranslationsForPrefix(PREFIX, Locale.US));
204 }
205
206 @Test(expected = NullPointerException.class)
207 public void getAllTranslationsWithNullPrefixThrowsNullPointerException() {
208 Mockito.when(plugin.getResourceDescriptors("i18n")).thenReturn(Arrays.asList(bundleResourceDescriptor1));
209 resolver.pluginEnabled(new PluginEnabledEvent(plugin));
210 resolver.getAllTranslationsForPrefix(null, Locale.US);
211 }
212
213 @Test
214 public void getAllTranslationsWithEmptyPrefixReturnsAllTranslationsInMatchingLocales() {
215 Mockito.when(plugin.getResourceDescriptors("i18n"))
216 .thenReturn(Arrays.asList(bundleResourceDescriptor1, bundleResourceDescriptor2));
217 resolver.pluginEnabled(new PluginEnabledEvent(plugin));
218
219 Map<String, String> expectations = new HashMap<String, String>();
220 expectations.put(KEY_WITH_PREFIX_AT_START_1, US_VALUE_FOR_KEY_WITH_PREFIX_AT_START_1);
221 expectations.put(KEY_WITHOUT_PREFIX_1, US_VALUE_FOR_KEY_WITHOUT_PREFIX_1);
222 expectations.put(KEY_WITH_PREFIX_NOT_AT_START_1, US_VALUE_FOR_KEY_WITH_PREFIX_NOT_AT_START_1);
223 expectations.put(KEY_WITHOUT_PREFIX_2, US_VALUE_FOR_KEY_WITHOUT_PREFIX_2);
224 expectations.put(KEY_WITH_PREFIX_NOT_AT_START_2, US_VALUE_FOR_KEY_WITH_PREFIX_NOT_AT_START_2);
225 expectations.put(KEY_WITH_PREFIX_AT_START_2, US_VALUE_FOR_KEY_WITH_PREFIX_AT_START_2);
226
227 assertEquals(expectations, resolver.getAllTranslationsForPrefix("", Locale.US));
228 }
229
230 @Test(expected = NullPointerException.class)
231 public void getAllTranslationsWithNullLocaleThrowsNullPointerException() {
232 Mockito.when(plugin.getResourceDescriptors("i18n")).thenReturn(Arrays.asList(bundleResourceDescriptor1));
233 resolver.pluginEnabled(new PluginEnabledEvent(plugin));
234 resolver.getAllTranslationsForPrefix(PREFIX, null);
235 }
236
237 @Test
238 public void resolveText() throws Exception {
239 Mockito.when(plugin.getResourceDescriptors("i18n")).thenReturn(Arrays.asList(bundleResourceDescriptor3));
240 resolver.pluginEnabled(new PluginEnabledEvent(plugin));
241
242 assertEquals("Hello World", resolver.resolveText(KEY_3, new Serializable[]{"World"}));
243 assertEquals(KEY_WITHOUT_PREFIX_2, resolver.resolveText(KEY_WITHOUT_PREFIX_2, new Serializable[0]));
244 }
245
246 @Test
247 public void resolveTextInEnglish() throws Exception {
248 Mockito.when(plugin.getResourceDescriptors("i18n")).thenReturn(Arrays.asList(bundleResourceDescriptor1, bundleResourceDescriptor2));
249 resolver.pluginEnabled(new PluginEnabledEvent(plugin));
250 assertEquals(US_VALUE_FOR_KEY_WITHOUT_PREFIX_1, resolver.getText(Locale.US, KEY_WITHOUT_PREFIX_1));
251 }
252
253 @Test
254 public void resolveTextInFrench() throws Exception {
255 Mockito.when(plugin.getResourceDescriptors("i18n")).thenReturn(Arrays.asList(bundleResourceDescriptor1, bundleResourceDescriptor2));
256 resolver.pluginEnabled(new PluginEnabledEvent(plugin));
257 assertEquals(FR_VALUE_FOR_KEY_WITHOUT_PREFIX_1, resolver.getText(Locale.FRANCE, KEY_WITHOUT_PREFIX_1));
258 }
259
260 @Test
261 public void resolveTextLocaleUnknownFallbackToDefault() {
262 Mockito.when(plugin.getResourceDescriptors("i18n")).thenReturn(Arrays.asList(bundleResourceDescriptor3));
263 resolver.pluginEnabled(new PluginEnabledEvent(plugin));
264 assertEquals("Hello World", resolver.getText(Locale.KOREA, KEY_3, "World"));
265 }
266
267 @Test
268 public void resolveTextInEnglishWithArguments() throws Exception {
269 Mockito.when(plugin.getResourceDescriptors("i18n")).thenReturn(Arrays.asList(bundleResourceDescriptor3));
270 resolver.pluginEnabled(new PluginEnabledEvent(plugin));
271 assertEquals("Hello World", resolver.getText(Locale.US, KEY_3, "World"));
272 }
273
274 @Test
275 public void getRawText() throws Exception {
276 Mockito.when(plugin.getResourceDescriptors("i18n")).thenReturn(Arrays.asList(bundleResourceDescriptor3));
277 resolver.pluginEnabled(new PluginEnabledEvent(plugin));
278
279 assertEquals(VALUE_FOR_KEY_3, resolver.getRawText(KEY_3));
280 assertEquals(KEY_WITHOUT_PREFIX_2, resolver.resolveText(KEY_WITHOUT_PREFIX_2, new Serializable[0]));
281 }
282
283 private static ResourceDescriptor mockResourceDescriptor(String location) {
284 ResourceDescriptor resourceDescriptor = Mockito.mock(ResourceDescriptor.class);
285 Mockito.when(resourceDescriptor.getLocation()).thenReturn(location);
286 return resourceDescriptor;
287 }
288 }