Selenium Localization

Not sure how other corporations are localizing Selenium. It has been an issue with ours. Since the creation of selenium we have not embedded localization into the infrastructure…oops, right?! The funny thing is that it took two of us to implement this simple solution in a couple hours. Once done we sent it off for review by the Automation Testing team. I wanted to let others take a look in case they were in the same situation that we were in.

One key is that we call into our Java server using a JSP would change depending upon how you get your localization entries for selenium.

How we localized Selenium:

•Added a class RBUtil that has methods overloaded method getValue(). As an example it is used in the following way:

1
2
3
4
5
String localizedValue = RBUtil.getValue(KEY_TO_LOCALIZATION)

//There are also signatures for the following:
RBUtil.getValue(key, default)
RBUtil.getValue(key, text insert array)

• The way this works is by calling the server with the resource bundle key. We are using the same Tomcat session as selenium to get the localized value.
• A key is that we are re-using the Tomcat session id so that we are not creating new sessions for each resource bundle (or localized string).
• We also cache the locale, username, etc. In fact, we will probably need to do more caching in the future but the main goal is that this will get us on our feet for having selenium localized.

Implementation Class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
package com.ptc.selenium.localization;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;

import org.apache.log4j.Logger;

import sun.misc.BASE64Encoder;

import com.ptc.selenium.SeleniumLogger;
import com.ptc.selenium.SeleniumSession;
import com.ptc.selenium.SolventSelenium;
import com.ptc.selenium.SolventTestCase;

/**
 * Singleton class that is used to get the localization values from the RBInfo class file entries.
 *
 * This will retrieve values for selenium tests to be able to localize and attribute clicks to rbinfo files.
 *
 */

public class RBUtil {

    private static final Logger log = SeleniumLogger.getLogger(SolventTestCase.class.getName());

    private static RBUtil singleton;

    private final String baseURL;

    private final String username;

    private final String password;

    private final String cookie;

    private final String locale;

    private RBUtil() {
        SolventSelenium selenium = SeleniumSession.get();

        // Cache these values on the instance
        baseURL = selenium.getBaseURL();
        password = selenium.getPassword();
        username = selenium.getUsername();
        cookie = selenium.getCookieByName("JSESSIONID");
        locale = selenium.getEval("selenium.browserbot.getCurrentWindow().getLocale()");
    }

    public static RBUtil getInstance() {
        if (singleton == null) {
            singleton = new RBUtil();
        }
        return singleton;
    }

    /**
     * Will retrieve the resource bundle value given the key in the form of class.key. For example,
     * com.ptc.windchill.enterprise.folder.folderResource.PARTS_VIEW
     *
     * @param key
     *            In the form of CLASS.KEY. For example,
     *            "com.ptc.windchill.enterprise.folder.folderResource.PARTS_VIEW".
     * @return The value returned from the resource bundle lookup. If the resource could not be found empty string is
     *         returned
     */

    public static String getValue(String key) {
        return getValue(key, "");
    }

    /**
     * Will retrieve the resource bundle value given the key in the form of class.key.
     *
     * @param key
     *            In the form of CLASS.KEY. For example,
     *            "com.ptc.windchill.enterprise.folder.folderResource.PARTS_VIEW".
     * @param def
     *            The default value you want in the case that the locale could not be looked up.
     * @return The value returned from the resource bundle lookup.
     */

    public static String getValue(String key, String def) {
        String value = getInstance().getValueFromServer(key);
        return (value == null) ? def : value;
    }

    /**
     * Gets the localized string, unescapes the quot and puts the inserts in.
     *
     * @param key
     *            In the form of CLASS.KEY. For example,
     *            "com.ptc.windchill.enterprise.folder.folderResource.PARTS_VIEW".
     * @param inserts
     *            A list of inserts in order of the numbering in the rbinfo file.
     * @return The final string.
     */

    public static String getValue(String key, List<String> inserts) {
        String value = getInstance().getValueFromServer(key);

        for (int i = 0; i < inserts.size(); i++) {
            value = value.replace("{" + i + "}", inserts.get(i));
        }

        value = value.replaceAll("&quot;", "\"");

        return value;
    }

    private String getValueFromServer(String key) {
        InputStream ins = null;
        try {
            log.debug("Using Session Cookie = " + this.cookie);
            URL url = new URL(this.baseURL + "/netmarkets/jsp/util/getBundleKey.jsp?key=" + key);
            URLConnection conn = url.openConnection();

            conn.setRequestProperty("Cookie", "JSESSIONID=" + this.cookie);
            conn.setRequestProperty("Accept-Language", this.locale);
            conn.setRequestProperty("Authorization", "Basic " + encode(this.username + ":" + this.password));

            String value = null;
            try {
                ins = conn.getInputStream();
                BufferedReader reader = new BufferedReader(new InputStreamReader(ins));
                value = reader.readLine();
                log.debug("Fetched RbInfo Key=" + key + " Value=" + value);
            } finally {
                if (ins != null) {
                    ins.close();
                }
            }

            return value;
        } catch (Exception e) {
            throw new RuntimeException("Unable to reach server.", e);
        }
    }

    /**
     * Encode the string for use in the header.
     *
     * @param source
     *            The string you want to encode using base 64 encoding.
     * @return The encoded string.
     */

    public static String encode(String source) {
        BASE64Encoder enc = new sun.misc.BASE64Encoder();
        return (enc.encode(source.getBytes()));
    }

}

2 thoughts on “Selenium Localization

  1. Ryan,

    Sorry for my English, I’m French.
    I’m very interested in your work since it seems to be close from what I’m doing.
    I’m working in a French aerospace company and I use selenium webdriver in order to pull a bunch of information from PDMLink .
    It’s working not too bad but not as good as it should.
    Some of the pages are so big that they simply can’t be shown.
    I don’t think using webdriver is the state of the art way of pulling information from PDMLink.
    Do you know if there is a way to request data from PDMLink in a different format, json for example?

    Many thanks for any answer.

    Fabrice.

  2. Fabrice,

    Good afternoon! You can pull information from PDMLink in many different ways. Depends on what version of PDMLink you have installed. Some information is available as JSON but that is in the newest version. I am guessing you are pulling information off of tables on the page? If so, there is an export option that you can use (for instance on the folder browser). The export option supports XML, Excel, HTML, and plain text. There is also the ability to use Info*Engine or the query builder. These would give you faster performance for pulling data.

    Not sure if that helps or not.

    – Ryan

Leave a Reply

Your email address will not be published. Required fields are marked *