/*
* JBoss, Home of Professional Open Source
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.seam.example.common.test.selenium;
import java.text.DateFormatSymbols;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.StringTokenizer;
/**
* Selects date using Selenium in calendar provided by framework. Each framework
* is responsible for managing movement in calendar grid
*
* @author kpiwko
*
*/
public enum SeleniumDateSelector
{
RICHFACES
{
@Override
public void setDay(SeamSelenium browser, int day)
{
String locator = "xpath=//td[contains(@class, 'rich-calendar-cell') and not(contains(@class,'rich-calendar-boundary-dates')) and text() ='" + Integer.toString(day) + "']";
browser.waitForElement(locator);
browser.click(locator);
}
@Override
public void setMonth(SeamSelenium browser, int month)
{
String monthLocator = "xpath=//div[@class='rich-calendar-tool-btn' and contains(.,',')]";
StringTokenizer stk = new StringTokenizer(browser.getText(monthLocator), ",");
String calMonth = stk.nextToken().trim();
int steps = monthStepsCount(calMonth, month);
movement(browser, "xpath=//div[@class='rich-calendar-tool-btn' and text()='<']", "xpath=//div[@class='rich-calendar-tool-btn' and text()='>']", steps);
}
@Override
public void setYear(SeamSelenium browser, int year)
{
String yearLocator = "xpath=//div[@class='rich-calendar-tool-btn' and contains(.,',')]";
StringTokenizer stk = new StringTokenizer(browser.getText(yearLocator), ",");
// omit first token
stk.nextToken();
String calYear = stk.nextToken().trim();
int steps = yearStepsCount(calYear, year);
movement(browser, "xpath=//div[@class='rich-calendar-tool-btn' and text()='<<']", "xpath=//div[@class='rich-calendar-tool-btn' and text()='>>'", steps);
}
},
ICEFACES
{
@Override
public void setDay(SeamSelenium browser, int day)
{
String locator = "xpath=//td[@class='iceSelInpDateDay']/a[./span/text()='" + Integer.toString(day) + "']";
browser.waitForElement(locator);
browser.click(locator);
}
@Override
public void setMonth(SeamSelenium browser, int month)
{
String monthLocator = "xpath=//td[@class='iceSelInpDateMonthYear'][2]";
String calMonth = browser.getText(monthLocator).trim();
int steps = monthStepsCount(calMonth, month);
movement(browser, "xpath=//td[@class='iceSelInpDateMonthYear'][1]/a", "xpath=//td[@class='iceSelInpDateMonthYear'][3]/a", steps);
}
@Override
public void setYear(SeamSelenium browser, int year)
{
String yearLocator = "xpath=//td[@class='iceSelInpDateMonthYear'][6]";
String calYear = browser.getText(yearLocator).trim();
int steps = yearStepsCount(calYear, year);
movement(browser, "xpath=//td[@class='iceSelInpDateMonthYear'][5]/a", "xpath=//td[@class='iceSelInpDateMonthYear'][7]/a", steps);
}
/**
* IceFaces forces partial submit, so we must wait for page reload
*/
@Override
protected void click(SeamSelenium browser, String locator)
{
browser.clickAndWait(locator);
}
};
/**
* Selects date using Selenium browser
*
* @param browser
* Selenium browser instance
* @param date
* Date to be selected
*/
public void setDate(SeamSelenium browser, Date date)
{
Calendar cal = Calendar.getInstance();
cal.setTime(date);
setYear(browser, cal.get(Calendar.YEAR));
setMonth(browser, cal.get(Calendar.MONTH));
setDay(browser, cal.get(Calendar.DAY_OF_MONTH));
}
/**
* Selects day in calendar
*
* @param browser
* Selenium browser instance
* @param day
* Integer containing the day to be selected, indexing from 1
*/
protected abstract void setDay(SeamSelenium browser, int day);
/**
* Selects month in calendar
*
* @param browser
* Selenium browser instance
* @param month
* Integer containing the month to be selected, indexing from 1
*/
protected abstract void setMonth(SeamSelenium browser, int month);
/**
* Selects year in calendar
*
* @param browser
* Selenium browser instance
* @param year
* Integer containing the year to be selected
*/
protected abstract void setYear(SeamSelenium browser, int year);
/**
* Determines direction of month in calendar interface
*
* @param calMonth
* Which month is currently shown on calendar
* @param month
* Which month is desired to be set, indexing from 1
* @return Number of steps which must be done in either of direction, where
* sign has meaning:
* <ul>
* <li>- goes to past</li>
* <li>+ goes to future</li>
* </ul>
*/
protected int monthStepsCount(String calMonth, int month)
{
final List<String> months = Arrays.asList((new DateFormatSymbols()).getMonths());
int mindex = months.indexOf(calMonth);
if (mindex == -1)
throw new IllegalArgumentException("Unknown month: " + calMonth + " for locale: " + Locale.getDefault());
return month - (mindex + 1);
}
/**
* Determines direction of year in calendar interface
*
* @param calYear
* Which year is currently shown on calendar
* @param year
* Which month is desired to be set, indexing from 1
* @return Number of steps which must be done in either of direction, where
* sign has meaning:
* <ul>
* <li>- goes to past</li>
* <li>+ goes to future</li>
* </ul>
*/
protected final int yearStepsCount(String calYear, int year)
{
int yindex;
try
{
yindex = Integer.valueOf(calYear);
}
catch (NumberFormatException nfe)
{
throw new IllegalArgumentException("Invalid year: " + calYear, nfe);
}
return year - yindex;
}
/**
* Moves in either backward or forward direction according to step count.
* Uses locator of element for both directions.
*
* @param browser
* Selenium browser instance
* @param backLocator
* Element which moves calendar to past
* @param forwardLocator
* Element which moves calendar to future
* @param steps
* Number of steps to be done, determined by monthStepsCount() or
* yearStepsCount() function
* @see SeleniumDateSelector#monthStepsCount(String, int)
* @see SeleniumDateSelector#yearStepsCount(String, int)
*/
protected void movement(SeamSelenium browser, String backLocator, String forwardLocator, int steps)
{
// going to past
if (steps < 0)
{
for (int i = 0; i > steps; i--)
click(browser, backLocator);
}
// going to future
else
{
for (int i = 0; i < steps; i++)
click(browser, forwardLocator);
}
}
/**
* Clicks on element. Allow differentiate action according to framework, such
* as wait for page to load for IceFaces
*
* @param browser Selenium browser
* @param locator Locator of element to be clicked on
*/
protected void click(SeamSelenium browser, String locator)
{
browser.click(locator);
}
}