001: package org.uispec4j;
002:
003: import junit.framework.Assert;
004: import junit.framework.AssertionFailedError;
005: import org.uispec4j.assertion.Assertion;
006: import org.uispec4j.assertion.UISpecAssert;
007: import org.uispec4j.utils.Utils;
008: import org.uispec4j.xml.XmlAssert;
009: import org.uispec4j.xml.XmlEscape;
010:
011: import javax.swing.*;
012: import javax.swing.event.HyperlinkEvent;
013: import javax.swing.event.HyperlinkListener;
014: import javax.swing.text.JTextComponent;
015: import java.net.MalformedURLException;
016: import java.net.URL;
017: import java.util.ArrayList;
018: import java.util.List;
019: import java.util.regex.Matcher;
020: import java.util.regex.Pattern;
021:
022: class TextBoxHandlerForHtmlTextComponent extends
023: AbstractTextBoxHandlerForTextComponent {
024: public static final Pattern HYPERLINK_PATTERN = Pattern
025: .compile("<(a|A)[ ]+([a-zA-Z0-9]+=\"[^\"]+\"[ ]+)*href=\"([^\"]+)\"([ ]+[a-zA-Z0-9]+=\"[^\"]+\"[ ]*)*>([^\"]+)</(a|A)>");
026:
027: public static TextBox.Handler init(JTextComponent textComponent) {
028: return (accept(textComponent)) ? new TextBoxHandlerForHtmlTextComponent(
029: textComponent)
030: : null;
031: }
032:
033: private TextBoxHandlerForHtmlTextComponent(
034: JTextComponent textComponent) {
035: super (textComponent);
036: }
037:
038: public Assertion textIsEmpty() {
039: return new Assertion() {
040: public void check() {
041: String actualText = jTextComponent.getText();
042: JTextPane dummyPane = createHtmlTextPane();
043: if (isEquivalent(dummyPane, actualText)) {
044: return;
045: }
046:
047: dummyPane.setText("<html><p></html>");
048: dummyPane.setText("");
049: if (isEquivalent(dummyPane, actualText)) {
050: return;
051: }
052:
053: dummyPane.setText("<p></p>");
054: if (isEquivalent(dummyPane, actualText)) {
055: return;
056: }
057:
058: Assert.fail("Text should be empty but contains: "
059: + actualText);
060: }
061: };
062: }
063:
064: private boolean isEquivalent(JTextPane dummyPane, String actualText) {
065: try {
066: XmlAssert.assertEquivalent(dummyPane.getText(), actualText);
067: return true;
068: } catch (AssertionFailedError e) {
069: return false;
070: } catch (Exception e) {
071: throw new RuntimeException(e);
072: }
073: }
074:
075: public Assertion textEquals(final String text) {
076: return new Assertion() {
077: public void check() {
078: String actual = jTextComponent.getText().replaceAll(
079: "<[^<>]+>", "").replaceAll("\n", "")
080: .replaceAll(Utils.LINE_SEPARATOR, "")
081: .replaceAll("[ ]+", " ").trim();
082: Assert.assertEquals(text, XmlEscape
083: .convertXmlEntitiesToText(actual));
084: }
085: };
086: }
087:
088: public Assertion htmlEquals(final String html) {
089: return new Assertion() {
090: public void check() {
091: if (html.equals("")) {
092: textIsEmpty();
093: return;
094: }
095: JTextPane dummyPane = createHtmlTextPane();
096: dummyPane.setText(html);
097: Assert.assertEquals(dummyPane.getText(), jTextComponent
098: .getText());
099: }
100: };
101: }
102:
103: public void clickOnHyperlink(String link) {
104: HyperLinkFoundAssertion hyperLinkAssertion = new HyperLinkFoundAssertion(
105: link);
106: UISpecAssert.assertTrue(hyperLinkAssertion);
107: dispatchHyperlinkEvent(hyperLinkAssertion.getHref());
108: }
109:
110: private void dispatchHyperlinkEvent(String href) {
111: URL url;
112: try {
113: JEditorPane editorPane = (JEditorPane) jTextComponent;
114: url = new URL(editorPane.getPage(), href);
115: } catch (MalformedURLException e) {
116: url = null;
117: }
118: HyperlinkEvent event = new HyperlinkEvent(jTextComponent,
119: HyperlinkEvent.EventType.ACTIVATED, url, href);
120: JEditorPane editorPane = (JEditorPane) jTextComponent;
121: HyperlinkListener[] listeners = editorPane
122: .getHyperlinkListeners();
123: for (int i = 0; i < listeners.length; i++) {
124: listeners[i].hyperlinkUpdate(event);
125: }
126: }
127:
128: private JTextPane createHtmlTextPane() {
129: JTextPane dummyPane = new JTextPane();
130: dummyPane.setContentType("text/html; charset=UTF-8");
131: return dummyPane;
132: }
133:
134: private static boolean accept(JTextComponent jTextComponent) {
135: if (!JEditorPane.class.isAssignableFrom(jTextComponent
136: .getClass())) {
137: return false;
138: }
139: JEditorPane editorPane = (JEditorPane) jTextComponent;
140: return editorPane.getEditorKit().getContentType().startsWith(
141: "text/html");
142: }
143:
144: private class HyperLinkFoundAssertion extends Assertion {
145: private String link;
146: private String href;
147:
148: public HyperLinkFoundAssertion(String link) {
149: this .link = link;
150: }
151:
152: public String getHref() {
153: return href;
154: }
155:
156: public void check() throws Exception {
157: href = getHyperLink(link);
158: }
159:
160: private String getHyperLink(String link) {
161: String text = jTextComponent.getText();
162: Matcher matcher = HYPERLINK_PATTERN.matcher(text);
163: String lowerCaseLink = link.toLowerCase();
164: List exactResults = new ArrayList();
165: List approximativeResults = new ArrayList();
166: while (matcher.find()) {
167: String label = matcher.group(5).replaceAll(
168: Utils.LINE_SEPARATOR, "").replaceAll("\n", "")
169: .toLowerCase().replaceAll("[ ]+", " ").trim();
170: String href = matcher.group(3);
171: if (label.equals(lowerCaseLink)) {
172: exactResults.add(href);
173: } else if (label.indexOf(lowerCaseLink) != -1) {
174: approximativeResults.add(href);
175: }
176: }
177: if ((exactResults.isEmpty())
178: && (approximativeResults.isEmpty())) {
179: Assert.fail("Hyperlink '" + link + "' not found");
180: }
181: if ((exactResults.size() > 1)
182: || (approximativeResults.size() > 1)) {
183: Assert
184: .fail("Ambiguous command - found several hyperlinks matching '"
185: + link + "'");
186: }
187: return (String) ((exactResults.size() == 1) ? exactResults
188: .get(0) : approximativeResults.get(0));
189: }
190: }
191: }
|