View Javadoc
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 }