001 /** 002 * Copyright 2004-2013 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package org.kuali.hr.test; 017 018 import java.io.File; 019 import java.util.ArrayList; 020 import java.util.Calendar; 021 import java.util.List; 022 023 import com.gargoylesoftware.htmlunit.BrowserVersion; 024 import com.gargoylesoftware.htmlunit.WebClient; 025 import com.gargoylesoftware.htmlunit.html.*; 026 import org.apache.log4j.Logger; 027 import org.junit.Assert; 028 import org.kuali.hr.time.test.HtmlUnitUtil; 029 import org.kuali.hr.time.test.TkTestConstants; 030 import org.kuali.hr.time.util.*; 031 import org.kuali.rice.core.api.config.property.Config; 032 import org.kuali.rice.core.api.config.property.ConfigContext; 033 import org.kuali.rice.core.api.lifecycle.BaseLifecycle; 034 import org.kuali.rice.core.api.lifecycle.Lifecycle; 035 import org.kuali.rice.core.impl.services.CoreImplServiceLocator; 036 import org.kuali.rice.krad.UserSession; 037 import org.kuali.rice.krad.service.KRADServiceLocatorInternal; 038 import org.kuali.rice.krad.util.GlobalVariables; 039 import org.kuali.rice.krad.util.MessageMap; 040 import org.kuali.rice.test.RiceInternalSuiteDataTestCase; 041 import org.kuali.rice.test.TransactionalLifecycle; 042 import org.kuali.rice.test.lifecycles.JettyServerLifecycle; 043 import org.kuali.rice.test.lifecycles.JettyServerLifecycle.ConfigMode; 044 import org.kuali.rice.test.lifecycles.KPMEXmlDataLoaderLifecycle; 045 import org.springframework.cache.CacheManager; 046 import org.springframework.mock.web.MockHttpServletRequest; 047 048 /** 049 * Default test base for a full KPME unit test. 050 */ 051 public abstract class KPMETestCase extends RiceInternalSuiteDataTestCase { 052 053 private static final String FILE_PREFIX = System.getProperty("user.dir") + "/src/main/config/workflow/"; 054 055 private static final String RELATIVE_WEBAPP_ROOT = "/src/main/webapp"; 056 057 private TransactionalLifecycle transactionalLifecycle; 058 private WebClient webClient; 059 060 @Override 061 protected String getModuleName() { 062 return "kpme"; 063 } 064 065 @Override 066 public void setUp() throws Exception { 067 if (System.getProperty("basedir") == null) { 068 System.setProperty("basedir", System.getProperty("user.dir") + "/"); 069 } 070 071 super.setUp(); 072 073 GlobalVariables.setMessageMap(new MessageMap()); 074 075 final boolean needsSpring = false; 076 if (needsSpring) { 077 transactionalLifecycle = new TransactionalLifecycle(); 078 transactionalLifecycle.setTransactionManager(KRADServiceLocatorInternal.getTransactionManager()); 079 transactionalLifecycle.start(); 080 } 081 082 new ClearDatabaseLifecycle().start(); 083 084 new LoadDatabaseDataLifeCycle(this.getClass()).start(); 085 086 //lets try to create a user session 087 GlobalVariables.setUserSession(new UserSession("admin")); 088 TKContext.setHttpServletRequest(new MockHttpServletRequest()); 089 setWebClient(new WebClient(BrowserVersion.FIREFOX_10)); 090 getWebClient().setJavaScriptEnabled(true); 091 getWebClient().setTimeout(0); 092 } 093 094 @Override 095 public void tearDown() throws Exception { 096 // runs custom SQL at the end of each test. 097 // useful for difficult to reset test additions, not handled by 098 // our ClearDatabaseLifecycle. 099 TKUser.clearTargetUser(); 100 getWebClient().closeAllWindows(); 101 new DatabaseCleanupDataLifecycle(this.getClass()).start(); 102 103 final boolean needsSpring = true; 104 if (needsSpring) { 105 if ( (transactionalLifecycle != null) && (transactionalLifecycle.isStarted()) ) { 106 transactionalLifecycle.stop(); 107 } 108 } 109 110 GlobalVariables.setMessageMap(new MessageMap()); 111 112 super.tearDown(); 113 } 114 115 @Override 116 protected List<Lifecycle> getPerTestLifecycles() { 117 List<Lifecycle> lifecycles = super.getPerTestLifecycles(); 118 lifecycles.add(new ClearCacheLifecycle()); 119 return lifecycles; 120 } 121 122 @Override 123 protected List<Lifecycle> getSuiteLifecycles() { 124 List<Lifecycle> lifecycles = super.getPerTestLifecycles(); 125 lifecycles.add(new Lifecycle() { 126 boolean started = false; 127 128 public boolean isStarted() { 129 return this.started; 130 } 131 132 public void start() throws Exception { 133 setModuleName(getModuleName()); 134 setBaseDirSystemProperty(getModuleName()); 135 Config config = getTestHarnessConfig(); 136 ConfigContext.init(config); 137 this.started = true; 138 } 139 140 public void stop() throws Exception { 141 this.started = false; 142 } 143 }); 144 /** 145 * Loads the TestHarnessSpringBeans.xml file which obtains connections to the DB for us 146 */ 147 /*lifecycles.add(getTestHarnessSpringResourceLoader());*/ 148 149 /** 150 * Establishes the TestHarnessServiceLocator so that it has a reference to the Spring context 151 * created from TestHarnessSpringBeans.xml 152 */ 153 /*lifecycles.add(new BaseLifecycle() { 154 @Override 155 public void start() throws Exception { 156 TestHarnessServiceLocator.setContext(getTestHarnessSpringResourceLoader().getContext()); 157 super.start(); 158 } 159 });*/ 160 161 lifecycles.add(new Lifecycle() { 162 private JettyServerLifecycle jettyServerLifecycle; 163 164 public boolean isStarted() { 165 return jettyServerLifecycle.isStarted(); 166 } 167 168 public void start() throws Exception { 169 System.setProperty("web.bootstrap.spring.file", "classpath:TestHarnessSpringBeans.xml"); 170 jettyServerLifecycle = new JettyServerLifecycle(HtmlUnitUtil.getPort(), HtmlUnitUtil.getContext(), RELATIVE_WEBAPP_ROOT); 171 jettyServerLifecycle.setConfigMode(ConfigMode.OVERRIDE); 172 jettyServerLifecycle.start(); 173 } 174 175 public void stop() throws Exception { 176 this.jettyServerLifecycle.stop(); 177 } 178 }); 179 180 ClearDatabaseLifecycle clearDatabaseLifecycle = new ClearDatabaseLifecycle(); 181 clearDatabaseLifecycle.getAlternativeTablesToClear().add("KREW_RULE_T"); 182 clearDatabaseLifecycle.getAlternativeTablesToClear().add("KREW_RULE_RSP_T"); 183 clearDatabaseLifecycle.getAlternativeTablesToClear().add("KREW_DLGN_RSP_T"); 184 clearDatabaseLifecycle.getAlternativeTablesToClear().add("KREW_RULE_ATTR_T"); 185 clearDatabaseLifecycle.getAlternativeTablesToClear().add("KREW_RULE_TMPL_T"); 186 clearDatabaseLifecycle.getAlternativeTablesToClear().add("KREW_DOC_TYP_T"); 187 lifecycles.add(clearDatabaseLifecycle); 188 189 File[] files = new File(FILE_PREFIX).listFiles(); 190 if (files != null) { 191 for (File file : files) { 192 if (file.getName().endsWith(".xml")) { 193 lifecycles.add(new KPMEXmlDataLoaderLifecycle(FILE_PREFIX + file.getName())); 194 } 195 } 196 } 197 return lifecycles; 198 } 199 200 protected final void setFieldValue(HtmlPage page, String fieldId, String fieldValue) { 201 HtmlElement element = page.getHtmlElementById(fieldId); 202 Assert.assertTrue("element " + fieldId + " is null, page: " + page.asText(), element != null); 203 204 if (element instanceof HtmlTextInput) { 205 HtmlTextInput textField = (HtmlTextInput) element; 206 textField.setValueAttribute(fieldValue); 207 } else if (element instanceof HtmlTextArea) { 208 HtmlTextArea textAreaField = (HtmlTextArea) element; 209 textAreaField.setText(fieldValue); 210 } else if (element instanceof HtmlHiddenInput) { 211 HtmlHiddenInput hiddenField = (HtmlHiddenInput) element; 212 hiddenField.setValueAttribute(fieldValue); 213 } else if (element instanceof HtmlSelect) { 214 HtmlSelect selectField = (HtmlSelect) element; 215 try { 216 selectField.setSelectedAttribute(fieldValue, true); 217 } catch (IllegalArgumentException e) { 218 Assert.fail("select element [" + element.asText() + "] " + e.getMessage()); 219 } 220 } else if (element instanceof HtmlCheckBoxInput) { 221 HtmlCheckBoxInput checkboxField = (HtmlCheckBoxInput) element; 222 if (fieldValue.equals("on")) { 223 checkboxField.setChecked(true); 224 } else if (fieldValue.equals("off")) { 225 checkboxField.setChecked(false); 226 } else { 227 Assert.assertTrue("Invalid checkbox value", false); 228 } 229 } else if (element instanceof HtmlFileInput) { 230 HtmlFileInput fileInputField = (HtmlFileInput) element; 231 fileInputField.setValueAttribute(fieldValue); 232 } else if (element instanceof HtmlRadioButtonInput) { 233 HtmlRadioButtonInput radioButton = (HtmlRadioButtonInput) element; 234 if (fieldValue.equals("on")) { 235 radioButton.setChecked(true); 236 } else if (fieldValue.equals("off")) { 237 radioButton.setChecked(false); 238 } 239 } else { 240 Assert.fail("Unknown control field: " + fieldId); 241 } 242 } 243 244 public void futureEffectiveDateValidation(String baseUrl) throws Exception { 245 HtmlPage page = HtmlUnitUtil.gotoPageAndLogin(getWebClient(), baseUrl); 246 Assert.assertNotNull(page); 247 248 HtmlForm form = page.getFormByName("KualiForm"); 249 Assert.assertNotNull("Search form was missing from page.", form); 250 // use past dates 251 setFieldValue(page, "document.newMaintainableObject.effectiveDate", "04/01/2011"); 252 HtmlInput input = HtmlUnitUtil.getInputContainingText(form, "methodToCall.route"); 253 Assert.assertNotNull("Could not locate submit button", input); 254 page = ((HtmlButtonInput)page.getElementByName("methodToCall.route")).click(); 255 Assert.assertTrue("page text does not contain:\n" + TkTestConstants.EFFECTIVE_DATE_ERROR, page.asText().contains(TkTestConstants.EFFECTIVE_DATE_ERROR)); 256 Calendar futureDate = Calendar.getInstance(); 257 futureDate.add(java.util.Calendar.YEAR, 2);// 2 years in the future 258 String futureDateString = "01/01/" + Integer.toString(futureDate.get(Calendar.YEAR)); 259 260 // use dates 2 years in the future 261 setFieldValue(page, "document.newMaintainableObject.effectiveDate", futureDateString); 262 page = ((HtmlButtonInput)page.getElementByName("methodToCall.route")).click(); 263 Assert.assertTrue("page text does not contain:\n" + TkTestConstants.EFFECTIVE_DATE_ERROR, page.asText().contains(TkTestConstants.EFFECTIVE_DATE_ERROR)); 264 Calendar validDate = Calendar.getInstance(); 265 validDate.add(java.util.Calendar.MONTH, 5); // 5 month in the future 266 String validDateString = Integer.toString(validDate.get(Calendar.MONTH)) + '/' + Integer.toString(validDate.get(Calendar.DAY_OF_MONTH)) 267 + '/' + Integer.toString(validDate.get(Calendar.YEAR)); 268 setFieldValue(page, "document.newMaintainableObject.effectiveDate", validDateString); 269 page = ((HtmlElement)page.getElementByName("methodToCall.route")).click(); 270 Assert.assertFalse("page text contains:\n" + TkTestConstants.EFFECTIVE_DATE_ERROR, page.asText().contains(TkTestConstants.EFFECTIVE_DATE_ERROR)); 271 } 272 273 public class ClearCacheLifecycle extends BaseLifecycle { 274 private final Logger LOG = Logger.getLogger(ClearCacheLifecycle.class); 275 276 @Override 277 public void start() throws Exception { 278 long startTime = System.currentTimeMillis(); 279 LOG.info("Starting cache flushing"); 280 List<CacheManager> cms = new ArrayList<CacheManager>(CoreImplServiceLocator.getCacheManagerRegistry().getCacheManagers()); 281 for (CacheManager cm : cms) { 282 for (String cacheName : cm.getCacheNames()) { 283 //LOG.info("Clearing cache: " + cacheName); 284 cm.getCache(cacheName).clear(); 285 } 286 } 287 long endTime = System.currentTimeMillis(); 288 LOG.info("Caches cleared in " + (endTime - startTime) + "ms"); 289 } 290 291 @Override 292 public void stop() throws Exception { 293 super.stop(); 294 } 295 296 } 297 298 public WebClient getWebClient() { 299 return this.webClient; 300 } 301 302 public void setWebClient(WebClient webClient) { 303 this.webClient = webClient; 304 } 305 306 }