Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Steur <thomas.steur@googlemail.com>2014-09-05 13:42:51 +0400
committerThomas Steur <thomas.steur@googlemail.com>2014-09-05 13:42:51 +0400
commit96ed663d643b55b2f6fa86777d58e25e53eb3fce (patch)
tree7e3bea0542b9c66a1732b8c63e79363c2720dd39
parente89de039de65e9bc8c92b738fd73ed3cf3fac371 (diff)
refs #4996 a lot of new tests and bugfixes, also some code improvements
-rw-r--r--js/piwik.js243
-rw-r--r--misc/internal-docs/content-tracking.md1
-rw-r--r--tests/javascript/content-fixtures/contentUtilities.html58
-rw-r--r--tests/javascript/index.php87
4 files changed, 275 insertions, 114 deletions
diff --git a/js/piwik.js b/js/piwik.js
index 2d85834e07..9ae51a4b9a 100644
--- a/js/piwik.js
+++ b/js/piwik.js
@@ -1116,6 +1116,9 @@ if (typeof Piwik !== 'object') {
},
find: function (selector)
{
+ // we use querySelectorAll only on document, not on nodes because of its unexpected behavior. See for
+ // instance http://stackoverflow.com/questions/11503534/jquery-vs-document-queryselectorall and
+ // http://jsfiddle.net/QdMc5/ and http://ejohn.org/blog/thoughts-on-queryselectorall
if (!document.querySelectorAll || !selector) {
return []; // we do not support all browsers
}
@@ -1141,6 +1144,15 @@ if (typeof Piwik !== 'object') {
return nodes;
},
+ findNodesByTagName: function (node, tagName) {
+ if (!node || !tagName || !node.getElementsByTagName) {
+ return [];
+ }
+
+ var foundNodes = node.getElementsByTagName(tagName);
+
+ return this.htmlCollectionToArray(foundNodes);
+ },
makeNodesUnique: function (nodes)
{
nodes.sort(function (n1, n2) {
@@ -1337,6 +1349,16 @@ if (typeof Piwik !== 'object') {
if (nodes && nodes.length) {
return nodes[0]; // TODO here we should check whether this node is also present within another nested piece of content and if there are multiple other nodes maybe use the next one
}
+ },
+ isLinkElement: function (node) {
+ if (!node) {
+ return false;
+ }
+
+ var elementName = (node.nodeName + '').toLowerCase();
+ var linkElementNames = ['a', 'area'];
+
+ return linkElementNames.indexOf(elementName) !== -1;
}
}
@@ -1369,6 +1391,8 @@ if (typeof Piwik !== 'object') {
return [];
}
+ // NOTE: we do not use query.findMultiple here as querySelectorAll would most likely not deliver the result we want
+
var nodes1 = query.findNodesHavingCssClass(node, this.CONTENT_CLASS);
var nodes2 = query.findNodesHavingAttribute(node, this.CONTENT_ATTR);
@@ -1560,7 +1584,8 @@ if (typeof Piwik !== 'object') {
var mediaElements = ['img', 'embed', 'video', 'audio'];
var elementName = node.nodeName.toLowerCase();
- if (-1 !== mediaElements.indexOf(elementName) && query.findFirstNodeHavingAttributeWithValue(node, 'src')) {
+ if (-1 !== mediaElements.indexOf(elementName) &&
+ query.findFirstNodeHavingAttributeWithValue(node, 'src')) {
var sourceNode = query.findFirstNodeHavingAttributeWithValue(node, 'src');
@@ -1570,6 +1595,24 @@ if (typeof Piwik !== 'object') {
if (elementName === 'object' && query.hasNodeAttributeWithValue(node, 'data')) {
return query.getAttributeValueFromNode(node, 'data');
+
+ } else if (elementName === 'object') {
+ var params = query.findNodesByTagName(node, 'param');
+ if (params && params.length) {
+ var index;
+ for (index = 0; index < params.length; index++) {
+ if ('movie' === query.getAttributeValueFromNode(params[index], 'name') &&
+ query.hasNodeAttributeWithValue(params[index], 'value')) {
+
+ return query.getAttributeValueFromNode(params[index], 'value');
+ }
+ }
+ }
+
+ var embed = query.findNodesByTagName(node, 'embed');
+ if (embed && embed.length) {
+ return this.findMediaUrlInNode(embed[0]);
+ }
}
},
trim: function (text) {
@@ -1704,8 +1747,8 @@ if (typeof Piwik !== 'object') {
return this.getLocation().origin + this.getLocation().pathname + url;
}
- // Eg mailto:x@y.z tel:012345, ... market:... sms:... and many more
- if (0 === url.search('^[a-zA-Z]{2,8}:')) {
+ // Eg mailto:x@y.z tel:012345, ... market:... sms:..., javasript:... ecmascript: ... and many more
+ if (0 === url.search('^[a-zA-Z]{2,11}:')) {
return url;
}
@@ -1718,43 +1761,16 @@ if (typeof Piwik !== 'object') {
var base = this.getLocation().origin + this.getLocation().pathname.match(/(.*\/)/)[0]
return base + url
},
- findInternalTargetLinkFromHref: function (targetNode)
- {
- if (!targetNode) {
- return;
- }
-
- var link;
- if (query.hasNodeAttributeWithValue(targetNode, 'href')) {
- link = query.getAttributeValueFromNode(targetNode, 'href');
- }
-
- if (!link) {
- return;
- }
-
- if (link !== this.removeDomainIfIsUrl(link)) {
- return; // outlink or download?
- }
-
- return link;
- },
- replaceTargetLink: function (node, url)
+ setHrefAttribute: function (node, url)
{
- var clickNode = this.findTargetNode(node);
-
- if (!clickNode) {
- return;
- }
-
- var elementName = clickNode.nodeName.toLowerCase();
-
- if (elementName !== 'a') {
+ if (!node || !url) {
return;
}
- if (clickNode && clickNode.setAttribute) {
- clickNode.setAttribute('href', url);
+ if (node.setAttribute) {
+ node.setAttribute('href', url);
+ } else {
+ node.href = url;
}
},
shouldIgnoreInteraction: function (targetNode) {
@@ -2930,72 +2946,52 @@ if (typeof Piwik !== 'object') {
}
for (index = 0; index < contentNodes.length; index++) {
- // TODO should we consult getLinkType()?
var targetNode = content.findTargetNode(contentNodes[index]);
- if (!targetNode) {
+ if (!targetNode || targetNode.contentInteractionTrackingSetupDone) {
continue;
}
- if (targetNode.contentTrackingRedirectSetupDone) {
- continue;
- }
-
- targetNode.contentTrackingRedirectSetupDone = true;
+ targetNode.contentInteractionTrackingSetupDone = true;
if (content.shouldIgnoreInteraction(targetNode)) {
continue;
}
- if (targetNode.nodeName.toLowerCase() === 'a' &&
- query.hasNodeAttributeWithValue(targetNode, 'href')) {
+ addEventListener(targetNode, 'click', function () {
- var internalLink = content.findInternalTargetLinkFromHref(targetNode);
+ var link = getLinkIfShouldBeProcessed(this);
- if (internalLink) {
-
- content.replaceTargetLink(targetNode, buildTrackingRedirectUrl(internalLink));
+ if (link && link.type) {
+ // click ignore, will be tracked via processClick, we do not want to track it twice
+ return;
+ }
- addEventListener(targetNode, 'click', function () {
- var url = content.findInternalTargetLinkFromHref(this);
- if (!url) {
- return;
- }
+ var contentBlock = content.findParentContentNode(this);
+ var contentName = content.findContentName(contentBlock);
+ var contentPiece = content.findContentPiece(contentBlock);
+ var contentTarget = content.findContentTarget(contentBlock);
+ var targetNode = content.findTargetNode(contentBlock); // should be actually same as 'this'
- var contentName = content.findContentName(this);
- var contentPiece = content.findContentPiece(this);
- var contentTarget = content.findContentTarget(this);
+ if (query.isLinkElement(targetNode) &&
+ query.hasNodeAttributeWithValue(targetNode, 'href')) {
+ var url = query.getAttributeValueFromNode(targetNode, 'href');
- if (0 === internalLink.indexOf('#')) {
- var request = buildContentInteractionTrackingRequest('click', contentName, contentPiece, contentTarget);
- sendRequest(request);
- } else {
- var targetUrl = buildContentInteractionTrackingRedirectUrl(internalLink, contentName, contentPiece, contentTarget);
+ if (0 !== url.indexOf('#')) {
- // location.href does not respect target=_blank so we prefer to use this
- content.replaceTargetLink(content.findTargetNode(this), targetUrl);
- }
+ var targetUrl = buildContentInteractionTrackingRedirectUrl(url, contentName, contentPiece, contentTarget);
- });
+ // location.href does not respect target=_blank so we prefer to use this
+ content.setHrefAttribute(targetNode, targetUrl);
+ return;
+ }
- } else {
- // outlink or download
}
- } else {
- // trigger event
-
- addEventListener(targetNode, 'click', function () {
- var contentName = content.findContentName(this);
- var contentPiece = content.findContentPiece(this);
- var contentTarget = content.findContentTarget(this);
-
- var request = buildContentInteractionTrackingRequest('', contentName, contentPiece, contentTarget);
-
- sendRequest(request);
- });
- }
-
+ // click on any non link element, or on a link element that has not an href attribute or on an anchor
+ var request = buildContentInteractionTrackingRequest('click', contentName, contentPiece, contentTarget);
+ sendRequest(request, configTrackerPause);
+ });
}
var index, request;
@@ -3236,52 +3232,83 @@ if (typeof Piwik !== 'object') {
// does file extension indicate that it is a download?
downloadExtensionsPattern = new RegExp('\\.(' + configDownloadExtensions + ')([?&#]|$)', 'i');
- // optimization of the if..elseif..else construct below
- return linkPattern.test(className) ? 'link' : (downloadPattern.test(className) || downloadExtensionsPattern.test(href) ? 'download' : (isInLink ? 0 : 'link'));
+ if (linkPattern.test(className)) {
+ return 'link';
+ }
+
+ if (downloadPattern.test(className) || downloadExtensionsPattern.test(href)) {
+ return 'download';
+ }
+
+ if (isInLink) {
+ return 0;
+ }
+
+ return 'link';
}
- /*
- * Process clicks
- */
- function processClick(sourceElement) {
- var parentElement,
- tag,
- linkType,
- originalSource;
+ function getSourceElement(sourceElement)
+ {
+ var parentElement;
- originalSource = sourceElement;
parentElement = sourceElement.parentNode;
while (parentElement !== null &&
/* buggy IE5.5 */
isDefined(parentElement)) {
- tag = sourceElement.tagName.toUpperCase();
- if (tag === 'A' || tag === 'AREA') {
+
+ if (query.isLinkElement(sourceElement)) {
break;
}
sourceElement = parentElement;
parentElement = sourceElement.parentNode;
}
- if (isDefined(sourceElement.href)) {
- // browsers, such as Safari, don't downcase hostname and href
- var originalSourceHostName = sourceElement.hostname || getHostName(sourceElement.href),
- sourceHostName = originalSourceHostName.toLowerCase(),
- sourceHref = sourceElement.href.replace(originalSourceHostName, sourceHostName),
- scriptProtocol = new RegExp('^(javascript|vbscript|jscript|mocha|livescript|ecmascript|mailto):', 'i');
+ return sourceElement;
+ }
+
+ function getLinkIfShouldBeProcessed(sourceElement)
+ {
+ sourceElement = getSourceElement(sourceElement);
+
+ if (!isDefined(sourceElement.href)) {
+ return;
+ }
+
+ // browsers, such as Safari, don't downcase hostname and href
+ var originalSourceHostName = sourceElement.hostname || getHostName(sourceElement.href);
+ var sourceHostName = originalSourceHostName.toLowerCase();
+ var sourceHref = sourceElement.href.replace(originalSourceHostName, sourceHostName);
+
+ // browsers, such as Safari, don't downcase hostname and href
+ var scriptProtocol = new RegExp('^(javascript|vbscript|jscript|mocha|livescript|ecmascript|mailto):', 'i');
- // ignore script pseudo-protocol links
- if (!scriptProtocol.test(sourceHref)) {
- // track outlinks and all downloads
- linkType = getLinkType(sourceElement.className, sourceHref, isSiteHostName(sourceHostName));
+ if (!scriptProtocol.test(sourceHref)) {
+ // track outlinks and all downloads
+ var linkType = getLinkType(sourceElement.className, sourceHref, isSiteHostName(sourceHostName));
- // urldecode %xx
- sourceHref = urldecode(sourceHref);
- logLink(sourceHref, linkType, undefined, null, originalSource);
+ if (linkType) {
+ return {
+ type: linkType,
+ href: sourceHref
+ };
}
}
}
/*
+ * Process clicks
+ */
+ function processClick(sourceElement) {
+ var link = getLinkIfShouldBeProcessed(sourceElement);
+
+ if (link && link.type) {
+ // urldecode %xx
+ link.href = urldecode(link.href);
+ logLink(link.href, link.type, undefined, null, sourceElement);
+ }
+ }
+
+ /*
* Handle click event
*/
function clickHandler(evt) {
diff --git a/misc/internal-docs/content-tracking.md b/misc/internal-docs/content-tracking.md
index 92ab8b3c23..a61fbe98f8 100644
--- a/misc/internal-docs/content-tracking.md
+++ b/misc/internal-docs/content-tracking.md
@@ -62,6 +62,7 @@ If we do not find any specific content piece element, we will use the content bl
* The simplest scenario is to provide an HTML attribute `data-content-piece="foo"` including a value anywhere within the content block or in the content block element itself.
* If there is no such attribute we will check whether the content piece element is a media (audio, video, image) and we will try to detect the URL to the media automatically. For instance using the `src` attribute.
+ * In case of video and audio elements, when there are multiple sources defined, we will choose the URL of the first source
* If we haven't found anything we will fall back to use the value "Unknown". In such a case you should set the attribute `data-content-piece` telling us explicitly what the content is.
Examples:
diff --git a/tests/javascript/content-fixtures/contentUtilities.html b/tests/javascript/content-fixtures/contentUtilities.html
index 92d6a690ae..e9a3e83b99 100644
--- a/tests/javascript/content-fixtures/contentUtilities.html
+++ b/tests/javascript/content-fixtures/contentUtilities.html
@@ -4,6 +4,64 @@
<div id="ignoreInteraction2" data-track-content>
<a href="http://www.example.com" class="piwikContentTarget" data-content-ignoreinteraction>Link</a>
</div>
+<!-- targetNode in this example is the content block node -->
+<div id="ignoreInteraction3" data-track-content data-content-ignoreinteraction>
+ <a href="http://www.example.com">Link</a>
+</div>
+<!-- targetNode in this example is the content block node -->
+<div id="ignoreInteraction4" data-track-content class="piwikContentIgnoreInteraction">
+ <a href="http://www.example.com">Link</a>
+</div>
+
<div id="notIgnoreInteraction1" data-track-content>
<a href="http://www.example.com" class="piwikContentTarget">Link</a>
+</div>
+<!-- Will not be ignored since set on wrong element, has to be set on content target node -->
+<div id="notIgnoreInteraction2" data-track-content data-content-ignoreinteraction class="piwikContentIgnoreInteraction">
+ <a href="http://www.example.com" class="piwikContentTarget">Link</a>
+</div>
+
+<a href="http://www.example.com" id="aLinkToBeChanged">Link</a>
+
+<div class="media">
+ <div id="mediaDiv" src="test/img.jpg"/>
+ <img id="mediaImg" src="test/img.jpg"/>
+
+ <video id="mediaVideo" width="320" height="240" controls>
+ <source src="movie.mp4" type="video/mp4">
+ <source src="movie.ogg" type="video/ogg">
+ Your browser does not support the video tag.
+ </video>
+
+ <audio id="mediaAudio" controls>
+ <source src="audio.ogg" type="audio/ogg">
+ <source src="audio.mp3" type="audio/mpeg">
+ Your browser does not support the audio element.
+ </audio>
+
+ <embed id="mediaEmbed" src="embed.swf">
+
+ <object id="mediaObjectSimple" width="400" height="400" data="objectSimple.swf"></object>
+
+ <object id="mediaObjectParam" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="550"
+ height="400" id="movie_name" align="middle">
+ <param name="anything" value="anyvalue"/>
+ <param name="movie" value="movie_param1.swf"/>
+ <!--[if !IE]>-->
+ <object type="application/x-shockwave-flash" data="movie_inner.swf" width="550" height="400">
+ <param name="movie" value="movie_param2.swf"/>
+ <!<![endif]--> <a href="http://www.adobe.com/go/getflash"> <img
+ src="http://www.adobe.com/de/images/shared/download_buttons/get_flash_player.gif"
+ alt="Get Adobe Flash player"/> </a> <!--[if !IE]>--> </object>
+ <!<![endif]-->
+ </object>
+
+ <object id="mediaObjectPdf" data="document.pdf" type="application/pdf">
+ <embed src="document2.pdf" type="application/pdf" />
+ </object>
+
+ <!-- should fall back to embed as no data specified -->
+ <object id="mediaObjectEmbed" data="" type="application/pdf">
+ <embed src="document2.pdf" type="application/pdf" />
+ </object>
</div> \ No newline at end of file
diff --git a/tests/javascript/index.php b/tests/javascript/index.php
index 9e876445f6..dca94b2db4 100644
--- a/tests/javascript/index.php
+++ b/tests/javascript/index.php
@@ -200,6 +200,10 @@ function setupContentTrackingFixture(name) {
</ul>
<div id="clickDiv"></div>
</div>
+ <map name="map">
+ <area id="area1" shape="rect" coords="0,0,10,10" href="img.jpg" alt="Piwik">
+ <area shape="circle" coords="10,10,10,20" href="img2.jpg" alt="Piwik2">
+ </map>
<ol id="qunit-tests"></ol>
@@ -562,6 +566,25 @@ function PiwikTest() {
ok(-1 !== actual.indexOf(_e('click1')), 'htmlCollectionToArray, random check to make sure it contains a link');
+ actual = query.isLinkElement();
+ strictEqual(actual, false, "isLinkElement, no element set");
+
+ actual = query.isLinkElement(_e('div1'));
+ strictEqual(actual, false, "isLinkElement, a div is not a link element");
+
+ actual = query.isLinkElement(document.createTextNode('ff'));
+ strictEqual(actual, false, "isLinkElement, a text node is not a link element");
+
+ actual = query.isLinkElement(document.createComment('tt'));
+ strictEqual(actual, false, "isLinkElement, a comment is not a link element");
+
+ actual = query.isLinkElement(_e('area1'));
+ strictEqual(actual, true, "isLinkElement, an area element is a link element");
+
+ actual = query.isLinkElement(_e('click1'));
+ strictEqual(actual, true, "isLinkElement, an a element is a link element");
+
+
actual = query.find();
propEqual(actual, [], "find, no selector passed should return an empty array");
@@ -598,6 +621,26 @@ function PiwikTest() {
actual = query.findMultiple(['.piwik_link', '[data-content-piece]', '#image2', '#div1']);
propEqual(actual, [_e('image2'), _e('div1'), _e('click5')], "findMultiple, should make nodes unique in case we select the same multiple times");
+
+
+ actual = query.findNodesByTagName();
+ propEqual(actual, [], "findNodesByTagName, no element and no tag name set");
+
+ actual = query.findNodesByTagName(document.body);
+ propEqual(actual, [], "findNodesByTagName, no tag name set");
+
+ actual = query.findNodesByTagName(document.body, 'notExistingOne');
+ propEqual(actual, [], "findNodesByTagName, should not find any such element");
+
+ actual = query.findNodesByTagName(document.body, 'a');
+ ok($.isArray(actual), "findNodesByTagName, should always return an array");
+
+ actual = query.findNodesByTagName(document.body, 'h1');
+ propEqual(actual, [_e('qunit-header')], "findNodesByTagName, find exactly one");
+
+ actual = query.findNodesByTagName(document.body, 'a');
+ ok(actual.length > 10, "findNodesByTagName, find many, even nested ones");
+ ok(actual.indexOf(_e('click1')), "findNodesByTagName, just a random test to make sure it actually contains a link");
});
test("contentFindContentBlock", function() {
@@ -764,6 +807,7 @@ function PiwikTest() {
var tracker = Piwik.getTracker();
var content = tracker.getContent();
+ var query = tracker.getQuery();
content.setLocation(); // clear possible previous location
var actual, expected;
@@ -806,6 +850,11 @@ function PiwikTest() {
strictEqual(content.shouldIgnoreInteraction(node), false, message);
}
+ function assertFoundMediaUrl(id, expected, message) {
+ var node = content.findPieceNode(_e(id));
+ strictEqual(content.findMediaUrlInNode(node), expected, message);
+ }
+
var locationAlias = $.extend({}, window.location);
var origin = locationAlias.origin;
@@ -852,10 +901,11 @@ function PiwikTest() {
assertBuildsAbsoluteUrl('path/x?p=5', origin + '/tests/javascript/path/x?p=5', 'relative path');
assertBuildsAbsoluteUrl('#test', origin + '/tests/javascript/#test', 'anchor url');
assertBuildsAbsoluteUrl('//' + locationAlias.host + '/test/img.jpg', origin + '/test/img.jpg', 'inherit protocol url');
- assertBuildsAbsoluteUrl('mailto:test@example.com', 'mailto:test@example.com', 'mailto special url');
- assertBuildsAbsoluteUrl('tel:0123456789', 'tel:0123456789', 'tel special url');
- assertBuildsAbsoluteUrl('anythingg:test', origin + '/tests/javascript/anythingg:test', 'we do not treat this one as special url as we recognize max 8 characters currently');
- assertBuildsAbsoluteUrl('k1dm:test', origin + '/tests/javascript/k1dm:test', 'we do not treat this one as special url as it contains a number');
+ assertBuildsAbsoluteUrl('mailto:test@example.com', 'mailto:test@example.com', 'mailto pseudo-protocol url');
+ assertBuildsAbsoluteUrl('javascript:void 0', 'javascript:void 0', 'javascript pseudo-protocol url');
+ assertBuildsAbsoluteUrl('tel:0123456789', 'tel:0123456789', 'tel pseudo-protocol url');
+ assertBuildsAbsoluteUrl('anythinggggggggg:test', origin + '/tests/javascript/anythinggggggggg:test', 'we do not treat this one as pseudo-protocol url as there are too many characters before colon');
+ assertBuildsAbsoluteUrl('k1dm:test', origin + '/tests/javascript/k1dm:test', 'we do not treat this one as pseudo-protocol url as it contains a number');
locationAlias.pathname = '/test/';
content.setLocation(locationAlias);
@@ -886,12 +936,37 @@ function PiwikTest() {
ok("test shouldIgnoreInteraction(targetNode)");
assertShouldIgnoreInteraction('ignoreInteraction1', 'should be ignored because of CSS class');
assertShouldIgnoreInteraction('ignoreInteraction2', 'should be ignored because of Attribute');
+ assertShouldIgnoreInteraction('ignoreInteraction3', 'should be ignored because of CSS class');
+ assertShouldIgnoreInteraction('ignoreInteraction4', 'should be ignored because of Attribute');
assertShouldNotIgnoreInteraction('notIgnoreInteraction1', 'should not be ignored');
+ assertShouldNotIgnoreInteraction('notIgnoreInteraction2', 'should not be ignored as set in wrong element');
+
+
+ ok("test setHrefAttribute(node, url)");
+ var aElement = _e('aLinkToBeChanged');
+ content.setHrefAttribute(); // should not fail if no arguments
+ strictEqual(query.getAttributeValueFromNode(aElement, 'href'), 'http://www.example.com', 'setHrefAttribute, check initial link value');
+ content.setHrefAttribute(aElement);
+ content.setHrefAttribute(aElement, '');
+ strictEqual(query.getAttributeValueFromNode(aElement, 'href'), 'http://www.example.com', 'setHrefAttribute, an empty URL should not be set');
+ content.setHrefAttribute(aElement, '/test');
+ strictEqual(query.getAttributeValueFromNode(aElement, 'href'), '/test', 'setHrefAttribute, link should be changed now');
+
+ strictEqual(content.findMediaUrlInNode(), undefined, 'should not fail if no node passed');
+ ok(_e('click1') && _e('mediaDiv'), 'make sure both nodes exist otherwise following two assertions to not test what we want');
+ assertFoundMediaUrl('click1', undefined, 'should not find anything in a link as it is not a media');
+ assertFoundMediaUrl('mediaDiv', undefined, 'should not find anything in a non media element even if it defines a src attribute');
+ assertFoundMediaUrl('mediaImg', 'test/img.jpg', 'should find url of image');
+ assertFoundMediaUrl('mediaVideo', 'movie.mp4', 'should find url of video, first one should be used');
+ assertFoundMediaUrl('mediaAudio', 'audio.ogg', 'should find url of audio, first one should be used');
+ assertFoundMediaUrl('mediaEmbed', 'embed.swf', 'should find url of embed element');
+ assertFoundMediaUrl('mediaObjectSimple', 'objectSimple.swf', 'should find url of a simple object element');
+ assertFoundMediaUrl('mediaObjectParam', 'movie_param1.swf', 'should find url of a simple object element');
+ assertFoundMediaUrl('mediaObjectPdf', 'document.pdf', 'should find url of an object that contains non flash resources such as pdf');
+ assertFoundMediaUrl('mediaObjectEmbed', 'document2.pdf', 'should fallback to an embed in an object');
// isOrWasNodeInViewport
// isNodeVisible
- // findInternalTargetLinkFromHref
- // replaceTargetLink
});