001: package org.uispec4j;
002:
003: import junit.framework.AssertionFailedError;
004: import org.uispec4j.utils.AssertionFailureNotDetectedError;
005: import org.uispec4j.utils.FileTestUtils;
006: import org.uispec4j.utils.Functor;
007: import org.uispec4j.utils.UIComponentFactory;
008: import org.uispec4j.xml.XmlAssert;
009:
010: import javax.swing.*;
011: import javax.swing.event.HyperlinkEvent;
012: import javax.swing.event.HyperlinkListener;
013: import javax.swing.text.JTextComponent;
014: import java.awt.*;
015: import java.io.File;
016: import java.io.IOException;
017: import java.net.URL;
018:
019: public class TextboxForHtmlTestComponentTest extends
020: TextBoxComponentTestCase {
021: private JTextComponent jTextComponent;
022:
023: protected void setUp() throws Exception {
024: super .setUp();
025: initWithHtmlTextPane();
026: }
027:
028: protected void createTextBox(String text) {
029: textBox = new TextBox(jTextComponent);
030: textBox.setText(text);
031: }
032:
033: public void testGetComponentTypeName() throws Exception {
034: assertEquals("textBox", UIComponentFactory.createUIComponent(
035: new JTextPane()).getDescriptionTypeName());
036: }
037:
038: public void testGetDescription() throws Exception {
039: XmlAssert.assertEquivalent("<textBox name='myText'/>", textBox
040: .getDescription());
041: }
042:
043: public void testFactory() throws Exception {
044: checkFactory(new JTextArea(), TextBox.class);
045: checkFactory(new JTextPane(), TextBox.class);
046: checkFactory(new JEditorPane(), TextBox.class);
047: checkFactory(new JTextField(), TextBox.class);
048: }
049:
050: public void testAssertTextEqualsWithHtml() throws Exception {
051: initWithHtmlTextPane();
052: String text = "Universal <b>rules</b>:"
053: + "<ul>"
054: + "<li style=\"margin-top: 0\" align=\"center\">a < b</li>"
055: + "<li>2 > 1</li>" + "</ul>";
056: textBox.setText(text);
057: assertTrue(textBox.textEquals("Universal rules: a < b 2 > 1"));
058: try {
059: assertTrue(textBox
060: .textEquals("Universal rules: a < b 2 > 1, seb is the best"));
061: throw new AssertionFailureNotDetectedError();
062: } catch (AssertionFailedError e) {
063: }
064: }
065:
066: public void testAssertHtmlEqualsWithMetaInHeader() throws Exception {
067: initWithHtmlTextPane();
068: String text = "<html>" + " <head>"
069: + " <meta name=\"UISpec4J\" land=\"en\"/>"
070: + " <title name=\"Universal rules\"/>" + " </head>"
071: + " <body>" + " Universal <b>rules</b>:"
072: + " <ul>" + " <li>a < b</li>"
073: + " <li>2 > 1</li>" + " </ul>" + " </body>"
074: + "</html>";
075: textBox.setText(text);
076: assertTrue(textBox.htmlEquals(text));
077: try {
078: assertTrue(textBox.htmlEquals("Universal <b>rules</b>:"
079: + "<ul>" + "<li>a < b</li>" + "</ul>"));
080: throw new AssertionFailureNotDetectedError();
081: } catch (AssertionFailedError e) {
082: }
083: }
084:
085: public void testAssertHtmlEquals() throws Exception {
086: initWithHtmlTextPane();
087: String text = "Universal <b>rules</b>:" + "<ul>"
088: + "<li>a < b</li>" + "<li>2 > 1</li>" + "</ul>";
089: textBox.setText(text);
090: assertTrue(textBox.htmlEquals(text));
091: try {
092: assertTrue(textBox.htmlEquals("Universal <b>rules</b>:"
093: + "<ul>" + "<li>a < b</li>" + "</ul>"));
094: throw new AssertionFailureNotDetectedError();
095: } catch (AssertionFailedError e) {
096: }
097: }
098:
099: public void testAssertTextContainsWithHtml() throws Exception {
100: initWithHtmlTextPane();
101: String text = "My name is <b>Bond</b>";
102: textBox.setText(text);
103: assertTrue(textBox.textContains("Bond"));
104: try {
105: assertTrue(textBox.textContains("error"));
106: throw new AssertionFailureNotDetectedError();
107: } catch (AssertionFailedError e) {
108: assertEquals(
109: "The component text does not contain 'error' - actual content is:<html>\n"
110: + " <head>\n" + " </head>\n"
111: + " <body>My name is <b>Bond</b></body>\n"
112: + "</html>\n", e.getMessage());
113: }
114: }
115:
116: public void testAssertTextEqualsWithEmptyStringIsTheSameAsAssertTextIsEmpty()
117: throws Exception {
118: initWithHtmlTextPane();
119: assertTrue(textBox.textEquals(""));
120: jTextComponent.setText("blah");
121: jTextComponent.setText("");
122: assertTrue(textBox.textEquals(""));
123: }
124:
125: public void testAssertTextContainsHandlesHtmlLineBreaksAndFormatting()
126: throws Exception {
127: initWithHtmlTextPane();
128: StringBuffer buffer = new StringBuffer();
129: for (int i = 0; i < 20; i++) {
130: buffer.append("blah ");
131: }
132: String text = buffer.toString();
133: textBox.setText(text);
134: assertTrue(textBox.textContains(text));
135: }
136:
137: public void testAssertEmptyWithHtml() throws Exception {
138: initWithHtmlTextPane();
139: assertTrue(textBox.textIsEmpty());
140: jTextComponent.setText("");
141: assertTrue(textBox.textIsEmpty());
142: jTextComponent.setText("a");
143: try {
144: assertTrue(textBox.textIsEmpty());
145: throw new AssertionFailureNotDetectedError();
146: } catch (AssertionFailedError e) {
147: assertEquals("Text should be empty but contains: <html>\n"
148: + " <head>\n" + " \n" + " </head>\n"
149: + " <body>\n" + " a\n" + " </body>\n"
150: + "</html>\n", e.getMessage());
151: }
152:
153: jTextComponent.setText("<html>\n" + " <head>\n" + "\n"
154: + " </head>\n" + " <body>\n" + " <p>\n"
155: + " \n" + " </p>\n" + " </body>\n"
156: + "</html>\n" + "\n" + "");
157: assertTrue(textBox.textIsEmpty());
158:
159: jTextComponent.setText("<html><p></html>");
160: jTextComponent.setText("");
161: assertTrue(textBox.textIsEmpty());
162: }
163:
164: public void testAssertEmptyAfterReset() throws Exception {
165: initWithHtmlTextPane();
166: assertTrue(textBox.textIsEmpty());
167: jTextComponent.setText("blah");
168: jTextComponent.setText("");
169: assertTrue(textBox.textIsEmpty());
170: }
171:
172: private JTextPane createHtmlTextPane(String html) {
173: JTextPane textPane = new JTextPane();
174: textPane.setContentType("text/html");
175: textPane.setText(html);
176: return textPane;
177: }
178:
179: //TODO: this test should pass
180: public void disabled_testClickOnHyperLinkWhenPageLoadingIsNotImmediate()
181: throws Exception {
182: final JEditorPane editorPane = new JEditorPane(
183: "http://www.agilemanifesto.org/");
184: JScrollPane editorScrollPane = new JScrollPane(editorPane);
185: editorScrollPane
186: .setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
187: editorScrollPane.setPreferredSize(new Dimension(250, 145));
188: editorScrollPane.setMinimumSize(new Dimension(10, 10));
189:
190: clickOnHyperLink(editorPane, "about the manifesto",
191: "history.html");
192: }
193:
194: public void testClickOnHyperlink() throws Exception {
195: checkClickOnHyperlink(
196: "<html>blah blah<a href=\"http://www.junit.org\">link text</a>reblah</html>",
197: "link text", "http://www.junit.org");
198: }
199:
200: public void testClickOnHyperlinkAcceptsSubstrings()
201: throws Exception {
202: checkClickOnHyperlink(
203: "<html>blah blah<a href=\"http://www.junit.org\">link text</a>reblah</html>",
204: "link", "http://www.junit.org");
205: }
206:
207: public void testClickOnHyperLinkAcceptsLineSeparators()
208: throws Exception {
209: String link = "link text is very long so it will be on two lines";
210: checkClickOnHyperlink(
211: "<html>blah blah<a href=\"http://www.junit.org\">"
212: + link + "</a>reblah</html>", link,
213: "http://www.junit.org");
214: }
215:
216: public void testClickOnHyperlinkIsCaseInsensitive()
217: throws Exception {
218: checkClickOnHyperlink(
219: "<html>blah blah<a href=\"http://www.junit.org\">link text</a>reblah</html>",
220: "liNk tEXt", "http://www.junit.org");
221: }
222:
223: public void testClickOnHyperLinkWaitsForTheCompletePageLoad()
224: throws Exception {
225: String content1 = "<html>\n" + " <head>\n"
226: + " <title>Subject 1</title>\n" + " </head>\n"
227: + " <body>\n" + " <p>blabla</p>"
228: + " <a href=\"file2.html\">Subject 2</a>\n"
229: + " </body>\n" + "</html>";
230: String content2 = "<html>\n" + " <head>\n"
231: + " <title>Subject 2</title>\n" + " </head>\n"
232: + " <body>\n" + " <p>blabla</p>"
233: + " <a href=\"file1.html\">Subject 1</a>\n"
234: + " </body>\n" + "</html>";
235:
236: File file1 = FileTestUtils.dumpStringToFile("file1.html",
237: content1);
238: File file2 = FileTestUtils.dumpStringToFile("file2.html",
239: content2);
240:
241: final JEditorPane textComponent = createTextPaneFromUrl(file1
242: .toURL());
243: checkSwitchBetweenPages(textComponent, content1, content2);
244:
245: File archiveFile = FileTestUtils.createZipArchive(FileTestUtils
246: .getFile("archive.zip"), new File[] { file1, file2 });
247: textComponent.setPage(new URL("jar:" + archiveFile.toURL()
248: + "!/file1.html"));
249: checkSwitchBetweenPages(textComponent, content1, content2);
250: }
251:
252: public void testClickOnHyperlinkGivesPriorityToExactMatches()
253: throws Exception {
254: checkClickOnHyperlink(
255: "<html>blah blah<a href=\"http://www.junit.org\">a link text</a>reblah"
256: + "blah blah<a href=\"http://www.apache.org\">link text</a>reblah</html>",
257: "link text", "http://www.apache.org");
258: }
259:
260: public void testClickOnUnknownHyperlink() throws Exception {
261: checkClickOnHyperlinkError(
262: "<html>blah blah<a href=\"http://www.junit.org\">a link text</a>reblah"
263: + "blah blah<a href=\"http://www.apache.org\">link text</a>reblah</html>",
264: "unknown", "Hyperlink 'unknown' not found");
265: }
266:
267: public void testClickOnHyperlinkWithAmbiguity() throws Exception {
268: checkClickOnHyperlinkError(
269: "<html>blah blah<a href=\"http://www.junit.org\">a link text</a>reblah"
270: + "blah blah<a href=\"http://www.apache.org\">another link text</a>reblah</html>",
271: "link text",
272: "Ambiguous command - found several hyperlinks matching 'link text'");
273: }
274:
275: public void testClickOnHyperlinkAcceptsAttributesOnATag()
276: throws Exception {
277: checkClickOnHyperlink(
278: "<html>blah blah<a title=\"JUNIT \" "
279: + " href=\"http://www.junit.org\" "
280: + " name = \"junit hyperlink\">link text</a>reblah</html>",
281: "link text", "http://www.junit.org");
282: }
283:
284: public void testClickOnHyperlinkWithBigHtml() throws Exception {
285: StringBuffer htmlText = new StringBuffer(
286: "<html>"
287: + " <head>"
288: + " <meta name=\"UISpec4J\" lang=\"en\" content=\"text/HTML; charset=utf-8\"/>"
289: + " <title name=\"Universal rules\"/>"
290: + " </head>"
291: + " <body>"
292: + " Universal <b>rules</b>:"
293: + " <a href=\"http://www.junit.org\">link text</a>");
294: for (int i = 0; i < 5000; i++) {
295: htmlText
296: .append(
297: "<a href=\"http://www.otherlink.org\">other link text")
298: .append(i).append("</a>");
299: }
300: htmlText.append("</body></html>");
301: checkClickOnHyperlink(htmlText.toString(), "link text",
302: "http://www.junit.org");
303: }
304:
305: private void checkSwitchBetweenPages(JTextComponent textComponent,
306: String content1, String content2) {
307: TextBox textBox = new TextBox(textComponent);
308: assertTrue(textBox.htmlEquals(content1));
309:
310: textBox.clickOnHyperlink("Subject 2");
311: textBox.clickOnHyperlink("Subject 1");
312: waitUntil(textBox.htmlEquals(content1), 1000);
313:
314: textBox.clickOnHyperlink("Subject 2");
315: assertTrue(textBox.htmlEquals(content2));
316: }
317:
318: private JTextPane createTextPaneFromUrl(URL url) throws IOException {
319: final JTextPane jTextPane = new JTextPane();
320: jTextPane.setContentType("text/html");
321: jTextPane.setPage(url);
322:
323: jTextPane.addHyperlinkListener(new HyperlinkListener() {
324: public void hyperlinkUpdate(HyperlinkEvent event) {
325: try {
326: jTextPane.setPage(event.getURL());
327: } catch (IOException e) {
328: }
329: }
330: });
331: return jTextPane;
332: }
333:
334: private void checkClickOnHyperlink(String html, String link,
335: String expectedTarget) throws Exception {
336: JTextPane textPane = createHtmlTextPane(html);
337: clickOnHyperLink(textPane, link, expectedTarget);
338: }
339:
340: private void clickOnHyperLink(JEditorPane editorPane, String link,
341: String expectedTarget) throws Exception {
342: DummyHyperlinkListener listener = new DummyHyperlinkListener();
343: editorPane.addHyperlinkListener(listener);
344: TextBox textComponent = new TextBox(editorPane);
345: textComponent.clickOnHyperlink(link);
346: assertEquals(1, listener.getCallCount());
347: assertEquals(expectedTarget, listener.getLastEvent()
348: .getDescription());
349:
350: listener.reset();
351: textComponent.triggerClickOnHyperlink(link).run();
352: assertEquals(1, listener.getCallCount());
353: assertEquals(expectedTarget, listener.getLastEvent()
354: .getDescription());
355: }
356:
357: private void checkClickOnHyperlinkError(String html,
358: final String link, String errorMessage) throws Exception {
359: final TextBox textComponent = new TextBox(
360: createHtmlTextPane(html));
361: checkAssertionFailedError(new Functor() {
362: public void run() throws Exception {
363: textComponent.clickOnHyperlink(link);
364: }
365: }, errorMessage);
366:
367: checkAssertionFailedError(new Functor() {
368: public void run() throws Exception {
369: textComponent.triggerClickOnHyperlink(link).run();
370: }
371: }, errorMessage);
372: }
373:
374: private static class DummyHyperlinkListener implements
375: HyperlinkListener {
376: int callCount;
377: HyperlinkEvent lastEvent;
378:
379: public void hyperlinkUpdate(HyperlinkEvent event) {
380: callCount++;
381: this .lastEvent = event;
382: }
383:
384: public int getCallCount() {
385: return callCount;
386: }
387:
388: public HyperlinkEvent getLastEvent() {
389: return lastEvent;
390: }
391:
392: public void reset() {
393: callCount = 0;
394: lastEvent = null;
395: }
396: }
397:
398: private void initWithHtmlTextPane() {
399: JTextPane pane = new JTextPane();
400: pane.setContentType("text/html; charset=EUC-JP");
401: init(pane);
402: }
403:
404: private void init(JTextComponent swingComponent) {
405: jTextComponent = swingComponent;
406: jTextComponent.setName("myText");
407: createTextBox("");
408: }
409: }
|