name.gluino.webmailfeed.InjectIntoWebmailAddressBook.java Source code

Java tutorial

Introduction

Here is the source code for name.gluino.webmailfeed.InjectIntoWebmailAddressBook.java

Source

package name.gluino.webmailfeed;

import java.util.Collections;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.concurrent.TimeUnit;

import org.openqa.selenium.Alert;
import org.openqa.selenium.By;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.ui.Select;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static com.example.BasicChecks.*;

import com.mplify.logging.LogFacilities;
import com.mplify.logstarter.LogbackStarter;
import com.mplify.tools.Sleep;

/* 34567890123456789012345678901234567890123456789012345678901234567890123456789
 * *****************************************************************************
 * Copyright (c) 2013, David Tonhofer
 *
 * Distributed under: "The MIT License" (http://opensource.org/licenses/MIT)
 *******************************************************************************
 * ** This is where it's at! **
 * 
 * Fill the address book of the P&T Luxembourg Webmail application
 * (https://webmail.pt.lu/) via its not-entirely-well-navigable web interface
 * with the data coming from a club membership list (a CSV document; TODO: 
 * extract the data directly from an Excel sheet)
     
 * This is set of methods configured as a JUnit TestCase so that one can
 * execute this via Eclipse JUnit runner or something.
 * 
 * 2013.04.XX - Created
 * 2013.06.14 - Cleanup
 ******************************************************************************/

public class InjectIntoWebmailAddressBook {

    private final static String CLASS = InjectIntoWebmailAddressBook.class.getName();
    private final static Logger LOGGER_loginToWebmail = LoggerFactory.getLogger(CLASS + ".loginToWebmail");
    private final static Logger LOGGER_goToWebmailLoginPage = LoggerFactory
            .getLogger(CLASS + ".goToWebmailLoginPage");
    private final static Logger LOGGER_createAddressbook = LoggerFactory.getLogger(CLASS + ".createAddressbook");
    private final static Logger LOGGER_logoutFromWebmail = LoggerFactory.getLogger(CLASS + ".logoutFromWebmail");
    private final static Logger LOGGER_openContactsMenu = LoggerFactory.getLogger(CLASS + ".openContactsMenu");
    private final static Logger LOGGER_makeSureFolderDoesNotExist = LoggerFactory
            .getLogger(CLASS + ".makeSureFolderDoesNotExist");
    private final static Logger LOGGER_addNewFolder = LoggerFactory.getLogger(CLASS + ".addNewFolder");
    private final static Logger LOGGER_makeSureFolderDoesExist = LoggerFactory
            .getLogger(CLASS + ".makeSureFolderDoesExist");
    private final static Logger LOGGER_enterFolder = LoggerFactory.getLogger(CLASS + ".enterFolder");
    private final static Logger LOGGER_enterRelevantContacts = LoggerFactory
            .getLogger(CLASS + ".enterRelevantContacts");

    private final PropertiesReader config; // immutable configuration
    private final Set<ClubMember> allMembers; // immutable set of all the club members
    private final WebDriver driver;

    private final int DOG_SLOW_SECONDS = 10;
    private final int MEDIUM_SLOW_SECONDS = 10;

    /**
     * We also have a simple facility to store several problems in a string buffer
     */

    private boolean acceptNextAlert = true;
    private StringBuffer verificationErrors = new StringBuffer();

    /**
     * Constructor
     */

    public InjectIntoWebmailAddressBook(PropertiesReader config, Set<ClubMember> allMembers) {
        checkNotNull(config, "config");
        checkNotNull(allMembers, "allMembers");
        this.config = config;
        this.allMembers = Collections.unmodifiableSet(allMembers);
        this.driver = new FirefoxDriver();
        this.driver.manage().timeouts().implicitlyWait(DOG_SLOW_SECONDS, TimeUnit.SECONDS);
    }

    /**
     * Cleaning up after a "test" function has been run
     */

    public void tearDown() {
        driver.quit();
        String verificationErrorString = verificationErrors.toString();
        if (!"".equals(verificationErrorString)) {
            instaFail(verificationErrorString);
        }
    }

