/* * � Copyright IBM Corp. 2014 * * 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: 21 Feb 2014 * DojoCheckBoxDefaultValueDisabledTest.java */ package xsp.extlib.test.control; import java.io.IOException; import java.util.Arrays; import java.util.HashMap; import java.util.Map; import javax.faces.component.UIViewRoot; import javax.faces.context.FacesContext; import javax.servlet.http.HttpServletRequest; import com.ibm.commons.util.StringUtil; 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.render.ResponseBuffer; import com.ibm.xsp.test.framework.setup.SkipFileContent; /** * * @author Maire Kehoe (mkehoe@ie.ibm.com) */ public class DojoCheckBoxDefaultValueDisabledTest extends AbstractXspTest { @Override public String getDescription() { // like InputDefaultValueDisabledTest except specifically testing the xe:djCheckBox behavior // which is different from the normal input behavior because the submitted values are "on" and (none) // while the saved values depend on the values of the checkedValue and uncheckedValue properties // that are set in the XPage source. return "that xe:djCheckBox controls handle having a default value & being disabled correctly"; } public void testCheckBoxDefaultValueSaving() throws Exception { String fails = ""; String pageName = "/pages/testCheckBoxDefaultValueDisabled.xsp"; UIViewRoot root; String[][] controlClientIdsAndSaveLocations; String[] controlInitialDisplayStates; { // create view FacesContext contextForInitialPageDisplay = TestProject.createFacesContext(this); root = TestProject.loadView(this, contextForInitialPageDisplay, pageName); // renderResponse ResponseBuffer.initContext(contextForInitialPageDisplay); String page = ResponseBuffer.encode(root, contextForInitialPageDisplay); controlClientIdsAndSaveLocations = new String[][]{ {"view:_id1:inputText1", "value1"}, // [0] {"view:_id1:inputText2", "value2"}, // [1] // not-disabled checkboxes {"view:_id1:djCheckBox1", "value3"}, // [2] {"view:_id1:djCheckBox2", "value4"}, // [3] {"view:_id1:djCheckBox3", "value5"}, // [4] {"view:_id1:djCheckBox4", "value6"}, // [5] {"view:_id1:djCheckBox5", "value7"}, // [6] {"view:_id1:djCheckBox6", "value8"}, // [7] // disabled checkboxes {"view:_id1:djCheckBox7", "value9"}, // [8] {"view:_id1:djCheckBox8", "value10"}, // [9] {"view:_id1:djCheckBox9", "value11"}, // [10] {"view:_id1:djCheckBox10", "value12"}, // [11] {"view:_id1:djCheckBox11", "value13"}, // [12] {"view:_id1:djCheckBox12", "value14"}, // [13] }; String[] actualDisplayedInitialValues = getDisplayedValues(page,controlClientIdsAndSaveLocations); controlInitialDisplayStates = new String[]{ "aaa", // [0] "aaa", // [1] // not-disabled checkboxes "unchecked", // [2] "unchecked", // [3] "checked", // [4] "checked", // [5] "unchecked", // [6] "unchecked", // [7] // disabled checkboxes "unchecked", // [8] "unchecked", // [9] "checked", // [10] "checked", // [11] "unchecked", // [12] "unchecked", // [13] }; String[] expectedInitialDisplayValues = controlInitialDisplayStates; for (int i = 0; i < expectedInitialDisplayValues.length; i++) { String actual = actualDisplayedInitialValues[i]; String expected = expectedInitialDisplayValues[i]; if( ! StringUtil.equals(actual, expected) ){ String clientId = controlClientIdsAndSaveLocations[i][0]; fails += pageName+" "+clientId+" [Initial page display] Control state not as expected; expected: "+expected+", was: "+actual+"\n"; } } } String[] initialSavedValues; { // next try faking a POST request, with control values // equivalent to just hitting submit on the already displayed page - no value changes. // fake the request from the browser Map<String, String> extraParams = new HashMap<String, String>(); String[] controlInitialSubmittedStates = new String[controlInitialDisplayStates.length]; // arraycopy(Object src, int srcPos, Object dest, int destPos, int length) // editBoxes and not-disabled checkboxes same as initial display states System.arraycopy(controlInitialDisplayStates, 0, controlInitialSubmittedStates, 0, 8); // disabled checkboxes all submit nothing (like unchecked state) // fill(Object[] a, int fromIndex, int toIndex, Object val) Arrays.fill(controlInitialSubmittedStates, 8, controlInitialSubmittedStates.length, "unchecked"); for (int i = 0; i < controlInitialSubmittedStates.length; i++) { String clientId = controlClientIdsAndSaveLocations[i][0]; String state = controlInitialSubmittedStates[i]; if( "checked".equals(state) ){ extraParams.put(clientId, "on"); }else if( "unchecked".equals(state) ){ // do not add the clientId to the submit valeus }else{ // edit box value extraParams.put(clientId, state); } } FacesContext contextForPost = createContextForPost(pageName, root, extraParams); String page = doSubmitAndRedisplay(root, contextForPost); // verify the displayed values are still as the same after submit & redisplay String[] actualRedisplayStates = getDisplayedValues(page,controlClientIdsAndSaveLocations); String[] expectedRedisplayValues = controlInitialDisplayStates; for (int i = 0; i < expectedRedisplayValues.length; i++) { String actual = actualRedisplayStates[i]; String expected = expectedRedisplayValues[i]; if( ! StringUtil.equals(actual, expected) ){ String clientId = controlClientIdsAndSaveLocations[i][0]; fails += pageName+" "+clientId+" [Redisplay after Submit initial values] Control state not as expected; expected: "+expected+", was: "+actual+"\n"; } } // verify the saved values are as expected initialSavedValues = new String[]{ "aaa", // [0] "aaa", // [1] // not-disabled checkboxes "NotSelected", // [2] "false", // [3] "Selected", // [4] "true", // [5] "NotSelected", // [6] "false", // [7] // disabled checkboxes "NotSelected", // [8] "false", // [9] "Selected", // [10] "true", // [11] "NotSelected", // [12] "false", // [13] }; Map<String,Object> viewScope = getViewMap(root); String[] expectedSavedValues = initialSavedValues; for (int i = 0; i < controlClientIdsAndSaveLocations.length; i++) { String saveLocation = controlClientIdsAndSaveLocations[i][1]; String expected = expectedSavedValues[i]; Object actual = viewScope.get(saveLocation); if( ! expected.equals(actual) ){ String clientId = controlClientIdsAndSaveLocations[i][0]; fails += pageName+" "+clientId+" [Submit initial values] Saved value not as expected; expected: "+expected+", was: "+actual+"\n"; } } } { // next fake a POST request, with control values // equivalent to changing all the values on the already displayed page // (and changing the submitted values of the disabled controls to all checked, // knowing that their submitted values will be ignored). // fake the request from the browser // the non-disabled modified control states should change // the disabled control states don't change String[] changedControlSubmittedStates = new String[]{ "bbb", // [0] "bbb", // [1] // not-disabled checkboxes "checked", // [2] "checked", // [3] "unchecked", // [4] "unchecked", // [5] "checked", // [6] "checked", // [7] // disabled checkboxes // note disabled values all unchecked submission state, so doing fill for those. "checked", // [8] "checked", // [9] "checked", // [10] "checked", // [11] "checked", // [12] "checked", // [13] }; Map<String, String> extraParams = new HashMap<String, String>(); for (int i = 0; i < changedControlSubmittedStates.length; i++) { String clientId = controlClientIdsAndSaveLocations[i][0]; String state = changedControlSubmittedStates[i]; if( "checked".equals(state) ){ extraParams.put(clientId, "on"); }else if( "unchecked".equals(state) ){ // do not add the clientId to the submit valeus }else{ // edit box value extraParams.put(clientId, state); } } FacesContext contextForPost = createContextForPost(pageName, root, extraParams); String page = doSubmitAndRedisplay(root, contextForPost); // verify the changed displayed values are as expected after submit & redisplay String[] changedSubmitRedisplayValues = new String[changedControlSubmittedStates.length]; // arraycopy(Object src, int srcPos, Object dest, int destPos, int length) // edit box values same as changedControlSubmittedValues // and non-disabled checkbox values same as changedControlSubmittedValues System.arraycopy(changedControlSubmittedStates, 0, changedSubmitRedisplayValues, 0, 8); // disabled checkbox values same as controlInitialDisplayStates System.arraycopy(controlInitialDisplayStates, 8, changedSubmitRedisplayValues, 8, 6); // Note, you would expect the 2nd edit box, since it is disabled, // to not save the changed submittedValue, but it does. String[] actualRedisplayStates = getDisplayedValues(page,controlClientIdsAndSaveLocations); String[] expectedRedisplayValues = changedSubmitRedisplayValues; for (int i = 0; i < expectedRedisplayValues.length; i++) { String actual = actualRedisplayStates[i]; String expected = expectedRedisplayValues[i]; if( ! StringUtil.equals(actual, expected) ){ String clientId = controlClientIdsAndSaveLocations[i][0]; fails += pageName+" "+clientId+" [Redisplay after Submit changed values] Control state not as expected; expected: "+expected+", was: "+actual+"\n"; } } String[] changedSavedValues = new String[changedControlSubmittedStates.length]; String[] differentValues = new String[]{ "bbb", // [0] // Note, you would expect the 2nd edit box, since it is disabled, // to not save the changed submittedValue, but it does. "bbb", // [1] // not-disabled checkboxes "Selected", // [2] "true", // [3] "NotSelected", // [4] "false", // [5] "Selected", // [6] "true", // [7] // note disabled values same as initial, so doing arraycopy for those. }; // arraycopy(Object src, int srcPos, Object dest, int destPos, int length) System.arraycopy(differentValues, 0, changedSavedValues, 0, 8); // disabled checkbox values same as initialSavedValues System.arraycopy(initialSavedValues, 8, changedSavedValues, 8, 6); Map<String,Object> viewScope = getViewMap(root); String[] expectedSavedValues = changedSavedValues; for (int i = 0; i < controlClientIdsAndSaveLocations.length; i++) { String saveLocation = controlClientIdsAndSaveLocations[i][1]; String expected = expectedSavedValues[i]; Object actual = viewScope.get(saveLocation); if( ! expected.equals(actual) ){ String clientId = controlClientIdsAndSaveLocations[i][0]; fails += pageName+" "+clientId+" [Submit changed values] Saved value not as expected; expected: "+expected+", was: "+actual+"\n"; } } } fails = XspTestUtil.removeMultilineFailSkips(fails, SkipFileContent.concatSkips(null, this, "testCheckBoxDefaultValueSaving")); if( fails.length() > 0 ){ fail( XspTestUtil.getMultilineFailMessage(fails)); } } /** * @param root * @return */ @SuppressWarnings("unchecked") private Map<String, Object> getViewMap(UIViewRoot root) { return root.getViewMap(); } /** * @param root * @param contextForPost * @return * @throws IOException */ private String doSubmitAndRedisplay(UIViewRoot root, FacesContext contextForPost) throws IOException { String page; // now fake the JSF lifecycle root.processDecodes(contextForPost); root.processValidators(contextForPost); if( contextForPost.getMessages().hasNext() ){ fail("messages found after validate"); } root.processUpdates(contextForPost); root.processApplication(contextForPost); if( contextForPost.getMessages().hasNext() ) fail("messages found"); ResponseBuffer.initContext(contextForPost); page = ResponseBuffer.encode(root, contextForPost); return page; } /** * @param pageName * @param root * @param extraParams * @return * @throws Exception */ private FacesContext createContextForPost(String pageName, UIViewRoot root, Map<String, String> extraParams) throws Exception { FacesContext contextForPost; extraParams.put("view:_id1", ""); // the <form element itself //String submittedValue = InputSaveValueTest.getSubmittedValue(instance, ""); //extraParams.put("view:_id1:input1", submittedValue); HttpServletRequest request = TestProject.createRequest(this, pageName, extraParams); contextForPost = TestProject.createFacesContext(this,request); ResponseBuffer.initContext(contextForPost); contextForPost.setViewRoot(root); return contextForPost; } /** * @param page * @param clientIdAndOther * @return */ private String[] getDisplayedValues(String page, String[][] clientIdAndOtherArr) { String[] results = new String[clientIdAndOtherArr.length]; int i = 0; for (String[] clientIdAndOther : clientIdAndOtherArr) { String clientId = clientIdAndOther[0]; String snippet = getInputSnippetFor(page, clientId); if( clientId.contains("inputText") ){ // edit box String valueAttr = XspRenderUtil.findAttribute(snippet, "value"); if( null == valueAttr ) throw new RuntimeException("No value attr found in edit box: "+snippet); results[i] = valueAttr; }else{ // check box String checkedAttr = XspRenderUtil.findAttribute(snippet, "checked"); String checkedState = (null == checkedAttr)? "unchecked" : "checked"; results[i] = checkedState; } i++; } return results; } /** * @param clientId * @return */ private String getInputSnippetFor(String page, String clientId) { String expectedIdAttr = " id=\"" +clientId+"\""; int idIndex = page.indexOf(expectedIdAttr); if( -1 == idIndex ){ System.err.println("DojoCheckBoxDefaultValueDisabledTest.getInputSnippetFor() " + "Expected HTML output not found for " + clientId + " in:\n" + page); throw new RuntimeException("Expected HTML output not found for " +clientId+ " in: "+page); } String expectedStartInput = "<input"; int startInputIndex = page.lastIndexOf(expectedStartInput, idIndex); if( -1 == startInputIndex ) throw new RuntimeException(); int endInputIndex = page.indexOf(">", idIndex); if( -1 == endInputIndex ) throw new RuntimeException(); endInputIndex += 1; String snippet = page.substring(startInputIndex, endInputIndex); return snippet; } }