/** * Copyright 2008 Google Inc. * * 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. * */ package org.waveprotocol.wave.client.editor.integration; import com.google.gwt.junit.client.GWTTestCase; import org.waveprotocol.wave.client.debug.logger.BufferedLogger; import org.waveprotocol.wave.client.debug.logger.LogLevel; import org.waveprotocol.wave.client.editor.Editor; import org.waveprotocol.wave.client.editor.EditorTestingUtil; import org.waveprotocol.wave.client.editor.testing.ContentSerialisationUtil; import org.waveprotocol.wave.client.editor.testing.TestEditors; import org.waveprotocol.wave.client.editor.testing.TestInlineDoodad; import org.waveprotocol.wave.client.editor.testtools.Abbreviations; import org.waveprotocol.wave.client.editor.testtools.ContentWithSelection; import org.waveprotocol.wave.client.editor.testtools.EditorAssert; import org.waveprotocol.wave.common.logging.LoggerBundle; import org.waveprotocol.wave.model.document.operation.automaton.DocumentSchema; import org.waveprotocol.wave.model.document.util.DocProviders; import org.waveprotocol.wave.model.document.util.FocusedRange; import org.waveprotocol.wave.model.document.util.LineContainers; import org.waveprotocol.wave.model.operation.OperationException; import org.waveprotocol.wave.model.schema.conversation.ConversationSchemas; import java.util.List; /** * Base class for Editor unit tests * */ public abstract class TestBase extends GWTTestCase { /** * Grab EditorTest's editor */ protected Editor editor; /** * A logger in case we're running the test in the harness */ protected LoggerBundle logger; /** * A map of abbreviations, e.g., * <smiles/> -> * <image attachment='pics/Smiles.jpg'> * <caption>Smiles</caption> * </image> */ protected Abbreviations abbreviations = new Abbreviations(); private static final DocumentSchema TEST_SCHEMA = new DocumentSchema() { @Override public List<String> getRequiredInitialChildren(String typeOrNull) { return ConversationSchemas.BLIP_SCHEMA_CONSTRAINTS.getRequiredInitialChildren(typeOrNull); } @Override public boolean permitsAttribute(String type, String attributeName) { return ConversationSchemas.BLIP_SCHEMA_CONSTRAINTS.permitsAttribute(type, attributeName); } @Override public boolean permitsAttribute(String type, String attributeName, String attributeValue) { return ConversationSchemas.BLIP_SCHEMA_CONSTRAINTS.permitsAttribute(type, attributeName, attributeValue); } @Override public boolean permitsChild(String parentTypeOrNull, String childType) { return ("body".equals(parentTypeOrNull) && TestInlineDoodad.FULL_TAGNAME.equals(childType)) || ConversationSchemas.BLIP_SCHEMA_CONSTRAINTS.permitsChild(parentTypeOrNull, childType); } @Override public PermittedCharacters permittedCharacters(String typeOrNull) { if (TestInlineDoodad.FULL_TAGNAME.equals(typeOrNull)) { return PermittedCharacters.BLIP_TEXT; } else { return ConversationSchemas.BLIP_SCHEMA_CONSTRAINTS.permittedCharacters(typeOrNull); } } }; /** * {@inheritDoc} */ @Override public String getModuleName() { return "org.waveprotocol.wave.client.editor.integration.Tests"; } @Override protected void gwtSetUp() throws Exception { super.gwtSetUp(); prepareTest(); } /** * Prepares test. Call this at beginning of each testXXX method. * * This is needed because you cannot call GWT.create() inside setUp() */ protected void prepareTest() { if (logger == null) { logger = new BufferedLogger("test"); if (editor == null) { editor = createEditor(); } } LineContainers.setTopLevelContainerTagname("body"); abbreviations.clear(); } protected Editor createEditor() { return TestEditors.getMinimalEditor(); } @Override protected void gwtTearDown() throws Exception { super.gwtTearDown(); } /** * Asserts that the selection in an editor (roughly) matches that given * by a {@link ContentWithSelection} as defined by * {@link EditorAssert#assertLocationsEquals(String, int, int, String)} * * @param msg * @param expected * @param actualEditor */ protected void assertSelectionEquals( String msg, ContentWithSelection expected, Editor actualEditor) { EditorAssert.assertSelectionEquals(msg + ". Selections differ. ", expected.selection, // TODO(danilatos): Check directed ranges actualEditor.getSelectionHelper().getSelectionRange() != null ? actualEditor.getSelectionHelper().getSelectionRange().asRange() : null, expected.content); } /** * Asserts Editor content and selection is as expected. * * @param msg * @param expectedContentWithSelection * @param actualEditor * @throws OperationException */ protected void assertEditorContent(String msg, String expectedContentWithSelection, Editor actualEditor) throws OperationException { // Parse the expected content ContentWithSelection expected = parseContent(expectedContentWithSelection); // Assert result assertEditorContent( msg, expected, actualEditor); } /** * Asserts Editor content and selection is as expected * * @param msg * @param expected * @param actualEditor */ protected void assertEditorContent(String msg, ContentWithSelection expected, Editor actualEditor) { // Assert content EditorAssert.assertXmlEquals(msg, expected.content, ContentSerialisationUtil.getContentString(editor)); // Assert selection assertSelectionEquals(msg, expected, editor); } /** * Unabbreviates and parses selection from strings like <p>ab|cd</p> * * @param content * @return parsed content + selection * @throws OperationException */ protected ContentWithSelection parseContent(String content) throws OperationException { return new ContentWithSelection(abbreviations.expand(content)); } /** * Sets editor content and selection with string like <p>a[bc]d</p> * First expands the string according to current abbreviations. * Also asserts that resulting content + selection got set properly * * @param editor * @param content * @throws OperationException */ protected void setContent(Editor editor, String content) throws OperationException { // Parse content ContentWithSelection parsed = parseContent(content); // Set content + selection in editor editor.setContent(DocProviders.POJO.parse(parsed.content).asOperation(), TEST_SCHEMA); editor.getSelectionHelper().setSelectionRange(parsed.selection == null ? null : new FocusedRange(parsed.selection.getStart(), parsed.selection.getEnd())); // Assert editor health (editor already does this in debug builds) if (!LogLevel.showDebug()) { EditorTestingUtil.checkHealth(editor); } // Assert content and selection assertEditorContent( "Editor.setContent(" + abbreviations.expand(content) + ")", parsed, editor); } }