    /**
     * Helper
     */

    private void goToWebmailLoginPage() {
        Logger logger = LOGGER_goToWebmailLoginPage;
        logger.info("Opening login page at " + config.getBaseURL());
        driver.manage().timeouts().implicitlyWait(MEDIUM_SLOW_SECONDS, TimeUnit.SECONDS);
        driver.get(config.getBaseURL() + "/webmail");
        //
        // On return, check that the login page is up
        //
        String text = driver.findElement(By.cssSelector("BODY")).getText();
        logger.info("Text in BODY: '" + LogFacilities.mangleString(text) + "'");
        checkTrue(text.contains("Webmail Login"), "Did not find 'Webmail Login'");
        checkTrue(text.contains("POST Luxembourg"), "Did not find 'POST Luxembourg'");
        logger.info("Apparently the login page is visible");
    }

    /**
     * Helper
     */

    private void loginToWebmail() {
        Logger logger = LOGGER_loginToWebmail;
        logger.info("Logging in");
        driver.findElement(By.name("user")).clear();
        driver.findElement(By.name("user")).sendKeys(config.getUsername());
        driver.findElement(By.name("password")).clear();
        driver.findElement(By.name("password")).sendKeys(config.getPassword());
        new Select(driver.findElement(By.name("lang"))).selectByVisibleText("English");
        driver.findElement(By.cssSelector("button[type=\"submit\"]")).click();
        Sleep.sleepTwoSeconds();
        //
        // On return, we should be logged in
        //
        driver.get(config.getBaseURL() + "/webmail/overview");
        String title = driver.getTitle();
        logger.info("Title of page: '" + LogFacilities.mangleString(title) + "'");
        // checkTrue(title.matches(".*?P&T\u00A0Luxembourg\u00A0Webmail.*?"), "Looked for P&T Luxembourg Webmail string");
        String text = driver.findElement(By.cssSelector("BODY")).getText();
        logger.info("Text in BODY: '" + LogFacilities.mangleString(text) + "'");
        checkTrue(text.contains(config.getUsername()), "Looked for '" + config.getUsername() + "'");
        checkTrue(text.contains("Logout"), "Looked for 'Logout'");
        //
        // The icon for "contacts" should be there
        //
        checkTrue(isElementPresent(By.cssSelector("span.icon_manager.navigation_addr")),
                "The 'Contacts' icon is there");
        logger.info("Apparently we are logged in");
    }

    /**
     * Helper
     */

    private boolean isElementPresent(By by) {
        try {
            driver.findElement(by);
            return true;
        } catch (NoSuchElementException e) {
            return false;
        }
    }

    private void waitForExportImportInAddressBookMenu() {
        for (int second = 0;; second++) {
            checkFalse(second >= 60, "timeout");
            try {
                if (isElementPresent(By.id("text_action_export")))
                    break;
            } catch (Exception e) {
                // NOP          

            }
            Sleep.sleepHalfASecond();
        }

        for (int second = 0;; second++) {
            checkFalse(second >= 60, "timeout");
            try {
                if (isElementPresent(By.id("text_action_import_addrimport")))
                    break;
            } catch (Exception e) {
                // NOP
            }
            Sleep.sleepHalfASecond();
        }

    }

    /**
     * Helper
     */

    private void openContactsMenu() {
        Logger logger = LOGGER_openContactsMenu;
        logger.info("Opening contacts menu");
        driver.findElement(By.cssSelector("span.icon_manager.navigation_addr")).click();
        Sleep.sleepTwoSeconds();
        //
        // On return, the web page should be in "address book mode".
        // Finding out that this is so is kind difficult.
        //
        checkTrue(driver.findElement(By.cssSelector("BODY")).getText().matches("^[\\s\\S]*Contacts[\\s\\S]*$"),
                "Looked for 'Contacts'");
        waitForExportImportInAddressBookMenu();
        checkTrue(isElementPresent(By.id("icon_action_add_folder")), "Add folder icon should be there");
        //
        // Click at least twice then click once more if "Contacts" is not yet there
        //
        driver.findElement(By.xpath("(//a[contains(text(),'" + config.getUsername() + "')])[2]")).click();
        Sleep.sleepTwoSeconds();
        driver.findElement(By.xpath("(//a[contains(text(),'" + config.getUsername() + "')])[2]")).click();
        Sleep.sleepTwoSeconds();
        if (!isElementPresent(By.xpath("//a[contains(text(),'Contacts')]"))) {
            driver.findElement(By.xpath("(//a[contains(text(),'" + config.getUsername() + "')])[2]")).click();
            Sleep.sleepTwoSeconds();
        }
        //
        // Contacts must now be there
        //
        checkTrue(isElementPresent(By.xpath("//a[contains(text(),'Contacts')]")), "Was looking for 'Contacts'");
        logger.info("Apparently 'Contacts' are now visible");

    }

