/*
* � 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: Brian Gleeson (bgleeson@ie.ibm.com)
* Date: 30 Aug 2011
* InputReadOnlyPropertyTest.java
*/
package com.ibm.xsp.test.framework.registry.annotate;
import java.util.Collection;
import java.util.Map;
import javax.faces.component.UIComponent;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import com.ibm.commons.util.StringUtil;
import com.ibm.xsp.registry.FacesComponentDefinition;
import com.ibm.xsp.registry.FacesDefinition;
import com.ibm.xsp.registry.FacesProperty;
import com.ibm.xsp.registry.FacesSharableRegistry;
import com.ibm.xsp.registry.parse.ParseUtil;
import com.ibm.xsp.test.framework.AbstractXspTest;
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.registry.annotate.PropertiesHaveCategoriesTest.PropertyCategoryAnnotater;
import com.ibm.xsp.test.framework.registry.annotate.SpellCheckTest.DescriptionDisplayNameAnnotater;
import com.ibm.xsp.test.framework.render.RenderIdTest;
import com.ibm.xsp.test.framework.render.ResponseBuffer;
import com.ibm.xsp.test.framework.setup.SkipFileContent;
import com.ibm.xsp.util.TypedUtil;
/**
* @author Brian Gleeson
*
*/
public class InputReadOnlyPropertyTest extends AbstractXspTest {
@Override
public String getDescription() {
return "that input controls should have a readonly renderer, inherited from UIInputEx (not redefined), and (post-8.5.3) should support showReadonlyAsDisabled";
}
public void testInputReadOnlyProperty() throws Exception {
String fails = "";
FacesSharableRegistry reg = TestProject.createRegistryWithAnnotater(
this, new PropertyCategoryAnnotater(),
new DescriptionDisplayNameAnnotater(),
new PropertyTagsAnnotater());
// set up the page to be rendered
FacesContext context = TestProject.createFacesContext(this);
ResponseBuffer.initContext(context);
UIViewRoot root = TestProject.loadEmptyPage(this, context);
UIComponent p = XspRenderUtil.createContainerParagraph(root);
for (FacesComponentDefinition def : TestProject.getLibComponents(reg, this)) {
if( !def.isTag() ){
// Do not try to render abstract controls
continue;
}
// create a control instance
UIComponent instance;
try{
instance = (UIComponent) def.getJavaClass().newInstance();
}catch(Exception e){
// no need to fail here as RenderControlTest
// will already be failing for the issue.
continue;
}
//Setup the control instance in the <p> instance
XspRenderUtil.resetContainerChild(root, p, instance);
XspRenderUtil.initControl(this, instance, context);
//Render the xpage with the control in a paragraph
String page;
try{
page = ResponseBuffer.encode(p, context);
}catch(Exception e){
// no need to fail here as RenderControlTest
// will already be failing for the issue.
ResponseBuffer.clear(context);
continue;
}
//Verify that the page was rendered correctly
if( !page.startsWith("<p>") || page.equals("<p></p>") ){
// no need to fail here as RenderControlTest
// will already be failing for the issue.
continue;
}
//Find rendered input tag on the page if it exists
String renderedInputOnMainTag = RenderIdTest.findRenderedTag(page, "input", true);
boolean actualInputPresent = (null != renderedInputOnMainTag);
//Verify readOnly and showReadonlyAsDisabled
FacesProperty readonlyProp = def.getProperty("readonly");
FacesProperty readOnly2Prop = def.getProperty("readOnly");
FacesProperty showAsDisabledProp = def.getProperty("showReadonlyAsDisabled");
boolean isReadonlyPresent = (null != readonlyProp);
boolean isReadOnly2Present = (null != readOnly2Prop);
boolean isShowAsDisabledPresent = (null != showAsDisabledProp);
//Set the caption and summary values
boolean setReadonly = true;
String altReadonly = "readonly";
boolean setReadOnly2 = true;
boolean setShowAsDisabled = true;
String text = "text" + (int)(Math.random()*1000);
if(actualInputPresent) {
//First check that this input control doesn't redefine the readonly or readOnly properties
if( !def.isTag() ){
continue; // skip non-tags
}
// for all properties (excluding inherited from UIInputEx)
boolean hasReadonly1 = false;
FacesDefinition ancestorDefiningReadonly1 = null;
boolean hasReadonly2 = false;
FacesDefinition ancestorDefiningReadonly2 = null;
for (FacesDefinition ancestor = def; null != ancestor; ancestor = ancestor.getParent()) {
if( "com.ibm.xsp.component.UIInputEx".equals(ancestor.getJavaClass().getName())
|| "com.ibm.xsp.component.UISelectOneEx".equals(ancestor.getJavaClass().getName())
|| "com.ibm.xsp.component.UISelectManyEx".equals(ancestor.getJavaClass().getName()) ){
break;
}
Collection<String> properties = ancestor.getDefinedPropertyNames();
if( !hasReadonly1 && properties.contains("readonly") ){
hasReadonly1 = true;
if( ancestor != def ){
ancestorDefiningReadonly1 = ancestor;
}
}
if( !hasReadonly2 && properties.contains("readOnly") ){
hasReadonly2 = true;
if( ancestor != def ){
ancestorDefiningReadonly2 = ancestor;
}
}
}
if(hasReadonly1){
// the "readonly" property should not be defined by a control or complex type
String definedAt = null == ancestorDefiningReadonly1? ""
: " [readonly property inherited from "
+ ParseUtil.getTagRef(ancestorDefiningReadonly1)+"]";
System.err.println(XspTestUtil.loc(def) + " readonly property is re-defined in input control properties. It should not be."+definedAt);
fails += XspTestUtil.loc(def) + " readonly property is re-defined in control properties. It should not be." +definedAt+"\n";
}else{
// System.out.println(XspTestUtil.loc(def) + " readonly property not defined by control as expected");
}
if(hasReadonly2){
// the "readOnly" property should not be defined by a control or complex type
String definedAt = null == ancestorDefiningReadonly2? ""
: " [readOnly property inherited from "
+ ParseUtil.getTagRef(ancestorDefiningReadonly2)+"]";
System.err.println(XspTestUtil.loc(def) + " readOnly property is re-defined in input control properties. It should not be."+definedAt);
fails += XspTestUtil.loc(def) + " readOnly property is re-defined in input control properties. It should not be." +definedAt+"\n";
}else{
// System.out.println(XspTestUtil.loc(def) + " readOnly property not defined by control as expected");
}
}
if(actualInputPresent && (isReadonlyPresent || isReadOnly2Present) && isShowAsDisabledPresent){
//Set the input as read only with "showReadonlyAsDisabled=false"
{
Map<String, Object> attrsMap = TypedUtil.getAttributes(instance);
attrsMap.put("readonly", setReadonly);
attrsMap.put("readOnly", setReadOnly2);
attrsMap.put("showReadonlyAsDisabled", false);
attrsMap.put("text", text);
//Setup the control instance in the <p> instance
XspRenderUtil.resetContainerChild(root, p, instance);
XspRenderUtil.initControl(this, instance, context);
//Render the xpage with the control in a paragraph
String page2;
try{
page2 = ResponseBuffer.encode(p, context);
}catch(Exception e){
e.printStackTrace();
fails += XspTestUtil.loc(def) + " Problem rendering page: "+e+"\n";
ResponseBuffer.clear(context);
continue;
}
//Verify that the page was rendered correctly
if( !page2.startsWith("<p>") ){
//Page should not start with paragraph tag
fails += XspTestUtil.loc(def)
+ " Wrote attributes to the parent <p> tag: "
+ page2 + "\n";
continue;
}
if( page2.equals("<p></p>") ){
//Page should not contain only paragraph tag
fails += XspTestUtil.loc(def)
+ " No output rendered.\n";
continue;
}
// System.out.println("Input tag present - InputReadOnlyTest with " +XspTestUtil.loc(def)+" rendering: \n"+page2);
//With showAsDisabled set to false, ext-lib read-only inputs dont appear as input tags in the html
String inputTag = RenderIdTest.findRenderedTag(page2, "input", true);
boolean inputTagExists = (null != inputTag);
if(!inputTagExists) {
// System.out.println("showReadonlyAsDisabled=\"true\" successfully disabled the input control as expected");
}else{
fails += XspTestUtil.loc(def) + " Expected no input tag as \"showReadonlyAsDisabled=\"false\". But input tag was found: " + page2 + "\n";
}
}
//Set the input as read only with "showReadonlyAsDisabled=true"
{
Map<String, Object> attrsMap = TypedUtil.getAttributes(instance);
attrsMap.put("showReadonlyAsDisabled", setShowAsDisabled);
//Setup the control instance in the <p> instance
XspRenderUtil.resetContainerChild(root, p, instance);
XspRenderUtil.initControl(this, instance, context);
//Render the xpage with the control in a paragraph
String page3;
try{
page3 = ResponseBuffer.encode(p, context);
}catch(Exception e){
e.printStackTrace();
fails += XspTestUtil.loc(def) + " Problem rendering page: "+e+"\n";
ResponseBuffer.clear(context);
continue;
}
//Verify that the page was rendered correctly
if( !page3.startsWith("<p>") ){
//Page should not start with paragraph tag
fails += XspTestUtil.loc(def)
+ " Wrote attributes to the parent <p> tag: "
+ page3 + "\n";
continue;
}
if( page3.equals("<p></p>") ){
//Page should not contain only paragraph tag
fails += XspTestUtil.loc(def)
+ " No output rendered.\n";
continue;
}
// System.out.println("Input tag present - InputReadOnlyShowAsDisabledTest with " +XspTestUtil.loc(def)+" rendering: \n"+page3);
//With showAsDisabled set to true, readonly=readonly or readOnly=true should appear in input tags
String readonlyValue = RenderIdTest.findAttributeOnATag(page3, "input", "readonly");
String readOnly2Value = RenderIdTest.findAttributeOnATag(page3, "input", "readOnly");
boolean readonlyExists = (null != readonlyValue);
boolean readOnly2Exists = (null != readOnly2Value);
if(readonlyExists) {
boolean isReadonlyCorrect = StringUtil.equals(readonlyValue, "" + setReadonly) || StringUtil.equals(readonlyValue, altReadonly);
if(!isReadonlyCorrect) {
fails += XspTestUtil.loc(def) + " Expected readonly=\""+setReadonly+"\" attribute in input tag. Found " + readonlyValue + "\n";
}else{
// System.out.println("readonly attribute found as expected - " + setReadonly);
}
}else if(readOnly2Exists) {
boolean isReadOnly2Correct = StringUtil.equals(readOnly2Value, "" + setReadOnly2);
if(!isReadOnly2Correct) {
fails += XspTestUtil.loc(def) + " Expected readonly=\""+setReadonly+"\" attribute in input tag. Found " + readOnly2Value + "\n";
}else{
// System.out.println("readonly attribute found as expected - " + setReadOnly2);
}
}else{
if(!readonlyExists) {
fails += XspTestUtil.loc(def) + " Expected readonly attribute in input tag does not exist.\n";
}
if(!readOnly2Exists) {
fails += XspTestUtil.loc(def) + " Expected readOnly attribute in input tag does not exist.\n";
}
}
}
}
}
fails = XspTestUtil.removeMultilineFailSkips(fails,
SkipFileContent.concatSkips(getSkipFails(), this, "testInputReadOnlyProperty"));
if( fails.length() > 0 ){
fail( XspTestUtil.getMultilineFailMessage(fails));
}
}
protected String[] getSkipFails(){
return StringUtil.EMPTY_STRING_ARRAY;
}
}