001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.tools.seleniumbuilder;
016    
017    import com.liferay.portal.kernel.util.ArrayUtil;
018    import com.liferay.portal.kernel.util.GetterUtil;
019    import com.liferay.portal.kernel.util.SetUtil;
020    import com.liferay.portal.kernel.util.StringBundler;
021    import com.liferay.portal.kernel.util.StringPool;
022    import com.liferay.portal.kernel.util.StringUtil;
023    import com.liferay.portal.kernel.xml.Element;
024    import com.liferay.portal.tools.ArgumentsUtil;
025    import com.liferay.portal.tools.ToolDependencies;
026    
027    import java.util.List;
028    import java.util.Map;
029    import java.util.Set;
030    import java.util.TreeMap;
031    import java.util.TreeSet;
032    
033    /**
034     * @author Michael Hashimoto
035     */
036    public class SeleniumBuilder {
037    
038            public static void main(String[] args) throws Exception {
039                    ToolDependencies.wireBasic();
040    
041                    new SeleniumBuilder(args);
042            }
043    
044            /**
045             * Constructs a Selenium Builder based on the arguments.
046             *
047             * @param  args the command-line arguments
048             * @throws Exception if an exception occurred
049             */
050            public SeleniumBuilder(String[] args) throws Exception {
051                    Map<String, String> arguments = ArgumentsUtil.parseArguments(args);
052    
053                    String baseDirName = arguments.get("selenium.base.dir");
054                    String projectDirName = arguments.get("project.dir");
055    
056                    _seleniumBuilderFileUtil = new SeleniumBuilderFileUtil(
057                            baseDirName, projectDirName);
058    
059                    _seleniumBuilderContext = new SeleniumBuilderContext(
060                            _seleniumBuilderFileUtil);
061    
062                    Set<String> actionNames = _seleniumBuilderContext.getActionNames();
063    
064                    for (String actionName : actionNames) {
065                            _seleniumBuilderContext.validateActionElements(actionName);
066                    }
067    
068                    Set<String> functionNames = _seleniumBuilderContext.getFunctionNames();
069    
070                    for (String functionName : functionNames) {
071                            _seleniumBuilderContext.validateFunctionElements(functionName);
072                    }
073    
074                    Set<String> macroNames = _seleniumBuilderContext.getMacroNames();
075    
076                    for (String macroName : macroNames) {
077                            _seleniumBuilderContext.validateMacroElements(macroName);
078                    }
079    
080                    Set<String> testCaseNames = _seleniumBuilderContext.getTestCaseNames();
081    
082                    for (String testCaseName : testCaseNames) {
083                            _seleniumBuilderContext.validateTestCaseElements(testCaseName);
084                    }
085    
086                    Set<String> types = SetUtil.fromArray(
087                            StringUtil.split(arguments.get("selenium.types")));
088    
089                    if (types.contains("action")) {
090                            ActionConverter actionConverter = new ActionConverter(
091                                    _seleniumBuilderContext, _seleniumBuilderFileUtil);
092    
093                            for (String actionName : actionNames) {
094                                    actionConverter.convert(actionName);
095                            }
096                    }
097    
098                    if (types.contains("function")) {
099                            FunctionConverter functionConverter = new FunctionConverter(
100                                    _seleniumBuilderContext, _seleniumBuilderFileUtil);
101    
102                            for (String functionName : functionNames) {
103                                    functionConverter.convert(functionName);
104                            }
105                    }
106    
107                    if (types.contains("macro")) {
108                            MacroConverter macroConverter = new MacroConverter(
109                                    _seleniumBuilderContext, _seleniumBuilderFileUtil);
110    
111                            for (String macroName : macroNames) {
112                                    macroConverter.convert(macroName);
113                            }
114                    }
115    
116                    if (types.contains("path")) {
117                            PathConverter pathConverter = new PathConverter(
118                                    _seleniumBuilderContext, _seleniumBuilderFileUtil);
119    
120                            Set<String> pathNames = _seleniumBuilderContext.getPathNames();
121    
122                            for (String pathName : pathNames) {
123                                    pathConverter.convert(pathName);
124                            }
125                    }
126    
127                    if (types.contains("testcase")) {
128                            TestCaseConverter testCaseConverter = new TestCaseConverter(
129                                    _seleniumBuilderContext, _seleniumBuilderFileUtil);
130    
131                            String testClass = arguments.get("test.class");
132    
133                            if (!testClass.equals("${test.class}")) {
134                                    String testCaseCommandName = null;
135                                    String testCaseName = null;
136    
137                                    if (testClass.contains("#")) {
138                                            String[] testClassParts = StringUtil.split(testClass, "#");
139    
140                                            testCaseCommandName = testClassParts[1];
141                                            testCaseName = testClassParts[0];
142                                    }
143                                    else {
144                                            testCaseName = testClass;
145                                    }
146    
147                                    if ((testCaseCommandName != null) &&
148                                            testCaseCommandName.startsWith("test")) {
149    
150                                            testCaseCommandName = StringUtil.replaceFirst(
151                                                    testCaseCommandName, "test", "");
152                                    }
153    
154                                    if (testCaseName.endsWith("TestCase")) {
155                                            testCaseName = StringUtil.replaceLast(
156                                                    testCaseName, "TestCase", "");
157                                    }
158    
159                                    Element rootElement =
160                                            _seleniumBuilderContext.getTestCaseRootElement(
161                                                    testCaseName);
162    
163                                    String extendsTestCaseName = rootElement.attributeValue(
164                                            "extends");
165    
166                                    if (extendsTestCaseName != null) {
167                                            testCaseConverter.convert(
168                                                    extendsTestCaseName, testCaseCommandName);
169                                    }
170    
171                                    testCaseConverter.convert(testCaseName, testCaseCommandName);
172                            }
173                    }
174    
175                    _writeTestCaseMethodNamesFile();
176                    _writeTestCasePropertiesFile();
177    
178                    System.out.println(
179                            "\nThere are " + _getTestCaseMethodCount() + " test cases.");
180            }
181    
182            /**
183             * Returns the total number of test case methods by adding the number of
184             * methods inside each test case file.
185             *
186             * @return the total number of test case methods
187             */
188            private int _getTestCaseMethodCount() {
189                    int testCaseCount = 0;
190    
191                    Set<String> testCaseNames = _seleniumBuilderContext.getTestCaseNames();
192    
193                    for (String testCaseName : testCaseNames) {
194                            Element rootElement =
195                                    _seleniumBuilderContext.getTestCaseRootElement(testCaseName);
196    
197                            if (GetterUtil.getBoolean(rootElement.attributeValue("ignore"))) {
198                                    continue;
199                            }
200    
201                            String extendsTestCaseName = rootElement.attributeValue("extends");
202    
203                            if (extendsTestCaseName != null) {
204                                    Element extendsRootElement =
205                                            _seleniumBuilderContext.getTestCaseRootElement(
206                                                    extendsTestCaseName);
207    
208                                    List<Element> commandElements =
209                                            _seleniumBuilderFileUtil.getAllChildElements(
210                                                    extendsRootElement, "command");
211    
212                                    testCaseCount += commandElements.size();
213                            }
214    
215                            List<Element> commandElements =
216                                    _seleniumBuilderFileUtil.getAllChildElements(
217                                            rootElement, "command");
218    
219                            testCaseCount += commandElements.size();
220                    }
221    
222                    return testCaseCount;
223            }
224    
225            private boolean _isCommandNameOverridden(
226                    Element rootElement, String commandName) {
227    
228                    List<Element> commandElements =
229                            _seleniumBuilderFileUtil.getAllChildElements(
230                                    rootElement, "command");
231    
232                    for (Element commandElement : commandElements) {
233                            if (commandName.equals(commandElement.attributeValue("name"))) {
234                                    return true;
235                            }
236                    }
237    
238                    return false;
239            }
240    
241            private boolean _isIgnoreCommandName(
242                    Element rootElement, String commandName) {
243    
244                    String ignoreCommandNamesString = rootElement.attributeValue(
245                            "ignore-command-names");
246    
247                    if (ignoreCommandNamesString == null) {
248                            return false;
249                    }
250    
251                    String[] ignoreCommandNames = StringUtil.split(
252                            ignoreCommandNamesString);
253    
254                    ignoreCommandNamesString = StringUtil.replace(
255                            ignoreCommandNamesString, new String[] {" ", "\n", "\t"},
256                            new String[] {"", "", ""});
257    
258                    return ArrayUtil.contains(ignoreCommandNames, commandName);
259            }
260    
261            /**
262             * Writes lists of all test case method names, aggregated by component, to a
263             * properties file named <code>test.case.method.names.properties</code>.
264             *
265             * <p>
266             * Each property follows the format: <code>componentName +
267             * "_TEST_CASE_METHOD_NAMES=" + testCaseName + "TestCase#test" +
268             * commandName</code>
269             * </p>
270             *
271             * <p>
272             * Example <code>test.case.method.names.properties</code> output file:
273             * </p>
274             *
275             * <p>
276             * <pre>
277             * <code>
278             * MARKETPLACE_TEST_CASE_METHOD_NAMES=PortalSmokeTestCase#testSmoke
279             * PORTAL_APIS_TEST_CASE_METHOD_NAMES=ApisTestCase#testAdd ApisTestCase#test
280             * </code>
281             * </pre>
282             * </p>
283             *
284             * @throws Exception if an exception occurred
285             */
286            private void _writeTestCaseMethodNamesFile() throws Exception {
287                    Map<String, Set<String>> testCaseMethodNameMap =
288                            new TreeMap<String, Set<String>>();
289    
290                    Set<String> testCaseNames = _seleniumBuilderContext.getTestCaseNames();
291    
292                    for (String testCaseName : testCaseNames) {
293                            Element rootElement =
294                                    _seleniumBuilderContext.getTestCaseRootElement(testCaseName);
295    
296                            if (GetterUtil.getBoolean(rootElement.attributeValue("ignore"))) {
297                                    continue;
298                            }
299    
300                            String componentName = rootElement.attributeValue("component-name");
301    
302                            Set<String> compontentTestCaseMethodNames = new TreeSet<String>();
303    
304                            if (testCaseMethodNameMap.containsKey(componentName)) {
305                                    compontentTestCaseMethodNames = testCaseMethodNameMap.get(
306                                            componentName);
307                            }
308    
309                            String extendsTestCaseName = rootElement.attributeValue("extends");
310    
311                            if (extendsTestCaseName != null) {
312                                    Element extendsRootElement =
313                                            _seleniumBuilderContext.getTestCaseRootElement(
314                                                    extendsTestCaseName);
315    
316                                    List<Element> commandElements =
317                                            _seleniumBuilderFileUtil.getAllChildElements(
318                                                    extendsRootElement, "command");
319    
320                                    for (Element commandElement : commandElements) {
321                                            String commandName = commandElement.attributeValue("name");
322    
323                                            if (_isCommandNameOverridden(rootElement, commandName)) {
324                                                    continue;
325                                            }
326    
327                                            if (_isIgnoreCommandName(rootElement, commandName)) {
328                                                    continue;
329                                            }
330    
331                                            String testCaseMethodName =
332                                                    testCaseName + "TestCase#test" + commandName;
333    
334                                            compontentTestCaseMethodNames.add(testCaseMethodName);
335                                    }
336                            }
337    
338                            List<Element> commandElements =
339                                    _seleniumBuilderFileUtil.getAllChildElements(
340                                            rootElement, "command");
341    
342                            for (Element commandElement : commandElements) {
343                                    String testCaseMethodName =
344                                            testCaseName + "TestCase#test" +
345                                                    commandElement.attributeValue("name");
346    
347                                    String knownIssues = commandElement.attributeValue(
348                                            "known-issues");
349    
350                                    if (knownIssues != null) {
351                                            String knownIssuesComponent = "portal-known-issues";
352    
353                                            if (componentName.startsWith("marketplace")) {
354                                                    knownIssuesComponent = "marketplace-known-issues";
355                                            }
356                                            else if (componentName.startsWith("social-office")) {
357                                                    knownIssuesComponent = "social-office-known-issues";
358                                            }
359    
360                                            Set<String> knownIssuesTestCaseMethodNames =
361                                                    new TreeSet<String>();
362    
363                                            if (testCaseMethodNameMap.containsKey(
364                                                            knownIssuesComponent)) {
365    
366                                                    knownIssuesTestCaseMethodNames =
367                                                            testCaseMethodNameMap.get(knownIssuesComponent);
368                                            }
369    
370                                            knownIssuesTestCaseMethodNames.add(testCaseMethodName);
371    
372                                            testCaseMethodNameMap.put(
373                                                    knownIssuesComponent, knownIssuesTestCaseMethodNames);
374                                    }
375                                    else {
376                                            compontentTestCaseMethodNames.add(testCaseMethodName);
377                                    }
378                            }
379    
380                            if (!compontentTestCaseMethodNames.isEmpty()) {
381                                    testCaseMethodNameMap.put(
382                                            componentName, compontentTestCaseMethodNames);
383                            }
384                    }
385    
386                    List<String> componentNames =
387                            _seleniumBuilderFileUtil.getComponentNames();
388    
389                    StringBundler sb = new StringBundler();
390    
391                    for (String componentName : componentNames) {
392                            String componentNameKey = componentName;
393    
394                            componentName = StringUtil.replace(componentName, "-", "_");
395                            componentName = StringUtil.upperCase(componentName);
396    
397                            sb.append(componentName);
398                            sb.append("_TEST_CASE_METHOD_NAMES=");
399    
400                            if (testCaseMethodNameMap.containsKey(componentNameKey)) {
401                                    Set<String> compontentTestCaseMethodNames =
402                                            testCaseMethodNameMap.get(componentNameKey);
403    
404                                    String testCaseMethodNamesString = StringUtil.merge(
405                                            compontentTestCaseMethodNames.toArray(
406                                                    new String[compontentTestCaseMethodNames.size()]),
407                                            StringPool.SPACE);
408    
409                                    sb.append(testCaseMethodNamesString);
410                                    sb.append("\n");
411                            }
412                            else {
413                                    sb.append("PortalSmokeTestCase#testSmoke\n");
414                            }
415                    }
416    
417                    _seleniumBuilderFileUtil.writeFile(
418                            "../../../test.case.method.names.properties", sb.toString(), false);
419            }
420    
421            /**
422             * Writes lists of all test case method properties, aggregated by test case
423             * definition scope and test case command scope, to a properties file named
424             * <code>test.generated.properties</code>.
425             *
426             * <p>
427             * The test case method properties scoped to test case definitions follow
428             * the format: <code>testCaseName + "TestCase.all." + propertyName =
429             * propertyValue</code>
430             * </p>
431             *
432             * <p>
433             * The test case method properties scoped to test case commands follow the
434             * format: <code>testCaseName + "TestCase.test" + commandName + "." +
435             * propertyName = propertyValue</code>
436             * </p>
437             *
438             * <p>
439             * Example <code>test.generated.properties</code> output file:
440             * </p>
441             *
442             * <p>
443             * <pre>
444             * <code>
445             * SOProfileTestCase.all.hook.plugins.includes=deploy-listener-hook,...
446             * SOProfileTestCase.all.portlet.plugins.includes=calendar-portlet,chat-...
447             * SOProfileTestCase.all.theme.plugins.includes=so-theme
448             * SOProfileTestCase.all.web.plugins.includes=resources-importer-web
449             * </code>
450             * </pre>
451             * </p>
452             *
453             * @throws Exception if an exception occurred
454             */
455            private void _writeTestCasePropertiesFile() throws Exception {
456                    Set<String> testCaseProperties = new TreeSet<String>();
457    
458                    Set<String> testCaseNames = _seleniumBuilderContext.getTestCaseNames();
459    
460                    for (String testCaseName : testCaseNames) {
461                            Element rootElement =
462                                    _seleniumBuilderContext.getTestCaseRootElement(testCaseName);
463    
464                            List<Element> rootPropertyElements = rootElement.elements(
465                                    "property");
466    
467                            StringBundler sb = new StringBundler();
468    
469                            sb.append(testCaseName);
470                            sb.append("TestCase.all.testray.testcase.product.edition=CE");
471    
472                            testCaseProperties.add(sb.toString());
473    
474                            for (Element rootPropertyElement : rootPropertyElements) {
475                                    sb = new StringBundler();
476    
477                                    sb.append(testCaseName);
478                                    sb.append("TestCase.all.");
479    
480                                    String rootPropertyName = rootPropertyElement.attributeValue(
481                                            "name");
482    
483                                    sb.append(rootPropertyName);
484    
485                                    sb.append("=");
486                                    sb.append(rootPropertyElement.attributeValue("value"));
487    
488                                    testCaseProperties.add(sb.toString());
489    
490                                    String rootPropertyDelimiter =
491                                            rootPropertyElement.attributeValue("delimiter");
492    
493                                    if ((rootPropertyDelimiter != null) &&
494                                            rootPropertyName.equals("ignore.errors")) {
495    
496                                            sb = new StringBundler();
497    
498                                            sb.append(testCaseName);
499                                            sb.append("TestCase.all.");
500                                            sb.append(rootPropertyName);
501                                            sb.append(".delimiter=");
502                                            sb.append(rootPropertyDelimiter);
503    
504                                            testCaseProperties.add(sb.toString());
505                                    }
506                            }
507    
508                            List<Element> commandElements =
509                                    _seleniumBuilderFileUtil.getAllChildElements(
510                                            rootElement, "command");
511    
512                            for (Element commandElement : commandElements) {
513                                    List<Element> commandPropertyElements =
514                                            _seleniumBuilderFileUtil.getAllChildElements(
515                                                    commandElement, "property");
516    
517                                    for (Element commandPropertyElement : commandPropertyElements) {
518                                            sb = new StringBundler();
519    
520                                            sb.append(testCaseName);
521                                            sb.append("TestCase.test");
522                                            sb.append(commandElement.attributeValue("name"));
523                                            sb.append(".");
524                                            sb.append(commandPropertyElement.attributeValue("name"));
525                                            sb.append("=");
526                                            sb.append(commandPropertyElement.attributeValue("value"));
527    
528                                            testCaseProperties.add(sb.toString());
529                                    }
530    
531                                    sb = new StringBundler();
532    
533                                    sb.append(testCaseName);
534                                    sb.append("TestCase.test");
535                                    sb.append(commandElement.attributeValue("name"));
536                                    sb.append(".testray.testcase.description=");
537    
538                                    if (commandElement.attributeValue("description") != null) {
539                                            sb.append(commandElement.attributeValue("description"));
540                                    }
541    
542                                    testCaseProperties.add(sb.toString());
543    
544                                    sb = new StringBundler();
545    
546                                    sb.append(testCaseName);
547                                    sb.append("TestCase.test");
548                                    sb.append(commandElement.attributeValue("name"));
549                                    sb.append(".testray.testcase.name=");
550                                    sb.append(testCaseName);
551                                    sb.append("#");
552                                    sb.append(commandElement.attributeValue("name"));
553    
554                                    testCaseProperties.add(sb.toString());
555    
556                                    sb = new StringBundler();
557    
558                                    sb.append(testCaseName);
559                                    sb.append("TestCase.test");
560                                    sb.append(commandElement.attributeValue("name"));
561                                    sb.append(".testray.testcase.priority=");
562                                    sb.append(commandElement.attributeValue("priority"));
563    
564                                    testCaseProperties.add(sb.toString());
565                            }
566                    }
567    
568                    String testCasePropertiesString = StringUtil.merge(
569                            testCaseProperties.toArray(new String[testCaseProperties.size()]),
570                            StringPool.NEW_LINE);
571    
572                    _seleniumBuilderFileUtil.writeFile(
573                            "../../../test.generated.properties", testCasePropertiesString,
574                            false);
575            }
576    
577            private SeleniumBuilderContext _seleniumBuilderContext;
578            private SeleniumBuilderFileUtil _seleniumBuilderFileUtil;
579    
580    }