Bug 562790: Support paid results in the add-ons search results. r=Unfocused, a=blocks-betaN

This commit is contained in:
Dave Townsend 2011-01-07 09:09:09 -08:00
Родитель 1e4c622c5c
Коммит 0266782ff5
9 изменённых файлов: 647 добавлений и 18 удалений

Просмотреть файл

@ -220,6 +220,22 @@ AddonSearchResult.prototype = {
*/
contributionAmount: null,
/**
* The URL to visit in order to purchase the add-on
*/
purchaseURL: null,
/**
* The numerical cost of the add-on in some currency, for sorting purposes
* only
*/
purchaseAmount: null,
/**
* The display cost of the add-on, for display purposes only
*/
purchaseDisplayAmount: null,
/**
* The rating of the add-on, 0-5
*/
@ -278,10 +294,16 @@ AddonSearchResult.prototype = {
/**
* True or false depending on whether the add-on is compatible with the
* current version and platform of the application
* current version of the application
*/
isCompatible: true,
/**
* True or false depending on whether the add-on is compatible with the
* current platform
*/
isPlatformCompatible: true,
/**
* True if the add-on has a secure means of updating
*/
@ -928,6 +950,17 @@ var AddonRepository = {
addon.contributionAmount = suggestedAmount;
}
break
case "payment_data":
let link = this._getDescendantTextContent(node, "link");
let amountTag = this._getUniqueDescendant(node, "amount");
let amount = parseFloat(amountTag.getAttribute("amount"));
let displayAmount = this._getTextContent(amountTag);
if (link != null && amount != null && displayAmount != null) {
addon.purchaseURL = link;
addon.purchaseAmount = amount;
addon.purchaseDisplayAmount = displayAmount;
}
break
case "rating":
let averageRating = parseInt(this._getTextContent(node));
if (averageRating >= 0)
@ -946,6 +979,13 @@ var AddonRepository = {
if (!isNaN(repositoryStatus))
addon.repositoryStatus = repositoryStatus;
break;
case "all_compatible_os":
let nodes = node.getElementsByTagName("os");
addon.isPlatformCompatible = Array.some(nodes, function(aNode) {
let text = aNode.textContent.toLowerCase().trim();
return text == "all" || text == Services.appinfo.OS.toLowerCase();
});
break;
case "install":
// No os attribute means the xpi is compatible with any os
if (node.hasAttribute("os")) {
@ -1030,8 +1070,13 @@ var AddonRepository = {
if (requiredAttributes.some(function(aAttribute) !result.addon[aAttribute]))
continue;
// Add only if there was an xpi compatible with this OS
if (!result.xpiURL)
// Add only if the add-on is compatible with the platform
if (!result.addon.isPlatformCompatible)
continue;
// Add only if there was an xpi compatible with this OS or there was a
// way to purchase the add-on
if (!result.xpiURL && !result.addon.purchaseURL)
continue;
results.push(result);
@ -1057,9 +1102,14 @@ var AddonRepository = {
self._reportSuccess(results, aTotalResults);
}
if (aResult.xpiURL) {
AddonManager.getInstallForURL(aResult.xpiURL, callback,
"application/x-xpinstall", aResult.xpiHash,
addon.name, addon.iconURL, addon.version);
}
else {
callback(null);
}
});
},

Просмотреть файл

@ -948,6 +948,16 @@ var gViewController = {
}
},
cmd_purchaseItem: {
isEnabled: function(aAddon) {
if (!aAddon)
return false;
return !!aAddon.purchaseURL;
},
doCommand: function(aAddon) {
openURL(aAddon.purchaseURL);
}
},
cmd_uninstallItem: {
isEnabled: function(aAddon) {
@ -1181,7 +1191,7 @@ function createItem(aObj, aIsInstall, aIsRemote) {
function sortElements(aElements, aSortBy, aAscending) {
const DATE_FIELDS = ["updateDate"];
const INTEGER_FIELDS = ["size", "relevancescore"];
const NUMERIC_FIELDS = ["size", "relevancescore", "purchaseAmount"];
function dateCompare(a, b) {
var aTime = a.getTime();
@ -1193,7 +1203,7 @@ function sortElements(aElements, aSortBy, aAscending) {
return 0;
}
function intCompare(a, b) {
function numberCompare(a, b) {
return a - b;
}
@ -1218,8 +1228,8 @@ function sortElements(aElements, aSortBy, aAscending) {
var sortFunc = stringCompare;
if (DATE_FIELDS.indexOf(aSortBy) != -1)
sortFunc = dateCompare;
else if (INTEGER_FIELDS.indexOf(aSortBy) != -1)
sortFunc = intCompare;
else if (NUMERIC_FIELDS.indexOf(aSortBy) != -1)
sortFunc = numberCompare;
aElements.sort(function(a, b) {
if (!aAscending)
@ -1736,6 +1746,7 @@ var gSearchView = {
this.showEmptyNotice(false);
this.showAllResultsLink(0);
this.showLoading(true);
this._sorters.showprice = false;
gHeader.searchQuery = aQuery;
aQuery = aQuery.trim().toLocaleLowerCase();
@ -1770,8 +1781,11 @@ var gSearchView = {
let item = createItem(aObj, aIsInstall, aIsRemote);
item.setAttribute("relevancescore", score);
if (aIsRemote)
if (aIsRemote) {
gCachedAddons[aObj.id] = aObj;
if (aObj.purchaseURL)
self._sorters.showprice = true;
}
elements.push(item);
});
@ -2244,6 +2258,14 @@ var gDetailView = {
contributions.hidden = true;
}
if ("purchaseURL" in aAddon && aAddon.purchaseURL) {
var purchase = document.getElementById("detail-purchase-btn");
purchase.label = gStrings.ext.formatStringFromName("cmd.purchaseAddon.label",
[aAddon.purchaseDisplayAmount],
1);
purchase.accesskey = gStrings.ext.GetStringFromName("cmd.purchaseAddon.accesskey");
}
var updateDateRow = document.getElementById("detail-dateUpdated");
if (aAddon.updateDate) {
var date = formatDate(aAddon.updateDate);

Просмотреть файл

@ -248,6 +248,10 @@
label="&sort.dateUpdated.label;"
tooltiptext="&sort.dateUpdated.tooltip;"
oncommand="this.parentNode._handleChange('updateDate');"/>
<xul:button anonid="price-btn" class="sorter" hidden="true"
label="&sort.price.label;"
tooltiptext="&sort.price.tooltip;"
oncommand="this.parentNode._handleChange('purchaseAmount');"/>
<xul:button anonid="relevance-btn" class="sorter" hidden="true"
label="&sort.relevance.label;"
tooltiptext="&sort.relevance.tooltip;"
@ -262,6 +266,9 @@
if (this.getAttribute("showrelevance") == "true")
this._btnRelevance.hidden = false;
if (this.getAttribute("showprice") == "true")
this._btnPrice.hidden = false;
this._refreshState();
]]></constructor>
@ -272,6 +279,9 @@
<field name="_btnDate">
document.getAnonymousElementByAttribute(this, "anonid", "date-btn");
</field>
<field name="_btnPrice">
document.getAnonymousElementByAttribute(this, "anonid", "price-btn");
</field>
<field name="_btnRelevance">
document.getAnonymousElementByAttribute(this, "anonid", "relevance-btn");
</field>
@ -301,6 +311,28 @@
]]></setter>
</property>
<property name="showrelevance">
<getter><![CDATA[
return (this.getAttribute("showrelevance") == "true");
]]></getter>
<setter><![CDATA[
val = !!val;
this.setAttribute("showrelevance", val);
this._btnRelevance.hidden = !val;
]]></setter>
</property>
<property name="showprice">
<getter><![CDATA[
return (this.getAttribute("showprice") == "true");
]]></getter>
<setter><![CDATA[
val = !!val;
this.setAttribute("showprice", val);
this._btnPrice.hidden = !val;
]]></setter>
</property>
<method name="setSort">
<parameter name="aSort"/>
<parameter name="aAscending"/>
@ -325,7 +357,7 @@
<method name="_handleChange">
<parameter name="aSort"/>
<body><![CDATA[
const ASCENDING_SORT_FIELDS = ["name"];
const ASCENDING_SORT_FIELDS = ["name", "purchaseAmount"];
// Toggle ascending if sort by is not changing, otherwise
// name sorting defaults to ascending, others to descending
@ -357,6 +389,14 @@
this._btnDate.checked = false;
}
if (sortBy == "purchaseAmount") {
this._btnPrice.checkState = checkState;
this._btnPrice.checked = true;
} else {
this._btnPrice.checkState = 0;
this._btnPrice.checked = false;
}
if (sortBy == "relevancescore") {
this._btnRelevance.checkState = checkState;
this._btnRelevance.checked = true;
@ -484,6 +524,9 @@
<content>
<xul:label anonid="message"/>
<xul:progressmeter anonid="progress" class="download-progress"/>
<xul:button anonid="purchase-remote-btn" hidden="true"
class="addon-control"
oncommand="document.getBindingParent(this).purchaseRemote();"/>
<xul:button anonid="install-remote-btn" hidden="true"
class="addon-control install" label="&addon.install.label;"
tooltiptext="&addon.install.tooltip;"
@ -500,7 +543,7 @@
this.initWithInstall(this.mInstall);
else if (this.mControl.mAddon.install)
this.initWithInstall(this.mControl.mAddon.install);
else if (this.mAddon)
else
this.refreshState();
]]></constructor>
@ -515,6 +558,10 @@
<field name="_progress">
document.getAnonymousElementByAttribute(this, "anonid", "progress");
</field>
<field name="_purchaseRemote">
document.getAnonymousElementByAttribute(this, "anonid",
"purchase-remote-btn");
</field>
<field name="_installRemote">
document.getAnonymousElementByAttribute(this, "anonid",
"install-remote-btn");
@ -549,6 +596,7 @@
<body><![CDATA[
var showInstallRemote = false;
var showRestartInstall = false;
var showPurchase = false;
if (this.mInstall) {
@ -586,8 +634,17 @@
break;
}
} else if (this.mControl.mAddon.purchaseURL) {
this._progress.hidden = true;
showPurchase = true;
this._purchaseRemote.label =
gStrings.ext.formatStringFromName("addon.purchase.label",
[this.mControl.mAddon.purchaseDisplayAmount], 1);
this._purchaseRemote.tooltiptext =
gStrings.ext.GetStringFromName("addon.purchase.tooltip");
}
this._purchaseRemote.hidden = !showPurchase;
this._installRemote.hidden = !showInstallRemote;
this._restartInstall.hidden = !showRestartInstall;
]]></body>
@ -608,6 +665,12 @@
]]></body>
</method>
<method name="purchaseRemote">
<body><![CDATA[
openURL(this.mControl.mAddon.purchaseURL);
]]></body>
</method>
<method name="installRemote">
<body><![CDATA[
if (this.mControl.getAttribute("remote") != "true")
@ -1206,8 +1269,8 @@
this.setAttribute("active", this.mAddon.isActive);
var showProgress = this.mAddon.install &&
this.mAddon.install.state != AddonManager.STATE_INSTALLED;
var showProgress = this.mAddon.purchaseURL || (this.mAddon.install &&
this.mAddon.install.state != AddonManager.STATE_INSTALLED);
this._showStatus(showProgress ? "progress" : "none");
]]></body>
</method>

Просмотреть файл

@ -136,6 +136,7 @@
<command id="cmd_enableItem"/>
<command id="cmd_disableItem"/>
<command id="cmd_installItem"/>
<command id="cmd_purchaseItem"/>
<command id="cmd_uninstallItem"/>
<command id="cmd_cancelUninstallItem"/>
<command id="cmd_cancelOperation"/>
@ -642,6 +643,8 @@
label="&cmd.uninstallAddon.label;"
accesskey="&cmd.uninstallAddon.accesskey;"
command="cmd_uninstallItem"/>
<button id="detail-purchase-btn" class="addon-control purchase"
command="cmd_purchaseItem"/>
<button id="detail-install-btn" class="addon-control install"
label="&cmd.installAddon.label;"
accesskey="&cmd.installAddon.accesskey;"

Просмотреть файл

@ -77,6 +77,7 @@ _MAIN_TEST_FILES = \
browser_globalwarnings.js \
browser_eula.js \
browser_updateid.js \
browser_purchase.js \
$(NULL)
_TEST_FILES = \
@ -99,6 +100,7 @@ _TEST_RESOURCES = \
browser_install.xml \
browser_install1_3.xpi \
browser_eula.xml \
browser_purchase.xml \
discovery.html \
redirect.sjs \
releaseNotes.xhtml \

Просмотреть файл

@ -0,0 +1,192 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
// Tests that marketplace results show up in searches, are sorted right and
// attempting to buy links through to the right webpage
const PREF_GETADDONS_GETSEARCHRESULTS = "extensions.getAddons.search.url";
const SEARCH_URL = TESTROOT + "browser_purchase.xml";
var gManagerWindow;
function test() {
// Turn on searching for this test
Services.prefs.setIntPref(PREF_SEARCH_MAXRESULTS, 15);
Services.prefs.setCharPref(PREF_GETADDONS_GETSEARCHRESULTS, SEARCH_URL);
waitForExplicitFinish();
open_manager("addons://list/extension", function(aWindow) {
gManagerWindow = aWindow;
waitForFocus(function() {
var searchBox = gManagerWindow.document.getElementById("header-search");
searchBox.value = "foo";
EventUtils.synthesizeMouseAtCenter(searchBox, { }, gManagerWindow);
EventUtils.synthesizeKey("VK_RETURN", { }, gManagerWindow);
wait_for_view_load(gManagerWindow, function() {
var remoteFilter = gManagerWindow.document.getElementById("search-filter-remote");
EventUtils.synthesizeMouseAtCenter(remoteFilter, { }, gManagerWindow);
run_next_test();
});
}, aWindow);
});
}
function end_test() {
close_manager(gManagerWindow, function() {
// Will have created an install so cancel it
AddonManager.getAllInstalls(function(aInstalls) {
is(aInstalls.length, 1, "Should have been one install created");
aInstalls[0].cancel();
finish();
});
});
}
function get_node(parent, anonid) {
return parent.ownerDocument.getAnonymousElementByAttribute(parent, "anonid", anonid);
}
function get_install_btn(parent) {
var installStatus = get_node(parent, "install-status");
return get_node(installStatus, "install-remote-btn");
}
function get_purchase_btn(parent) {
var installStatus = get_node(parent, "install-status");
return get_node(installStatus, "purchase-remote-btn");
}
// Tests that the expected results appeared
add_test(function() {
var list = gManagerWindow.document.getElementById("search-list");
var items = Array.filter(list.childNodes, function(e) {
return e.tagName == "richlistitem";
});
is(items.length, 5, "Should be 5 results");
is(get_node(items[0], "name").value, "Ludicrously Expensive Add-on", "Add-on 0 should be in expected position");
is_element_hidden(get_install_btn(items[0]), "Add-on 0 install button should be hidden");
is_element_visible(get_purchase_btn(items[0]), "Add-on 0 purchase button should be visible");
is(get_purchase_btn(items[0]).label, "Purchase for $101\u2026", "Add-on 0 should have the right price");
is(get_node(items[1], "name").value, "Cheap Add-on", "Add-on 1 should be in expected position");
is_element_hidden(get_install_btn(items[1]), "Add-on 1 install button should be hidden");
is_element_visible(get_purchase_btn(items[1]), "Add-on 1 purchase button should be visible");
is(get_purchase_btn(items[1]).label, "Purchase for $0.99\u2026", "Add-on 2 should have the right price");
is(get_node(items[2], "name").value, "Reasonable Add-on", "Add-on 2 should be in expected position");
is_element_hidden(get_install_btn(items[2]), "Add-on 2 install button should be hidden");
is_element_visible(get_purchase_btn(items[2]), "Add-on 2 purchase button should be visible");
is(get_purchase_btn(items[2]).label, "Purchase for $1\u2026", "Add-on 3 should have the right price");
is(get_node(items[3], "name").value, "Free Add-on", "Add-on 3 should be in expected position");
is_element_visible(get_install_btn(items[3]), "Add-on 3 install button should be visible");
is_element_hidden(get_purchase_btn(items[3]), "Add-on 3 purchase button should be hidden");
is(get_node(items[4], "name").value, "More Expensive Add-on", "Add-on 4 should be in expected position");
is_element_hidden(get_install_btn(items[4]), "Add-on 4 install button should be hidden");
is_element_visible(get_purchase_btn(items[4]), "Add-on 4 purchase button should be visible");
is(get_purchase_btn(items[4]).label, "Purchase for $1.01\u2026", "Add-on 4 should have the right price");
run_next_test();
});
// Tests that sorting by price works
add_test(function() {
var list = gManagerWindow.document.getElementById("search-list");
var sorters = gManagerWindow.document.getElementById("search-sorters");
var priceSorter = get_node(sorters, "price-btn");
info("Changing sort order");
EventUtils.synthesizeMouseAtCenter(priceSorter, { }, gManagerWindow);
var items = Array.filter(list.childNodes, function(e) {
return e.tagName == "richlistitem";
});
is(get_node(items[0], "name").value, "Free Add-on", "Add-on 0 should be in expected position");
is(get_node(items[1], "name").value, "Cheap Add-on", "Add-on 1 should be in expected position");
is(get_node(items[2], "name").value, "Reasonable Add-on", "Add-on 2 should be in expected position");
is(get_node(items[3], "name").value, "More Expensive Add-on", "Add-on 3 should be in expected position");
is(get_node(items[4], "name").value, "Ludicrously Expensive Add-on", "Add-on 4 should be in expected position");
info("Changing sort order");
EventUtils.synthesizeMouseAtCenter(priceSorter, { }, gManagerWindow);
var items = Array.filter(list.childNodes, function(e) {
return e.tagName == "richlistitem";
});
is(get_node(items[0], "name").value, "Ludicrously Expensive Add-on", "Add-on 0 should be in expected position");
is(get_node(items[1], "name").value, "More Expensive Add-on", "Add-on 1 should be in expected position");
is(get_node(items[2], "name").value, "Reasonable Add-on", "Add-on 2 should be in expected position");
is(get_node(items[3], "name").value, "Cheap Add-on", "Add-on 3 should be in expected position");
is(get_node(items[4], "name").value, "Free Add-on", "Add-on 4 should be in expected position");
run_next_test();
});
// Tests that clicking the buy button works from the list
add_test(function() {
gBrowser.addEventListener("load", function() {
if (gBrowser.currentURI.spec == "about:blank")
return;
gBrowser.removeEventListener("load", arguments.callee, true);
is(gBrowser.currentURI.spec, TESTROOT + "releaseNotes.xhtml?addon5", "Should have loaded the right page");
gBrowser.removeCurrentTab();
if (gUseInContentUI) {
is(gBrowser.currentURI.spec, "about:addons", "Should be back to the add-ons manager");
run_next_test();
}
else {
waitForFocus(run_next_test, gManagerWindow);
}
}, true);
var list = gManagerWindow.document.getElementById("search-list");
EventUtils.synthesizeMouseAtCenter(get_purchase_btn(list.firstChild), { }, gManagerWindow);
});
// Tests that clicking the buy button from the details view works
add_test(function() {
gBrowser.addEventListener("load", function() {
if (gBrowser.currentURI.spec == "about:blank")
return;
gBrowser.removeEventListener("load", arguments.callee, true);
is(gBrowser.currentURI.spec, TESTROOT + "releaseNotes.xhtml?addon4", "Should have loaded the right page");
gBrowser.removeCurrentTab();
if (gUseInContentUI) {
is(gBrowser.currentURI.spec, "about:addons", "Should be back to the add-ons manager");
run_next_test();
}
else {
waitForFocus(run_next_test, gManagerWindow);
}
}, true);
var list = gManagerWindow.document.getElementById("search-list");
var item = list.firstChild.nextSibling;
list.ensureElementIsVisible(item);
EventUtils.synthesizeMouseAtCenter(item, { clickCount: 2 }, gManagerWindow);
wait_for_view_load(gManagerWindow, function() {
var btn = gManagerWindow.document.getElementById("detail-purchase-btn");
is_element_visible(btn, "Purchase button should be visible");
EventUtils.synthesizeMouseAtCenter(btn, { }, gManagerWindow);
});
});

Просмотреть файл

@ -0,0 +1,180 @@
<?xml version="1.0" encoding="utf-8" ?>
<searchresults total_results="100">
<addon>
<name>Ludicrously Expensive Add-on</name>
<type id='1'>Extension</type>
<guid>addon5@tests.mozilla.org</guid>
<version>1.0</version>
<authors>
<author>
<name>Test Creator</name>
<link>http://example.com/creator.html</link>
</author>
</authors>
<status id='4'>Public</status>
<summary>Test summary</summary>
<description>Test description</description>
<compatible_applications>
<application>
<name>Firefox</name>
<appID>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</appID>
<min_version>0</min_version>
<max_version>*</max_version>
</application>
<application>
<name>SeaMonkey</name>
<appID>{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}</appID>
<min_version>0</min_version>
<max_version>*</max_version>
</application>
</compatible_applications>
<all_compatible_os>
<os>ALL</os>
</all_compatible_os>
<payment_data>
<link>http://example.com/browser/toolkit/mozapps/extensions/test/browser/releaseNotes.xhtml?addon5</link>
<amount amount="101">$101</amount>
</payment_data>
</addon>
<addon>
<name>Cheap Add-on</name>
<type id='1'>Extension</type>
<guid>addon2@tests.mozilla.org</guid>
<version>1.0</version>
<authors>
<author>
<name>Test Creator</name>
<link>http://example.com/creator.html</link>
</author>
</authors>
<status id='4'>Public</status>
<summary>Test summary</summary>
<description>Test description</description>
<compatible_applications>
<application>
<name>Firefox</name>
<appID>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</appID>
<min_version>0</min_version>
<max_version>*</max_version>
</application>
<application>
<name>SeaMonkey</name>
<appID>{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}</appID>
<min_version>0</min_version>
<max_version>*</max_version>
</application>
</compatible_applications>
<all_compatible_os>
<os>ALL</os>
</all_compatible_os>
<payment_data>
<link>http://example.com/browser/toolkit/mozapps/extensions/test/browser/releaseNotes.xhtml?addon2</link>
<amount amount="0.99">$0.99</amount>
</payment_data>
</addon>
<addon>
<name>Reasonable Add-on</name>
<type id='1'>Extension</type>
<guid>addon3@tests.mozilla.org</guid>
<version>1.0</version>
<authors>
<author>
<name>Test Creator</name>
<link>http://example.com/creator.html</link>
</author>
</authors>
<status id='4'>Public</status>
<summary>Test summary</summary>
<description>Test description</description>
<compatible_applications>
<application>
<name>Firefox</name>
<appID>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</appID>
<min_version>0</min_version>
<max_version>*</max_version>
</application>
<application>
<name>SeaMonkey</name>
<appID>{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}</appID>
<min_version>0</min_version>
<max_version>*</max_version>
</application>
</compatible_applications>
<all_compatible_os>
<os>ALL</os>
</all_compatible_os>
<payment_data>
<link>http://example.com/browser/toolkit/mozapps/extensions/test/browser/releaseNotes.xhtml?addon3</link>
<amount amount="1">$1</amount>
</payment_data>
</addon>
<addon>
<name>Free Add-on</name>
<type id='1'>Extension</type>
<guid>addon1@tests.mozilla.org</guid>
<version>1.0</version>
<authors>
<author>
<name>Test Creator</name>
<link>http://example.com/creator.html</link>
</author>
</authors>
<status id='4'>Public</status>
<summary>Test summary</summary>
<description>Test description</description>
<compatible_applications>
<application>
<name>Firefox</name>
<appID>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</appID>
<min_version>0</min_version>
<max_version>*</max_version>
</application>
<application>
<name>SeaMonkey</name>
<appID>{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}</appID>
<min_version>0</min_version>
<max_version>*</max_version>
</application>
</compatible_applications>
<all_compatible_os>
<os>ALL</os>
</all_compatible_os>
<install size="1">http://example.com/addon1.xpi</install>
</addon>
<addon>
<name>More Expensive Add-on</name>
<type id='1'>Extension</type>
<guid>addon4@tests.mozilla.org</guid>
<version>1.0</version>
<authors>
<author>
<name>Test Creator</name>
<link>http://example.com/creator.html</link>
</author>
</authors>
<status id='4'>Public</status>
<summary>Test summary</summary>
<description>Test description</description>
<compatible_applications>
<application>
<name>Firefox</name>
<appID>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</appID>
<min_version>0</min_version>
<max_version>*</max_version>
</application>
<application>
<name>SeaMonkey</name>
<appID>{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}</appID>
<min_version>0</min_version>
<max_version>*</max_version>
</application>
</compatible_applications>
<all_compatible_os>
<os>ALL</os>
</all_compatible_os>
<payment_data>
<link>http://example.com/browser/toolkit/mozapps/extensions/test/browser/releaseNotes.xhtml?addon4</link>
<amount amount="1.01">$1.01</amount>
</payment_data>
</addon>
</searchresults>

Просмотреть файл

@ -678,6 +678,96 @@
<install>http://localhost:4444/addons/test_AddonRepository_2.xpi</install>
</addon>
<!-- Passes because the add-on has the right payment info -->
<addon>
<name>PASS</name>
<type id="1">Extension</type>
<guid>purchase1@tests.mozilla.org</guid>
<version>2.0</version>
<authors>
<author>
<name>Test Creator - Last Passing</name>
<link>http://localhost:4444/creatorLastPassing.html</link>
</author>
</authors>
<status id="4">Public</status>
<all_compatible_os>
<os>ALL</os>
</all_compatible_os>
<compatible_applications>
<application>
<appID>xpcshell@tests.mozilla.org</appID>
<min_version>1</min_version>
<max_version>1</max_version>
</application>
</compatible_applications>
<rating>5</rating>
<payment_data>
<link>http://localhost:4444/purchaseURL1</link>
<amount amount="5">$5</amount>
</payment_data>
</addon>
<!-- Passes because the add-on has the right payment info -->
<addon>
<name>PASS</name>
<type id="1">Extension</type>
<guid>purchase2@tests.mozilla.org</guid>
<version>2.0</version>
<authors>
<author>
<name>Test Creator - Last Passing</name>
<link>http://localhost:4444/creatorLastPassing.html</link>
</author>
</authors>
<status id="4">Public</status>
<all_compatible_os>
<os>XPCShell</os>
</all_compatible_os>
<compatible_applications>
<application>
<appID>xpcshell@tests.mozilla.org</appID>
<min_version>1</min_version>
<max_version>1</max_version>
</application>
</compatible_applications>
<rating>5</rating>
<payment_data>
<link>http://localhost:4444/purchaseURL2</link>
<amount amount="10.0">$10</amount>
</payment_data>
</addon>
<!-- Fails because the add-on doesn't match the platform -->
<addon>
<name>FAIL</name>
<type id="1">Extension</type>
<guid>purchase3@tests.mozilla.org</guid>
<version>2.0</version>
<authors>
<author>
<name>Test Creator - Last Passing</name>
<link>http://localhost:4444/creatorLastPassing.html</link>
</author>
</authors>
<status id="4">Public</status>
<all_compatible_os>
<os>FOO</os>
</all_compatible_os>
<compatible_applications>
<application>
<appID>xpcshell@tests.mozilla.org</appID>
<min_version>1</min_version>
<max_version>1</max_version>
</application>
</compatible_applications>
<rating>5</rating>
<payment_data>
<link>http://localhost:4444/purchaseURL3</link>
<amount amount="10">$10</amount>
</payment_data>
</addon>
<!-- Passes because the Addon that has a matching XPI URL
has a state = STATE_AVAILABLE (non-active install). This is the
last passing add-on. -->

Просмотреть файл

@ -35,7 +35,8 @@ var ADDON_PROPERTIES = ["id", "type", "version", "creator", "developers",
"supportURL", "contributionURL", "contributionAmount",
"averageRating", "reviewCount", "reviewURL",
"totalDownloads", "weeklyDownloads", "dailyUsers",
"sourceURI", "repositoryStatus", "size", "updateDate"];
"sourceURI", "repositoryStatus", "size", "updateDate",
"purchaseURL", "purchaseAmount", "purchaseDisplayAmount"];
// Results of getAddonsByIDs
var GET_RESULTS = [{
@ -172,6 +173,32 @@ var SEARCH_RESULTS = [{
repositoryStatus: 4,
size: 5555,
updateDate: new Date(1265033045000)
}, {
id: "purchase1@tests.mozilla.org",
type: "extension",
version: "2.0",
creator: {
name: "Test Creator - Last Passing",
url: BASE_URL + "/creatorLastPassing.html"
},
averageRating: 5,
repositoryStatus: 4,
purchaseURL: "http://localhost:4444/purchaseURL1",
purchaseAmount: 5,
purchaseDisplayAmount: "$5"
}, {
id: "purchase2@tests.mozilla.org",
type: "extension",
version: "2.0",
creator: {
name: "Test Creator - Last Passing",
url: BASE_URL + "/creatorLastPassing.html"
},
averageRating: 5,
repositoryStatus: 4,
purchaseURL: "http://localhost:4444/purchaseURL2",
purchaseAmount: 10,
purchaseDisplayAmount: "$10"
}, {
id: "test-lastPassing@tests.mozilla.org",
type: "extension",
@ -243,10 +270,10 @@ function check_results(aActualAddons, aExpectedAddons, aAddonCount, aInstallNull
if (aActualAddon.name != "PASS")
do_throw(aActualAddon.id + " - " + "invalid add-on name " + aActualAddon.name);
do_check_eq(aActualAddon.install == null, !!aInstallNull);
do_check_eq(aActualAddon.install == null, !!aInstallNull || !aActualAddon.sourceURI);
// Check that sourceURI property consistent within actual addon
if (!aInstallNull)
if (aActualAddon.install)
do_check_eq(aActualAddon.install.sourceURI.spec, aActualAddon.sourceURI.spec);
});
}