package org.codefx.libfx.dom; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import java.io.StringReader; import javafx.beans.property.Property; import javafx.beans.property.SimpleObjectProperty; import javax.swing.event.HyperlinkEvent; import javax.swing.event.HyperlinkEvent.EventType; import org.apache.xerces.dom.events.EventImpl; import org.cyberneko.html.parsers.DOMParser; import org.junit.Before; import org.junit.Test; import org.w3c.dom.Document; import org.w3c.dom.events.Event; import org.w3c.dom.events.EventTarget; import org.xml.sax.InputSource; /** * Abstract superclass to all test classes which convert DOM events. */ public abstract class AbstractDomEventConverterTest { // #begin FIELDS & INITIALIZATION /** * The URL used for all links. */ private static final String LINK_URL = "http://www.w3.org/TR/DOM-Level-3-Events/#event-types-list"; /** * The ID of the {@link #simpleLink}. Used to retrieve the corresponding element from the parsed HTML. */ private static final String SIMPLE_LINK_ID = "simple_link"; /** * The text displayed for the {@link #simpleLink}. */ private static final String SIMPLE_LINK_TEXT = "Link!"; /** * A simple HTML string. */ private static final String SIMPLE_HTML_STRING = "" + "<a" + " id=\"" + SIMPLE_LINK_ID + "\"" + " href=\"" + LINK_URL + "\">" + SIMPLE_LINK_TEXT + "</a>"; /** * A simple link which is used to generate DOM events. */ private EventTarget simpleLink; /** * Parses the HTML strings and extracts the id'd DOM event targets. * * @throws Exception * if parsing fails */ @Before public void setUp() throws Exception { DOMParser parser = new DOMParser(); parser.parse(new InputSource(new StringReader(SIMPLE_HTML_STRING))); Document htmlDocument = parser.getDocument(); simpleLink = (EventTarget) htmlDocument.getElementById(SIMPLE_LINK_ID); } // #end FIELDS & INITIALIZATION // #begin TESTS // #end FIELDS & INITIALIZATION // #begin TESTS /** * Tests whether all DOM events[1] which have a corresponding {@link EventType HyperlinkEventType} are correctly * reported to be convertible. * <p> * [1] http://www.w3.org/TR/DOM-Level-3-Events/#event-types-list */ @Test public void testCanConvertToHyperlinkEvent() { // all convertible DOM events String[] convertibleEventNames = new String[] { DomEventType.CLICK.getDomName(), DomEventType.MOUSE_ENTER.getDomName(), DomEventType.MOUSE_LEAVE.getDomName() }; for (String domEventName : convertibleEventNames) { Event domEvent = createDispatchAndCatchEvent(simpleLink, domEventName); boolean canConvert = canConvertToHyperlinkEvent(domEvent); assertTrue("Should be able to convert '" + domEventName + "'.", canConvert); } } /** * Tests whether all DOM events[1] which have no corresponding {@link EventType HyperlinkEventType} are correctly * reported to be not convertible. * <p> * [1] http://www.w3.org/TR/DOM-Level-3-Events/#event-types-list */ @Test public void testCanNotConvert() { // all existing DOM events[1] minus the convertible ones String[] notConvertibleEventNames = new String[] { "abort", "beforeinput", "blur", "compositionstart", "compositionupdate", "compositionend", "dblclick", "error", "focus", "focusin", "focusout", "input", "keydown", "keyup", "load", "mousedown", "mousemove", "mouseout", "mouseover", "mouseup", "resize", "scroll", "select", "unload", "wheel" }; for (String domEventName : notConvertibleEventNames) { Event domEvent = createDispatchAndCatchEvent(simpleLink, domEventName); boolean canConvert = canConvertToHyperlinkEvent(domEvent); assertFalse("Should not be able to convert '" + domEventName + "'.", canConvert); } } /** * Tests whether converted events have the correct event type. */ @Test public void testEventTypes() { for (DomEventType domEventType : DomEventType.values()) { if (!domEventType.toHyperlinkEventType().isPresent()) continue; Event domEvent = createDispatchAndCatchEvent(simpleLink, domEventType.getDomName()); HyperlinkEvent convertedEvent = convertToHyperlinkEvent(domEvent, new Object()); assertEquals(domEventType.toHyperlinkEventType().get(), convertedEvent.getEventType()); } } /** * Tests whether the converted event's {@link HyperlinkEvent#getSource() source} is correctly set. */ @Test public void testSource() { Event domEvent = createDispatchAndCatchEvent(simpleLink, DomEventType.CLICK.getDomName()); Object source = "the source"; HyperlinkEvent convertedEvent = convertToHyperlinkEvent(domEvent, source); assertSame(source, convertedEvent.getSource()); } /** * Tests whether the converted event's {@link HyperlinkEvent#getURL() URL} is correctly set. */ @Test public void testUrl() { Event domEvent = createDispatchAndCatchEvent(simpleLink, DomEventType.CLICK.getDomName()); HyperlinkEvent convertedEvent = convertToHyperlinkEvent(domEvent, new Object()); assertEquals(LINK_URL, convertedEvent.getURL().toExternalForm()); } /** * Tests whether the converted event's {@link HyperlinkEvent#getDescription description} is correctly set. */ @Test public void testDescription() { Event domEvent = createDispatchAndCatchEvent(simpleLink, DomEventType.CLICK.getDomName()); HyperlinkEvent convertedEvent = convertToHyperlinkEvent(domEvent, new Object()); assertEquals(SIMPLE_LINK_TEXT, convertedEvent.getDescription()); } /** * Tests whether the converted event's {@link HyperlinkEvent#getInputEvent() inputEvent} is null as per contract. */ @Test public void testInputEvent() { Event domEvent = createDispatchAndCatchEvent(simpleLink, DomEventType.CLICK.getDomName()); HyperlinkEvent convertedEvent = convertToHyperlinkEvent(domEvent, new Object()); assertNull(convertedEvent.getInputEvent()); } /** * Tests whether the converted event's {@link HyperlinkEvent#getSourceElement() sourceElement} is null as per * contract. */ @Test public void testSourceElement() { Event domEvent = createDispatchAndCatchEvent(simpleLink, DomEventType.CLICK.getDomName()); HyperlinkEvent convertedEvent = convertToHyperlinkEvent(domEvent, new Object()); assertNull(convertedEvent.getSourceElement()); } // #end TESTS // #begin ABSTRACT METHODS /** * Implemented by subclasses to check whether the specified event can be converted. * * @param domEvent * the {@link Event} to check * @return true if {@link #convertToHyperlinkEvent(Event, Object)} will succeed */ protected abstract boolean canConvertToHyperlinkEvent(Event domEvent); /** * Implemented by subclasses to convert the specified DOM event to a hyperlink event. * * @param domEvent * the {@link Event} to be converted * @param object * the new hyperlink event's source * @return a {@link HyperlinkEvent} */ protected abstract HyperlinkEvent convertToHyperlinkEvent(Event domEvent, Object object); // #end ABSTRACT METHODS // #begin HELPER METHODS /** * Creates a DOM event and dispatches it with the specified target. A listener on the same target catches any event * and returns it. * * @param target * the {@link EventTarget} which will {@link EventTarget#dispatchEvent(Event) dispatch} the created event * @param eventType * the type of the event as specified here: http://www.w3.org/TR/DOM-Level-3-Events/#event-types-list * @return the DOM-{@link Event} caught from the target */ private static Event createDispatchAndCatchEvent(EventTarget target, String eventType) { return createDispatchAndCatchEvent(target, eventType, true, true); } /** * Creates a DOM event and dispatches it with the specified target. A listener on the same target catches any event * and returns it. * * @param target * the {@link EventTarget} which will {@link EventTarget#dispatchEvent(Event) dispatch} the created event * @param eventType * the type of the event as specified here: http://www.w3.org/TR/DOM-Level-3-Events/#event-types-list * @param canBubbleArg * indicates whether the event can bubble * @param cancelableArg * indicates whether the event can be canceled * @return the DOM-{@link Event} caught from the target */ private static Event createDispatchAndCatchEvent( EventTarget target, String eventType, boolean canBubbleArg, boolean cancelableArg) { Property<Event> caughtEvent = new SimpleObjectProperty<>(); target.addEventListener(eventType, caughtEvent::setValue, false); Event createdEvent = createEvent(eventType, canBubbleArg, cancelableArg); target.dispatchEvent(createdEvent); return caughtEvent.getValue(); } /** * Creates and initializes a DOM event from the specified arguments. * * @param eventType * the type of the event as specified here: http://www.w3.org/TR/DOM-Level-3-Events/#event-types-list * @param canBubbleArg * indicates whether the event can bubble * @param cancelableArg * indicates whether the event can be canceled * @return the created and initialized DOM-{@link Event} */ private static Event createEvent(String eventType, boolean canBubbleArg, boolean cancelableArg) { Event event = new EventImpl(); event.initEvent(eventType, canBubbleArg, cancelableArg); return event; } // #end HELPER METHODS }