    /**
     * Helper
     */

    private void logoutFromWebmail() {
        Logger logger = LOGGER_logoutFromWebmail;
        logger.info("Logging out");
        driver.findElement(By.linkText("Logout")).click();
        Sleep.sleepTwoSeconds();
        String text = driver.findElement(By.cssSelector("BODY")).getText();
        logger.info("Text in BODY: '" + LogFacilities.mangleString(text) + "'");
        checkTrue(text.contains("Webmail Login"), "Did not find 'Webmail Login'");
        //checkTrue(text.contains("Entreprise des P&T"), "Did not find 'Entreprise des P&T'");
        logger.info("Apparently logged out");
    }

    /**
     * Helper
     */

    private void makeSureFolderDoesNotExist(String foldername) {
        Logger logger = LOGGER_makeSureFolderDoesNotExist;
        logger.info("Making sure there is no folder '" + foldername + "'");
        // for some reason this takes a LONG time
        checkFalse(isElementPresent(By.xpath("//a[contains(text(),'" + foldername + "')]")),
                "Was looking for '" + foldername + "'");
        logger.info("Apparently there is no folder '" + foldername + "'");
    }

    /**
     * Helper
     */

    private void makeSureFolderDoesExist(String foldername) {
        Logger logger = LOGGER_makeSureFolderDoesExist;
        logger.info("Making sure there is a folder '" + foldername + "'");
        checkTrue(isElementPresent(By.xpath("//a[contains(text(),'" + foldername + "')]")),
                "Was looking for '" + foldername + "'");
        logger.info("Apparently there is a folder '" + foldername + "'");
    }

    /**
     * Helper
     */

    private void addNewFolder(String foldername) {
        Logger logger = LOGGER_addNewFolder;
        driver.findElement(By.id("icon_action_add_folder")).click();
        Sleep.sleepTwoSeconds();
        checkTrue(isElementPresent(By.id("_button_cancel")), "Looked for CANCEL button");
        checkTrue(isElementPresent(By.id("_button_save")), "Looked for SAVE button");
        checkTrue(isElementPresent(By.id("parent")), "Looked for 'parent folder' entry field");
        checkTrue(isElementPresent(By.id("name")), "Looked for 'name' entry field");
        driver.findElement(By.id("name")).clear();
        driver.findElement(By.id("name")).sendKeys(foldername);
        driver.findElement(By.id("_button_save")).click();
        Sleep.sleepTwoSeconds();
        logger.info("Apparently folder '" + foldername + "' has been added");
    }

    /**
     * Helper
     */

