Skip to content

Commit b16771e

Browse files
author
Mike Reiche
authored
Merge pull request #138 from telekom/bugfix/thread-safe-localization
Removed automatic locale switch based on thread-unsafe Locale.getDefa…
2 parents bf19287 + 44b4d49 commit b16771e

File tree

9 files changed

+108
-42
lines changed

9 files changed

+108
-42
lines changed

build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ allprojects {
3131
apply plugin: 'java-library'
3232
apply plugin: 'project-report'
3333

34+
compileJava.options.encoding = 'UTF-8'
35+
compileTestJava.options.encoding = "UTF-8"
3436
sourceCompatibility = JavaVersion.VERSION_1_8
3537
targetCompatibility = JavaVersion.VERSION_1_8
3638
}

core-interop/src/main/java/eu/tsystems/mms/tic/testframework/l10n/LocalizedBundle.java

Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -26,40 +26,18 @@
2626
import java.util.ResourceBundle;
2727

2828
public class LocalizedBundle {
29-
private ResourceBundle resourceBundle;
29+
private final ResourceBundle resourceBundle;
3030
private static final ResourceBundle.Control resourceBundleController = new UTF8ResourceBundleControl();
31-
/**
32-
* When the bundle name is NULL, the {@link #resourceBundle} is fixed
33-
*/
34-
private final String bundleName;
3531

3632
public LocalizedBundle(String bundleName, Locale locale) {
37-
this.bundleName = null;
3833
this.resourceBundle = ResourceBundle.getBundle(bundleName, locale, resourceBundleController);
3934
}
4035

4136
public LocalizedBundle(String bundleName) {
42-
this.bundleName = bundleName;
43-
recreateLocalizedResourceBundle();
44-
}
45-
46-
private ResourceBundle getResourceBundle() {
47-
/**
48-
* When the locale is not fixed and differs from the default locale
49-
* than recreate the bundle.
50-
*/
51-
if (this.bundleName != null && Locale.getDefault() != this.resourceBundle.getLocale()) {
52-
recreateLocalizedResourceBundle();
53-
}
54-
return resourceBundle;
55-
}
56-
57-
private void recreateLocalizedResourceBundle() {
58-
this.resourceBundle = ResourceBundle.getBundle(this.bundleName, resourceBundleController);
37+
this(bundleName, Locale.getDefault());
5938
}
6039

6140
public String getString(String label) {
62-
ResourceBundle resourceBundle = getResourceBundle();
6341
if (resourceBundle.containsKey(label)) {
6442
return resourceBundle.getString(label);
6543
} else {

core-interop/src/main/java/eu/tsystems/mms/tic/testframework/l10n/SimpleLocalization.java

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,29 @@
2121
*/
2222
package eu.tsystems.mms.tic.testframework.l10n;
2323

24+
import java.util.Locale;
25+
import org.slf4j.Logger;
26+
import org.slf4j.LoggerFactory;
27+
2428
final public class SimpleLocalization {
25-
public static final String BUNDLE_NAME="lang";
26-
private static final LocalizedBundle bundle = new LocalizedBundle(BUNDLE_NAME);
29+
public static final String BUNDLE_NAME = "lang";
30+
private static LocalizedBundle bundle;
31+
private static final Logger LOGGER = LoggerFactory.getLogger(SimpleLocalization.class);
2732

2833
public static String getText(final String label) {
29-
return bundle.getString(label);
34+
return getDefaultBundle().getString(label);
35+
}
36+
37+
public static LocalizedBundle getDefaultBundle() {
38+
if (bundle == null) {
39+
setDefault(Locale.getDefault());
40+
}
41+
return bundle;
3042
}
3143

32-
public LocalizedBundle getBundle() {
44+
public static LocalizedBundle setDefault(Locale locale) {
45+
LOGGER.info("Change default locale to: " + locale);
46+
bundle = new LocalizedBundle(BUNDLE_NAME, locale);
3347
return bundle;
3448
}
3549
}

docs/src/docs/modules/localization.adoc

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,22 +60,39 @@ import eu.tsystems.mms.tic.testframework.l10n.SimpleLocalization;
6060
GuiElement loginBtn = new GuiElement(By.linkText(SimpleLocalization.getText("BTN_LOGIN")));
6161
----
6262

63-
But you can use your own localized bundles.
63+
`SimpleLocalization` uses `Locale.getDefault()` by default, but
64+
you can switch the default locale the following way.
65+
[source, java]
66+
----
67+
LocalizedBundle defaultBundle = SimpleLocalization.setDefault(Locale.GERMAN);
68+
----
69+
70+
== Session based localization
71+
72+
For thread-safe localization, you can use session based localization by initializing your localized bundles based on the session's locale.
6473

6574
[source, java]
6675
----
67-
import eu.tsystems.mms.tic.testframework.l10n.LocalizedBundle;
76+
Locale sessionLocale = WebDriverManager.getSessionLocale(WebDriver).orElse(Locale.getDefault());
6877
69-
LocalizedBundle bundle = new LocalizedBundle("testdata");
70-
bundle.getString("TEST_KEY");
78+
LocalizedBundle sessionBundle = new LocalizedBundle("testdata", sessionLocale);
79+
sessionBundle.getString("TEST_KEY");
7180
----
7281

73-
Or bundles with a fixed locale.
82+
When the SUT locale changes, you should also set the session's locale:
7483

7584
[source, java]
7685
----
77-
LocalizedBundle germanBundle = new LocalizedBundle("testdata", Locale.GERMAN);
78-
germanBundle.getString("TEST_KEY");
86+
public class LocalizedPage extends Page {
87+
88+
public void switchLocale(Locale locale) {
89+
// Implement your language switch here
90+
// ...
91+
92+
// Don't forget to set the sessions locale
93+
WebDriverManager.setSessionLocale(getWebDriver(), locale);
94+
}
95+
}
7996
----
8097

8198
== Change runtime locale

driver-ui/src/main/java/eu/tsystems/mms/tic/testframework/webdrivermanager/WebDriverManager.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,14 @@
2525
import eu.tsystems.mms.tic.testframework.internal.Flags;
2626
import eu.tsystems.mms.tic.testframework.internal.utils.DriverStorage;
2727
import eu.tsystems.mms.tic.testframework.pageobjects.POConfig;
28+
import eu.tsystems.mms.tic.testframework.report.model.context.SessionContext;
2829
import eu.tsystems.mms.tic.testframework.report.utils.ExecutionContextUtils;
2930
import eu.tsystems.mms.tic.testframework.useragents.UserAgentConfig;
3031
import eu.tsystems.mms.tic.testframework.utils.UITestUtils;
3132
import java.util.HashMap;
33+
import java.util.Locale;
3234
import java.util.Map;
35+
import java.util.Optional;
3336
import java.util.stream.Stream;
3437
import org.openqa.selenium.JavascriptExecutor;
3538
import org.openqa.selenium.WebDriver;
@@ -59,6 +62,7 @@ public final class WebDriverManager {
5962
private static WebDriverManagerConfig webdriverManagerConfig;
6063

6164
private static final HashMap<String, UserAgentConfig> userAgentConfigurators = new HashMap<>();
65+
private static final String SESSION_LOCALE = "locale";
6266

6367
/**
6468
* Private constructor to hide the public one since this a static only class.
@@ -365,4 +369,28 @@ public static void setUserAgentConfig(String browser, UserAgentConfig configurat
365369
static UserAgentConfig getUserAgentConfig(String browser) {
366370
return userAgentConfigurators.get(browser);
367371
}
372+
373+
/**
374+
* Sets the locale for a specified session
375+
* @param webDriver
376+
* @param locale
377+
* @return TRUE if locale has been set
378+
*/
379+
public static boolean setSessionLocale(WebDriver webDriver, Locale locale) {
380+
Optional<Map<String, Object>> optionalMetaData = WebDriverSessionsManager.getSessionContext(webDriver).map(SessionContext::getMetaData);
381+
optionalMetaData.ifPresent(map -> {
382+
map.put(SESSION_LOCALE, locale);
383+
});
384+
return optionalMetaData.isPresent();
385+
}
386+
387+
/**
388+
* Returns the session locale
389+
* @param webDriver
390+
*/
391+
public static Optional<Locale> getSessionLocale(WebDriver webDriver) {
392+
return WebDriverSessionsManager.getSessionContext(webDriver)
393+
.map(SessionContext::getMetaData)
394+
.map(map -> (Locale)map.get(SESSION_LOCALE));
395+
}
368396
}

integration-tests/src/test/java/eu/tsystems/mms/tic/testframework/test/l10n/LocalizationTest.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,13 @@ public class LocalizationTest extends AbstractWebDriverTest {
3333

3434
@Test(dataProvider = "locales")
3535
public void test_readUtf8FromResourceBundle(String locale, String expected) {
36-
Locale.setDefault(Locale.forLanguageTag(locale));
37-
Assert.assertEquals(SimpleLocalization.getText("TEST"), expected);
36+
LocalizedBundle defaultBundle = SimpleLocalization.setDefault(Locale.forLanguageTag(locale));
37+
Assert.assertEquals(defaultBundle.getString("TEST"), expected);
3838
}
3939

4040
@Test
4141
public void test_inexistentLocalizedProperty() {
42-
Assert.assertEquals("NOT_EXISTENT", SimpleLocalization.getText("NOT_EXISTENT"));
42+
Assert.assertEquals(SimpleLocalization.getText("NOT_EXISTENT"), "NOT_EXISTENT");
4343
}
4444

4545
@DataProvider
@@ -52,12 +52,11 @@ public Object[][] locales() {
5252

5353
@Test
5454
public void test_fixedLocale() {
55-
Locale.setDefault(Locale.ENGLISH);
55+
LocalizedBundle defaultBundle = SimpleLocalization.setDefault(Locale.ENGLISH);
5656
LocalizedBundle germanBundle = new LocalizedBundle(SimpleLocalization.BUNDLE_NAME, Locale.GERMAN);
57-
LocalizedBundle defaultBundle = new LocalizedBundle(SimpleLocalization.BUNDLE_NAME);
5857
Assert.assertNotEquals(germanBundle.getString("TEST"), defaultBundle.getString("TEST"));
5958

60-
Locale.setDefault(Locale.GERMAN);
59+
defaultBundle = SimpleLocalization.setDefault(Locale.GERMAN);
6160
Assert.assertEquals(germanBundle.getString("TEST"), defaultBundle.getString("TEST"));
6261
}
6362

integration-tests/src/test/java/eu/tsystems/mms/tic/testframework/test/webdrivermanager/WebDriverManagerTest.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import eu.tsystems.mms.tic.testframework.webdrivermanager.WebDriverManager;
3232
import eu.tsystems.mms.tic.testframework.webdrivermanager.WebDriverManagerConfig;
3333
import eu.tsystems.mms.tic.testframework.webdrivermanager.WebDriverSessionsManager;
34+
import java.util.Locale;
3435
import org.openqa.selenium.Dimension;
3536
import org.openqa.selenium.WebDriver;
3637
import org.openqa.selenium.chrome.ChromeDriver;
@@ -227,4 +228,17 @@ public void test_acceptInsecureCertificates() {
227228

228229
Assert.assertTrue(request.getDesiredCapabilities().acceptInsecureCerts());
229230
}
231+
232+
@Test
233+
public void test_SessionLocale() {
234+
Locale defaultLocale = Locale.getDefault();
235+
Locale sessionLocale = Locale.KOREAN;
236+
237+
Assert.assertNotEquals(defaultLocale, sessionLocale);
238+
239+
WebDriver webDriver = WebDriverManager.getWebDriver();
240+
Assert.assertTrue(WebDriverManager.setSessionLocale(webDriver, sessionLocale));
241+
242+
Assert.assertEquals(WebDriverManager.getSessionLocale(webDriver).orElse(null), sessionLocale);
243+
}
230244
}

integration-tests/src/test/resources/Integration.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
</groups>
1010
<packages>
1111
<package name="eu.tsystems.mms.tic.testframework.test.common"/>
12-
<package name="eu.tsystems.mms.tic.testframework.test.l10n"/>
1312
<package name="eu.tsystems.mms.tic.testframework.test.reporting"/>
1413
<package name="eu.tsystems.mms.tic.testframework.test.testdata"/>
1514
</packages>
@@ -30,6 +29,7 @@
3029
<suite-file path="GuiElementStandard.xml"></suite-file>
3130
<suite-file path="GuiElementVariations.xml"></suite-file>
3231
<suite-file path="PageObjects.xml"></suite-file>
32+
<suite-file path="Localization.xml"></suite-file>
3333
</suite-files>
3434

3535
<test name="Events" parallel="false">
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd" >
2+
<suite name="Localization " verbose="10" configfailurepolicy="continue" thread-count="10" parallel="false">
3+
4+
<test name="Core" parallel="methods">
5+
<groups>
6+
<run>
7+
<exclude name="SEQUENTIAL"/>
8+
</run>
9+
</groups>
10+
<packages>
11+
<package name="eu.tsystems.mms.tic.testframework.test.l10n"/>
12+
</packages>
13+
</test>
14+
</suite>

0 commit comments

Comments
 (0)