/* * � Copyright IBM Corp. 2013 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * implied. See the License for the specific language governing * permissions and limitations under the License. */ /* * Author: Maire Kehoe (mkehoe@ie.ibm.com) * Date: 12 Apr 2011 * DojoTypeTest.java */ package com.ibm.xsp.test.framework.render; import java.lang.reflect.Method; import java.util.Map; import javax.faces.component.UIComponent; import javax.faces.component.UIViewRoot; import javax.faces.context.FacesContext; import javax.faces.el.ValueBinding; import com.ibm.commons.util.StringUtil; import com.ibm.xsp.dojo.DojoAttribute; import com.ibm.xsp.dojo.FacesDojoComponent; import com.ibm.xsp.library.LibraryServiceLoader; import com.ibm.xsp.page.translator.JavaUtil; import com.ibm.xsp.registry.FacesComponentDefinition; import com.ibm.xsp.registry.FacesSharableRegistry; import com.ibm.xsp.test.framework.AbstractXspTest; import com.ibm.xsp.test.framework.ConfigUtil; import com.ibm.xsp.test.framework.TestProject; import com.ibm.xsp.test.framework.XspRenderUtil; import com.ibm.xsp.test.framework.XspTestUtil; import com.ibm.xsp.test.framework.setup.SkipFileContent; import com.ibm.xsp.util.TypedUtil; /** * * @author Maire Kehoe (mkehoe@ie.ibm.com) */ public class DojoTypeTest extends AbstractXspTest { @Override public String getDescription() { return "that the controls in the registry with a dojoType property support it correctly"; } public void testDojoType() throws Exception { // create an empty view FacesContext context = TestProject.createFacesContext(this); ResponseBuffer.initContext(context); UIViewRoot root = TestProject.loadEmptyPage(this, context); UIComponent p = XspRenderUtil.createContainerParagraph(root); String fails = ""; FacesSharableRegistry reg = TestProject.createRegistry(this); boolean isShouldLoadXspClientDojoUI = isShouldLoadXspClientDojoUI(); Object[][] renderDefaultDojoTypes = getRenderDefaultDojoTypes(); for (FacesComponentDefinition def : TestProject.getLibComponents(reg, this)) { if( !def.isTag() || !def.isProperty("dojoType") ){ continue; } final String expectedRenderDefaultDojoType = getExpectedDojoType(renderDefaultDojoTypes, def); // create a control instance UIComponent instance; try{ instance = (UIComponent) def.getJavaClass().newInstance(); }catch(Exception e){ fails += def.getFile().getFilePath()+" "+ XspTestUtil.getShortClass(def.getJavaClass()) +" Exception creating instance "+e+"\n"; continue; } if ( !(instance instanceof FacesDojoComponent) ){ fails += def.getFile().getFilePath()+" " +XspTestUtil.getShortClass(def.getJavaClass()) + " Has dojoType property but not a " + XspTestUtil.getShortClass(FacesDojoComponent.class) + ".\n"; // inspect the getter try{ def.getJavaClass().getMethod("getDojoType"); }catch(Exception e ){ fails += def.getFile().getFilePath()+" " +XspTestUtil.getShortClass(def.getJavaClass()) +" No getDojoType() method.\n"; } } String existingGetterDojoType = (String) instance.getAttributes().get("dojoType"); if( null != existingGetterDojoType ){ fails += def.getFile().getFilePath()+" " +XspTestUtil.getShortClass(def.getJavaClass()) +" Has getDojoType() default: " + existingGetterDojoType+"\n"; } // render the un-modified blank control instance XspRenderUtil.resetContainerChild(root, p, instance); XspRenderUtil.initControl(this, instance, context); // before encode, pre-process ids: String page; try{ page = ResponseBuffer.encode(p, context); }catch(Exception e){ e.printStackTrace(); fails += def.getFile().getFilePath()+" " +XspTestUtil.getShortClass(def.getJavaClass()) + " Problem rendering page: "+e+"\n"; ResponseBuffer.clear(context); continue; } String existingRenderDojoType = XspRenderUtil.findAttribute(page, "dojoType"); if( null == expectedRenderDefaultDojoType ){ if( null != existingRenderDojoType ){ fails += def.getFile().getFilePath() +" "+XspTestUtil.getShortClass(def.getJavaClass()) + " Outputs dojoType= when not explicitly set: " + existingRenderDojoType + "\n"; } }else{ if( ! StringUtil.equals(expectedRenderDefaultDojoType, existingRenderDojoType) ){ fails += def.getFile().getFilePath() +" "+XspTestUtil.getShortClass(def.getJavaClass()) + " Wrong dojoType= when not explicitly set, was: " + existingRenderDojoType + ", expected: " +expectedRenderDefaultDojoType+"\n"; } } if( null != existingGetterDojoType ){ if( !StringUtil.equals(existingGetterDojoType, existingRenderDojoType) ){ fails += def.getFile().getFilePath()+" " + XspTestUtil.getShortClass(def.getJavaClass()) + " dojoType= not same as getDojoType() when not explicitly set: " + "dojoType= " + existingRenderDojoType + " getDojoType():" + existingGetterDojoType + " \n"; } } boolean outputtedDojoType = null != existingRenderDojoType; boolean root_dojoParseOnLoad = ((Boolean)TypedUtil.getAttributes(root).get("dojoParseOnLoad")).booleanValue(); if( !StringUtil.equals(outputtedDojoType, root_dojoParseOnLoad) ){ fails += def.getFile().getFilePath()+" " +XspTestUtil.getShortClass(def.getJavaClass()) + " rootEx.isDojoParseOnLoad not as expected when render un-modified blank control: " + root_dojoParseOnLoad + "\n"; } boolean root_dojoTheme = ((Boolean)TypedUtil.getAttributes(root).get("dojoTheme")).booleanValue(); if( !StringUtil.equals(outputtedDojoType, root_dojoTheme) ){ fails += def.getFile().getFilePath()+" " +XspTestUtil.getShortClass(def.getJavaClass()) + " rootEx.isDojoTheme not as expected when render un-modified blank control: " + root_dojoTheme + "\n"; } boolean root_loadXspClientDojoUI = ((Boolean)TypedUtil.getAttributes(root).get("loadXspClientDojoUI")).booleanValue(); if( isShouldLoadXspClientDojoUI ){ if( !StringUtil.equals(outputtedDojoType, root_loadXspClientDojoUI) ){ fails += def.getFile().getFilePath()+" " +XspTestUtil.getShortClass(def.getJavaClass()) + " rootEx.isLoadXspClientDojoUI not as expected when render un-modified blank control: " + root_loadXspClientDojoUI + "\n"; } }else{ // !isCanLoadXspClientDojoUI if( root_loadXspClientDojoUI ){ fails += def.getFile().getFilePath()+" " +XspTestUtil.getShortClass(def.getJavaClass()) + " rootEx.isLoadXspClientDojoUI is true when render un-modified blank control," +" expected false since not testing an XPages runtime core library.\n"; } } String existingRenderId = XspRenderUtil.findAttribute(page, "id"); if( outputtedDojoType ){ if( null == existingRenderId ){ fails += def.getFile().getFilePath()+" " +XspTestUtil.getShortClass(def.getJavaClass()) + " Did not output an id= even though a dojoType was output" + "\n"; } }else{ // !outputtedDojoType if( null != existingRenderId ){ fails += def.getFile().getFilePath()+" " +XspTestUtil.getShortClass(def.getJavaClass()) + " Output an id= when !HtmlUtil.isUserId(String)" + " and dojoType not present" + "\n"; } } // set a dojoType and render that String testDojoType = "com.example.test.SomeDijit"; TypedUtil.getAttributes(instance).put("dojoType", testDojoType); // before encode, pre-process ids: if (instance.getId() == null) instance.setId(root.createUniqueId()); page = ResponseBuffer.encode(p, context); String actualRenderDojoType = XspRenderUtil.findAttribute(page, "dojoType"); if( ! StringUtil.equals(testDojoType, actualRenderDojoType) ){ fails += def.getFile().getFilePath()+" " +XspTestUtil.getShortClass(def.getJavaClass()) + " Output wrong dojoType= when setDojoType called: " + actualRenderDojoType + ", expected " + testDojoType+"\n"; } outputtedDojoType = null != actualRenderDojoType; root_dojoParseOnLoad = ((Boolean)TypedUtil.getAttributes(root).get("dojoParseOnLoad")).booleanValue(); if( ! StringUtil.equals(true, root_dojoParseOnLoad) ){ fails += def.getFile().getFilePath()+" " +XspTestUtil.getShortClass(def.getJavaClass()) + " rootEx.isDojoParseOnLoad not as expected when render dojoType control: " + root_dojoParseOnLoad + "\n"; } boolean expectDojoTheme = null != existingRenderDojoType; // if the control uses dojo by default root_dojoTheme = ((Boolean)TypedUtil.getAttributes(root).get("dojoTheme")).booleanValue(); if( !StringUtil.equals(expectDojoTheme, root_dojoTheme) ){ fails += def.getFile().getFilePath()+" " +XspTestUtil.getShortClass(def.getJavaClass()) + " rootEx.isDojoTheme not as expected when render dojoType control: " + root_dojoTheme + "\n"; } root_loadXspClientDojoUI = ((Boolean)TypedUtil.getAttributes(root).get("loadXspClientDojoUI")).booleanValue(); if( isShouldLoadXspClientDojoUI ){ if( ! StringUtil.equals(true, root_loadXspClientDojoUI) ){ fails += def.getFile().getFilePath()+" " +XspTestUtil.getShortClass(def.getJavaClass()) + " rootEx.isLoadXspClientDojoUI not as expected when render dojoType control: " + root_loadXspClientDojoUI + "\n"; } }else{ // !isCanLoadXspClientDojoUI if( root_loadXspClientDojoUI ){ fails += def.getFile().getFilePath()+" " +XspTestUtil.getShortClass(def.getJavaClass()) + " rootEx.isLoadXspClientDojoUI is true when render dojoTypeControl," +" expected false since not testing an XPages runtime core library.\n"; } } String actualRenderId = XspRenderUtil.findAttribute(page, "id"); if( null == actualRenderId ){ fails += def.getFile().getFilePath()+" " +XspTestUtil.getShortClass(def.getJavaClass()) + " Did not force an id= when a dojoType was set" + "\n"; } // reset the instance instance = (UIComponent) def.getJavaClass().newInstance(); // set some dojoAttributes and render those Method method = null; try{ method = instance.getClass().getMethod("addDojoAttribute", DojoAttribute.class); }catch(Exception e){ fails += def.getFile().getFilePath()+" " +XspTestUtil.getShortClass(def.getJavaClass()) + " Method not found: addDojoAttribute\n"; } if( null != method ){ DojoAttribute[] dojoAttrs = new DojoAttribute[]{ new DojoAttribute("aaaName", "aaaValue"), new DojoAttribute("bbbName", "bbbValue"), }; for (DojoAttribute dojoAttr : dojoAttrs) { method.invoke(instance, dojoAttr); } XspRenderUtil.resetContainerChild(root, p, instance); XspRenderUtil.initControl(this, instance, context); page = ResponseBuffer.encode(p, context); // when dojoType not present, dojo attributes shouldn't be present either for (DojoAttribute dojoAttr : dojoAttrs) { String name = dojoAttr.getName(); String actualDojoAttrValue = XspRenderUtil.findAttribute(page, name); if( null == existingRenderDojoType ){ if( null != actualDojoAttrValue ){ fails += def.getFile().getFilePath()+" " +XspTestUtil.getShortClass(def.getJavaClass()) + " DojoAttribute was output when dojoType absent\n"; } }else{ if( null == actualDojoAttrValue ){ fails += def.getFile().getFilePath()+" " +XspTestUtil.getShortClass(def.getJavaClass()) + " DojoAttribute not output when default dojoType\n"; } } } // set a dojoType and verify the dojoAttributes are output TypedUtil.getAttributes(instance).put("dojoType", testDojoType); XspRenderUtil.resetContainerChild(root, p, instance); XspRenderUtil.initControl(this, instance, context); page = ResponseBuffer.encode(p, context); for (DojoAttribute dojoAttr : dojoAttrs) { String name = dojoAttr.getName(); String value = dojoAttr.getValue(); String actualDojoAttrValue = XspRenderUtil.findAttribute(page, name); if( !StringUtil.equals(value, actualDojoAttrValue) ){ if( null == existingRenderDojoType ){ fails += def.getFile().getFilePath()+" " +XspTestUtil.getShortClass(def.getJavaClass()) + " DojoAttribute not output as expected: " +actualDojoAttrValue+"\n"; }else{ fails += def.getFile().getFilePath()+" " +XspTestUtil.getShortClass(def.getJavaClass()) + " DojoAttribute not output as expected when custom dojoType: " +actualDojoAttrValue+"\n"; } } } } // reset the instance instance = (UIComponent) def.getJavaClass().newInstance(); // set a userId and verify the dojoType is output and the id only appears once. String testId = "myId"; // (note, the "view:" part of the clientID is only present for UIViewRootEx2.getClientId) String rootClientId = UIViewRoot.class.equals(root.getClass())? "" : "view:"; String testClientId = rootClientId+"_id1:"+testId; TypedUtil.getAttributes(instance).put("id", testId); XspRenderUtil.resetContainerChild(root, p, instance); XspRenderUtil.initControl(this, instance, context); page = ResponseBuffer.encode(p, context); actualRenderId = XspRenderUtil.findAttribute(page, "id"); if( !StringUtil.equals(testClientId, actualRenderId) ){ fails += def.getFile().getFilePath()+" " +XspTestUtil.getShortClass(def.getJavaClass()) + " id not output as expected: " +actualRenderId+"\n"; } actualRenderDojoType = XspRenderUtil.findAttribute(page, "dojoType"); if( null == expectedRenderDefaultDojoType ){ if( null != actualRenderDojoType ){ fails += def.getFile().getFilePath() +" "+XspTestUtil.getShortClass(def.getJavaClass()) + " Outputs dojoType= when not explicitly set & userId is set: " + actualRenderDojoType + "\n"; } }else{ if( ! StringUtil.equals(expectedRenderDefaultDojoType, actualRenderDojoType) ){ fails += def.getFile().getFilePath() +" "+XspTestUtil.getShortClass(def.getJavaClass()) + " Wrong dojoType= when not explicitly set & userId is set, was: " + actualRenderDojoType + ", expected: " + expectedRenderDefaultDojoType+"\n"; } } TypedUtil.getAttributes(instance).put("dojoType", testDojoType); XspRenderUtil.resetContainerChild(root, p, instance); XspRenderUtil.initControl(this, instance, context); page = ResponseBuffer.encode(p, context); if( !StringUtil.equals(testClientId, actualRenderId) ){ fails += def.getFile().getFilePath()+" " +XspTestUtil.getShortClass(def.getJavaClass()) + " id not output as expected when dojoType present: " +actualRenderId+"\n"; } actualRenderDojoType = XspRenderUtil.findAttribute(page, "dojoType"); if( !StringUtil.equals(testDojoType, actualRenderDojoType) ){ fails += def.getFile().getFilePath()+" " +XspTestUtil.getShortClass(def.getJavaClass()) + " dojoType= not as expected when userId set: " + actualRenderDojoType+", expected " + testDojoType+ "\n"; } // reset the instance instance = (UIComponent) def.getJavaClass().newInstance(); // verify that getDojoType is only computed once. Map<String, Object> viewScope = getViewMap(root); DojoTypeInvokeCounter counter = new DojoTypeInvokeCounter(testDojoType); viewScope.put("counter", counter); String expr = "#{viewScope.counter.dojoType}"; ValueBinding vb = TestProject.getApplication(this).createValueBinding(expr); instance.setValueBinding("dojoType", vb); XspRenderUtil.resetContainerChild(root, p, instance); XspRenderUtil.initControl(this, instance, context); page = ResponseBuffer.encode(p, context); int invokeCount = counter.count; actualRenderDojoType = XspRenderUtil.findAttribute(page, "dojoType"); if( !StringUtil.equals(testDojoType, actualRenderDojoType) ){ fails += def.getFile().getFilePath()+" " +XspTestUtil.getShortClass(def.getJavaClass()) + " dojoType= not as expected when compute dojoType: " +actualRenderDojoType +", expected " +testDojoType+"\n"; } if( 1 != invokeCount ){ fails += def.getFile().getFilePath()+" " +XspTestUtil.getShortClass(def.getJavaClass()) + " Computed dojoType, expected compute once, was " +invokeCount+" times\n"; } } for (Object[] classToDojoType : renderDefaultDojoTypes) { if( null != classToDojoType ){ fails += "Unused expected render default dojoType: {" + XspTestUtil.getShortClass((Class<?>)classToDojoType[0]) + ".class, " + JavaUtil.toJavaString((String)classToDojoType[1]) +"} \n"; } } fails = XspTestUtil.removeMultilineFailSkips(fails, SkipFileContent.concatSkips(getSkipFails(), this, "testDojoType")); if( fails.length() > 0 ){ fail( XspTestUtil.getMultilineFailMessage(fails) ); } } /** * new Object[][]{ * new Object[]{ controlClass1, expectedDojoTypeString1}, * new Object[]{ controlClass2, expectedDojoTypeString2}, * }, * @return */ protected Object[][] getRenderDefaultDojoTypes() { return new Object[0][]; } private String getExpectedDojoType(Object[][] renderDefaultDojoTypes, FacesComponentDefinition def){ int foundIndex = -1; Class<?> defClass = def.getJavaClass(); int i = 0; for (Object[] classToDojoType : renderDefaultDojoTypes) { if( null != classToDojoType ){ Class<?> compClass = (Class<?>) classToDojoType[0]; if( compClass.equals(defClass) ){ foundIndex = i; break; } } i++; } if( -1 == foundIndex ){ return null; } Object[] classToDojoType = renderDefaultDojoTypes[foundIndex]; renderDefaultDojoTypes[foundIndex] = null; String dojoType = (String) classToDojoType[1]; if( null == dojoType ){ throw new RuntimeException(); } return dojoType; } /** * Available to override in subclasses * @return */ private boolean isShouldLoadXspClientDojoUI() { String libraryId = ConfigUtil.getTargetLibrary(this); if( null == libraryId ){ return false; } // if it's one of ..xsp.core, ..xsp.extsn, etc - the libraries // in the XPages core runtime. Not an extension to the runtime. return LibraryServiceLoader.isXPagesRuntimeLibrary(libraryId); } @SuppressWarnings("unchecked") private Map<String, Object> getViewMap(UIViewRoot root) { return root.getViewMap(); } protected String[] getSkipFails() { return StringUtil.EMPTY_STRING_ARRAY; } public static class DojoTypeInvokeCounter{ public int count = 0; private String dojoType; public DojoTypeInvokeCounter(String dojoType) { super(); this.dojoType = dojoType; } public String getDojoType() { count++; return dojoType; } } }