    private void enterFolder(String foldername) {
        Logger logger = LOGGER_enterFolder;
        waitForExportImportInAddressBookMenu();
        logger.info("Trying to enter '" + foldername + "'");
        driver.findElement(By.cssSelector("span.icon_manager.navigation_mail")).click();
        Sleep.sleepTwoSeconds();
        driver.findElement(By.cssSelector("span.icon_manager.navigation_addr")).click();
        Sleep.sleepTwoSeconds();
        //
        // Click at least twice then click once more if "Contacts" is not yet there
        //
        driver.findElement(By.xpath("(//a[contains(text(),'" + config.getUsername() + "')])[2]")).click();
        Sleep.sleepTwoSeconds();
        driver.findElement(By.xpath("(//a[contains(text(),'" + config.getUsername() + "')])[2]")).click();
        Sleep.sleepTwoSeconds();
        if (!isElementPresent(By.xpath("//a[contains(text(),'" + foldername + "')]"))) {
            driver.findElement(By.xpath("(//a[contains(text(),'" + config.getUsername() + "')])[2]")).click();
            Sleep.sleepTwoSeconds();
        }
        driver.findElement(By.xpath("//a[contains(text(),'" + foldername + "')]")).click();
        Sleep.sleepTwoSeconds();

        checkTrue(isElementPresent(By.id("icon_action_add")), "Looked for 'icon_action_add' action");
        checkTrue(driver.findElement(By.cssSelector("BODY")).getText().contains(foldername),
                "Looked for '" + foldername + "'");
        checkTrue(driver.findElement(By.cssSelector("BODY")).getText().contains("No items"),
                "Looked for 'No items'");
        logger.info("Apparently we are ready to enter contacts");
    }

    /**
     * Helper
     */

    private void enterRelevantContacts(Acceptor acceptor) {
        Logger logger = LOGGER_enterRelevantContacts;
        for (ClubMember m : allMembers) {
            if (acceptor.accept(m)) {
                int count = 0;
                for (String addr : m.emailAddressList) {
                    logger.info("Trying to add " + m);
                    driver.findElement(By.id("icon_action_add")).click();
                    Sleep.sleepTwoSeconds();
                    driver.findElement(By.id("firstname")).clear();
                    driver.findElement(By.id("firstname")).sendKeys(m.firstName);
                    driver.findElement(By.id("lastname")).clear();
                    if (count == 0) {
                        driver.findElement(By.id("lastname")).sendKeys(m.lastName);
                    } else {
                        driver.findElement(By.id("lastname")).sendKeys(m.lastName + " (" + count + ")");
                    }
                    count++;
                    driver.findElement(By.id("email")).clear();
                    driver.findElement(By.id("email")).sendKeys(addr);
                    driver.findElement(By.id("company")).clear();
                    driver.findElement(By.id("company")).sendKeys(acceptor.getCompany(m));
                    driver.findElement(By.id("_button_save")).click();
                    Sleep.sleepTwoSeconds();
                    logger.info("Looks like this succeeded!");
                }
            }
        }
    }

    /**
     * Helper
     */

    private void createAddressbook(String foldername, Acceptor acceptor) {
        @SuppressWarnings("unused")
        Logger logger = LOGGER_createAddressbook;
        //
        goToWebmailLoginPage();
        //
        loginToWebmail();
        //
        openContactsMenu();
        //
        makeSureFolderDoesNotExist(foldername);
        //
        addNewFolder(foldername);
        //
        openContactsMenu();
        //
        makeSureFolderDoesExist(foldername);
        //
        enterFolder(foldername);
        //
        enterRelevantContacts(acceptor);
        //
        logoutFromWebmail();
    }

    /**
     * Helper
     */

    @SuppressWarnings("unused")
    private String closeAlertAndGetItsText() {
        try {
            Alert alert = driver.switchTo().alert();
            if (acceptNextAlert) {
                alert.accept();
            } else {
                alert.dismiss();
            }
            return alert.getText();
        } finally {
            acceptNextAlert = true;
        }
    }

    /**
     * Proper action: Adding all committee member. The "Acceptor" returns true if a
     * given "ClubMember" is detected as being a "committee member"
     */

    public void addSubsetCommittee() {
        Acceptor acceptor = new Acceptor() {
            public boolean accept(ClubMember x) {
                assert x != null;
                return x.isCommittee();
            }

            public String getCompany(ClubMember x) {
                assert x != null;
                return "Comit ACL";
            }
        };
        createAddressbook("### Subset: Comit ###", acceptor);
    }

    /**
     * Proper action: Adding all the black belters. The "Acceptor" returns true if a
     * given "ClubMember" is detected as being a "black belter"
     */

    public void addSubsetCeinturesNoires() {
        Acceptor acceptor = new Acceptor() {
            public boolean accept(ClubMember x) {
                assert x != null;
                return x.isCeintureNoire();
            }

            public String getCompany(ClubMember x) {
                assert x != null;
                return "Ceinture Noire: " + ((x.level == null) ? "?" : x.level);
            }
        };
        createAddressbook("### Subset: Ceintures Noires ###", acceptor);
    }

