bug 428248 - Implement tests for nsIAccessibleHyperText interface r=Alexander Surkov (surkov.alexander@gmail.com) a1.9=beltzner
--- a/accessible/public/nsIAccessibleHyperText.idl
+++ b/accessible/public/nsIAccessibleHyperText.idl
@@ -37,21 +37,43 @@
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
#include "nsIAccessibleHyperLink.idl"
-[scriptable, uuid(dec56474-2887-4d44-9826-1594cfe4a2f4)]
+/**
+ * A cross-platform interface that deals with text which contains hyperlinks.
+ */
+
+[scriptable, uuid(d56bd454-8ff3-4edc-b266-baeada00267b)]
interface nsIAccessibleHyperText : nsISupports
{
- readonly attribute long links;
-
- nsIAccessibleHyperLink getLink (in long index);
+ /**
+ * Returns the number of links contained within this hypertext object.
+ */
+ readonly attribute long linkCount;
/*
- * Return the link index at this character index.
- * Return value of -1 indicates no link at that index.
+ * Returns the link index at the given character index.
+ * Each link is an embedded object representing exactly 1 character within
+ * the hypertext.
+ *
+ * @param charIndex the 0-based character index.
+ *
+ * @returns long 0-based link's index.
+ * A return value of -1 indicates no link is present at that index.
*/
- long getLinkIndex (in long charIndex);
+ long getLinkIndex(in long charIndex);
+
+ /**
+ * Retrieves the nsIAccessibleHyperLink object at the given link index.
+ *
+ * @param linkIndex 0-based index of the link that is to be retrieved.
+ * This can be retrieved via getLinkIndex (see above).
+ *
+ * @returns nsIAccessibleHyperLink Object representing the link properties
+ * or NS_ERROR_INVALID_ARG if there is no link at that index.
+ */
+ nsIAccessibleHyperLink getLink(in long linkIndex);
};
--- a/accessible/src/atk/nsAccessibleWrap.cpp
+++ b/accessible/src/atk/nsAccessibleWrap.cpp
@@ -868,17 +868,17 @@ getChildCountCB(AtkObject *aAtkObj)
return 0;
}
PRInt32 count = 0;
nsCOMPtr<nsIAccessibleHyperText> hyperText;
accWrap->QueryInterface(NS_GET_IID(nsIAccessibleHyperText), getter_AddRefs(hyperText));
if (hyperText) {
// If HyperText, then number of links matches number of children
- hyperText->GetLinks(&count);
+ hyperText->GetLinkCount(&count);
}
else {
nsCOMPtr<nsIAccessibleText> accText;
accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText), getter_AddRefs(accText));
if (!accText) { // Accessible text that is not a HyperText has no children
accWrap->GetChildCount(&count);
}
}
--- a/accessible/src/atk/nsMaiInterfaceHypertext.cpp
+++ b/accessible/src/atk/nsMaiInterfaceHypertext.cpp
@@ -87,17 +87,17 @@ getLinkCountCB(AtkHypertext *aText)
return -1;
nsCOMPtr<nsIAccessibleHyperText> hyperText;
accWrap->QueryInterface(NS_GET_IID(nsIAccessibleHyperText),
getter_AddRefs(hyperText));
NS_ENSURE_TRUE(hyperText, -1);
PRInt32 count = -1;
- nsresult rv = hyperText->GetLinks(&count);
+ nsresult rv = hyperText->GetLinkCount(&count);
NS_ENSURE_SUCCESS(rv, -1);
return count;
}
gint
getLinkIndexCB(AtkHypertext *aText, gint aCharIndex)
{
--- a/accessible/src/html/nsHyperTextAccessible.cpp
+++ b/accessible/src/html/nsHyperTextAccessible.cpp
@@ -1266,54 +1266,59 @@ nsHyperTextAccessible::GetOffsetAtPoint(
NS_ENSURE_TRUE(textLength >= 0, NS_ERROR_FAILURE);
offset += textLength;
}
return NS_OK; // Not found, will return -1
}
// ------- nsIAccessibleHyperText ---------------
-NS_IMETHODIMP nsHyperTextAccessible::GetLinks(PRInt32 *aLinks)
+NS_IMETHODIMP
+nsHyperTextAccessible::GetLinkCount(PRInt32 *aLinkCount)
{
- *aLinks = 0;
+ NS_ENSURE_ARG_POINTER(aLinkCount);
+ *aLinkCount = 0;
if (!mDOMNode) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIAccessible> accessible;
while (NextChild(accessible)) {
if (IsEmbeddedObject(accessible)) {
- ++*aLinks;
+ ++*aLinkCount;
}
}
return NS_OK;
}
NS_IMETHODIMP
-nsHyperTextAccessible::GetLink(PRInt32 aIndex, nsIAccessibleHyperLink **aLink)
+nsHyperTextAccessible::GetLink(PRInt32 aLinkIndex, nsIAccessibleHyperLink **aLink)
{
NS_ENSURE_ARG_POINTER(aLink);
*aLink = nsnull;
if (IsDefunct())
return NS_ERROR_FAILURE;
+ PRInt32 linkIndex = aLinkIndex;
nsCOMPtr<nsIAccessible> accessible;
while (NextChild(accessible)) {
- if (IsEmbeddedObject(accessible) && aIndex-- == 0)
+ if (IsEmbeddedObject(accessible) && linkIndex-- == 0)
return CallQueryInterface(accessible, aLink);
}
return NS_ERROR_INVALID_ARG;
}
-NS_IMETHODIMP nsHyperTextAccessible::GetLinkIndex(PRInt32 aCharIndex, PRInt32 *aLinkIndex)
+NS_IMETHODIMP
+nsHyperTextAccessible::GetLinkIndex(PRInt32 aCharIndex, PRInt32 *aLinkIndex)
{
+ NS_ENSURE_ARG_POINTER(aLinkIndex);
*aLinkIndex = -1; // API says this magic value means 'not found'
PRInt32 characterCount = 0;
PRInt32 linkIndex = 0;
if (!mDOMNode) {
return NS_ERROR_FAILURE;
}
--- a/accessible/src/msaa/CAccessibleHypertext.cpp
+++ b/accessible/src/msaa/CAccessibleHypertext.cpp
@@ -75,40 +75,40 @@ CAccessibleHypertext::get_nHyperlinks(lo
__try {
*aHyperlinkCount = 0;
nsCOMPtr<nsIAccessibleHyperText> hyperAcc(do_QueryInterface(this));
if (!hyperAcc)
return E_FAIL;
PRInt32 count = 0;
- nsresult rv = hyperAcc->GetLinks(&count);
+ nsresult rv = hyperAcc->GetLinkCount(&count);
if (NS_FAILED(rv))
return GetHRESULT(rv);
*aHyperlinkCount = count;
return S_OK;
} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
return E_FAIL;
}
STDMETHODIMP
-CAccessibleHypertext::get_hyperlink(long aIndex,
+CAccessibleHypertext::get_hyperlink(long aLinkIndex,
IAccessibleHyperlink **aHyperlink)
{
__try {
*aHyperlink = NULL;
nsCOMPtr<nsIAccessibleHyperText> hyperAcc(do_QueryInterface(this));
if (!hyperAcc)
return E_FAIL;
nsCOMPtr<nsIAccessibleHyperLink> hyperLink;
- nsresult rv = hyperAcc->GetLink(aIndex, getter_AddRefs(hyperLink));
+ nsresult rv = hyperAcc->GetLink(aLinkIndex, getter_AddRefs(hyperLink));
if (NS_FAILED(rv))
return GetHRESULT(rv);
nsCOMPtr<nsIWinAccessNode> winAccessNode(do_QueryInterface(hyperLink));
if (!winAccessNode)
return E_FAIL;
void *instancePtr = NULL;
--- a/accessible/tests/mochitest/Makefile.in
+++ b/accessible/tests/mochitest/Makefile.in
@@ -51,12 +51,13 @@ include $(topsrcdir)/config/rules.mk
test_groupattrs.xul \
test_table_indexes.html \
test_nsIAccessibleTable_1.html \
test_nsIAccessibleTable_2.html \
test_nsIAccessibleTable_3.html \
test_nsIAccessibleTable_4.html \
test_nsIAccessibleTable_listboxes.xul \
test_nsIAccessibleHyperLink.html \
+ test_nsIAccessibleHyperText.html \
$(NULL)
libs:: $(_TEST_FILES)
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/a11y/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/test_nsIAccessibleHyperText.html
@@ -0,0 +1,114 @@
+<!DOCTYPE html>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=428248
+-->
+<head>
+ <title>nsIHyper>TextAccessible chrome tests</title>
+ <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+ <script type="application/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
+ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+ <script type="application/javascript">
+ var gParagraphAcc;
+
+ function testThis(aID, aCharIndex, aExpectedLinkIndex, aName)
+ {
+ is(gParagraphAcc.getLinkIndex(aCharIndex), aExpectedLinkIndex,
+ "Wrong link index for ID " + aID + "!");
+ var linkAcc;
+ try {
+ linkAcc = gParagraphAcc.getLink(aExpectedLinkIndex);
+ } catch(e) {
+ ok(linkAcc, "No accessible for link " + aID + "!");
+ }
+ // Just test the link's name to make sure we get the right one.
+ is(linkAcc.getAnchor(0).name, aName, "Wrong name for " + aID + "!");
+ }
+
+ function doTest()
+ {
+ var accService = Components.classes["@mozilla.org/accessibleRetrieval;1"].
+ getService(Components.interfaces.nsIAccessibleRetrieval);
+
+ var paragraphElement = document.getElementById("testParagraph");
+ try {
+ gParagraphAcc = accService.getAccessibleFor(paragraphElement).
+ QueryInterface(Components.interfaces.nsIAccessibleHyperText);
+ } catch(e) {
+ ok(gParagraphAcc, "No interface for the paragraph!");
+ }
+
+ // Test link count
+ is(gParagraphAcc.linkCount, 7, "Wrong link count for paragraph!");
+
+ // normal hyperlink
+ testThis("NormalHyperlink", 14, 0, "Mozilla Foundation");
+
+ // ARIA hyperlink
+ testThis("AriaHyperlink", 28, 1, "Mozilla Foundation Home");
+
+ // ARIA hyperlink with status invalid
+ testThis("InvalidAriaHyperlink", 64, 2, "Invalid link");
+
+ // image map, but not its link children. They are not part of hypertext.
+ testThis("imgmap", 78, 3, "b");
+
+ // empty hyperlink
+ testThis("emptyLink", 93, 4, "");
+
+ // normal hyperlink with embedded span
+ testThis("LinkWithSpan", 119, 5, "Heise Online");
+
+ // Named anchor
+ testThis("namedAnchor", 197, 6, "This should never be of state_linked");
+
+ SimpleTest.finish();
+ }
+
+ SimpleTest.waitForExplicitFinish();
+ addLoadEvent(doTest);
+ </script>
+</head>
+<body>
+
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=418368">Mozilla Bug 418368</a>
+ <p id="display"></p>
+ <div id="content" style="display: none"></div>
+ <pre id="test">
+ </pre>
+ <p id="testParagraph">
+ <br>Simple link:<br>
+ <a id="NormalHyperlink" href="http://www.mozilla.org">Mozilla Foundation</a>
+ <br>ARIA link:<br>
+ <span id="AriaHyperlink" role="link"
+ onclick="window.open('http://www.mozilla.org/');"
+ tabindex="0">Mozilla Foundation Home</span>
+ <br>Invalid, non-focusable hyperlink:<br>
+ <span id="InvalidAriaHyperlink" role="link" aria-invalid="true"
+ onclick="window.open('http:/www.mozilla.org/');">Invalid link</span>
+ <br>Image map:<br>
+ <map name="atoz_map">
+ <area href="http://www.bbc.co.uk/radio4/atoz/index.shtml#b"
+ coords="17,0,30,14"
+ alt="b"
+ shape="rect"></area>
+ <area href="http://www.bbc.co.uk/radio4/atoz/index.shtml#a"
+ coords="0,0,13,14"
+ alt="a"
+ shape="rect"></area>
+ </map>
+ <img width="447" id="imgmap"
+ height="15"
+ usemap="#atoz_map"
+ src="http://www.bbc.co.uk/radio4/images/letters.gif"></img>
+ <br>Empty link:<br>
+ <a id="emptyLink" href=""><img src=""></img></a>
+ <br>Link with embedded span<br>
+ <a id="LinkWithSpan" href="http://www.heise.de/"><span lang="de">Heise Online</span></a>
+ <br>Named anchor, must not have "linked" state for it to be exposed correctly:<br>
+ <a id="namedAnchor" name="named_anchor">This should never be of state_linked</a>
+ </p>
+</body>
+</html>