    /**
     * Proper action: Adding all the children. The "Acceptor" returns true if a
     * given "ClubMember" is detected as being a "child"
     */

    public void addSubsetEnfants() {
        Acceptor acceptor = new Acceptor() {
            public boolean accept(ClubMember x) {
                assert x != null;
                return x.isEnfant();
            }

            public String getCompany(ClubMember x) {
                assert x != null;
                return "Enfant g de: " + x.getAge() + " ans";
            }
        };
        createAddressbook("### Subset: Enfants ###", acceptor);
    }

    /**
     * Proper action: Adding all the adults. The "Acceptor" returns true if a
     * given "ClubMember" is detected as being an "adult"
     */

    public void addSubsetAdultes() {
        Acceptor acceptor = new Acceptor() {
            public boolean accept(ClubMember x) {
                assert x != null;
                return x.isAdulte();
            }

            public String getCompany(ClubMember x) {
                assert x != null;
                return "Adulte g de: " + x.getAge() + " ans";
            }
        };
        createAddressbook("### Subset: Adultes ###", acceptor);
    }

    /**
     * Proper action: Adding everybody
     */

    public void addSubsetTousLesMembres() {
        Acceptor acceptor = new Acceptor() {
            public boolean accept(ClubMember x) {
                assert x != null;
                return true;
            }

            public String getCompany(ClubMember x) {
                assert x != null;
                return "Membre ACL";
            }
        };
        createAddressbook("### Tous les Membres du Club ###", acceptor);
    }

    /**
     * Main
     */

    private enum Action {
        addSubsetCommittee, addSubsetCeinturesNoires, addSubsetEnfants, addSubsetAdultes, addSubsetTousLesMembres
    }

    private static SortedSet<Action> actionSet = new TreeSet<Action>();

    static {
        actionSet.add(Action.addSubsetCommittee);
        actionSet.add(Action.addSubsetCeinturesNoires);
        actionSet.add(Action.addSubsetEnfants);
        actionSet.add(Action.addSubsetAdultes);
        actionSet.add(Action.addSubsetTousLesMembres);
    }

    @SuppressWarnings("unchecked")
    public static void main(String[] argv) {
        Logger logger = LoggerFactory.getLogger(CLASS + ".main");
        //
        // Fire up logging through "SLF4J" over "Logback"
        // This looks like a zero-effect statement but it's actually an initialization
        //
        new LogbackStarter(InjectIntoWebmailAddressBook.class);
        //
        // The resource "config.xml" in the package in which "Hook" resides is read and a directly
        // usable structure is returned.
        //
        PropertiesReader config = new PropertiesReader(name.gluino.webmailfeed.data.Hook.class, "config.xml");
        //
        // Hoover up all the member information and put it into a Set<Member>
        //
        Set<ClubMember> allMembers;
        try {
            allMembers = (new MemberListSlurper(config.getFqInputResource(), config.getCommitteEmails())).members;
        } catch (Exception exe) {
            throw new IllegalStateException(exe);
        }
        //
        // Run interaction
        //
        for (Action ax : actionSet) {

            InjectIntoWebmailAddressBook inj = null;
            try {
                inj = new InjectIntoWebmailAddressBook(config, allMembers);
                switch (ax) {
                case addSubsetCommittee:
                    inj.addSubsetCommittee();
                    break;
                case addSubsetCeinturesNoires:
                    inj.addSubsetCeinturesNoires();
                    break;
                case addSubsetEnfants:
                    inj.addSubsetEnfants();
                    break;
                case addSubsetAdultes:
                    inj.addSubsetAdultes();
                    break;
                case addSubsetTousLesMembres:
                    inj.addSubsetTousLesMembres();
                    break;
                default:
                    // NOP
                }
            } catch (Exception exe) {
                logger.error("While running", exe);
                System.exit(1);
            } finally {
                if (inj != null) {
                    inj.tearDown();
                }
            }
        }
    }
}