drop django-qunit as we're not using it anymore
This commit is contained in:
Родитель
d4ccc97030
Коммит
728cedfc38
|
@ -9,7 +9,6 @@ INSTALLED_APPS += (
|
|||
'debug_toolbar',
|
||||
'django_extensions',
|
||||
'fixture_magic',
|
||||
'django_qunit',
|
||||
)
|
||||
|
||||
# You want one of the caching backends. Dummy won't do any caching, locmem is
|
||||
|
|
|
@ -50,5 +50,3 @@ JavaScript
|
|||
// ...
|
||||
}
|
||||
});
|
||||
|
||||
- Write :ref:`JavaScript tests <javascript-testing>` whenever possible.
|
||||
|
|
|
@ -117,68 +117,9 @@ need to recompile the .mo files manually, for example::
|
|||
|
||||
msgfmt --check-format -o django.mo django.po
|
||||
|
||||
.. _`javascript-testing`:
|
||||
|
||||
|
||||
API Tests
|
||||
---------
|
||||
|
||||
To run all Marketplace API tests, pass an additional `--config` flag to the test
|
||||
runner::
|
||||
|
||||
./manage.py test --config=mkt/api/tests/nose.cfg
|
||||
|
||||
If adding new test modules related to the API, ensure that you add them to the
|
||||
list at `mkt/api/tests/nose.cfg`.
|
||||
|
||||
|
||||
JavaScript Tests
|
||||
----------------
|
||||
|
||||
Frontend JavaScript is currently tested with QUnit_, a simple set of
|
||||
functions for test setup/teardown and assertions.
|
||||
|
||||
Running JavaScript Tests
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
You can run the tests a few different ways but during development you
|
||||
probably want to run them in a web browser by opening this page:
|
||||
http://127.0.0.1:8000/en-US/firefox/qunit/
|
||||
|
||||
Before you can load that page, you'll need to adjust your settings_local.py
|
||||
file so it includes django-qunit:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
INSTALLED_APPS += (
|
||||
# ...
|
||||
'django_qunit',
|
||||
)
|
||||
|
||||
Writing JavaScript Tests
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
QUnit_ tests for the HTML page above are discovered automatically. Just add
|
||||
some_test.js to ``media/js/zamboni/tests/`` and it will run in the suite. If
|
||||
you need to include a library file to test against, edit
|
||||
``media/js/zamboni/tests/suite.json``.
|
||||
|
||||
QUnit_ has some good examples for writing tests. Here are a few
|
||||
additional tips:
|
||||
|
||||
* Any HTML required for your test should go in a sandbox using
|
||||
``tests.createSandbox('#your-template')``.
|
||||
See js/zamboni/tests.js for details.
|
||||
* To make a useful test based on an actual production template, you can create
|
||||
a snippet and include that in ``templates/qunit.html`` assigned to its own
|
||||
div. During test setup, reference the div in createSandbox()
|
||||
* You can use `$.mockjax`_ to test how your code handles server responses,
|
||||
errors, and timeouts.
|
||||
|
||||
.. _`Django's Unit Testing`: http://docs.djangoproject.com/en/dev/topics/testing
|
||||
.. _`Selenium repository`: https://github.com/mozilla/Addon-Tests/
|
||||
.. _`the docs`: http://docs.djangoproject.com/en/dev/topics/testing#id1
|
||||
.. _Qunit: http://docs.jquery.com/Qunit
|
||||
.. _`$.mockjax`: http://enterprisejquery.com/2010/07/mock-your-ajax-requests-with-mockjax-for-rapid-development/
|
||||
.. _mock: http://pypi.python.org/pypi/mock
|
||||
.. _`nose-blockage`: https://github.com/andymckay/nose-blockage
|
||||
|
|
|
@ -1297,9 +1297,6 @@ PERF_THRESHOLD = 25
|
|||
|
||||
REDIS_BACKENDS = {'master': 'redis://localhost:6379?socket_timeout=0.5'}
|
||||
|
||||
# Directory of JavaScript test files for django_qunit to run
|
||||
QUNIT_TEST_DIRECTORY = os.path.join(MEDIA_ROOT, 'js', 'zamboni', 'tests')
|
||||
|
||||
# Full path or executable path (relative to $PATH) of the spidermonkey js
|
||||
# binary. It must be a version compatible with amo-validator
|
||||
SPIDERMONKEY = None
|
||||
|
|
|
@ -179,45 +179,6 @@ urlpatterns += patterns('piston.authentication.oauth.views',
|
|||
name='oauth.access_token'),
|
||||
)
|
||||
|
||||
if 'django_qunit' in settings.INSTALLED_APPS:
|
||||
|
||||
def _zamboni_qunit(request, path, template):
|
||||
from time import time
|
||||
import django_qunit.views
|
||||
import jingo
|
||||
import mock
|
||||
|
||||
# Patch `js` so that CI gets cache-busted JS with TEMPLATE_DEBUG=True.
|
||||
# (This will be fixed in `jingo-minify` with bug 717094.)
|
||||
from jingo_minify.helpers import _build_html
|
||||
import jinja2
|
||||
|
||||
def js(bundle, defer=False, async=False):
|
||||
items = settings.MINIFY_BUNDLES['js'][bundle]
|
||||
attrs = ['src="%s?v=%s"' % ('%s', time())]
|
||||
if defer:
|
||||
attrs.append('defer')
|
||||
if async:
|
||||
attrs.append('async')
|
||||
string = '<script %s></script>' % ' '.join(attrs)
|
||||
return _build_html(items, string)
|
||||
|
||||
ctx = django_qunit.views.get_suite_context(request, path)
|
||||
ctx.update(timestamp=time(), Mock=mock.Mock, js=js)
|
||||
response = render(request, template, ctx)
|
||||
# This allows another site to embed the QUnit suite
|
||||
# in an iframe (for CI).
|
||||
response['x-frame-options'] = ''
|
||||
return response
|
||||
|
||||
def zamboni_qunit(request, path):
|
||||
return _zamboni_qunit(request, path, 'qunit/qunit.html')
|
||||
|
||||
urlpatterns += patterns('',
|
||||
url(r'^qunit/(?P<path>.*)', zamboni_qunit),
|
||||
url(r'^_qunit/', include('django_qunit.urls')),
|
||||
)
|
||||
|
||||
if settings.TEMPLATE_DEBUG:
|
||||
# Remove leading and trailing slashes so the regex matches.
|
||||
media_url = settings.MEDIA_URL.lstrip('/').rstrip('/')
|
||||
|
|
|
@ -1,132 +0,0 @@
|
|||
|
||||
//
|
||||
// Adapter for JS TestNet
|
||||
// https://github.com/kumar303/jstestnet
|
||||
//
|
||||
// Be sure this file is loaded *after* qunit/testrunner.js or whatever else
|
||||
// you're using
|
||||
|
||||
(function() {
|
||||
|
||||
var canPost = false;
|
||||
try {
|
||||
canPost = !!window.top.postMessage;
|
||||
} catch(e){}
|
||||
if (!canPost) {
|
||||
return;
|
||||
}
|
||||
|
||||
function postMsg(data) {
|
||||
var msg = '';
|
||||
for (var k in data) {
|
||||
if (msg.length > 0) {
|
||||
msg += '&';
|
||||
}
|
||||
msg += k + '=' + encodeURI(data[k]);
|
||||
}
|
||||
window.top.postMessage(msg, '*');
|
||||
}
|
||||
|
||||
window.onerror = function(error, url, lineNumber) {
|
||||
var msg = {
|
||||
action: 'log',
|
||||
result: false, // failure
|
||||
message: 'Exception: ' + error.toString() + ' at ' + url + ':' + lineNumber,
|
||||
stacktrace: (typeof printStackTrace !== 'undefined') ? printStackTrace({e: error}): null
|
||||
};
|
||||
if (typeof console !== 'undefined') {
|
||||
// Get notified of exceptions during local development.
|
||||
console.error('Exception:');
|
||||
console.log(error);
|
||||
}
|
||||
postMsg(msg);
|
||||
};
|
||||
|
||||
// QUnit (jQuery)
|
||||
// http://docs.jquery.com/QUnit
|
||||
if ( typeof QUnit !== "undefined" ) {
|
||||
|
||||
QUnit.begin = function() {
|
||||
postMsg({
|
||||
action: 'hello',
|
||||
user_agent: navigator.userAgent
|
||||
});
|
||||
};
|
||||
|
||||
QUnit.done = function(failures, total) {
|
||||
// // Clean up the HTML (remove any un-needed test markup)
|
||||
// $("nothiddendiv").remove();
|
||||
// $("loadediframe").remove();
|
||||
// $("dl").remove();
|
||||
// $("main").remove();
|
||||
//
|
||||
// // Show any collapsed results
|
||||
// $('ol').show();
|
||||
|
||||
postMsg({
|
||||
action: 'done',
|
||||
failures: failures,
|
||||
total: total
|
||||
});
|
||||
};
|
||||
|
||||
QUnit.log = function(result, message, details) {
|
||||
// Strip out html:
|
||||
message = message.replace(/&/g, '&');
|
||||
message = message.replace(/>/g, '>');
|
||||
message = message.replace(/</g, '<');
|
||||
message = message.replace(/<[^>]+>/g, '');
|
||||
var msg = {
|
||||
action: 'log',
|
||||
result: result,
|
||||
message: message,
|
||||
stacktrace: null
|
||||
};
|
||||
if (details) {
|
||||
if (typeof(details.source) !== 'undefined') {
|
||||
msg.stacktrace = details.source;
|
||||
}
|
||||
if (typeof(details.expected) !== 'undefined') {
|
||||
msg.message += '; Expected: "' + details.expected + '"';
|
||||
}
|
||||
if (typeof(details.actual) !== 'undefined') {
|
||||
msg.message += '; Actual: "' + details.actual + '"';
|
||||
}
|
||||
}
|
||||
postMsg(msg);
|
||||
};
|
||||
|
||||
QUnit.moduleStart = function(name) {
|
||||
postMsg({
|
||||
action: 'set_module',
|
||||
name: name
|
||||
});
|
||||
};
|
||||
|
||||
QUnit.testStart = function(name) {
|
||||
postMsg({
|
||||
action: 'set_test',
|
||||
name: name
|
||||
});
|
||||
};
|
||||
|
||||
// window.TestSwarm.serialize = function(){
|
||||
// // Clean up the HTML (remove any un-needed test markup)
|
||||
// remove("nothiddendiv");
|
||||
// remove("loadediframe");
|
||||
// remove("dl");
|
||||
// remove("main");
|
||||
//
|
||||
// // Show any collapsed results
|
||||
// var ol = document.getElementsByTagName("ol");
|
||||
// for ( var i = 0; i < ol.length; i++ ) {
|
||||
// ol[i].style.display = "block";
|
||||
// }
|
||||
//
|
||||
// return trimSerialize();
|
||||
// };
|
||||
} else {
|
||||
throw new Error("Cannot adapt to jstestnet: Unknown test runner");
|
||||
}
|
||||
|
||||
})();
|
|
@ -1,167 +0,0 @@
|
|||
|
||||
/*
|
||||
Utilities for testing jQuery-based JavaScript code.
|
||||
*/
|
||||
tests = {};
|
||||
|
||||
tests.waitFor = function(checkCondition, config) {
|
||||
/*
|
||||
Wait for a condition before doing anything else.
|
||||
|
||||
Good for making async tests fast on fast machines.
|
||||
Use it like this::
|
||||
|
||||
tests.waitFor(function() {
|
||||
return (thing == 'done);
|
||||
}).thenDo(function() {
|
||||
equals(1,1);
|
||||
ok(stuff());
|
||||
});
|
||||
|
||||
You can pass in a config object as the second argument
|
||||
with these possible attributes:
|
||||
|
||||
**config.interval**
|
||||
milliseconds to wait between polling condition
|
||||
**config.timeout**
|
||||
milliseconds to wait before giving up on condition
|
||||
*/
|
||||
if (typeof(config) === 'undefined') {
|
||||
config = {};
|
||||
}
|
||||
var interval = config.interval || 20,
|
||||
timeout = config.timeout || 1000,
|
||||
run,
|
||||
runWhenReady,
|
||||
timeSpent = 0;
|
||||
|
||||
run = function() {
|
||||
if (timeSpent > timeout) {
|
||||
var cond = checkCondition.toString()
|
||||
ok(false, "Spent too long waiting for: " + cond);
|
||||
start();
|
||||
}
|
||||
timeSpent += interval;
|
||||
var ready = checkCondition();
|
||||
if (!ready) {
|
||||
setTimeout(run, interval);
|
||||
} else {
|
||||
if (typeof runWhenReady === 'function') {
|
||||
runWhenReady();
|
||||
}
|
||||
}
|
||||
};
|
||||
setTimeout(run, interval);
|
||||
return {
|
||||
thenDo: function(fn) {
|
||||
runWhenReady = fn;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
tests._sbCounter = 0;
|
||||
|
||||
tests.createSandbox = function(tmpl) {
|
||||
/*
|
||||
Returns a jQuery object for a temporary, unique div filled with html
|
||||
from a template.
|
||||
|
||||
**tmpl**
|
||||
An optional jQuery locator from which to copy html. This would
|
||||
typically be the ID of a div in your test runner HTML (e.g. qunit.html)
|
||||
|
||||
Example::
|
||||
|
||||
module('Group of tests', {
|
||||
setup: function() {
|
||||
this.sandbox = tests.createSandbox('#foobar-template');
|
||||
},
|
||||
teardown: function() {
|
||||
this.sandbox.remove();
|
||||
}
|
||||
});
|
||||
|
||||
test('some test', function() {
|
||||
this.sandbox.append('...');
|
||||
});
|
||||
*/
|
||||
tests._sbCounter++;
|
||||
var sb = $('<div id="sandbox-'+tests._sbCounter.toString()+'"></div>');
|
||||
if (tmpl) {
|
||||
sb.append($(tmpl).html());
|
||||
}
|
||||
$('#sandbox').append(sb);
|
||||
return sb;
|
||||
};
|
||||
|
||||
tests.StubOb = function(Orig, overrides) {
|
||||
/*
|
||||
Returns a class-like replacement for Orig.
|
||||
|
||||
**Orig**
|
||||
object you want to replace.
|
||||
**overrides**
|
||||
object containing properties to override in the original.
|
||||
|
||||
All properties in the overrides object will replace those of Orig's
|
||||
prototype when you create an instance of the class. This is useful
|
||||
for stubbing out certain methods. For example::
|
||||
|
||||
z.FileData = tests.StubOb(z.FormData, {
|
||||
send: function() {}
|
||||
});
|
||||
|
||||
This allows the creation of a FormData object that behaves just like
|
||||
the original except that send() does not actually post data during
|
||||
a test::
|
||||
|
||||
var fileData = new z.FileData();
|
||||
fileData.send(); // does nothing
|
||||
|
||||
Be sure to assign the original class back when you're done testing.
|
||||
*/
|
||||
return function() {
|
||||
var ob = {}
|
||||
Orig.apply(ob, this.arguments);
|
||||
for (k in overrides) {
|
||||
ob[k] = overrides[k];
|
||||
}
|
||||
return ob;
|
||||
}
|
||||
};
|
||||
|
||||
tests.hasClass = function($sel, cls) {
|
||||
/*
|
||||
Asserts that jQuery selector $sel has CSS class cls.
|
||||
|
||||
Otherwise, an instructive error is raised.
|
||||
*/
|
||||
equals($sel.hasClass(cls), true,
|
||||
'Expecting ' + cls + ', got: ' + $sel.attr('class'));
|
||||
}
|
||||
|
||||
tests.lacksClass = function($sel, cls) {
|
||||
/*
|
||||
Asserts that jQuery selector $sel does not have CSS class cls.
|
||||
|
||||
Otherwise, an instructive error is raised.
|
||||
*/
|
||||
equals($sel.hasClass(cls), false,
|
||||
'Should not have ' + cls + ', got: ' + $sel.attr('class'));
|
||||
};
|
||||
|
||||
tests.equalObjects = function(a, b) {
|
||||
/*
|
||||
Asserts that two objects are equal by comparing serialized strings.
|
||||
deepEqual is stupid and flaky.
|
||||
*/
|
||||
equal(JSON.stringify(a), JSON.stringify(b));
|
||||
}
|
||||
|
||||
tests.notEqualObjects = function(a, b) {
|
||||
/*
|
||||
Asserts that two objects are unequal by comparing serialized strings.
|
||||
notDeepEqual is stupid and flaky.
|
||||
*/
|
||||
notEqual(JSON.stringify(a), JSON.stringify(b));
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
var buttonFixtures = {
|
||||
setup: function() {
|
||||
this.sandbox = tests.createSandbox('#buttons');
|
||||
},
|
||||
teardown: function() {
|
||||
this.sandbox.remove();
|
||||
}
|
||||
};
|
||||
|
||||
module('Buttons', buttonFixtures);
|
||||
|
||||
test('Test backup button', function() {
|
||||
var attr = 'data-version-supported',
|
||||
current = this.sandbox.find('.install').first();
|
||||
current_wrapper = this.sandbox.find('.install-shell').first();
|
||||
backup = this.sandbox.find('.backup-button .install').first();
|
||||
backup_wrapper = this.sandbox.find('.backup-button').first();
|
||||
|
||||
equals(backup_wrapper.hasClass('hidden'), false);
|
||||
equals(current_wrapper.hasClass('hidden'), true);
|
||||
|
||||
current_wrapper.removeClass('hidden');
|
||||
backup_wrapper.addClass('hidden');
|
||||
backup.attr(attr, 'false');
|
||||
current.attr(attr, 'true');
|
||||
|
||||
this.sandbox.find('.backup-button').showBackupButton();
|
||||
equals(backup_wrapper.hasClass('hidden'), true);
|
||||
equals(current_wrapper.hasClass('hidden'), false);
|
||||
});
|
||||
|
||||
/* Fails in Jenkins 3.6.17, uncomment when we can figure out why.
|
||||
Does not locally.
|
||||
test('Test change elements on backup', function() {
|
||||
$('.backup-button', this.sandbox).showBackupButton();
|
||||
equals($('.addon-compatible td', this.sandbox).text(), 'Fx 1.0');
|
||||
equals($('.addon-updated time', this.sandbox).text(), 'today');
|
||||
});
|
||||
*/
|
|
@ -1,156 +0,0 @@
|
|||
module('Ajax Cache', {
|
||||
setup: function() {
|
||||
this.newItems = {'ajax': [], 'cache': []};
|
||||
z._AjaxCache = {};
|
||||
$.mockjaxClear();
|
||||
$.mockjaxSettings = {
|
||||
status: 200,
|
||||
responseTime: 0,
|
||||
contentType: 'text/json',
|
||||
dataType: 'json'
|
||||
};
|
||||
},
|
||||
teardown: function() {
|
||||
$.mockjaxClear();
|
||||
},
|
||||
query: function(term, url) {
|
||||
var self = this,
|
||||
results = [];
|
||||
if (url) {
|
||||
for (var i = 0; i < 10; i++) {
|
||||
results.push({'id': i, 'url': url});
|
||||
}
|
||||
} else {
|
||||
url = '/cacheMoney';
|
||||
results = [
|
||||
{'id': 1, 'url': 'gkoberger.net'},
|
||||
{'id': 2, 'url': 'gkoberger.net'},
|
||||
{'id': 3, 'url': 'gkoberger.net'}
|
||||
];
|
||||
}
|
||||
$.mockjax({
|
||||
url: url,
|
||||
responseText: JSON.stringify(results),
|
||||
status: 200,
|
||||
responseTime: 0
|
||||
});
|
||||
|
||||
var self = this;
|
||||
this.ajaxCalled = false;
|
||||
this.cacheCalled = false;
|
||||
return {
|
||||
url: url,
|
||||
data: {'q': term},
|
||||
ajaxSuccess: function(data, items) {
|
||||
self.newItems['ajax'].push(items);
|
||||
self.ajaxCalled = true;
|
||||
},
|
||||
cacheSuccess: function(data, items) {
|
||||
self.newItems['cache'].push(items);
|
||||
self.cacheCalled = true;
|
||||
}
|
||||
};
|
||||
},
|
||||
is_ajax: function() {
|
||||
equal(this.ajaxCalled, true);
|
||||
equal(this.cacheCalled, false);
|
||||
},
|
||||
is_cache: function() {
|
||||
equal(this.ajaxCalled, false);
|
||||
equal(this.cacheCalled, true);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
asyncTest('New request', function() {
|
||||
var self = this;
|
||||
|
||||
$.ajaxCache(self.query('some term')).done(function() {
|
||||
self.is_ajax();
|
||||
start();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
asyncTest('Identical requests', function() {
|
||||
var self = this,
|
||||
request1,
|
||||
request2;
|
||||
|
||||
request1 = $.ajaxCache(self.query('some term')).done(function() {
|
||||
self.is_ajax();
|
||||
|
||||
// This request should be cached.
|
||||
request2 = $.ajaxCache(self.query('some term'));
|
||||
self.is_cache();
|
||||
|
||||
// Ensure that we returned the correct items.
|
||||
tests.equalObjects(self.newItems['ajax'], self.newItems['cache']);
|
||||
|
||||
// When the request is cached, we don't return an $.ajax request.
|
||||
equal(request2, undefined);
|
||||
|
||||
start();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
asyncTest('Same URLs, unique parameters, same results', function() {
|
||||
var self = this,
|
||||
request1,
|
||||
request2,
|
||||
request3;
|
||||
|
||||
request1 = $.ajaxCache(self.query('some term')).done(function() {
|
||||
// This is a cached request.
|
||||
request2 = $.ajaxCache(self.query('some term'));
|
||||
|
||||
// This is a request with new parameters but will return same items.
|
||||
request3 = $.ajaxCache(self.query('new term')).done(function() {
|
||||
self.is_ajax();
|
||||
|
||||
// We return `undefined` when items remain unchanged.
|
||||
equal(self.newItems['ajax'][1], undefined);
|
||||
|
||||
start();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
asyncTest('Unique URLs, same parameters, unique results', function() {
|
||||
var self = this,
|
||||
request1,
|
||||
request2;
|
||||
|
||||
request1 = $.ajaxCache(self.query('some term', 'poop')).done(function() {
|
||||
self.is_ajax();
|
||||
|
||||
// This is a new request with a different URL.
|
||||
request2 = $.ajaxCache(self.query('some term', 'crap')).done(function() {
|
||||
self.is_ajax();
|
||||
tests.notEqualObjects(self.newItems['ajax'][0],
|
||||
self.newItems['ajax'][1]);
|
||||
start();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
asyncTest('Unique URLs, unique parameters, unique results', function() {
|
||||
var self = this,
|
||||
request1,
|
||||
request2;
|
||||
|
||||
request1 = $.ajaxCache(self.query('some term', 'poop')).done(function() {
|
||||
self.is_ajax();
|
||||
|
||||
// This is a new request with a different URL and different parameters.
|
||||
request2 = $.ajaxCache(self.query('diff term', 'crap')).done(function() {
|
||||
self.is_ajax();
|
||||
tests.notEqualObjects(self.newItems['ajax'][0],
|
||||
self.newItems['ajax'][1]);
|
||||
start();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,102 +0,0 @@
|
|||
var runtimePitchFixture = {
|
||||
setup: function(installed, seen_pitch, not_firefox) {
|
||||
this.sandbox = tests.createSandbox('#balloons');
|
||||
this.visitor = z.Storage('visitor');
|
||||
this._firefox = z.browser.firefox;
|
||||
this._key = 'seen_appruntime_pitch';
|
||||
this._app_runtime = z.capabilities.app_runtime;
|
||||
this._seen_pitch = this.visitor.get(this._key);
|
||||
|
||||
// The style="display: none" is getting destroyed in the sandbox. WTH.
|
||||
$('#appruntime-pitch', this.sandbox).hide();
|
||||
|
||||
// Mock whether Firefox is installed.
|
||||
z.browser.firefox = !not_firefox;
|
||||
|
||||
// Mock whether App Runtime extension is installed.
|
||||
z.capabilities.app_runtime = installed;
|
||||
|
||||
// Mock whether pitch was dismissed.
|
||||
if (seen_pitch) {
|
||||
this.visitor.set(this._key, '1');
|
||||
} else {
|
||||
this.visitor.remove(this._key);
|
||||
}
|
||||
|
||||
initBanners(this.sandbox);
|
||||
},
|
||||
teardown: function() {
|
||||
z.browser.firefox = this._firefox;
|
||||
z.capabilities.app_runtime = this._app_runtime;
|
||||
this.visitor.set(this._key, this._seen_pitch);
|
||||
this.sandbox.remove();
|
||||
},
|
||||
check: function(show_pitch) {
|
||||
var self = this,
|
||||
$balloon = $('#appruntime-pitch', self.sandbox);
|
||||
if (show_pitch) {
|
||||
equal($balloon.is(':visible'), true);
|
||||
$.when($balloon.find('.close').trigger('click')).done(function() {
|
||||
equal(self.visitor.get(self._key), '1');
|
||||
});
|
||||
} else {
|
||||
equal($balloon.is(':hidden'), true);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
module('App Runtime installed', $.extend({}, runtimePitchFixture, {
|
||||
setup: function() {
|
||||
runtimePitchFixture.setup.call(this, true, false);
|
||||
}
|
||||
}));
|
||||
test('Hide pitch message', function() {
|
||||
this.check(false);
|
||||
});
|
||||
|
||||
|
||||
module('App Runtime installed (dismissed)', $.extend({}, runtimePitchFixture, {
|
||||
setup: function() {
|
||||
// This could happen when the user first dismissed the pitch message
|
||||
// and then installed the extension.
|
||||
runtimePitchFixture.setup.call(this, true, true);
|
||||
}
|
||||
}));
|
||||
test('Hide pitch message', function() {
|
||||
this.check(false);
|
||||
});
|
||||
|
||||
|
||||
// This fails on jenkins for some reason, but the code works as expected in
|
||||
// Firefox. Trust me.
|
||||
/*
|
||||
module('App Runtime missing', $.extend({}, runtimePitchFixture, {
|
||||
setup: function() {
|
||||
runtimePitchFixture.setup.call(this, false, false);
|
||||
}
|
||||
}));
|
||||
test('Show pitch message', function() {
|
||||
this.check(true);
|
||||
});
|
||||
*/
|
||||
|
||||
|
||||
module('App Runtime missing in non-Firefox', $.extend({}, runtimePitchFixture, {
|
||||
setup: function() {
|
||||
runtimePitchFixture.setup.call(this, false, false, true);
|
||||
}
|
||||
}));
|
||||
test('Hide pitch message', function() {
|
||||
this.check(false);
|
||||
});
|
||||
|
||||
|
||||
module('App Runtime missing (seen warning)', $.extend({}, runtimePitchFixture, {
|
||||
setup: function() {
|
||||
runtimePitchFixture.setup.call(this, false, true);
|
||||
}
|
||||
}));
|
||||
test('Hide pitch message', function() {
|
||||
this.check(false);
|
||||
});
|
|
@ -1,194 +0,0 @@
|
|||
$(document).ready(function(){
|
||||
|
||||
|
||||
module('apps errors', {
|
||||
setup: function() {
|
||||
this.sandbox = tests.createSandbox('#apps-error-msg');
|
||||
$('.modal', this.sandbox).hide();
|
||||
},
|
||||
teardown: function() {
|
||||
this.sandbox.remove();
|
||||
},
|
||||
installAppWithError: function(manifestUrl, errorOb, errModalCallback) {
|
||||
var sb = this.sandbox,
|
||||
nav = {};
|
||||
nav.mozApps = {
|
||||
install: function(manifestUrl, data, success, error) {
|
||||
error(errorOb);
|
||||
}
|
||||
};
|
||||
if (!errModalCallback) {
|
||||
errModalCallback = function() {
|
||||
// False tells the modal code not to execute all the dom
|
||||
// re-positioning for rendering. Otherwise this makes
|
||||
// verifying the sandbox hard.
|
||||
return false;
|
||||
};
|
||||
}
|
||||
apps.install(manifestUrl, {domContext: sb,
|
||||
navigator: nav,
|
||||
errModalCallback: errModalCallback});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
asyncTest('test permission error', function() {
|
||||
var sb = this.sandbox;
|
||||
$(sb).one('error_shown.apps', function() {
|
||||
equals($('.apps-error-msg h2', sb).text(),
|
||||
'App installation not allowed.');
|
||||
equals($('.apps-error-msg p', sb).text(), 'detailed message');
|
||||
start();
|
||||
});
|
||||
this.installAppWithError('http://nice.com/nice.webapp',
|
||||
{code: 'permissionDenied',
|
||||
message: "detailed message"});
|
||||
});
|
||||
|
||||
|
||||
test('test user canceled', function() {
|
||||
var sb = this.sandbox,
|
||||
callback;
|
||||
callback = function() {
|
||||
ok(false, 'dialog should not be shown when a user cancels install');
|
||||
return false;
|
||||
};
|
||||
this.installAppWithError('http://nice.com/nice.webapp',
|
||||
{code: 'denied',
|
||||
message: 'user canceled installation'},
|
||||
callback);
|
||||
});
|
||||
|
||||
|
||||
asyncTest('test unexpected error', function() {
|
||||
var sb = this.sandbox;
|
||||
$(sb).one('error_shown.apps', function() {
|
||||
equals($('.apps-error-msg h2', sb).text(),
|
||||
'Install failed. Please try again later.');
|
||||
equals($('.apps-error-msg p', sb).text(), 'surprise');
|
||||
start();
|
||||
});
|
||||
this.installAppWithError('http://nice.com/nice.webapp', {code: 'bogus',
|
||||
message: "surprise"});
|
||||
});
|
||||
|
||||
|
||||
test('test successful app install', function() {
|
||||
var sb = this.sandbox,
|
||||
nav = {},
|
||||
callback;
|
||||
nav.mozApps = {
|
||||
install: function(manifestUrl, data, success, error) {}
|
||||
};
|
||||
callback = function() {
|
||||
ok(false, 'dialog should not be shown on successful app install');
|
||||
return false;
|
||||
};
|
||||
apps.install('http://nice.com/nice.webapp', {domContext: sb,
|
||||
navigator: nav,
|
||||
errModalCallback: callback});
|
||||
});
|
||||
|
||||
|
||||
asyncTest('test append to visible modal', function() {
|
||||
var $sb = $(this.sandbox);
|
||||
// Simulate a popup:
|
||||
$sb.append('<div class="existing modal"><div class="modal-inside"></div></div>');
|
||||
$sb.one('error_shown.apps', function() {
|
||||
equals($('.existing h2', $sb).text(),
|
||||
'App installation not allowed.');
|
||||
equals($('.existing p', $sb).text(),
|
||||
'detailed message');
|
||||
start();
|
||||
});
|
||||
this.installAppWithError('http://nice.com/nice.webapp',
|
||||
{code: 'permissionDenied',
|
||||
message: "detailed message"});
|
||||
});
|
||||
|
||||
|
||||
module('apps as wrapper', {
|
||||
setup: function() {
|
||||
this.sandbox = tests.createSandbox('#apps-error-msg');
|
||||
$('.modal', this.sandbox).hide();
|
||||
},
|
||||
teardown: function() {
|
||||
this.sandbox.remove();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
asyncTest('success callback', function() {
|
||||
var sb = this.sandbox,
|
||||
nav = {},
|
||||
callback;
|
||||
nav.mozApps = {
|
||||
install: function(manifestUrl, data, success, error) {
|
||||
success();
|
||||
}
|
||||
};
|
||||
callback = function() {
|
||||
ok(true, 'success was called');
|
||||
start();
|
||||
}
|
||||
apps.install('http://nice.com/nice.webapp', {domContext: sb,
|
||||
navigator: nav,
|
||||
success: callback});
|
||||
});
|
||||
|
||||
|
||||
asyncTest('install error: system unsupported', function() {
|
||||
var sb = this.sandbox,
|
||||
nav = {};
|
||||
$(sb).one('mobile_error_shown.apps', function() {
|
||||
equal($('.apps-error-msg h2', sb).text(), 'App installation failed.');
|
||||
equal($('.apps-error-msg p', sb).text(), 'This system does not support installing apps.');
|
||||
start();
|
||||
});
|
||||
apps.install('http://nice.com/nice.webapp', {domContext: sb, navigator: nav, mobile: true});
|
||||
});
|
||||
|
||||
|
||||
asyncTest('data', function() {
|
||||
var sb = this.sandbox,
|
||||
nav = {},
|
||||
callback,
|
||||
dataReceived;
|
||||
nav.mozApps = {
|
||||
install: function(manifestUrl, data, success, error) {
|
||||
dataReceived = data;
|
||||
success();
|
||||
}
|
||||
};
|
||||
callback = function() {
|
||||
equals(dataReceived.receipt, '<receipt>');
|
||||
start();
|
||||
}
|
||||
apps.install('http://nice.com/nice.webapp', {domContext: sb,
|
||||
navigator: nav,
|
||||
success: callback,
|
||||
data: {receipt: '<receipt>'}});
|
||||
});
|
||||
|
||||
|
||||
asyncTest('error callback', function() {
|
||||
var sb = this.sandbox,
|
||||
nav = {},
|
||||
callback;
|
||||
nav.mozApps = {
|
||||
install: function(manifestUrl, data, success, error) {
|
||||
error({code: 'someCode', message: 'some message'});
|
||||
}
|
||||
};
|
||||
callback = function(errOb) {
|
||||
equals(errOb.code, 'someCode');
|
||||
start();
|
||||
}
|
||||
apps.install('http://nice.com/nice.webapp', {domContext: sb,
|
||||
navigator: nav,
|
||||
errModalCallback: function() { return false; },
|
||||
error: callback});
|
||||
});
|
||||
|
||||
|
||||
});
|
|
@ -1,182 +0,0 @@
|
|||
$(document).ready(function(){
|
||||
module('browserid setup', {
|
||||
setup: function() {
|
||||
$(window).undelegate('.browserid-login', 'click');
|
||||
this.sandbox = tests.createSandbox('#browserid-test');
|
||||
this.originalGVE = gotVerifiedEmail;
|
||||
this.originalID = navigator.id;
|
||||
var that = this;
|
||||
gotVerifiedEmail = function(x, y){
|
||||
that.assertion = x;
|
||||
that.to = y;
|
||||
};
|
||||
},
|
||||
teardown: function() {
|
||||
gotVerifiedEmail = this.originalGVE;
|
||||
navigator.id = this.originaID;
|
||||
this.sandbox.remove();
|
||||
}
|
||||
});
|
||||
test('Setup with redirect', function() {
|
||||
var win = {
|
||||
'location': {'href': '/users/login?to=/en-US/firefox/'}
|
||||
};
|
||||
navigator.id = {
|
||||
'getVerifiedEmail': function (f) {
|
||||
f('fake-assertion');
|
||||
}
|
||||
};
|
||||
initBrowserID(win, this.sandbox);
|
||||
$('.browserid-login', this.sandbox).eq(0).click();
|
||||
equal(this.to, '/en-US/firefox/');
|
||||
equal(this.assertion, 'fake-assertion');
|
||||
});
|
||||
|
||||
test('Setup with absolute redirect', function() {
|
||||
var win = {
|
||||
'location': {'href': 'http://evilsite.com/badnews/'}
|
||||
};
|
||||
navigator.id = {
|
||||
'getVerifiedEmail': function (f) {
|
||||
f('fake-assertion');
|
||||
}
|
||||
};
|
||||
initBrowserID(win, this.sandbox);
|
||||
$('.browserid-login').click();
|
||||
equal(this.to, '/');
|
||||
equal(this.assertion, 'fake-assertion');
|
||||
});
|
||||
|
||||
test('Setup with no redirect', function() {
|
||||
var win = {
|
||||
'location': {'href': '/users/login'}
|
||||
};
|
||||
navigator.id = {
|
||||
'getVerifiedEmail': function (f) {
|
||||
f('fake-assertion');
|
||||
}
|
||||
};
|
||||
initBrowserID(win, this.sandbox);
|
||||
$('.browserid-login').click();
|
||||
equal(this.to, '/');
|
||||
equal(this.assertion, 'fake-assertion');
|
||||
});
|
||||
|
||||
test('Setup with no redirect from non login page', function() {
|
||||
var win = {
|
||||
'location': {'href': '/users/test'}
|
||||
};
|
||||
navigator.id = {
|
||||
'getVerifiedEmail': function (f) {
|
||||
f('fake-assertion');
|
||||
}
|
||||
};
|
||||
initBrowserID(win, this.sandbox);
|
||||
$('.browserid-login').click();
|
||||
equal(this.to, '/users/test');
|
||||
equal(this.assertion, 'fake-assertion');
|
||||
});
|
||||
|
||||
module('browserid login', {
|
||||
setup: function() {
|
||||
this.origRedirect = browserIDRedirect;
|
||||
this.sandbox = tests.createSandbox('#browserid-test');
|
||||
},
|
||||
teardown: function() {
|
||||
this.sandbox.remove();
|
||||
browserIDRedirect = this.origRedirect;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
asyncTest('Login failure (error from server)', function() {
|
||||
var sandbox = this.sandbox;
|
||||
$('.browserid-login', sandbox).attr('data-url', '/browserid-login-fail');
|
||||
equal($('.primary .notification-box', sandbox).length, 0);
|
||||
browserIDRedirect = function() {};
|
||||
var i = $.mockjax({url: '/browserid-login-fail',
|
||||
responseText: '',
|
||||
status: 401});
|
||||
gotVerifiedEmail('browserid-assertion', '/', sandbox).always(
|
||||
function(ex) {
|
||||
equal($('.primary .notification-box h2', sandbox).text().indexOf(
|
||||
"BrowserID login failed. Maybe you don't have an account"
|
||||
+ ' under that email address?'), 0);
|
||||
$('.primary .notification-box', sandbox).remove();
|
||||
$.mockjaxClear(i);
|
||||
start();
|
||||
});
|
||||
});
|
||||
|
||||
asyncTest('Login failure (message from server)', function() {
|
||||
var TESTMSG = 'Example error message';
|
||||
var sandbox = this.sandbox;
|
||||
$('.browserid-login', sandbox).attr('data-url', '/browserid-login-fail');
|
||||
equal($('.primary .notification-box', sandbox).length, 0);
|
||||
browserIDRedirect = function() { };
|
||||
var i = $.mockjax({url: '/browserid-login-fail',
|
||||
responseText: TESTMSG,
|
||||
status: 401});
|
||||
gotVerifiedEmail('browserid-assertion', '/', sandbox).fail(
|
||||
function() {
|
||||
equal($('.primary .notification-box h2', sandbox).text().indexOf(
|
||||
TESTMSG), 0);
|
||||
$('.primary .notification-box', sandbox).remove();
|
||||
$.mockjaxClear(i);
|
||||
start();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
test('Login cancellation', function() {
|
||||
var sandbox = this.sandbox;
|
||||
$('.browserid-login', sandbox).attr('data-url', '/browserid-login-cancel');
|
||||
var i = $.mockjax({url: '/browserid-login-cancel',
|
||||
response: function () {
|
||||
ok(false, 'XHR call made when user cancelled');
|
||||
}});
|
||||
equal(gotVerifiedEmail(null, '/', sandbox), null);
|
||||
equal($('.primary .notification-box', sandbox).length, 0);
|
||||
$.mockjaxClear(i);
|
||||
});
|
||||
|
||||
asyncTest('Login success', function() {
|
||||
var ajaxCalled = false,
|
||||
sandbox = this.sandbox;
|
||||
$('.browserid-login', sandbox).attr('data-url', '/browserid-login-success');
|
||||
equal($('.primary .notification-box', sandbox).length, 0);
|
||||
browserIDRedirect = function(to) {
|
||||
return function() { ajaxCalled = true; };
|
||||
};
|
||||
var i = $.mockjax({url: '/browserid-login-success',
|
||||
responseText: '',
|
||||
status: 200});
|
||||
gotVerifiedEmail('browserid-assertion', '/', sandbox).done(
|
||||
function() {
|
||||
ok(ajaxCalled);
|
||||
$.mockjaxClear(i);
|
||||
start();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
asyncTest('Admin login failure', function() {
|
||||
var sandbox = this.sandbox;
|
||||
$('.browserid-login', sandbox).attr('data-url', '/browserid-login-fail');
|
||||
equal($('.primary .notification-box', sandbox).length, 0);
|
||||
browserIDRedirect = function() {};
|
||||
var i = $.mockjax({url: '/browserid-login-fail',
|
||||
responseText: '',
|
||||
status: 400});
|
||||
gotVerifiedEmail('browserid-assertion', '/', sandbox).fail(
|
||||
function() {
|
||||
equal($('.primary .notification-box h2', sandbox).text(),
|
||||
'Admins and editors must provide a password'
|
||||
+ ' to log in.');
|
||||
$('.primary .notification-box', sandbox).remove();
|
||||
$.mockjaxClear(i);
|
||||
start();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
|
@ -1,570 +0,0 @@
|
|||
$(document).ready(function(){
|
||||
|
||||
var catFixture = {
|
||||
setup: function() {
|
||||
this.sandbox = tests.createSandbox('#addon-cats');
|
||||
initCatFields(this.sandbox);
|
||||
},
|
||||
teardown: function() {
|
||||
this.sandbox.remove();
|
||||
}
|
||||
};
|
||||
|
||||
module('initCatFields', catFixture);
|
||||
|
||||
test('Default with initial categories', function() {
|
||||
var scope = $("#addon-cats-fx", this.sandbox);
|
||||
var checkedChoices = $("input:checked", scope);
|
||||
equals(checkedChoices.length, 2);
|
||||
equals(checkedChoices[0].id, "id_form-0-categories_1");
|
||||
equals(checkedChoices[1].id, "id_form-0-categories_2");
|
||||
|
||||
// 2 categories are selected, the other category should be disabled.
|
||||
var max = scope.parent("div").attr("data-max-categories");
|
||||
equals(parseInt(max, 10), 2);
|
||||
var disabledChoices = $("input:disabled", this.sandbox);
|
||||
equals(disabledChoices.length, 1);
|
||||
equals(disabledChoices[0].id, "id_form-0-categories_0");
|
||||
});
|
||||
|
||||
test('Default without initial categories', function() {
|
||||
equals($("#addon-cats-tb input:checked", this.sandbox).length, 0);
|
||||
});
|
||||
|
||||
|
||||
module('addonUploaded', {
|
||||
setup: function() {
|
||||
this._FormData = z.FormData;
|
||||
this.FormDataStub = tests.StubOb(z.FormData, {
|
||||
send: function() {}
|
||||
});
|
||||
z.FormData = this.FormDataStub;
|
||||
this.sandbox = tests.createSandbox('#file-upload-template');
|
||||
$.fx.off = true;
|
||||
|
||||
this.uploader = $('#upload-file-input', this.sandbox).addonUploader();
|
||||
|
||||
this.el = $('#upload-file-input', this.sandbox)[0];
|
||||
this.file = {
|
||||
size: 200,
|
||||
name: 'some-addon.xpi'
|
||||
};
|
||||
this.el.files = [this.file];
|
||||
|
||||
$(this.el).trigger('change');
|
||||
// sets all animation durations to 0
|
||||
$.fx.off = true;
|
||||
},
|
||||
teardown: function() {
|
||||
$.fx.off = false;
|
||||
this.sandbox.remove();
|
||||
z.FormData = this._FormData;
|
||||
$.fx.off = false;
|
||||
}
|
||||
});
|
||||
|
||||
test('JSON error', function() {
|
||||
$(this.el).trigger("upload_success_results",
|
||||
[{name: 'somefile.txt'},
|
||||
{'error': "Traceback (most recent call last): ...NameError"}]);
|
||||
|
||||
ok($('#upload-status-bar', this.sandbox).hasClass('bar-fail'));
|
||||
equals($('#upload_errors', this.sandbox).text(),
|
||||
'Unexpected server error while validating.')
|
||||
});
|
||||
|
||||
test('Too many messages', function() {
|
||||
var results = {
|
||||
validation: {
|
||||
"errors": 7,
|
||||
"success": false,
|
||||
"warnings": 0,
|
||||
"ending_tier": 3,
|
||||
"messages": [{
|
||||
"message": "Invalid maximum version number",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"message": "Missing translation file",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"message": "Missing translation file",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"message": "Missing translation file",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"message": "Missing translation file",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"message": "Missing translation file",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"message": "Missing translation file",
|
||||
"type": "error"
|
||||
}],
|
||||
"rejected": false,
|
||||
"detected_type": "extension",
|
||||
"notices": 0,
|
||||
},
|
||||
error: null,
|
||||
full_report_url: '/full-report'
|
||||
};
|
||||
|
||||
$(this.el).trigger("upload_success_results",
|
||||
[{name: 'somefile.txt'}, results]);
|
||||
|
||||
equals($('#upload-status-results ul li', this.sandbox).length, 6);
|
||||
equals($('#upload-status-results ul li:eq(5)', this.sandbox).text(),
|
||||
'…and 2 more');
|
||||
});
|
||||
|
||||
|
||||
test('form errors are cleared', function() {
|
||||
var fxt = this;
|
||||
// Simulate django form errors from the POST
|
||||
this.sandbox.find('form').prepend(
|
||||
'<ul class="errorlist"><li>Duplicate UUID found.</li></ul>');
|
||||
|
||||
$(this.el).trigger("upload_start", [{name: 'somefile.txt'}]);
|
||||
|
||||
equals($('ul.errorlist', this.sandbox).length, 0);
|
||||
});
|
||||
|
||||
test('Notices count as warnings', function() {
|
||||
|
||||
var results = {
|
||||
validation: {
|
||||
"warnings": 4,
|
||||
"notices": 4,
|
||||
"errors": 0,
|
||||
"success": true,
|
||||
"ending_tier": 3,
|
||||
"rejected": false,
|
||||
"detected_type": "extension"
|
||||
},
|
||||
error: null,
|
||||
full_report_url: '/full-report',
|
||||
platforms_to_exclude: []
|
||||
};
|
||||
|
||||
$(this.el).trigger("upload_success_results",
|
||||
[{name: 'somefile.txt'}, results]);
|
||||
|
||||
equals($('##upload-status-results strong', this.sandbox).text(),
|
||||
'Your add-on passed validation with no errors and 8 warnings.');
|
||||
});
|
||||
|
||||
test('HTML in errors', function() {
|
||||
var results = {
|
||||
validation: {
|
||||
"errors": 1,
|
||||
"success": false,
|
||||
"warnings": 0,
|
||||
"ending_tier": 3,
|
||||
"messages": [{
|
||||
// TODO(Kumar) when validator is no longer escaped, change this
|
||||
"message": "invalid properties in the install.rdf like <em:id>",
|
||||
"type": "error"
|
||||
}],
|
||||
"rejected": false,
|
||||
"detected_type": "extension",
|
||||
"notices": 0,
|
||||
},
|
||||
error: null,
|
||||
full_report_url: '/full-report'
|
||||
};
|
||||
$(this.el).trigger("upload_success_results",
|
||||
[{name: 'somefile.txt'}, results]);
|
||||
ok($('#upload-status-bar', this.sandbox).hasClass('bar-fail'));
|
||||
equals($('#upload_errors', this.sandbox).text(),
|
||||
'invalid properties in the install.rdf like <em:id>')
|
||||
});
|
||||
|
||||
test('HTML in filename (on start)', function() {
|
||||
$(this.el).trigger("upload_start", [{name: "tester's add-on2.xpi"}]);
|
||||
equals($('#upload-status-text', this.sandbox).text(),
|
||||
"Uploading tester's add-on2.xpi");
|
||||
});
|
||||
|
||||
test('HTML in filename (on error)', function() {
|
||||
var errors = [],
|
||||
results = {};
|
||||
$(this.el).trigger("upload_errors",
|
||||
[{name: "tester's add-on2.xpi"}, errors, results]);
|
||||
equals($('#upload-status-text', this.sandbox).text(),
|
||||
"Error with tester's add-on2.xpi");
|
||||
});
|
||||
|
||||
test('HTML in filename (on success)', function() {
|
||||
$.mockjax({
|
||||
url: '/poll-for-results-success',
|
||||
responseText: {
|
||||
error: ""
|
||||
},
|
||||
status: 200
|
||||
});
|
||||
var results = {url: '/poll-for-results-success'};
|
||||
$(this.el).trigger("upload_success",
|
||||
[{name: "tester's add-on2.xpi"}, results]);
|
||||
equals($('#upload-status-text', this.sandbox).text(),
|
||||
"Validating tester's add-on2.xpi");
|
||||
});
|
||||
|
||||
test('400 JSON error', function() {
|
||||
var xhr = {
|
||||
readyState: 4,
|
||||
status: 400,
|
||||
responseText: JSON.stringify({
|
||||
"validation": {
|
||||
"messages": [{"type": "error", "message": "Some form error"}]
|
||||
}
|
||||
})
|
||||
};
|
||||
this.uploader.trigger('upload_onreadystatechange', [this.file, xhr]);
|
||||
equals(this.sandbox.find('#upload_errors').text().trim(), 'Some form error');
|
||||
});
|
||||
|
||||
asyncTest('400 JSON error after polling', function() {
|
||||
var sb = this.sandbox;
|
||||
$.mockjax({
|
||||
url: '/poll-for-results',
|
||||
responseText: {
|
||||
validation: {
|
||||
messages: [{tier: 1,
|
||||
message: "UUID doesn't match add-on.",
|
||||
"type": "error"}]},
|
||||
error: ""
|
||||
},
|
||||
status: 400
|
||||
});
|
||||
this.uploader.trigger('upload_success_results',
|
||||
[this.file, {validation: '', url: '/poll-for-results'}]);
|
||||
// It would be nice to stub out setTimeout but that throws permission errors.
|
||||
tests.waitFor(function() {
|
||||
return $('#upload_errors', sb).length;
|
||||
}, {timeout: 2000} ).thenDo(function() {
|
||||
equals(sb.find('#upload_errors').text().trim(), "UUID doesn't match add-on.");
|
||||
start();
|
||||
});
|
||||
});
|
||||
|
||||
test('append form data callback', function() {
|
||||
var called = false,
|
||||
self = this;
|
||||
$('#upload-file-input', this.sandbox).addonUploader({
|
||||
appendFormData: function(formData) {
|
||||
called = true;
|
||||
ok(formData.append);
|
||||
}
|
||||
});
|
||||
$(this.el).trigger('change');
|
||||
ok(called);
|
||||
});
|
||||
|
||||
test('Unrecognized file type', function() {
|
||||
var errors;
|
||||
$(this.el).bind('upload_errors', function(e, file, error_msgs) {
|
||||
errors = error_msgs;
|
||||
});
|
||||
this.file.name = 'somefile.pdf';
|
||||
$(this.el).trigger('change');
|
||||
equals(errors[0], "The filetype you uploaded isn't recognized.");
|
||||
});
|
||||
|
||||
|
||||
module('fileUpload', {
|
||||
setup: function() {
|
||||
var fxt = this;
|
||||
this.sandbox = tests.createSandbox('#file-upload-template');
|
||||
initUploadControls();
|
||||
this.uploadFile = window.uploadFile;
|
||||
this.uploadFileCalled = false;
|
||||
// stub out the XHR calls:
|
||||
window.uploadFile = function() {
|
||||
fxt.uploadFileCalled = true;
|
||||
return null;
|
||||
};
|
||||
},
|
||||
teardown: function() {
|
||||
this.sandbox.remove();
|
||||
window.uploadFile = this.uploadFile;
|
||||
}
|
||||
});
|
||||
|
||||
module('preview_edit', {
|
||||
setup: function() {
|
||||
this.sandbox = tests.createSandbox('#preview-list');
|
||||
initUploadPreview();
|
||||
},
|
||||
teardown: function() {
|
||||
this.sandbox.remove();
|
||||
}
|
||||
});
|
||||
|
||||
test('Clicking delete screenshot marks checkbox.', function() {
|
||||
// $.fx.off sets all animation durations to 0
|
||||
$.fx.off = true;
|
||||
$(".edit-previews-text a.remove", this.sandbox).trigger('click');
|
||||
equals($(".delete input", this.sandbox).attr("checked"), 'checked');
|
||||
equals($(".preview:visible", this.sandbox).length, 0);
|
||||
$.fx.off = false;
|
||||
});
|
||||
|
||||
|
||||
module('addon platform chooser', {
|
||||
setup: function() {
|
||||
this.sandbox = tests.createSandbox('#addon-platform-chooser');
|
||||
},
|
||||
teardown: function() {
|
||||
this.sandbox.remove();
|
||||
},
|
||||
check: function(sel) {
|
||||
$(sel, this.sandbox).attr('checked', 'checked').trigger('change');
|
||||
}
|
||||
});
|
||||
|
||||
test('platforms > ALL', function() {
|
||||
// Check some platforms:
|
||||
this.check('input[value="2"]');
|
||||
this.check('input[value="3"]');
|
||||
// Check ALL platforms:
|
||||
this.check('input[value="1"]');
|
||||
equals($('input[value="2"]', this.sandbox).attr('checked'), undefined);
|
||||
equals($('input[value="3"]', this.sandbox).attr('checked'), undefined);
|
||||
});
|
||||
|
||||
test('ALL > platforms', function() {
|
||||
// Check ALL platforms:
|
||||
this.check('input[value="1"]');
|
||||
// Check any other platform:
|
||||
this.check('input[value="2"]');
|
||||
equals($('input[value="1"]', this.sandbox).attr('checked'), undefined);
|
||||
});
|
||||
|
||||
test('mobile / desktop', function() {
|
||||
// Check ALL desktop platforms:
|
||||
this.check('input[value="1"]');
|
||||
// Check ALL mobile platforms:
|
||||
this.check('input[value="9"]');
|
||||
// desktop platforms are still checked:
|
||||
equals($('input[value="1"]', this.sandbox).attr('checked'), 'checked');
|
||||
});
|
||||
|
||||
test('mobile > ALL', function() {
|
||||
// Check ALL mobile platforms:
|
||||
this.check('input[value="9"]');
|
||||
// Check Android:
|
||||
this.check('input[value="7"]');
|
||||
// ALL mobile is no longer checked:
|
||||
equals($('input[value="9"]', this.sandbox).attr('checked'), undefined);
|
||||
});
|
||||
|
||||
test('ALL > mobile', function() {
|
||||
// Check Android, Maemo:
|
||||
this.check('input[value="7"]');
|
||||
this.check('input[value="8"]');
|
||||
// Check ALL mobile platforms:
|
||||
this.check('input[value="9"]');
|
||||
// Specific platforms are no longer checked:
|
||||
equals($('input[value="7"]', this.sandbox).attr('checked'), undefined);
|
||||
equals($('input[value="8"]', this.sandbox).attr('checked'), undefined);
|
||||
});
|
||||
|
||||
// TODO(Kumar) uncomment when bug 706597 is fixed
|
||||
// module('slugified fields', {
|
||||
// setup: function() {
|
||||
// this.sandbox = tests.createSandbox('#slugified-field');
|
||||
// },
|
||||
// teardown: function() {
|
||||
// this.sandbox.remove();
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// asyncTest('non-customized', function() {
|
||||
// load_unicode();
|
||||
// tests.waitFor(function() {
|
||||
// return z == null || z.unicode_letters;
|
||||
// }).thenDo(function() {
|
||||
// $("#id_name").val("password exporter");
|
||||
// slugify();
|
||||
// equals($("#id_slug").val(), 'password-exporter');
|
||||
// $("#id_name").val("password exporter2");
|
||||
// slugify();
|
||||
// equals($("#id_slug").val(), 'password-exporter2');
|
||||
// start();
|
||||
// });
|
||||
// });
|
||||
//
|
||||
// asyncTest('customized', function() {
|
||||
// load_unicode();
|
||||
// tests.waitFor(function() {
|
||||
// return z == null || z.unicode_letters;
|
||||
// }).thenDo(function() {
|
||||
// $("#id_name").val("password exporter");
|
||||
// slugify();
|
||||
// equals($("#id_slug").val(), 'password-exporter');
|
||||
// $("#id_slug").attr("data-customized", 1);
|
||||
// $("#id_name").val("password exporter2");
|
||||
// slugify();
|
||||
// equals($("#id_slug").val(), 'password-exporter');
|
||||
// start();
|
||||
// });
|
||||
// });
|
||||
|
||||
|
||||
module('exclude platforms', {
|
||||
setup: function() {
|
||||
this._FormData = z.FormData;
|
||||
z.FormData = tests.StubOb(z.FormData, {
|
||||
send: function() {}
|
||||
});
|
||||
this.sandbox = tests.createSandbox('#addon-platform-exclusion');
|
||||
|
||||
$.fx.off = true;
|
||||
|
||||
$('#upload-file-input', this.sandbox).addonUploader();
|
||||
|
||||
this.el = $('#upload-file-input', this.sandbox)[0];
|
||||
this.el.files = [{
|
||||
size: 200,
|
||||
name: 'some-addon.xpi'
|
||||
}];
|
||||
|
||||
$(this.el).trigger('change');
|
||||
},
|
||||
teardown: function() {
|
||||
this.sandbox.remove();
|
||||
z.FormData = this._FormData;
|
||||
}
|
||||
});
|
||||
|
||||
test('mobile / android', function() {
|
||||
var sb = this.sandbox;
|
||||
results = {
|
||||
validation: {
|
||||
"errors": 0,
|
||||
"detected_type": "mobile",
|
||||
"success": true,
|
||||
"warnings": 0,
|
||||
"notices": 0,
|
||||
"message_tree": {},
|
||||
"messages": [],
|
||||
"rejected": false
|
||||
},
|
||||
// exclude all but mobile:
|
||||
platforms_to_exclude: ['1', '2', '3', '5']
|
||||
};
|
||||
|
||||
$(this.el).trigger("upload_success_results",
|
||||
[{name: 'somefile.txt'}, results]);
|
||||
|
||||
// All desktop platforms disabled:
|
||||
equal($('.desktop-platforms input:disabled', sb).length, 4);
|
||||
ok($('.desktop-platforms label:eq(0)', sb).hasClass('platform-disabled'));
|
||||
|
||||
ok($('.platform ul.errorlist', sb).length > 0, 'Message shown to user');
|
||||
|
||||
// All mobile platforms not disabled:
|
||||
equal($('.mobile-platforms input:disabled', sb).length, 0);
|
||||
});
|
||||
|
||||
test('existing platforms', function() {
|
||||
var sb = this.sandbox;
|
||||
results = {
|
||||
validation: {
|
||||
"errors": 0,
|
||||
"detected_type": "extension",
|
||||
"success": true,
|
||||
"warnings": 0,
|
||||
"notices": 0,
|
||||
"message_tree": {},
|
||||
"messages": [],
|
||||
"rejected": false
|
||||
},
|
||||
// exclude one platform as if this version already fulfilled it
|
||||
platforms_to_exclude: ['2']
|
||||
};
|
||||
|
||||
$(this.el).trigger("upload_success_results",
|
||||
[{name: 'somefile.txt'}, results]);
|
||||
|
||||
equals($('.desktop-platforms input:eq(0)', sb).attr('disabled'), undefined);
|
||||
equals($('.desktop-platforms input:eq(1)', sb).attr('disabled'), 'disabled');
|
||||
equals($('.desktop-platforms label:eq(0)', sb).hasClass('platform-disabled'),
|
||||
false);
|
||||
});
|
||||
|
||||
|
||||
module('perf-tests', {
|
||||
setup: function() {
|
||||
this.sandbox = tests.createSandbox('#file-perf-tests');
|
||||
initPerfTests(this.sandbox);
|
||||
},
|
||||
teardown: function() {
|
||||
this.sandbox.remove();
|
||||
}
|
||||
});
|
||||
|
||||
asyncTest('success', function() {
|
||||
var $sb = this.sandbox;
|
||||
$('.start-perf-tests', $sb).attr('href', '/file-perf-stub1');
|
||||
$.mockjax({
|
||||
url: '/file-perf-stub1',
|
||||
responseText: {success: true},
|
||||
status: 200,
|
||||
responseTime: 0
|
||||
});
|
||||
$('.start-perf-tests', $sb).trigger('click');
|
||||
tests.waitFor(function() {
|
||||
return $('.perf-results', $sb).attr('data-got-response') == '1';
|
||||
}).thenDo(function() {
|
||||
// TODO(Kumar) add checks for polling
|
||||
equals($('.perf-results', $sb).text(), 'Waiting for test results...')
|
||||
start();
|
||||
});
|
||||
});
|
||||
|
||||
asyncTest('failure', function() {
|
||||
var $sb = this.sandbox;
|
||||
$('.start-perf-tests', $sb).attr('href', '/file-perf-stub2');
|
||||
$.mockjax({
|
||||
url: '/file-perf-stub2',
|
||||
responseText: {success: false},
|
||||
status: 200,
|
||||
responseTime: 0
|
||||
});
|
||||
$('.start-perf-tests', $sb).trigger('click');
|
||||
tests.waitFor(function() {
|
||||
return $('.perf-results', $sb).attr('data-got-response') == '1';
|
||||
}).thenDo(function() {
|
||||
equals($('.perf-results', $sb).text(), 'Internal Server Error')
|
||||
start();
|
||||
});
|
||||
});
|
||||
|
||||
asyncTest('500 error', function() {
|
||||
var $sb = this.sandbox;
|
||||
$('.start-perf-tests', $sb).attr('href', '/file-perf-stub3');
|
||||
$.mockjax({
|
||||
url: '/file-perf-stub3',
|
||||
responseText: '',
|
||||
status: 500,
|
||||
responseTime: 0
|
||||
});
|
||||
$('.start-perf-tests', $sb).trigger('click');
|
||||
tests.waitFor(function() {
|
||||
return $('.perf-results', $sb).attr('data-got-response') == '1';
|
||||
}).thenDo(function() {
|
||||
equals($('.perf-results', $sb).text(), 'Internal Server Error')
|
||||
start();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
});
|
|
@ -1,138 +0,0 @@
|
|||
$(document).ready(function(){
|
||||
|
||||
var editorFixtures = {
|
||||
setup: function() {
|
||||
this.sandbox = tests.createSandbox('#editors-search-form');
|
||||
},
|
||||
teardown: function() {
|
||||
this.sandbox.remove();
|
||||
},
|
||||
selectOpt: function(index) {
|
||||
var doc = this.sandbox;
|
||||
$('#id_application_id option', doc).eq(index).attr('selected', 'selected');
|
||||
$('#id_application_id', doc).trigger('change');
|
||||
}
|
||||
};
|
||||
|
||||
module('editors search form 1', editorFixtures);
|
||||
|
||||
asyncTest('select application', function() {
|
||||
var doc = this.sandbox;
|
||||
$('#id_application_id', doc).attr('data-url', '/app-ver1.json');
|
||||
initQueueSearch(doc);
|
||||
$.mockjax({
|
||||
url: '/app-ver1.json',
|
||||
status: 200,
|
||||
response: function(settings) {
|
||||
equals(settings.data.application_id, '1');
|
||||
this.responseText = {
|
||||
choices: [['', ''],
|
||||
['4.0b2pre', '4.0b2pre'],
|
||||
['2.0a1pre', '2.0a1pre'],
|
||||
['1.0', '1.0']]
|
||||
};
|
||||
}
|
||||
});
|
||||
this.selectOpt(1);
|
||||
tests.waitFor(function() {
|
||||
return ($('#id_max_version option', doc).length > 1);
|
||||
}).thenDo(function() {
|
||||
var values = [];
|
||||
$.each($('#id_max_version option', doc), function(i, e) {
|
||||
values.push($(e).val());
|
||||
});
|
||||
same(values, ["", "4.0b2pre", "2.0a1pre", "1.0"]);
|
||||
start();
|
||||
});
|
||||
});
|
||||
|
||||
module('editors search form 2', editorFixtures);
|
||||
|
||||
asyncTest('de-select application', function() {
|
||||
var suite = this,
|
||||
doc = this.sandbox;
|
||||
$('#id_application_id', doc).attr('data-url', '/app-ver2.json');
|
||||
initQueueSearch(doc);
|
||||
$.mockjax({
|
||||
url: '/app-ver2.json',
|
||||
status: 200,
|
||||
responseText: {choices: [['', ''], ['4.0b2pre', '4.0b2pre']]}
|
||||
});
|
||||
suite.selectOpt(1);
|
||||
tests.waitFor(function() {
|
||||
return ($('#id_max_version option', doc).length > 1);
|
||||
}).thenDo(function() {
|
||||
suite.selectOpt(0);
|
||||
tests.waitFor(function() {
|
||||
return ($('#id_max_version option', doc).length == 1);
|
||||
}).thenDo(function() {
|
||||
equals($('#id_max_version option', doc).text(),
|
||||
'Select an application first');
|
||||
start();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
module('editors MOTD', {
|
||||
setup: function() {
|
||||
z.Storage().remove('motd_closed');
|
||||
this.sandbox = tests.createSandbox('#editors-motd-template');
|
||||
$('.daily-message .close', this.sandbox).hide();
|
||||
initDailyMessage(this.sandbox);
|
||||
},
|
||||
teardown: function() {
|
||||
this.sandbox.remove();
|
||||
}
|
||||
});
|
||||
|
||||
test('is closable', function() {
|
||||
var doc = this.sandbox;
|
||||
equals($('.daily-message .close:visible', doc).length, 1);
|
||||
});
|
||||
|
||||
asyncTest('click to close', function() {
|
||||
var doc = this.sandbox;
|
||||
$('.daily-message .close', doc).trigger('click');
|
||||
tests.waitFor(function() {
|
||||
return $('.daily-message .close:visible', doc).length == 0;
|
||||
}).thenDo(function() {
|
||||
ok(true, 'message was closed');
|
||||
start();
|
||||
});
|
||||
});
|
||||
|
||||
module('editors MOTD page', {
|
||||
setup: function() {
|
||||
this.sandbox = tests.createSandbox('#editors-motd-for-edit-template');
|
||||
$('.daily-message .close', this.sandbox).hide();
|
||||
initDailyMessage(this.sandbox);
|
||||
},
|
||||
teardown: function() {
|
||||
this.sandbox.remove();
|
||||
}
|
||||
});
|
||||
|
||||
test('not closable', function() {
|
||||
var doc = this.sandbox;
|
||||
equals($('.daily-message .close:visible', doc).length, 0);
|
||||
});
|
||||
|
||||
module('editors MOTD after clicking', {
|
||||
setup: function() {
|
||||
z.Storage().set('motd_closed', 'This is an announcement');
|
||||
this.sandbox = tests.createSandbox('#editors-motd-template');
|
||||
initDailyMessage(this.sandbox);
|
||||
},
|
||||
teardown: function() {
|
||||
this.sandbox.remove();
|
||||
}
|
||||
});
|
||||
|
||||
test('message hidden', function() {
|
||||
var doc = this.sandbox;
|
||||
equals($('.daily-message .close:visible', doc).length, 0);
|
||||
});
|
||||
|
||||
|
||||
|
||||
});
|
|
@ -1,25 +0,0 @@
|
|||
$(document).ready(function(){
|
||||
var fileViewer = {
|
||||
setup: function() {
|
||||
this.sandbox = tests.createSandbox('#files-wrapper');
|
||||
},
|
||||
teardown: function() {
|
||||
this.sandbox.remove();
|
||||
}
|
||||
};
|
||||
|
||||
module('File viewer', fileViewer);
|
||||
|
||||
test('Show leaf', function() {
|
||||
var nodes = {
|
||||
$files: this.sandbox.find($('#files'))
|
||||
};
|
||||
var viewer = bind_viewer(nodes);
|
||||
viewer.toggle_leaf(this.sandbox.find('a.directory'));
|
||||
equal(this.sandbox.find('a.directory').hasClass('open'), true);
|
||||
equal(this.sandbox.find('ul:hidden').length, 0);
|
||||
viewer.toggle_leaf(this.sandbox.find('a.directory'));
|
||||
equal(this.sandbox.find('a.directory').hasClass('open'), false);
|
||||
equal(this.sandbox.find('ul:hidden').length, 1);
|
||||
});
|
||||
});
|
|
@ -1,98 +0,0 @@
|
|||
$(document).ready(function(){
|
||||
|
||||
function _inspectHeaders(inspector, url) {
|
||||
var headersInspected = false,
|
||||
url = url || '/local-request-for-csrf.json';
|
||||
$.mockjax({
|
||||
url: url,
|
||||
status: 200,
|
||||
response: function(settings) {
|
||||
inspector(this.headers);
|
||||
start();
|
||||
}
|
||||
});
|
||||
$.ajax({
|
||||
url: url,
|
||||
type: 'post',
|
||||
data: 'foo=bar',
|
||||
success: function(response) {},
|
||||
error: function(xhr) {
|
||||
console.log('ajax request Failed');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
module('jQuery exists', {
|
||||
setup: function() {
|
||||
this.sandbox = tests.createSandbox('#exists');
|
||||
},
|
||||
teardown: function() {
|
||||
this.sandbox.remove();
|
||||
}
|
||||
});
|
||||
|
||||
test('Element exists', function() {
|
||||
equals($('.exists', this.sandbox).exists(), true);
|
||||
});
|
||||
|
||||
test('Element does not exist', function() {
|
||||
equals($('.doesnotexist', this.sandbox).exists(), false);
|
||||
});
|
||||
|
||||
module('CSRF Token from input', {
|
||||
setup: function() {
|
||||
this._csrf = $.cookie('csrftoken');
|
||||
$.cookie('csrftoken', '');
|
||||
this.sandbox = tests.createSandbox('#csrf-template');
|
||||
},
|
||||
teardown: function() {
|
||||
this.sandbox.remove();
|
||||
if (this._csrf) {
|
||||
$.cookie('csrftoken', this._csrf);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
asyncTest('header sent', function() {
|
||||
_inspectHeaders(function(headers) {
|
||||
equals(headers['X-CSRFToken'], '<csrf-from-input>');
|
||||
});
|
||||
});
|
||||
|
||||
module('CSRF Token: remote', {
|
||||
setup: function() {
|
||||
$.cookie('csrftoken', null);
|
||||
}
|
||||
});
|
||||
|
||||
// these started failing after upgrading some libs
|
||||
|
||||
// asyncTest('CSRF not sent 1', function() {
|
||||
// _inspectHeaders(function(headers) {
|
||||
// var htype = typeof headers['X-CSRFToken'];
|
||||
// equals(htype, 'undefined');
|
||||
// }, 'http://someserver/hijack1');
|
||||
// });
|
||||
//
|
||||
// asyncTest('CSRF not sent 2', function() {
|
||||
// _inspectHeaders(function(headers) {
|
||||
// var htype = typeof headers['X-CSRFToken'];
|
||||
// equals(htype, 'undefined');
|
||||
// }, 'https://someserver/hijack2');
|
||||
// });
|
||||
//
|
||||
// asyncTest('CSRF not sent 3', function() {
|
||||
// _inspectHeaders(function(headers) {
|
||||
// var htype = typeof headers['X-CSRFToken'];
|
||||
// equals(htype, 'undefined');
|
||||
// }, '//someserver/hijack');
|
||||
// });
|
||||
//
|
||||
// asyncTest('CSRF not sent 4', function() {
|
||||
// _inspectHeaders(function(headers) {
|
||||
// var htype = typeof headers['X-CSRFToken'];
|
||||
// equals(htype, 'undefined');
|
||||
// }, '://someserver/hijack2');
|
||||
// });
|
||||
|
||||
});
|
|
@ -1,28 +0,0 @@
|
|||
$(document).ready(function(){
|
||||
|
||||
var hovercardFixture = {
|
||||
setup: function() {
|
||||
this.sandbox = tests.createSandbox('#hovercard-grid');
|
||||
this.grid = listing_grid.call(this.sandbox.find(".listing-grid"));
|
||||
},
|
||||
teardown: function() {
|
||||
this.sandbox.remove();
|
||||
}
|
||||
};
|
||||
|
||||
module('hovercards', hovercardFixture);
|
||||
|
||||
test('paginator exists', function() {
|
||||
equals($('nav.pager', this.sandbox).length, 1);
|
||||
});
|
||||
|
||||
test('paginator has correct number of pages', function() {
|
||||
equals($('nav.pager .dot', this.sandbox).length, 3);
|
||||
});
|
||||
|
||||
test('paginator works properly', function() {
|
||||
this.grid.go(2);
|
||||
equals($('section:visible', this.sandbox).index(), 2);
|
||||
});
|
||||
|
||||
});
|
|
@ -1,263 +0,0 @@
|
|||
$(document).ready(function() {
|
||||
var installButtonFixture = {
|
||||
setup: function(sandboxId) {
|
||||
this.sandbox = tests.createSandbox(sandboxId);
|
||||
this.button = $('.button', this.sandbox);
|
||||
this.expected = {};
|
||||
},
|
||||
teardown: function() {
|
||||
this.sandbox.remove();
|
||||
},
|
||||
check: function(expected) {
|
||||
for (var prop in expected) {
|
||||
if (expected.hasOwnProperty(prop)) {
|
||||
equal(this.button.attr(prop), expected[prop]);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module('Install Button', $.extend({}, installButtonFixture, {
|
||||
setup: function() {
|
||||
installButtonFixture.setup.call(this, '#install-button');
|
||||
}
|
||||
}));
|
||||
test('add-on', function() {
|
||||
// Patch user agent as Firefox 3.6.
|
||||
var _browserVersion = z.browserVersion;
|
||||
z.app = 'firefox';
|
||||
z.browser.firefox = true;
|
||||
z.browserVersion = '3.6';
|
||||
z.platform = 'mac';
|
||||
|
||||
var installer = $('.install', this.sandbox).installButton();
|
||||
equal(installer.length, 1);
|
||||
equal(installer.attr('data-version-supported'), 'true');
|
||||
equal(installer.find('a.installer').attr('href'), 'http://testurl.com');
|
||||
|
||||
_browserVersion = z.browserVersion;
|
||||
});
|
||||
|
||||
module('Install Button', $.extend({}, installButtonFixture, {
|
||||
setup: function() {
|
||||
installButtonFixture.setup.call(this, '#install-button-warning');
|
||||
}
|
||||
}));
|
||||
test('app, warning, mobile', function() {
|
||||
this.expected['data-hash'] = undefined;
|
||||
this.expected['href'] = '#';
|
||||
this.expected['data-realurl'] = undefined;
|
||||
|
||||
this.check(this.expected);
|
||||
});
|
||||
|
||||
module('Install Button', $.extend({}, installButtonFixture, {
|
||||
setup: function() {
|
||||
installButtonFixture.setup.call(this, '#install-button-eula');
|
||||
}
|
||||
}));
|
||||
test('app, eula, mobile', function() {
|
||||
this.expected['data-hash'] = undefined;
|
||||
this.expected['href'] = '#';
|
||||
this.expected['data-realurl'] = undefined;
|
||||
|
||||
this.check(this.expected);
|
||||
});
|
||||
|
||||
module('Install Button', $.extend({}, installButtonFixture, {
|
||||
setup: function() {
|
||||
installButtonFixture.setup.call(this, '#install-button-premium');
|
||||
}
|
||||
}));
|
||||
test('premium, mobile', function() {
|
||||
this.expected['data-hash'] = undefined;
|
||||
this.expected['href'] = 'http://testurl.com';
|
||||
this.expected['data-realurl'] = undefined;
|
||||
|
||||
this.check(this.expected);
|
||||
});
|
||||
|
||||
module('Install Button', $.extend({}, installButtonFixture, {
|
||||
setup: function() {
|
||||
installButtonFixture.setup.call(this, '#install-button-contrib');
|
||||
}
|
||||
}));
|
||||
test('contrib, mobile', function() {
|
||||
this.expected['data-hash'] = '1337';
|
||||
this.expected['href'] = 'http://testurl.com';
|
||||
this.expected['data-realurl'] = undefined;
|
||||
|
||||
this.check(this.expected);
|
||||
});
|
||||
|
||||
module('Install Button', $.extend({}, installButtonFixture, {
|
||||
setup: function() {
|
||||
installButtonFixture.setup.call(this, '#install-button-purchasable');
|
||||
}
|
||||
}));
|
||||
test('can be purchased, mobile', function() {
|
||||
this.expected['data-hash'] = '1337';
|
||||
this.expected['href'] = 'http://testurl.com';
|
||||
this.expected['data-realurl'] = undefined;
|
||||
|
||||
this.check(this.expected);
|
||||
});
|
||||
|
||||
module('Install Button', $.extend({}, installButtonFixture, {
|
||||
setup: function() {
|
||||
installButtonFixture.setup.call(this, '#install-button-app-premium');
|
||||
}
|
||||
}));
|
||||
test('app, premium, mobile', function() {
|
||||
this.expected['data-hash'] = undefined;
|
||||
this.expected['href'] = '#';
|
||||
this.expected['data-realurl'] = undefined;
|
||||
|
||||
this.check(this.expected);
|
||||
});
|
||||
|
||||
module('Install Button', $.extend({}, installButtonFixture, {
|
||||
setup: function() {
|
||||
installButtonFixture.setup.call(this, '#install-button-app-contrib');
|
||||
}
|
||||
}));
|
||||
test('app, contrib, mobile', function() {
|
||||
this.expected['data-hash'] = undefined;
|
||||
this.expected['href'] = '#';
|
||||
this.expected['data-realurl'] = undefined;
|
||||
|
||||
this.check(this.expected);
|
||||
});
|
||||
|
||||
module('Install Button', $.extend({}, installButtonFixture, {
|
||||
setup: function() {
|
||||
installButtonFixture.setup.call(this, '#install-button-app-purchasable');
|
||||
}
|
||||
}));
|
||||
test('app, can be purchased, mobile', function() {
|
||||
this.expected['data-hash'] = undefined;
|
||||
this.expected['href'] = '#';
|
||||
this.expected['data-realurl'] = undefined;
|
||||
|
||||
this.check(this.expected);
|
||||
});
|
||||
|
||||
module('Install Button', $.extend({}, installButtonFixture, {
|
||||
setup: function() {
|
||||
installButtonFixture.setup.call(this, '#install-button-mp-warning');
|
||||
}
|
||||
}));
|
||||
test('marketplace, app, warning, mobile', function() {
|
||||
this.expected['data-hash'] = undefined;
|
||||
this.expected['href'] = '#';
|
||||
this.expected['data-realurl'] = undefined;
|
||||
|
||||
this.check(this.expected);
|
||||
});
|
||||
|
||||
module('Install Button', $.extend({}, installButtonFixture, {
|
||||
setup: function() {
|
||||
installButtonFixture.setup.call(this, '#install-button-mp-eula');
|
||||
}
|
||||
}));
|
||||
test('marketplace, app, eula, mobile', function() {
|
||||
this.expected['data-hash'] = undefined;
|
||||
this.expected['href'] = '#';
|
||||
this.expected['data-realurl'] = undefined;
|
||||
|
||||
this.check(this.expected);
|
||||
});
|
||||
|
||||
module('Install Button', $.extend({}, installButtonFixture, {
|
||||
setup: function() {
|
||||
installButtonFixture.setup.call(this, '#install-button-mp-premium');
|
||||
}
|
||||
}));
|
||||
test('marketplace, premium, mobile', function() {
|
||||
this.expected['data-hash'] = undefined;
|
||||
this.expected['href'] = 'http://testurl.com';
|
||||
this.expected['data-realurl'] = undefined;
|
||||
|
||||
this.check(this.expected);
|
||||
});
|
||||
|
||||
module('Install Button', $.extend({}, installButtonFixture, {
|
||||
setup: function() {
|
||||
installButtonFixture.setup.call(this, '#install-button-mp-contrib');
|
||||
}
|
||||
}));
|
||||
test('marketplace, contrib, mobile', function() {
|
||||
this.expected['data-hash'] = '1337';
|
||||
this.expected['href'] = 'http://testurl.com';
|
||||
this.expected['data-realurl'] = undefined;
|
||||
|
||||
this.check(this.expected);
|
||||
});
|
||||
|
||||
// All compatible.
|
||||
module('D2C Install Button', $.extend({}, installButtonFixture, {
|
||||
setup: function() {
|
||||
installButtonFixture.setup.call(this, '#button-d2c-compatible');
|
||||
}
|
||||
}));
|
||||
test('d2c, is_compatible', function() {
|
||||
this.expected['class'] = 'button add installer';
|
||||
this.check(this.expected);
|
||||
equal($('.extra', this.sandbox).length, 0);
|
||||
});
|
||||
|
||||
// Compatible, but with an override.
|
||||
module('D2C Install Button', $.extend({}, installButtonFixture, {
|
||||
setup: function() {
|
||||
installButtonFixture.setup.call(this, '#button-d2c-compatible-override');
|
||||
}
|
||||
}));
|
||||
test('d2c, is_compatible, override', function() {
|
||||
this.expected['class'] = 'button add concealed';
|
||||
this.check(this.expected);
|
||||
equal($('.extra', this.sandbox).length, 1);
|
||||
equal($('.notavail', this.sandbox).text().substr(0, 13), 'Not available');
|
||||
equal($('.d2c-reasons-popup ul li', this.sandbox).length, 1);
|
||||
equal($('.d2c-reasons-popup ul', this.sandbox).html().indexOf('marked this version as incompatible') !== -1, true);
|
||||
});
|
||||
|
||||
// Server side checks are incompatible.
|
||||
module('D2C Install Button', $.extend({}, installButtonFixture, {
|
||||
setup: function() {
|
||||
installButtonFixture.setup.call(this, '#button-d2c-not-compatible');
|
||||
}
|
||||
}));
|
||||
test('d2c, is_compatible, older browser', function() {
|
||||
this.expected['class'] = 'button add concealed';
|
||||
this.check(this.expected);
|
||||
equal($('.extra', this.sandbox).length, 1);
|
||||
equal($('.notavail', this.sandbox).text().substr(0, 13), 'Not available');
|
||||
});
|
||||
|
||||
// Browser version is < the minimum supported app version.
|
||||
module('D2C Install Button', $.extend({}, installButtonFixture, {
|
||||
setup: function() {
|
||||
installButtonFixture.setup.call(this, '#button-d2c-older-browser');
|
||||
}
|
||||
}));
|
||||
test('d2c, is_compatible, older browser', function() {
|
||||
this.expected['class'] = 'button add concealed';
|
||||
this.check(this.expected);
|
||||
equal($('.extra', this.sandbox).length, 1);
|
||||
equal($('.notavail', this.sandbox).text().substr(0, 13), 'Not available');
|
||||
});
|
||||
|
||||
// Max version isn't high enough to support d2c.
|
||||
module('D2C Install Button', $.extend({}, installButtonFixture, {
|
||||
setup: function() {
|
||||
installButtonFixture.setup.call(this, '#button-d2c-old-max');
|
||||
}
|
||||
}));
|
||||
test('d2c, not is_compatible, max version', function() {
|
||||
this.expected['class'] = 'button add concealed';
|
||||
this.check(this.expected);
|
||||
equal($('.d2c-reasons-popup', this.sandbox).length, 0);
|
||||
equal($('.d2c-reasons-help', this.sandbox).length, 0);
|
||||
equal($('.notavail', this.sandbox).text().substr(0, 13), 'Not available');
|
||||
});
|
||||
});
|
|
@ -1,37 +0,0 @@
|
|||
$(document).ready(function(){
|
||||
|
||||
var transFixture = {
|
||||
setup: function() {
|
||||
this.sandbox = tests.createSandbox('#l10n-translation');
|
||||
},
|
||||
teardown: function() {
|
||||
this.sandbox.remove();
|
||||
}
|
||||
};
|
||||
|
||||
module('z.refreshL10n', transFixture);
|
||||
|
||||
test('English', function() {
|
||||
z.refreshL10n('en-us');
|
||||
equals($('textarea:visible', this.sandbox).text().trim(),
|
||||
'Firebug integrates with Firefox to put a wealth of ' +
|
||||
'development tools...');
|
||||
});
|
||||
|
||||
test('Japanese (existing translation)', function() {
|
||||
z.refreshL10n('ja');
|
||||
equals($('textarea:visible', this.sandbox).text().trim(),
|
||||
'Firebug は、Web ページを閲覧中にクリック一つで使える豊富な開発ツールを Firefox' +
|
||||
' に統合します。あなたはあらゆる');
|
||||
});
|
||||
|
||||
test('Afrikaans (new translation)', function() {
|
||||
z.refreshL10n('af');
|
||||
equals($('[lang=af]', this.sandbox).length, 1);
|
||||
equals($('textarea:visible', this.sandbox).text().trim(),
|
||||
'Firebug integrates with Firefox to put a wealth of ' +
|
||||
'development tools...');
|
||||
equals($('textarea:visible', this.sandbox).hasClass('cloned'), true);
|
||||
});
|
||||
|
||||
});
|
|
@ -1,22 +0,0 @@
|
|||
$(document).ready(function(){
|
||||
var payments = {
|
||||
setup: function() {
|
||||
this.sandbox = tests.createSandbox('#upsell-test');
|
||||
initPayments(this.sandbox);
|
||||
},
|
||||
teardown: function() {
|
||||
this.sandbox.remove();
|
||||
}
|
||||
};
|
||||
module('Payment form', payments);
|
||||
test('Upsell addon click', function() {
|
||||
this.sandbox.find("#id_free").focus();
|
||||
equal(this.sandbox.find("#id_do_upsell_1").attr("checked"),
|
||||
"checked");
|
||||
});
|
||||
test('Upsell description click', function() {
|
||||
this.sandbox.find("#id_text").focus();
|
||||
equal(this.sandbox.find("#id_do_upsell_1").attr("checked"),
|
||||
"checked");
|
||||
});
|
||||
});
|
|
@ -1,35 +0,0 @@
|
|||
$(document).ready(function(){
|
||||
var password = {
|
||||
setup: function() {
|
||||
this.sandbox = tests.createSandbox('#password-strength');
|
||||
this.$node = this.sandbox.find('input[type=password]');
|
||||
initStrength(this.$node);
|
||||
},
|
||||
teardown: function() {
|
||||
this.sandbox.remove();
|
||||
}
|
||||
};
|
||||
|
||||
module('Passwords', password);
|
||||
|
||||
test('Length', function() {
|
||||
this.$node.val('123457890').trigger('blur');
|
||||
equal(this.$node.parent().find('ul.errorlist li:hidden').exists(), true);
|
||||
|
||||
this.$node.val('123').trigger('blur');
|
||||
equal(this.$node.parent().find('ul.errorlist li:hidden').exists(), false);
|
||||
});
|
||||
|
||||
test('Complexity', function() {
|
||||
var $strength = this.$node.parent().find('ul.errorlist li.strength progress');
|
||||
|
||||
this.$node.val('123').trigger('blur');
|
||||
equal($strength.attr('value'), 20);
|
||||
|
||||
this.$node.val('123abcDEF').trigger('blur');
|
||||
equal($strength.attr('value'), 60);
|
||||
|
||||
this.$node.val('АзәрбајҹанA13').trigger('blur');
|
||||
equal($strength.attr('value'), 80);
|
||||
});
|
||||
});
|
|
@ -1,49 +0,0 @@
|
|||
$(document).ready(function() {
|
||||
|
||||
var personaFixture = {
|
||||
setup: function() {
|
||||
this.sandbox = tests.createSandbox('#personas');
|
||||
initLicense();
|
||||
},
|
||||
teardown: function() {
|
||||
this.sandbox.remove();
|
||||
},
|
||||
selectRadio: function(name, value) {
|
||||
var suite = this.sandbox;
|
||||
$('input[name=' + name + ']', suite).val(value);
|
||||
$('input[name=' + name + '][value=' + value + ']', suite)
|
||||
.attr('checked', true).trigger('change');
|
||||
}
|
||||
};
|
||||
|
||||
module('Personas', personaFixture);
|
||||
|
||||
test('License Chooser', function() {
|
||||
var that = this,
|
||||
suite = that.sandbox;
|
||||
function ccTest(values, licenseName, licenseId) {
|
||||
that.selectRadio('cc-attrib', values[0]);
|
||||
if (values.length > 1) {
|
||||
that.selectRadio('cc-noncom', values[1]);
|
||||
if (values.length > 2) {
|
||||
that.selectRadio('cc-noderiv', values[2]);
|
||||
}
|
||||
}
|
||||
equals($('#cc-license', suite).text(), licenseName);
|
||||
equals(parseInt($('#id_license', suite).val()), licenseId);
|
||||
}
|
||||
ccTest([0], 'Creative Commons Attribution 3.0', 9);
|
||||
ccTest([0, 0], 'Creative Commons Attribution 3.0', 9);
|
||||
ccTest([0, 0, 0], 'Creative Commons Attribution 3.0', 9);
|
||||
ccTest([0, 0, 0], 'Creative Commons Attribution 3.0', 9);
|
||||
ccTest([0, 0, 1], 'Creative Commons Attribution-ShareAlike 3.0', 13);
|
||||
ccTest([0, 0, 2], 'Creative Commons Attribution-NoDerivs 3.0', 12);
|
||||
ccTest([0, 1, 0], 'Creative Commons Attribution-NonCommercial 3.0', 10);
|
||||
ccTest([0, 1, 1], 'Creative Commons Attribution-NonCommercial-Share Alike 3.0', 8);
|
||||
ccTest([0, 1, 2], 'Creative Commons Attribution-NonCommercial-NoDerivs 3.0', 11);
|
||||
ccTest([1], 'All Rights Reserved', 7);
|
||||
ccTest([1, 0], 'All Rights Reserved', 7);
|
||||
ccTest([1, 0, 0], 'All Rights Reserved', 7);
|
||||
});
|
||||
|
||||
});
|
|
@ -1,37 +0,0 @@
|
|||
module('Homepage promos', {
|
||||
setup: function(hasAppsSupport, hasSeenAppsSupportWarning) {
|
||||
this.sandbox = tests.createSandbox('#amo-promos');
|
||||
this.visitor = z.Storage('visitor');
|
||||
this.KEY = 'amo_home_promo_seen';
|
||||
this.MAX_SEEN = 5;
|
||||
this._promo_seen = this.visitor.get(this.KEY);
|
||||
this.visitor.remove(this.KEY);
|
||||
hideHomePromo(this.sandbox);
|
||||
},
|
||||
teardown: function() {
|
||||
this.visitor.set(this.KEY, this._promo_seen);
|
||||
this.sandbox.remove();
|
||||
},
|
||||
check: function(showPromo, cnt) {
|
||||
var $panel = $('#starter', this.sandbox).closest('.panel');
|
||||
equal($panel.length, showPromo ? 1 : 0);
|
||||
equal(parseInt(this.visitor.get(this.KEY), 10), cnt || 0);
|
||||
}
|
||||
});
|
||||
|
||||
test('No promos visible', function() {
|
||||
$('.panel', this.sandbox).remove('.panel');
|
||||
initPromos(this.sandbox);
|
||||
equal($('.slider:hidden', this.sandbox).length, 1);
|
||||
});
|
||||
|
||||
test('Home promo visible', function() {
|
||||
this.check(true, 1);
|
||||
});
|
||||
|
||||
test('Home promo not visible on 6th visit', function() {
|
||||
for (var i = 0; i < 5; i++) {
|
||||
hideHomePromo(this.sandbox);
|
||||
}
|
||||
this.check(false, 5);
|
||||
});
|
|
@ -1,108 +0,0 @@
|
|||
module('Autofill Platform for Search', {
|
||||
setup: function() {
|
||||
this._z = $.extend(true, {}, z); // Deep copy `z` so we can patch.
|
||||
this.sandbox = tests.createSandbox('#search-box');
|
||||
},
|
||||
teardown: function() {
|
||||
z = this._z;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
test('Firefox using Firefox', function() {
|
||||
z.appMatchesUserAgent = true;
|
||||
z.app = 'firefox';
|
||||
z.browser.firefox = true;
|
||||
z.browserVersion = '10.0';
|
||||
z.platform = 'mac';
|
||||
autofillPlatform(this.sandbox);
|
||||
equal($('input[name=appver]', this.sandbox).val(), z.browserVersion);
|
||||
equal($('input[name=platform]', this.sandbox).val(), z.platform);
|
||||
});
|
||||
|
||||
|
||||
test('Thunderbird using Firefox', function() {
|
||||
z.appMatchesUserAgent = false;
|
||||
z.app = 'thunderbird';
|
||||
z.browser.firefox = true;
|
||||
z.browserVersion = '10.0';
|
||||
z.platform = 'mac';
|
||||
autofillPlatform(this.sandbox);
|
||||
equal($('input[name=appver]', this.sandbox).val(), '');
|
||||
equal($('input[name=platform]', this.sandbox).val(), '');
|
||||
});
|
||||
|
||||
|
||||
test('Thunderbird using Thunderbird', function() {
|
||||
z.appMatchesUserAgent = true;
|
||||
z.app = 'thunderbird';
|
||||
z.browser.thunderbird = true;
|
||||
z.browserVersion = '10.0';
|
||||
z.platform = 'mac';
|
||||
autofillPlatform(this.sandbox);
|
||||
equal($('input[name=appver]', this.sandbox).val(), z.browserVersion);
|
||||
equal($('input[name=platform]', this.sandbox).val(), z.platform);
|
||||
});
|
||||
|
||||
|
||||
module('Pjax Search', {
|
||||
setup: function() {
|
||||
this.container = $('#pjax-results', this.sandbox);
|
||||
this.filters = $('#search-facets', this.sandbox);
|
||||
this.container.initSearchPjax(this.filters);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
test('Loading', function() {
|
||||
var loaded = false;
|
||||
this.container.bind('search.loading', function() {
|
||||
loaded = true;
|
||||
});
|
||||
$.when(this.container.trigger('start.pjax')).done(function() {
|
||||
ok(loaded);
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
test('Finished', function() {
|
||||
var finished = false;
|
||||
this.container.bind('search.finished', function() {
|
||||
finished = true;
|
||||
});
|
||||
$.when(this.container.trigger('end.pjax')).done(function() {
|
||||
ok(finished);
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
test('Rebuild links', function() {
|
||||
function check(s, expected) {
|
||||
// rebuildLink accepts the following parameters:
|
||||
// 1) previous target URL,
|
||||
// 2) fixed URL params,
|
||||
// 3) new query string (i.e, location.search)
|
||||
equal(rebuildLink(s[0], s[1], s[2]), expected);
|
||||
}
|
||||
|
||||
// We're showing results for Macs, so the filter URLs should get updated
|
||||
// to reflect that.
|
||||
check(['/en-US/firefox/search/?q=adblock&appver=10.0',
|
||||
'{"appver": "10.0"}',
|
||||
'?q=adblock&platform=mac'],
|
||||
'/en-US/firefox/search/?q=adblock&platform=mac&appver=10.0');
|
||||
|
||||
// We're showing results filtered by cat 14, so the filter URL for cat 72
|
||||
// should not change values.
|
||||
check(['/en-US/firefox/search/?q=adblock&appver=8.0&cat=72&atype=1',
|
||||
'{"atype": 1, "cat": 72}',
|
||||
'?q=adblock&cat=14&atype=1'],
|
||||
'/en-US/firefox/search/?q=adblock&cat=72&atype=1');
|
||||
|
||||
// We're showing results filtered by cat 14, so the filter URL to show
|
||||
// all categories/types should not contain cat=14.
|
||||
check(['/en-US/firefox/search/?q=adblock',
|
||||
'{"atype": null, "cat": null}',
|
||||
'?q=adblock&cat=14'],
|
||||
'/en-US/firefox/search/?q=adblock&cat=&atype=');
|
||||
});
|
|
@ -1,41 +0,0 @@
|
|||
module('Serializers');
|
||||
|
||||
|
||||
test('getVars', function() {
|
||||
function check(s, excl, expected) {
|
||||
tests.equalObjects(z.getVars(s, excl), expected);
|
||||
}
|
||||
check('', false, {});
|
||||
check('?', false, {});
|
||||
check('?a', true, {});
|
||||
check('?a', false, {'a': undefined});
|
||||
check('?==a', true, {});
|
||||
check('?==a', false, {});
|
||||
check('?a=apple&a=apricot', false, {'a': 'apricot'});
|
||||
check('?a=apple&b=banana&c=carrot', false,
|
||||
{'a': 'apple', 'b': 'banana', 'c': 'carrot'});
|
||||
check('?a?a=apple', false, {'a?a': 'apple'});
|
||||
check('?a=apple&b?c=banana', false, {'a': 'apple', 'b?c': 'banana'});
|
||||
check('?a=b=c&d=e', false, {'a': 'b', 'd': 'e'});
|
||||
check('?<script>alert("xss")</script>="a"', false,
|
||||
{'<script>alert("xss")</script>': '"a"'});
|
||||
check('?"a"=<script>alert("xss")</script>', false,
|
||||
{'"a"': '<script>alert("xss")</script>'});
|
||||
});
|
||||
|
||||
|
||||
test('JSON.parseNonNull', function() {
|
||||
function check(s, expected) {
|
||||
tests.equalObjects(JSON.parseNonNull(s), JSON.parse(expected));
|
||||
}
|
||||
check('[]', '[]');
|
||||
check('{}', '{}');
|
||||
check('{"x": "xxx", "y": "yyy"}',
|
||||
'{"x": "xxx", "y": "yyy"}');
|
||||
check('{"x": "null", "y": null}',
|
||||
'{"x": "null", "y": ""}');
|
||||
check('[{"x": "null", "y": null}, {"x": "null", "y": null}]',
|
||||
'[{"x": "null", "y": ""}, {"x": "null", "y": ""}]');
|
||||
check('[{"w": {"x": null, "y": {"z": null}}}]',
|
||||
'[{"w": {"x": "", "y": {"z": ""}}}]');
|
||||
});
|
|
@ -1,35 +0,0 @@
|
|||
$(document).ready(function() {
|
||||
|
||||
var storageFixture = {
|
||||
setup: function() {
|
||||
this.s = z.Storage();
|
||||
this.s_fruit = z.Storage('fruit');
|
||||
this.s_candy = z.Storage('candy');
|
||||
}
|
||||
};
|
||||
|
||||
module('storage', storageFixture);
|
||||
|
||||
test('Non-namespaced storage', function() {
|
||||
this.s.set('a', 'aaa');
|
||||
equals(localStorage.getItem('a'), 'aaa');
|
||||
equals(this.s.get('a'), 'aaa');
|
||||
|
||||
this.s.remove('a');
|
||||
equals(this.s.get('a'), null);
|
||||
equals(localStorage.getItem('a'), null);
|
||||
});
|
||||
|
||||
test('Namespaced storage', function() {
|
||||
this.s_fruit.set('a', 'apple');
|
||||
this.s_candy.set('a', 'airheads');
|
||||
equals(this.s_fruit.get('a'), 'apple');
|
||||
equals(localStorage.getItem('fruit-a'), 'apple');
|
||||
|
||||
this.s_fruit.remove('a');
|
||||
equals(this.s_fruit.get('a'), null);
|
||||
equals(localStorage.getItem('fruit-a'), null);
|
||||
equals(this.s_candy.get('a'), 'airheads');
|
||||
});
|
||||
|
||||
});
|
|
@ -1,368 +0,0 @@
|
|||
module('Search Suggestions', {
|
||||
setup: function() {
|
||||
this.sandbox = tests.createSandbox('#search-suggestions');
|
||||
this.results = $('#site-search-suggestions', this.sandbox);
|
||||
this.input = $('#search #search-q', this.sandbox);
|
||||
this.input.searchSuggestions(this.results, processResults, true);
|
||||
this.url = this.results.attr('data-src');
|
||||
|
||||
this.newItems = {'ajax': [], 'cache': []};
|
||||
z._AjaxCache = {};
|
||||
$.mockjaxClear();
|
||||
$.mockjaxSettings = {
|
||||
status: 200,
|
||||
responseTime: 0,
|
||||
contentType: 'text/json',
|
||||
dataType: 'json'
|
||||
};
|
||||
},
|
||||
teardown: function() {
|
||||
this.sandbox.remove();
|
||||
$.mockjaxClear();
|
||||
},
|
||||
mockRequest: function() {
|
||||
this.jsonResults = [];
|
||||
for (var i = 0; i < 10; i++) {
|
||||
this.jsonResults.push({'id': i, 'url': 'dekKobergerStudios.biz'});
|
||||
}
|
||||
$.mockjax({
|
||||
url: this.url,
|
||||
responseText: JSON.stringify(this.jsonResults),
|
||||
status: 200,
|
||||
responseTime: 0
|
||||
});
|
||||
},
|
||||
testInputEvent: function(eventType, fail) {
|
||||
var self = this,
|
||||
$input = self.input,
|
||||
$results = self.results,
|
||||
query = '<script>alert("xss")</script>';
|
||||
self.mockRequest();
|
||||
if (fail) {
|
||||
var inputIgnored = false;
|
||||
// If we send press a bad key, this will check that we ignored it.
|
||||
self.sandbox.bind('inputIgnored', function(e) {
|
||||
inputIgnored = true;
|
||||
});
|
||||
tests.waitFor(function() {
|
||||
return inputIgnored;
|
||||
}).thenDo(function() {
|
||||
ok(inputIgnored);
|
||||
start();
|
||||
});
|
||||
} else {
|
||||
self.sandbox.bind('resultsUpdated', function(e, items) {
|
||||
tests.equalObjects(items, self.jsonResults);
|
||||
var expected = escape_(query).replace(/'/g, "'")
|
||||
.replace(/"/g, '"');
|
||||
equal($results.find('.wrap p a.sel b').html(),
|
||||
'"' + expected + '"');
|
||||
start();
|
||||
});
|
||||
}
|
||||
$input.val(query);
|
||||
$input.triggerHandler(eventType);
|
||||
},
|
||||
testRowSelector: function(eventWhich, rowIndex) {
|
||||
var $input = this.input,
|
||||
$results = this.results,
|
||||
expected = null;
|
||||
|
||||
this.sandbox.bind('selectedRowUpdate', function(e, row) {
|
||||
expected = row;
|
||||
});
|
||||
|
||||
tests.waitFor(function() {
|
||||
return expected !== null;
|
||||
}).thenDo(function() {
|
||||
// Row index is zero-based. There are four rows: one for the
|
||||
// placeholder and three results.
|
||||
equal(expected, rowIndex,
|
||||
'Expected row ' + rowIndex + ' to be highlighted');
|
||||
start();
|
||||
});
|
||||
|
||||
// Let's pretend we made a query. Generate three result rows.
|
||||
for (var i = 0; i < 3; i++) {
|
||||
$results.append('<li><a></li>');
|
||||
}
|
||||
|
||||
// Initialize highlighting.
|
||||
$results.trigger('highlight', ['xxx']);
|
||||
|
||||
// Simulate keystrokes.
|
||||
$input.val('xxx');
|
||||
$input.triggerHandler({type: 'keydown', which: eventWhich});
|
||||
},
|
||||
testKeyIgnored: function(event) {
|
||||
var $input = this.input,
|
||||
$results = this.results,
|
||||
expected = null;
|
||||
|
||||
this.sandbox.bind('keyIgnored', function(e) {
|
||||
expected = true;
|
||||
});
|
||||
|
||||
tests.waitFor(function() {
|
||||
return expected !== null;
|
||||
}).thenDo(function() {
|
||||
ok(expected, 'Key binding should have been ignored');
|
||||
start();
|
||||
});
|
||||
|
||||
// Initialize highlighting.
|
||||
$results.trigger('highlight', ['xxx']);
|
||||
|
||||
// Simulate keystrokes.
|
||||
$input.val('xxx').triggerHandler(event);
|
||||
}
|
||||
});
|
||||
|
||||
function processResults(settings) {
|
||||
if (!settings || !settings.category) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Update the 'Search add-ons for <b>"{addon}"</b>' text.
|
||||
settings['$results'].find('p b').html(format('"{0}"',
|
||||
settings.searchTerm));
|
||||
|
||||
var li_item = template(
|
||||
'<li><a href="{url}"><span {cls} {icon}>{name}</span>{subtitle}</a></li>'
|
||||
);
|
||||
|
||||
$.ajaxCache({
|
||||
url: settings['$results'].attr('data-src'),
|
||||
data: settings['$form'].serialize() + '&cat=' + settings.category,
|
||||
newItems: function(formdata, items) {
|
||||
var eventName;
|
||||
if (items !== undefined) {
|
||||
var ul = '';
|
||||
$.each(items, function(i, item) {
|
||||
var d = {
|
||||
url: escape_(item.url) || '#',
|
||||
icon: '',
|
||||
cls: '',
|
||||
subtitle: '',
|
||||
};
|
||||
if (item.icons['32']) {
|
||||
d.icon = format(
|
||||
'style="background-image:url({0})"',
|
||||
escape_(item.icons['32'])
|
||||
);
|
||||
}
|
||||
if (item.cls) {
|
||||
d.cls = format('class="{0}"',
|
||||
escape_(item.cls));
|
||||
if (item.cls == 'cat') {
|
||||
d.subtitle = format(
|
||||
' <em class="subtitle">{0}</em>',
|
||||
gettext('Category')
|
||||
);
|
||||
}
|
||||
}
|
||||
if (item.name) {
|
||||
d.name = escape_(item.name);
|
||||
// Append the item only if it has a name.
|
||||
ul += li_item(d);
|
||||
}
|
||||
});
|
||||
settings['$results'].find('ul').html(ul);
|
||||
}
|
||||
settings['$results'].trigger('highlight', [settings.searchTerm])
|
||||
.trigger('resultsUpdated', [items]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
test('Generated HTML tags', function() {
|
||||
var $results = this.results,
|
||||
$sel = $results.find('.wrap p a.sel');
|
||||
equal($sel.length, 1);
|
||||
equal($sel.find('b').length, 1);
|
||||
equal($results.find('.wrap ul').length, 1);
|
||||
});
|
||||
|
||||
|
||||
test('Default search label', function() {
|
||||
var $results = this.results,
|
||||
$input = this.input;
|
||||
function check(cat, expected) {
|
||||
$results.attr('data-cat', cat);
|
||||
$.when($input.searchSuggestions($results, processResults, true))
|
||||
.done(function() {
|
||||
equal($results.find('p a.sel').text(), expected);
|
||||
});
|
||||
}
|
||||
check('', 'Search add-ons for {0}');
|
||||
check('all', 'Search add-ons for {0}');
|
||||
check('themes', 'Search themes for {0}');
|
||||
check('apps', 'Search apps for {0}');
|
||||
});
|
||||
|
||||
|
||||
test('Highlight search terms', function() {
|
||||
var items = [
|
||||
// Input, highlighted output
|
||||
['', ''],
|
||||
['x xx', 'x xx'],
|
||||
['xxx', '<b>xxx</b>'],
|
||||
[' XxX', ' <b>XxX</b>'],
|
||||
['XXX', '<b>XXX</b>'],
|
||||
['An XXX-rated add-on', 'An <b>XXX</b>-rated add-on'],
|
||||
['Myxxx', 'My<b>xxx</b>'],
|
||||
['XXX xxx XXX', '<b>XXX</b> <b>xxx</b> <b>XXX</b>'],
|
||||
|
||||
// Ignore non-alphanumeric characters (i.e., regex chars).
|
||||
['xxx: xxx', '<b>xxx</b>: <b>xxx</b>'],
|
||||
['xxx (){}[]*+:=?!\|^$. xxx', '<b>xxx</b> (){}[]*+:=?!\|^$. <b>xxx</b>']
|
||||
];
|
||||
|
||||
var $ul = $('<ul>');
|
||||
_.each(items, function(element) {
|
||||
$ul.append($('<li>', {'html': element[0]}));
|
||||
});
|
||||
|
||||
$.when($ul.find('li').highlightTerm('xxx')).done(function() {
|
||||
$ul.find('li').each(function(index) {
|
||||
equal($(this).html(), items[index][1]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
asyncTest('Results upon good keyup', function() {
|
||||
this.testInputEvent({type: 'keyup', which: 'x'.charCodeAt(0)});
|
||||
});
|
||||
|
||||
|
||||
asyncTest('Results upon bad keyup', function() {
|
||||
this.testInputEvent({type: 'keyup', which: 16}, true);
|
||||
});
|
||||
|
||||
|
||||
asyncTest('Results upon paste', function() {
|
||||
this.testInputEvent('paste');
|
||||
});
|
||||
|
||||
|
||||
asyncTest('Hide results upon escape/blur', function() {
|
||||
var $input = this.input,
|
||||
$results = this.results;
|
||||
$input.val('xxx').triggerHandler('blur');
|
||||
tests.lacksClass($results, 'visible');
|
||||
start();
|
||||
});
|
||||
|
||||
|
||||
asyncTest('Key bindings: Hijacked: arrow up', function() {
|
||||
this.testRowSelector(z.keys.UP, 0);
|
||||
});
|
||||
asyncTest('Key bindings: Hijacked: arrow down', function() {
|
||||
this.testRowSelector(z.keys.DOWN, 1);
|
||||
});
|
||||
|
||||
|
||||
asyncTest('Key bindings: Ignored: home', function() {
|
||||
this.testKeyIgnored({type: 'keydown', which: z.keys.HOME});
|
||||
});
|
||||
asyncTest('Key bindings: Ignored: end', function() {
|
||||
this.testKeyIgnored({type: 'keydown', which: z.keys.END});
|
||||
});
|
||||
asyncTest('Key bindings: Ignored: page up', function() {
|
||||
this.testKeyIgnored({type: 'keydown', which: z.keys.PAGE_UP});
|
||||
});
|
||||
asyncTest('Key bindings: Ignored: page down', function() {
|
||||
this.testKeyIgnored({type: 'keydown', which: z.keys.PAGE_DOWN});
|
||||
});
|
||||
|
||||
|
||||
asyncTest('Key bindings: Ignored: alt + home', function() {
|
||||
this.testKeyIgnored({type: 'keydown', which: z.keys.HOME, altKey: true});
|
||||
});
|
||||
asyncTest('Key bindings: Ignored: ctrl + home', function() {
|
||||
this.testKeyIgnored({type: 'keydown', which: z.keys.HOME, ctrlKey: true});
|
||||
});
|
||||
asyncTest('Key bindings: Ignored: meta + home', function() {
|
||||
this.testKeyIgnored({type: 'keydown', which: z.keys.HOME, metaKey: true});
|
||||
});
|
||||
asyncTest('Key bindings: Ignored: shift + home', function() {
|
||||
this.testKeyIgnored({type: 'keydown', which: z.keys.HOME, shiftKey: true});
|
||||
});
|
||||
|
||||
|
||||
asyncTest('Key bindings: Ignored: alt + end', function() {
|
||||
this.testKeyIgnored({type: 'keydown', which: z.keys.END, altKey: true});
|
||||
});
|
||||
asyncTest('Key bindings: Ignored: ctrl + end', function() {
|
||||
this.testKeyIgnored({type: 'keydown', which: z.keys.END, ctrlKey: true});
|
||||
});
|
||||
asyncTest('Key bindings: Ignored: meta + end', function() {
|
||||
this.testKeyIgnored({type: 'keydown', which: z.keys.END, metaKey: true});
|
||||
});
|
||||
asyncTest('Key bindings: Ignored: shift + end', function() {
|
||||
this.testKeyIgnored({type: 'keydown', which: z.keys.END, shiftKey: true});
|
||||
});
|
||||
|
||||
|
||||
asyncTest('Key bindings: Ignored: alt + left', function() {
|
||||
this.testKeyIgnored({type: 'keydown', which: z.keys.LEFT, altKey: true});
|
||||
});
|
||||
asyncTest('Key bindings: Ignored: alt + right', function() {
|
||||
this.testKeyIgnored({type: 'keydown', which: z.keys.RIGHT, altKey: true});
|
||||
});
|
||||
|
||||
|
||||
asyncTest('Key bindings: Ignored: ctrl + left', function() {
|
||||
this.testKeyIgnored({type: 'keydown', which: z.keys.LEFT, ctrlKey: true});
|
||||
});
|
||||
asyncTest('Key bindings: Ignored: ctrl + right', function() {
|
||||
this.testKeyIgnored({type: 'keydown', which: z.keys.RIGHT, ctrlKey: true});
|
||||
});
|
||||
|
||||
|
||||
asyncTest('Key bindings: Ignored: meta + left', function() {
|
||||
this.testKeyIgnored({type: 'keydown', which: z.keys.LEFT, metaKey: true});
|
||||
});
|
||||
asyncTest('Key bindings: Ignored: meta + right', function() {
|
||||
this.testKeyIgnored({type: 'keydown', which: z.keys.RIGHT, metaKey: true});
|
||||
});
|
||||
|
||||
|
||||
asyncTest('Key bindings: Ignored: shift + left', function() {
|
||||
this.testKeyIgnored({type: 'keydown', which: z.keys.LEFT, shiftKey: true});
|
||||
});
|
||||
asyncTest('Key bindings: Ignored: shift + right', function() {
|
||||
this.testKeyIgnored({type: 'keydown', which: z.keys.RIGHT, shiftKey: true});
|
||||
});
|
||||
|
||||
|
||||
asyncTest('Cached results do not change', function() {
|
||||
var self = this,
|
||||
$input = self.input,
|
||||
$results = self.results,
|
||||
query = 'xxx';
|
||||
self.mockRequest();
|
||||
self.sandbox.bind('resultsUpdated', function(e, items) {
|
||||
equal($results.find('.wrap p a.sel b').text(), '"' + query + '"');
|
||||
tests.equalObjects(items, self.jsonResults);
|
||||
if (z._AjaxCache === undefined) {
|
||||
$input.triggerHandler('paste');
|
||||
} else {
|
||||
tests.waitFor(function() {
|
||||
return z._AjaxCache;
|
||||
}).thenDo(function() {
|
||||
var cache = z.AjaxCache(self.url + ':get'),
|
||||
fields = self.sandbox.find('form').serialize(),
|
||||
args = JSON.stringify(fields + '&cat=' + $results.attr('data-cat'));
|
||||
tests.equalObjects(cache.items[args], items);
|
||||
tests.equalObjects(cache.previous.data, items);
|
||||
equal(cache.previous.args, args);
|
||||
start();
|
||||
});
|
||||
}
|
||||
});
|
||||
$input.val(query);
|
||||
$input.triggerHandler('paste');
|
||||
});
|
|
@ -1,14 +0,0 @@
|
|||
{
|
||||
"name": "Main Test Suite",
|
||||
"extra_media_urls": [
|
||||
"js/lib/jstestnet.js",
|
||||
"js/lib/stacktrace.js",
|
||||
"js/zamboni/tests.js",
|
||||
"js/zamboni/debouncer.js",
|
||||
"js/zamboni/devhub.js",
|
||||
"js/zamboni/validator.js",
|
||||
"js/zamboni/editors.js",
|
||||
"js/zamboni/files.js",
|
||||
"js/zamboni/password-strength.js"
|
||||
]
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
module('Truncation', {
|
||||
setup: function() {
|
||||
this.sandbox = tests.createSandbox();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
test('lineclamp: none', function() {
|
||||
var $src = $('<p>ballin</p>').appendTo(this.sandbox);
|
||||
|
||||
// Check that we return the same thing.
|
||||
equal($src.lineclamp(), $src);
|
||||
|
||||
// Check that `max-height` was not set.
|
||||
equal($src.css('max-height'), 'none');
|
||||
});
|
||||
|
||||
|
||||
test('lineclamp: round', function() {
|
||||
var $src = $('<p>ballin</p>').appendTo(this.sandbox);
|
||||
|
||||
// Set some arbitrary `line-height`.
|
||||
$src.css('line-height', '14.2px');
|
||||
|
||||
// Check that we return the same thing.
|
||||
equal($src.lineclamp(1), $src);
|
||||
|
||||
// If we're clamping one line with a `line-height` of 14.2px, then the
|
||||
// `max-height` should be 15px.
|
||||
equal($src.css('max-height'), '15px');
|
||||
});
|
||||
|
||||
|
||||
test('lineclamp: normal', function() {
|
||||
var $src = $('<p>ballin</p>').appendTo(this.sandbox);
|
||||
|
||||
// Set some arbitrary `line-height`.
|
||||
$src.css('line-height', '15px');
|
||||
|
||||
// Check that we return the same thing.
|
||||
equal($src.lineclamp(2), $src);
|
||||
|
||||
// If we're clamping two lines whose `line-height` are 15px, then the
|
||||
// `max-height` should be 50px.
|
||||
equal($src.css('max-height'), '30px');
|
||||
});
|
|
@ -1,25 +0,0 @@
|
|||
$(document).ready(function(){
|
||||
|
||||
module('format');
|
||||
|
||||
test('String Formatting', function() {
|
||||
equals(format("{0}{1}", ['a', 'b']), "ab");
|
||||
equals(format("{0}{1}", 'a', 'b'), "ab");
|
||||
equals(format("{x}{y}", {x: 'a', y: 'b'}), "ab");
|
||||
});
|
||||
|
||||
|
||||
module('escape_');
|
||||
|
||||
test('Entity Escaping', function() {
|
||||
function check(s, expected) {
|
||||
equal(escape_(s), expected);
|
||||
}
|
||||
check(undefined, undefined);
|
||||
check('', '');
|
||||
check("&&<<>>''\"\"", "&&<<>>''""");
|
||||
check("<script>alert('\"xss\"')</script>&&",
|
||||
"<script>alert('"xss"')</script>&&");
|
||||
});
|
||||
|
||||
});
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -112,7 +112,6 @@ suds==0.4
|
|||
-e git+https://github.com/washort/django-cache-machine@4690198122a96a88267323566dc18a5e0437681f#egg=django-cache-machine
|
||||
## Forked.
|
||||
-e git+https://github.com/andymckay/django-piston-oauth2.git@177aaf937860318af8d9c2bb74adc27860803eb9#egg=django-piston-oauth2
|
||||
-e git+https://github.com/kumar303/django-qunit.git@b0f468dcf33439488158c845df37ef3261852b55#egg=django-qunit
|
||||
-e git+https://github.com/andymckay/django-uuidfield.git@029dd1263794ec36c327617cd6c2346da81c8c33#egg=django-uuidfield
|
||||
-e git+https://github.com/washort/django-mysql-pool.git@47b7bc35a7b00a9798d4fe4792764ab00bfcb5b6#egg=django-mysql-pool
|
||||
|
||||
|
|
|
@ -3,5 +3,4 @@
|
|||
-r prod.txt
|
||||
|
||||
psutil==0.2.0
|
||||
jstestnetlib==0.3
|
||||
nose-blockage==0.1.2
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
"""
|
||||
A wrapper around nosetests to run JavaScript tests in a CI environment.
|
||||
|
||||
Example::
|
||||
|
||||
python run_jstests.py --with-xunit \
|
||||
--with-django-serv --django-host hudson.mozilla.org \
|
||||
--with-jstests \
|
||||
--jstests-server http://jstestnet.farmdev.com/ \
|
||||
--jstests-suite zamboni --jstests-browsers firefox
|
||||
|
||||
"""
|
||||
import os
|
||||
import site
|
||||
import subprocess
|
||||
|
||||
ROOT = os.path.join(os.path.dirname(__file__), '..')
|
||||
|
||||
site.addsitedir(os.path.join(ROOT, 'vendor'))
|
||||
site.addsitedir(os.path.join(ROOT, 'vendor/lib/python'))
|
||||
|
||||
from jstestnetlib.noseplugins import JSTests, DjangoServPlugin
|
||||
import nose
|
||||
|
||||
|
||||
def main():
|
||||
nose.main(addplugins=[DjangoServPlugin(ROOT), JSTests()])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -1,102 +0,0 @@
|
|||
# This script should be called from within Hudson
|
||||
|
||||
|
||||
cd $WORKSPACE
|
||||
VENV=$WORKSPACE/venv
|
||||
VENDOR=$WORKSPACE/vendor
|
||||
LOCALE=$WORKSPACE/locale
|
||||
LOG=$WORKSPACE/jstests-runserver.log
|
||||
|
||||
echo "Starting build on executor $EXECUTOR_NUMBER..." `date`
|
||||
|
||||
if [ -z $1 ]; then
|
||||
echo "Warning: You should provide a unique name for this job to prevent database collisions."
|
||||
echo "Usage: $0 <name>"
|
||||
echo "Continuing, but don't say you weren't warned."
|
||||
fi
|
||||
|
||||
echo "Setup..." `date`
|
||||
|
||||
# Make sure there's no old pyc files around.
|
||||
find . -name '*.pyc' | xargs rm
|
||||
|
||||
if [ ! -d "$VENV/bin" ]; then
|
||||
echo "No virtualenv found. Making one..."
|
||||
virtualenv $VENV --system-site-packages
|
||||
fi
|
||||
|
||||
source $VENV/bin/activate
|
||||
|
||||
pip install -U --exists-action=w --no-deps -q -r requirements/compiled.txt -r requirements/test.txt
|
||||
|
||||
# Create paths we want for addons
|
||||
if [ ! -d "/tmp/warez" ]; then
|
||||
mkdir /tmp/warez
|
||||
fi
|
||||
|
||||
if [ ! -d "$LOCALE" ]; then
|
||||
echo "No locale dir? Cloning..."
|
||||
svn co http://svn.mozilla.org/addons/trunk/site/app/locale/ $LOCALE
|
||||
fi
|
||||
|
||||
if [ ! -d "$VENDOR" ]; then
|
||||
echo "No vendor lib? Cloning..."
|
||||
git clone --recursive git://github.com/mozilla/zamboni-lib.git $VENDOR
|
||||
fi
|
||||
|
||||
# Update the vendor lib.
|
||||
echo "Updating vendor..."
|
||||
git submodule --quiet foreach 'git submodule --quiet sync'
|
||||
git submodule --quiet sync && git submodule update --init --recursive
|
||||
|
||||
cp -f docs/settings/settings_local.dev.py settings_local.py
|
||||
cat >> settings_local.py <<SETTINGS
|
||||
|
||||
ROOT_URLCONF = 'lib.urls_base'
|
||||
LOG_LEVEL = logging.ERROR
|
||||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'NAME': 'zamboni_$1',
|
||||
'HOST': 'localhost',
|
||||
'ENGINE': 'django.db.backends.mysql',
|
||||
'USER': 'hudson',
|
||||
'OPTIONS': {'init_command': 'SET storage_engine=InnoDB'},
|
||||
'TEST_NAME': 'test_zamboni_$1',
|
||||
'TEST_CHARSET': 'utf8',
|
||||
'TEST_COLLATION': 'utf8_general_ci',
|
||||
},
|
||||
}
|
||||
|
||||
CACHES = {
|
||||
'default': {
|
||||
'BACKEND': 'caching.backends.locmem.LocMemCache',
|
||||
}
|
||||
}
|
||||
CELERY_ALWAYS_EAGER = True
|
||||
ADDONS_PATH = '/tmp/warez'
|
||||
|
||||
# Activate Qunit:
|
||||
INSTALLED_APPS += (
|
||||
'django_qunit',
|
||||
)
|
||||
JINGO_EXCLUDE_APPS += (
|
||||
'qunit',
|
||||
)
|
||||
|
||||
SETTINGS
|
||||
|
||||
|
||||
# All DB tables need to exist so that runserver can start up.
|
||||
python manage.py syncdb --noinput
|
||||
|
||||
echo "Starting JS tests..." `date`
|
||||
|
||||
rm $LOG
|
||||
cd scripts
|
||||
# Some of these env vars are set in the Jenkins build step.
|
||||
BROWSERS=firefox
|
||||
XARGS="-v --with-xunit --with-django-serv --django-host $DJANGO_HOST --django-port $DJANGO_PORT --django-log $LOG --django-startup-uri /robots.txt --django-root-dir $WORKSPACE --with-jstests --jstests-server http://jstestnet.farmdev.com/ --jstests-suite zamboni --jstests-token $JSTESTS_TOKEN --jstests-browsers $BROWSERS --debug nose.plugins.jstests"
|
||||
python run_jstests.py --jstests-url http://$DJANGO_HOST:$DJANGO_PORT/en-US/qunit/ --xunit-file=nosetests.xml $XARGS
|
||||
|
||||
echo 'shazam!'
|
|
@ -1,65 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>QUnit Test Suite</title>
|
||||
<link rel="stylesheet" href="{{ url('qunit_css') }}?v={{ timestamp }}" type="text/css" media="screen">
|
||||
</head>
|
||||
<body
|
||||
data-app="{{ request.APP.short }}"
|
||||
data-appname="{{ request.APP.pretty }}"
|
||||
data-appid="{{ request.APP.id }}"
|
||||
data-min-beta-version="{{ settings.MIN_BETA_VERSION }}"
|
||||
data-nightly-version="8.0"
|
||||
data-anonymous="true"
|
||||
data-readonly="false"
|
||||
data-media-url="{{ MEDIA_URL }}"
|
||||
data-paypal-url="/paypal"
|
||||
data-default-locale="en-us">
|
||||
<h1 id="qunit-header">QUnit Test Suite ({{ suite.name }})</h1>
|
||||
<h2 id="qunit-banner"></h2>
|
||||
<div id="qunit-testrunner-toolbar"></div>
|
||||
{% if in_directory or subsuites %}
|
||||
<div id="navigation">
|
||||
{% if in_subdirectory %}
|
||||
<a href="{{ url('qunit_test_overview', previous_directory) }}">..</a>
|
||||
{% endif %}
|
||||
|
||||
{% for suite in subsuites %}
|
||||
<a href="{{ suite }}/">{{ suite }}</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
<h2 id="qunit-userAgent"></h2>
|
||||
<ol id="qunit-tests"></ol>
|
||||
<div id="qunit-fixture">test markup, will be hidden</div>
|
||||
<div id="sandbox"><!-- custom Zamboni sandbox area --></div>
|
||||
|
||||
{% block fixtures %}
|
||||
{% endblock %}
|
||||
|
||||
<script type="text/javascript">
|
||||
waffle = {
|
||||
flag: function () { return true; },
|
||||
switch: function () { return true; },
|
||||
sample: function () { return true; }
|
||||
}
|
||||
</script>
|
||||
|
||||
<script src="{{ static(url('jsi18n')) }}"></script>
|
||||
{% block init_scripts %}
|
||||
{% endblock %}
|
||||
<script async defer src="{{ static(url('addons.buttons.js')) }}"></script>
|
||||
<script type="text/javascript" src="{{ url('qunit_js') }}?v={{ timestamp }}"></script>
|
||||
<script type="text/javascript" src="{{ MEDIA_URL }}js/lib/jquery.mockjax.js?v={{ timestamp }}"></script>
|
||||
{% for url in suite.extra_urls %}
|
||||
<script type="text/javascript" src="{{ url }}?v={{ timestamp }}"></script>
|
||||
{% endfor %}
|
||||
{% for url in suite.extra_media_urls %}
|
||||
<script type="text/javascript" src="{{ MEDIA_URL }}{{ url }}?v={{ timestamp }}"></script>
|
||||
{% endfor %}
|
||||
{% for file in files %}
|
||||
<script type="text/javascript" src="{{ url('qunit_test', file) }}?v={{ timestamp }}"></script>
|
||||
{% endfor %}
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -1,845 +0,0 @@
|
|||
{% extends "qunit/base.html" %}
|
||||
|
||||
{% block init_scripts %}
|
||||
{{ js('preload') }}
|
||||
{{ js('impala') }}
|
||||
{{ js('zamboni/devhub') }}
|
||||
{% endblock %}
|
||||
|
||||
{% block fixtures %}
|
||||
{# The following HTML can be applied to #qunit-fixture in test setup #}
|
||||
|
||||
<div id="exists">
|
||||
<span class="exists"></span>
|
||||
</div>
|
||||
|
||||
<div id="csrf-template">
|
||||
<input id="csrfmiddlewaretoken" name="csrfmiddlewaretoken"
|
||||
value="<csrf-from-input>">
|
||||
</div>
|
||||
|
||||
<div id="l10n-translation">
|
||||
<div data-name="summary" class="trans" id="trans-summary">
|
||||
<textarea lang="en-us" name="summary_en-us" cols="40" rows="10"
|
||||
id="id_summary_0" style="display: block;">
|
||||
Firebug integrates with Firefox to put a wealth of development tools...
|
||||
</textarea>
|
||||
<textarea lang="ja" name="summary_ja" cols="40" rows="10" id="id_summary_1"
|
||||
style="display: none;">
|
||||
Firebug は、Web ページを閲覧中にクリック一つで使える豊富な開発ツールを Firefox に統合します。あなたはあらゆる
|
||||
</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div id="l10n-menu">
|
||||
<ul>
|
||||
<li><a href="#en-us" class="default-locale">English (US)</a></li>
|
||||
<li><a href="#ja">日本語</a></li>
|
||||
<li><a href="#id">Bahasa Indonesia</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div id="buttons">
|
||||
<h2 class="addon"><span class="version"></span></h2>
|
||||
<div id="addon-summary">
|
||||
<table>
|
||||
<tr class="addon-compatible"><td></td></tr>
|
||||
<tr class="addon-updated"><td></td></tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="install-shell">
|
||||
<div class="install featuredaddon" data-version-supported="false"></div>
|
||||
</div>
|
||||
<div class="backup-button hidden">
|
||||
<div class="install-shell">
|
||||
<div class="install featuredaddon"
|
||||
data-min=""
|
||||
data-max=""
|
||||
data-version="0.2"
|
||||
data-compatible-apps="Fx 1.0"
|
||||
data-lastupdated-isotime="today"
|
||||
data-lastupdated-datetime="today"
|
||||
data-version-supported="true">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="button-d2c-compatible">
|
||||
<div class="install-shell">
|
||||
<div class="install"
|
||||
data-min="4.0"
|
||||
data-max="5.0"
|
||||
data-is-compatible="true"
|
||||
data-is-compatible-app="true"
|
||||
data-compat-overrides="[]">
|
||||
<p class="install-button">
|
||||
<a class="button download" data-hash="1337" href="http://testurl.com">Foo</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="button-d2c-compatible-override">
|
||||
<div class="install-shell">
|
||||
<div class="install"
|
||||
data-min="4.0"
|
||||
data-max="5.0"
|
||||
data-is-compatible="true"
|
||||
data-is-compatible-app="true"
|
||||
data-compat-overrides="{{ [['10.0a1', '99.*']]|json }}">
|
||||
<p class="install-button">
|
||||
<a class="button download" data-hash="1337" href="http://testurl.com">Foo</a>
|
||||
</p>
|
||||
</div>
|
||||
<div class="d2c-reasons-popup popup"><ul></ul></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="button-d2c-not-compatible">
|
||||
<div class="install-shell">
|
||||
<div class="install"
|
||||
data-min="4.0"
|
||||
data-max="5.0"
|
||||
data-is-compatible="false"
|
||||
data-is-compatible-app="false"
|
||||
data-compat-overrides="[]">
|
||||
<p class="install-button">
|
||||
<a class="button download" data-hash="1337" href="http://testurl.com">Foo</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="button-d2c-older-browser">
|
||||
<div class="install-shell">
|
||||
<div class="install"
|
||||
data-min="98.0"
|
||||
data-max="99.0"
|
||||
data-is-compatible="true"
|
||||
data-is-compatible-app="true"
|
||||
data-compat-overrides="[]">
|
||||
<p class="install-button">
|
||||
<a class="button download" data-hash="1337" href="http://testurl.com">Foo</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="button-d2c-old-max">
|
||||
<div class="install-shell">
|
||||
<div class="install"
|
||||
data-min="3.0"
|
||||
data-max="3.5"
|
||||
data-is-compatible="true"
|
||||
data-is-compatible-app="true"
|
||||
data-compat-overrides="[]">
|
||||
<p class="install-button">
|
||||
<a class="button download" data-hash="1337" href="http://testurl.com">Foo</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="files-wrapper">
|
||||
<div id="files">
|
||||
<ul>
|
||||
<li><a class="file" href="">someurl</a></li>
|
||||
<li><a class="directory closed" href="">foo</a></li>
|
||||
<ul class="js-hidden">
|
||||
<li><a class="file" href="someurl">foo/bar.txt</a></li>
|
||||
</ul>
|
||||
</ul>
|
||||
<input type="checkbox" id="toggle-known">
|
||||
</div>
|
||||
</div>
|
||||
<div id="paypal">
|
||||
<div class="contribute">
|
||||
<a href="/paykey?src=direct" class="suggested-amount">Contribute</a>
|
||||
</div>
|
||||
</div>
|
||||
<div id="password-strength">
|
||||
<input type="password" data-min-length="8" />
|
||||
</div>
|
||||
|
||||
<div id="personas">
|
||||
<fieldset>
|
||||
<legend>Persona License</legend>
|
||||
<input type="hidden" name="license" id="id_license">
|
||||
<div id="cc-chooser">
|
||||
<h3>Can others share your Persona, as long as you're given credit?</h3>
|
||||
<ul>
|
||||
<li><label><input type="radio" name="cc-attrib" value="0"> Yes</label></li>
|
||||
<li><label><input type="radio" name="cc-attrib" value="1"> No</label></li>
|
||||
</ul>
|
||||
<h3>Can others make commercial use of your Persona?</h3>
|
||||
<ul>
|
||||
<li><label><input type="radio" name="cc-noncom" value="0"> Yes</label></li>
|
||||
<li><label><input type="radio" name="cc-noncom" value="1"> No</label></li>
|
||||
</ul>
|
||||
<h3>Can others create derivative works from your Persona?</h3>
|
||||
<ul>
|
||||
<li><label><input type="radio" name="cc-noderiv" value="0"> Yes</label></li>
|
||||
<li><label><input type="radio" name="cc-noderiv" value="1"> Yes, as long as they share alike</label></li>
|
||||
<li><label><input type="radio" name="cc-noderiv" value="2"> No</label></li>
|
||||
</ul>
|
||||
<div id="persona-license">
|
||||
<p>Your Persona will be released under the following license:</p>
|
||||
<p id="cc-license" class="license icon"></p>
|
||||
<p class="select-license">
|
||||
<a href="#">Select a different license.</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div id="persona-license-list" class="hidden">
|
||||
<h3>Select a license for your Persona.</h3>
|
||||
<ul>
|
||||
<li><label><input type="radio" name="license" value="7"> All Rights Reserved</label></li>
|
||||
<li><label><input type="radio" name="license" value="9"> Creative Commons Attribution 3.0</label></li>
|
||||
<li><label><input type="radio" name="license" value="10"> Creative Commons Attribution-NonCommercial 3.0</label></li>
|
||||
<li><label><input type="radio" name="license" value="11"> Creative Commons Attribution-NonCommercial-NoDerivs 3.0</label></li>
|
||||
<li><label><input type="radio" name="license" value="8"> Creative Commons Attribution-Noncommercial-Share Alike 3.0</label></li>
|
||||
<li><label><input type="radio" name="license" value="12"> Creative Commons Attribution-NoDerivs 3.0</label></li>
|
||||
<li><label><input type="radio" name="license" value="13"> Creative Commons Attribution-ShareAlike 3.0</label></li>
|
||||
</ul>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
<div id="browserid-test">
|
||||
<section class="primary"></section>
|
||||
<a class="browserid-login" href="#" data-url="/nowhere">BrowserID Login</a>
|
||||
</div>
|
||||
|
||||
<div id="upsell-test">
|
||||
<form action="/en-US/developers/addon/status-watch/payments" method="post">
|
||||
<div class="brform">
|
||||
<div>
|
||||
<ul>
|
||||
<li><label for="id_do_upsell_0"><input type="radio" name="do_upsell" value="0" id="id_do_upsell_0" checked="checked"> I don't have a free add-on to associate.</label></li>
|
||||
<li><label for="id_do_upsell_1"><input type="radio" name="do_upsell" value="1" id="id_do_upsell_1"> This is a premium upgrade to:</label></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="indent">
|
||||
<div>
|
||||
<select id="id_free" name="free">
|
||||
<option selected="selected" value=""></option>
|
||||
</select>
|
||||
</div>
|
||||
<div><textarea name="text" cols="40" rows="10" id="id_text"></textarea></div>
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit">Save Changes</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="search-suggestions">
|
||||
<form id="search" action="/en-us/firefox/search/">
|
||||
<input id="search-q" type="text" name="q" required autocomplete="off" title=""
|
||||
class="text placeholder" placeholder="search for add-ons" value="">
|
||||
<div id="site-search-suggestions" data-src="/askjeeves" data-cat="all"></div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="search-box">
|
||||
<form id="search" action="/en-us/firefox/search/">
|
||||
<input type="text" id="search-q" name="q">
|
||||
<input type="hidden" name="appver" id="id_appver">
|
||||
<input type="hidden" name="platform" id="id_platform">
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="pjax-search">
|
||||
<div id="search-facets">
|
||||
<ul class="facets island pjax-trigger"></ul>
|
||||
</div>
|
||||
<div id="pjax-results"></div>
|
||||
</div>
|
||||
|
||||
<div id="balloons">
|
||||
<div class="site-tip" id="appruntime-pitch" style="display: none">
|
||||
<p>Check out the App Runtime extension. It's baller.</p>
|
||||
<a href="#" class="close">Close</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="amo-promos">
|
||||
<section id="promos" class="island" style="display: none">
|
||||
<div>
|
||||
<ul class="slider">
|
||||
<li class="panel"><section id="starter"></section></li>
|
||||
<li class="panel"><section id="ryff"></section></li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div id="apps-error-msg">
|
||||
{% include 'addons/includes/apps_error_msg.html' %}
|
||||
</div>
|
||||
|
||||
<!-- Install button tests - it's possible not all combinations are being tested here -->
|
||||
|
||||
<div id="install-button">
|
||||
<div class="install-shell">
|
||||
<div class="install" data-min="3.0" data-max="4.0">
|
||||
<p class="install-button">
|
||||
<a class="button download" data-hash="1337" href="http://testurl.com">Foo</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- app, warning, mobile -->
|
||||
<div id="install-button-warning">
|
||||
{% with addon={'is_premium': Mock(return_value=False),
|
||||
'is_webapp': Mock(return_value=True)},
|
||||
|
||||
b={'show_warning': True,
|
||||
'addon': {'get_url_path': Mock(return_value='http://testurl.com')},
|
||||
'show_contrib': False,
|
||||
'xpiurl': 'http://xpiurl.com',
|
||||
'button_class': ['download', 'prominent']},
|
||||
|
||||
link={'url': 'http://testurl.com',
|
||||
'os': {'name': 'windows'},
|
||||
'file': {'hash': '1337'}},
|
||||
|
||||
shared_url=Mock(return_value='http://sharedurl.com'),
|
||||
waffle={'switch': Mock(return_value=False)},
|
||||
request={'MOBILE': True} %}
|
||||
|
||||
{% include 'addons/includes/install_button.html' %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
|
||||
<!-- app, eula, mobile -->
|
||||
<div id="install-button-eula">
|
||||
{% with addon={'is_premium': Mock(return_value=False),
|
||||
'is_webapp': Mock(return_value=True)},
|
||||
|
||||
b={'show_warning': False,
|
||||
'addon': {'get_url_path': Mock(return_value='http://testurl.com')},
|
||||
'show_contrib': False,
|
||||
'xpiurl': 'http://xpiurl.com',
|
||||
'button_class': ['download', 'prominent']},
|
||||
|
||||
link={'url': 'http://testurl.com',
|
||||
'os': {'name': 'windows'},
|
||||
'file': {'hash': '1337'}},
|
||||
|
||||
shared_url=Mock(return_value='http://sharedurl.com'),
|
||||
waffle={'switch': Mock(return_value=False)},
|
||||
request={'MOBILE': True} %}
|
||||
|
||||
{% include 'addons/includes/install_button.html' %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
|
||||
<!-- premium, mobile -->
|
||||
<div id="install-button-premium">
|
||||
{% with addon={'is_premium': Mock(return_value=True),
|
||||
'is_webapp': Mock(return_value=False)},
|
||||
|
||||
b={'show_warning': False,
|
||||
'addon': {'get_url_path': Mock(return_value='http://testurl.com')},
|
||||
'show_contrib': False,
|
||||
'xpiurl': 'http://xpiurl.com',
|
||||
'button_class': ['download', 'prominent']},
|
||||
|
||||
link={'url': 'http://testurl.com',
|
||||
'os': {'name': 'windows'},
|
||||
'file': {'hash': '1337'}},
|
||||
|
||||
shared_url=Mock(return_value='http://sharedurl.com'),
|
||||
waffle={'switch': Mock(return_value=False)},
|
||||
request={'MOBILE': True} %}
|
||||
|
||||
{% include 'addons/includes/install_button.html' %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
|
||||
<!-- contrib, mobile -->
|
||||
<div id="install-button-contrib">
|
||||
{% with addon={'is_premium': Mock(return_value=False),
|
||||
'is_webapp': Mock(return_value=False)},
|
||||
|
||||
b={'show_warning': False,
|
||||
'addon': {'get_url_path': Mock(return_value='http://testurl.com')},
|
||||
'show_contrib': True,
|
||||
'xpiurl': 'http://xpiurl.com',
|
||||
'button_class': ['download', 'prominent']},
|
||||
|
||||
link={'url': 'http://testurl.com',
|
||||
'os': {'name': 'windows'},
|
||||
'file': {'hash': '1337'}},
|
||||
|
||||
shared_url=Mock(return_value='http://sharedurl.com'),
|
||||
waffle={'switch': Mock(return_value=False)},
|
||||
request={'MOBILE': True} %}
|
||||
|
||||
{% include 'addons/includes/install_button.html' %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
|
||||
<!-- can be purchased, mobile -->
|
||||
<div id="install-button-purchasable">
|
||||
{% with addon={'is_premium': Mock(return_value=False),
|
||||
'is_webapp': Mock(return_value=False)},
|
||||
|
||||
b={'show_warning': False,
|
||||
'addon': {'get_url_path': Mock(return_value='http://testurl.com')},
|
||||
'show_contrib': False,
|
||||
'xpiurl': 'http://xpiurl.com',
|
||||
'button_class': ['download', 'prominent']},
|
||||
|
||||
link={'url': 'http://testurl.com',
|
||||
'os': {'name': 'windows'},
|
||||
'file': {'hash': '1337'}},
|
||||
|
||||
shared_url=Mock(return_value='http://sharedurl.com'),
|
||||
waffle={'switch': Mock(return_value=False)},
|
||||
request={'MOBILE': True} %}
|
||||
|
||||
{% include 'addons/includes/install_button.html' %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
|
||||
<!-- marketplace, mobile, can be purchased -->
|
||||
<div id="install-button-marketplace">
|
||||
{% with addon={'is_premium': Mock(return_value=False),
|
||||
'is_webapp': Mock(return_value=False)},
|
||||
|
||||
b={'show_warning': False,
|
||||
'addon': {'get_url_path': Mock(return_value='http://testurl.com')},
|
||||
'show_contrib': False,
|
||||
'xpiurl': 'http://xpiurl.com',
|
||||
'button_class': ['download', 'prominent']},
|
||||
|
||||
link={'url': 'http://testurl.com',
|
||||
'os': {'name': 'windows'},
|
||||
'file': {'hash': '1337'}},
|
||||
|
||||
shared_url=Mock(return_value='http://sharedurl.com'),
|
||||
waffle={'switch': Mock(return_value=True)},
|
||||
request={'MOBILE': True} %}
|
||||
|
||||
{% include 'addons/includes/install_button.html' %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
|
||||
<!-- app, marketplace, mobile, can be purchased -->
|
||||
<div id="install-button-app-marketplace">
|
||||
{% with addon={'is_premium': Mock(return_value=False),
|
||||
'is_webapp': Mock(return_value=True)},
|
||||
|
||||
b={'show_warning': False,
|
||||
'addon': {'get_url_path': Mock(return_value='http://testurl.com')},
|
||||
'show_contrib': False,
|
||||
'xpiurl': 'http://xpiurl.com',
|
||||
'button_class': ['download', 'prominent']},
|
||||
|
||||
link={'url': 'http://testurl.com',
|
||||
'os': {'name': 'windows'},
|
||||
'file': {'hash': '1337'}},
|
||||
|
||||
shared_url=Mock(return_value='http://sharedurl.com'),
|
||||
waffle={'switch': Mock(return_value=True)},
|
||||
request={'MOBILE': True} %}
|
||||
|
||||
{% include 'addons/includes/install_button.html' %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
|
||||
<!-- app, premium, mobile -->
|
||||
<div id="install-button-app-premium">
|
||||
{% with addon={'is_premium': Mock(return_value=True),
|
||||
'is_webapp': Mock(return_value=True),
|
||||
'has_purchased': Mock(return_value=False),
|
||||
'premium': Mock(return_value=False)},
|
||||
|
||||
b={'show_warning': False,
|
||||
'addon': {'get_url_path': Mock(return_value='http://testurl.com')},
|
||||
'show_contrib': False,
|
||||
'xpiurl': 'http://xpiurl.com',
|
||||
'button_class': ['download', 'prominent']},
|
||||
|
||||
link={'url': 'http://testurl.com',
|
||||
'os': {'name': 'windows'},
|
||||
'file': {'hash': '1337'}},
|
||||
|
||||
shared_url=Mock(return_value='http://sharedurl.com'),
|
||||
waffle={'switch': Mock(return_value=False)},
|
||||
request={'MOBILE': True} %}
|
||||
|
||||
{% include 'addons/includes/install_button.html' %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
|
||||
<!-- app, contrib, mobile -->
|
||||
<div id="install-button-app-contrib">
|
||||
{% with addon={'is_premium': Mock(return_value=False),
|
||||
'is_webapp': Mock(return_value=True)},
|
||||
|
||||
b={'show_warning': False,
|
||||
'addon': {'get_url_path': Mock(return_value='http://testurl.com')},
|
||||
'show_contrib': True,
|
||||
'xpiurl': 'http://xpiurl.com',
|
||||
'button_class': ['download', 'prominent']},
|
||||
|
||||
link={'url': 'http://testurl.com',
|
||||
'os': {'name': 'windows'},
|
||||
'file': {'hash': '1337'}},
|
||||
|
||||
shared_url=Mock(return_value='http://sharedurl.com'),
|
||||
waffle={'switch': Mock(return_value=False)},
|
||||
request={'MOBILE': True} %}
|
||||
|
||||
{% include 'addons/includes/install_button.html' %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
|
||||
<!-- app, can be purchased, mobile -->
|
||||
<div id="install-button-app-purchasable">
|
||||
{% with addon={'is_premium': Mock(return_value=False),
|
||||
'is_webapp': Mock(return_value=True)},
|
||||
|
||||
b={'show_warning': False,
|
||||
'addon': {'get_url_path': Mock(return_value='http://testurl.com')},
|
||||
'show_contrib': False,
|
||||
'xpiurl': 'http://xpiurl.com',
|
||||
'button_class': ['download', 'prominent']},
|
||||
|
||||
link={'url': 'http://testurl.com',
|
||||
'os': {'name': 'windows'},
|
||||
'file': {'hash': '1337'}},
|
||||
|
||||
shared_url=Mock(return_value='http://sharedurl.com'),
|
||||
waffle={'switch': Mock(return_value=False)},
|
||||
request={'MOBILE': True} %}
|
||||
|
||||
{% include 'addons/includes/install_button.html' %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
|
||||
<!-- marketplace, app, warning, mobile -->
|
||||
<div id="install-button-mp-warning">
|
||||
{% with addon={'is_premium': Mock(return_value=False),
|
||||
'is_webapp': Mock(return_value=True)},
|
||||
|
||||
b={'show_warning': True,
|
||||
'addon': {'get_url_path': Mock(return_value='http://testurl.com')},
|
||||
'show_contrib': False,
|
||||
'xpiurl': 'http://xpiurl.com',
|
||||
'button_class': ['download', 'prominent']},
|
||||
|
||||
link={'url': 'http://testurl.com',
|
||||
'os': {'name': 'windows'},
|
||||
'file': {'hash': '1337'}},
|
||||
|
||||
shared_url=Mock(return_value='http://sharedurl.com'),
|
||||
waffle={'switch': Mock(return_value=True)},
|
||||
request={'MOBILE': True} %}
|
||||
|
||||
{% include 'addons/includes/install_button.html' %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
|
||||
<!-- marketplace, app, eula, mobile -->
|
||||
<div id="install-button-mp-eula">
|
||||
{% with addon={'is_premium': Mock(return_value=False),
|
||||
'is_webapp': Mock(return_value=True)},
|
||||
|
||||
b={'show_warning': False,
|
||||
'addon': {'get_url_path': Mock(return_value='http://testurl.com')},
|
||||
'show_contrib': False,
|
||||
'xpiurl': 'http://xpiurl.com',
|
||||
'button_class': ['download', 'prominent']},
|
||||
|
||||
link={'url': 'http://testurl.com',
|
||||
'os': {'name': 'windows'},
|
||||
'file': {'hash': '1337'}},
|
||||
|
||||
shared_url=Mock(return_value='http://sharedurl.com'),
|
||||
waffle={'switch': Mock(return_value=True)},
|
||||
request={'MOBILE': True} %}
|
||||
|
||||
{% include 'addons/includes/install_button.html' %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
|
||||
<!-- marketplace, premium, mobile -->
|
||||
<div id="install-button-mp-premium">
|
||||
{% with addon={'is_premium': Mock(return_value=True),
|
||||
'is_webapp': Mock(return_value=False)},
|
||||
|
||||
b={'show_warning': False,
|
||||
'addon': {'get_url_path': Mock(return_value='http://testurl.com')},
|
||||
'show_contrib': False,
|
||||
'xpiurl': 'http://xpiurl.com',
|
||||
'button_class': ['download', 'prominent']},
|
||||
|
||||
link={'url': 'http://testurl.com',
|
||||
'os': {'name': 'windows'},
|
||||
'file': {'hash': '1337'}},
|
||||
|
||||
shared_url=Mock(return_value='http://sharedurl.com'),
|
||||
waffle={'switch': Mock(return_value=True)},
|
||||
request={'MOBILE': True} %}
|
||||
|
||||
{% include 'addons/includes/install_button.html' %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
|
||||
<!-- marketplace, contrib, mobile -->
|
||||
<div id="install-button-mp-contrib">
|
||||
{% with addon={'is_premium': Mock(return_value=False),
|
||||
'is_webapp': Mock(return_value=False)},
|
||||
|
||||
b={'show_warning': False,
|
||||
'addon': {'get_url_path': Mock(return_value='http://testurl.com')},
|
||||
'show_contrib': True,
|
||||
'xpiurl': 'http://xpiurl.com',
|
||||
'button_class': ['download', 'prominent']},
|
||||
|
||||
link={'url': 'http://testurl.com',
|
||||
'os': {'name': 'windows'},
|
||||
'file': {'hash': '1337'}},
|
||||
|
||||
shared_url=Mock(return_value='http://sharedurl.com'),
|
||||
waffle={'switch': Mock(return_value=True)},
|
||||
request={'MOBILE': True} %}
|
||||
|
||||
{% include 'addons/includes/install_button.html' %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
|
||||
|
||||
<div id="addon-validator-template">
|
||||
<div class="addon-validator-suite" id="addon-validator-suite-test"
|
||||
data-validateurl="/validate">
|
||||
{% with validate_url="/validate" %}
|
||||
{% include "devhub/addons/includes/validation_test_results.html" %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="addon-compatibility-template">
|
||||
<div class="addon-validator-suite" id="addon-validator-suite-test"
|
||||
data-validateurl="/validate">
|
||||
{% with app_trans={'{ec8030f7-c20a-464f-9b0e-13a3a9e97384}': 'Firefox'},
|
||||
version_change_links={'{ec8030f7-c20a-464f-9b0e-13a3a9e97384} 6.*': '/firefox-6-changes'},
|
||||
target_version={'{ec8030f7-c20a-464f-9b0e-13a3a9e97384}': '6.*'} %}
|
||||
{% include "devhub/addons/includes/validation_compat_test_results.html" %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="preview-list">
|
||||
<div id="edit-addon-media">
|
||||
<div id="file-list">
|
||||
<div class="preview">
|
||||
<span class="handle" style="display: none;"> </span>
|
||||
<div class="preview-thumb" data-url="" style="background-image: url();">
|
||||
</div>
|
||||
<input type="hidden" id="id_files-0-id" name="files-0-id">
|
||||
<span class="js-hidden delete"><input type="checkbox" id="id_files-0-DELETE" name="files-0-DELETE"><label for="id_files-0-DELETE">Delete</label></span>
|
||||
<div class="edit-previews-text">
|
||||
<label class="above-the-field" data-for="files-0-caption" for="id_files-0-caption_0">
|
||||
Please provide a caption for this screenshot:
|
||||
<span class="locale">English (US)</span>
|
||||
</label>
|
||||
<div data-name="files-0-caption" class="trans" id="trans-files-0-caption"><textarea lang="en-us" id="id_files-0-caption_0" cols="40" name="files-0-caption_en-us" rows="10" class="unsaved"></textarea><textarea lang="init" class="trans-init" cols="40" name="files-0-caption_init" rows="10" style="display: none;"></textarea></div>
|
||||
<a class="remove" href="#">x</a>
|
||||
</div>
|
||||
<div class="js-hidden position">
|
||||
<input type="text" id="id_files-0-position" value="0" name="files-0-position">
|
||||
</div>
|
||||
<div class="preview_extra">
|
||||
<input type="text" id="id_files-0-upload_hash" name="files-0-upload_hash">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="addon-platform-chooser">
|
||||
<!-- TODO(Kumar) create faux form objects and include add_file_modal.html here -->
|
||||
<form method="post" id="create-addon" class="item">
|
||||
<div class="platform">
|
||||
<div class="desktop-platforms">
|
||||
<label>Which desktop platforms is this file compatible with?</label>
|
||||
<ul>
|
||||
<li><label for="id_desktop_platforms_0">
|
||||
<input value="1" checked="checked" name="desktop_platforms" id="id_desktop_platforms_0" type="checkbox" class="platform">
|
||||
All Platforms</label></li>
|
||||
<li><label for="id_desktop_platforms_1">
|
||||
<input value="2" id="id_desktop_platforms_1" type="checkbox" class="platform" name="desktop_platforms">
|
||||
Linux</label></li>
|
||||
<li><label for="id_desktop_platforms_2">
|
||||
<input value="3" type="checkbox" id="id_desktop_platforms_2" name="desktop_platforms" class="platform">
|
||||
Mac OS X</label></li>
|
||||
<li><label for="id_desktop_platforms_3">
|
||||
<input value="5" class="platform" type="checkbox" id="id_desktop_platforms_3" name="desktop_platforms">
|
||||
Windows</label> </li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="mobile-platforms">
|
||||
<label>Which mobile platforms is this file compatible with?</label>
|
||||
<ul>
|
||||
<li><label for="id_mobile_platforms_0">
|
||||
<input value="9" type="checkbox" class="platform" name="mobile_platforms" id="id_mobile_platforms_0" />
|
||||
All Platforms</label></li>
|
||||
<li><label for="id_mobile_platforms_1">
|
||||
<input value="7" id="id_mobile_platforms_1" type="checkbox" class="platform" name="mobile_platforms" />
|
||||
Android</label></li>
|
||||
<li><label for="id_mobile_platforms_2">
|
||||
<input value="8" type="checkbox" id="id_mobile_platforms_2" name="mobile_platforms" class="platform" />
|
||||
Maemo</label></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="addon-platform-exclusion">
|
||||
<!-- TODO(Kumar) create faux form objects and include add_file_modal.html here -->
|
||||
<div id="file-upload-template">
|
||||
<form>
|
||||
<!-- for testing this has to be a non-input element, since
|
||||
you can't access ".file" on an input element -->
|
||||
<div data-upload-url="/" id="upload-file-input"></div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="platform">
|
||||
<div class="desktop-platforms">
|
||||
<label>Which desktop platforms is this file compatible with?</label>
|
||||
<ul>
|
||||
<li><label for="id_desktop_platforms_0">
|
||||
<input value="1" checked="checked" name="desktop_platforms" id="id_desktop_platforms_0" type="checkbox" class="platform">
|
||||
All Platforms</label></li>
|
||||
<li><label for="id_desktop_platforms_1">
|
||||
<input value="2" id="id_desktop_platforms_1" type="checkbox" class="platform" name="desktop_platforms">
|
||||
Linux</label></li>
|
||||
<li><label for="id_desktop_platforms_2">
|
||||
<input value="3" type="checkbox" id="id_desktop_platforms_2" name="desktop_platforms" class="platform">
|
||||
Mac OS X</label></li>
|
||||
<li><label for="id_desktop_platforms_3">
|
||||
<input value="5" class="platform" type="checkbox" id="id_desktop_platforms_3" name="desktop_platforms">
|
||||
Windows</label> </li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="mobile-platforms">
|
||||
<label>Which mobile platforms is this file compatible with?</label>
|
||||
<ul>
|
||||
<li><label for="id_mobile_platforms_0">
|
||||
<input value="9" type="checkbox" class="platform" name="mobile_platforms" id="id_mobile_platforms_0" />
|
||||
All Platforms</label></li>
|
||||
<li><label for="id_mobile_platforms_1">
|
||||
<input value="7" id="id_mobile_platforms_1" type="checkbox" class="platform" name="mobile_platforms" />
|
||||
Android</label></li>
|
||||
<li><label for="id_mobile_platforms_2">
|
||||
<input value="8" type="checkbox" id="id_mobile_platforms_2" name="mobile_platforms" class="platform" />
|
||||
Maemo</label></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="slugified-field">
|
||||
<input id="id_name" />
|
||||
<span id="slug_edit" class="edit_with_prefix edit_initially_hidden">
|
||||
<input type="text" maxlength="30" name="slug" id="id_slug">
|
||||
</span>
|
||||
<span id="slug_readonly">
|
||||
<span id="slug_value"></span>
|
||||
<a id="edit_slug" href="#">{{ _('Edit') }}</a>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div id="addon-cats" data-max-categories="2">
|
||||
<div data-max-categories="2">
|
||||
<div id="addon-cats-fx" class="addon-app-cats">
|
||||
<label>Select <b>up to 2</b> Firefox categories for this add-on:</label>
|
||||
<ul class="addon-categories">
|
||||
<li><label for="id_form-0-categories_0"><input type="checkbox" name="form-0-categories" value="72" id="id_form-0-categories_0" /> Alerts & Updates</label></li>
|
||||
<li><label for="id_form-0-categories_1"><input checked="checked" type="checkbox" name="form-0-categories" value="14" id="id_form-0-categories_1" /> Appearance</label></li>
|
||||
<li><label for="id_form-0-categories_2"><input checked="checked" type="checkbox" name="form-0-categories" value="22" id="id_form-0-categories_2" /> Bookmarks</label></li>
|
||||
</ul>
|
||||
<ul class="addon-misc-category">
|
||||
<li><label for="id_form-0-categories_13"><input type="checkbox" name="form-0-categories" value="73" id="id_form-0-categories_13" /> My add-on doesn't fit into any of the categories</label></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="addon-cats-tb" class="addon-app-cats">
|
||||
<label>Select <b>up to 2</b> Thunderbird categories for this add-on:</label>
|
||||
<ul class="addon-categories">
|
||||
<li><label for="id_form-1-categories_0"><input type="checkbox" name="form-1-categories" value="23" id="id_form-1-categories_0" /> Contacts</label></li>
|
||||
<li><label for="id_form-1-categories_1"><input type="checkbox" name="form-1-categories" value="69" id="id_form-1-categories_1" /> Language Support</label></li>
|
||||
</ul>
|
||||
<ul class="addon-misc-category">
|
||||
<li><label for="id_form-1-categories_4"><input type="checkbox" name="form-1-categories" value="50" id="id_form-1-categories_4" /> My add-on doesn't fit into any of the categories</label></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="file-perf-tests">
|
||||
{% with version={'all_files': [{'can_be_perf_tested': Mock(return_value=True), 'id': 1}]}, addon={'slug': 'foo'} %}
|
||||
{% include "devhub/addons/listing/perf_file_listing.html" %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
|
||||
<div id="editors-search-form">
|
||||
<form>
|
||||
<label for="id_application_id">Application</label>
|
||||
<select data-url="/application_versions.json" name="application_id" id="id_application_id">
|
||||
<option value="" selected="selected"></option>
|
||||
<option value="1">Firefox</option>
|
||||
<option value="2">Mozilla</option>
|
||||
</select>
|
||||
<label for="id_max_version">Max. Version</label>
|
||||
<select name="max_version" id="id_max_version">
|
||||
<option value="" selected="selected">Select an application first</option>
|
||||
</select>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="editors-motd-template">
|
||||
<style>
|
||||
/* We hide the message by default, and show it only if we're s'posed to. */
|
||||
.daily-message { display: none }
|
||||
</style>
|
||||
{% with motd='This is an announcement' %}
|
||||
{% include "editors/includes/daily-message.html" %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
|
||||
<div id="editors-motd-for-edit-template">
|
||||
{% with motd='This is an announcement' %}
|
||||
{% include "editors/includes/daily-message.html" %}
|
||||
{% endwith %}
|
||||
<div id="editor-motd"><!-- admin edit form and stuff --></div>
|
||||
</div>
|
||||
|
||||
<div id="hovercard-grid">
|
||||
<div class="island">
|
||||
<ul class="listing-grid">
|
||||
<section>
|
||||
<li></li>
|
||||
<li></li>
|
||||
<li></li>
|
||||
</section>
|
||||
<section>
|
||||
<li></li>
|
||||
<li></li>
|
||||
<li></li>
|
||||
</section>
|
||||
<section>
|
||||
<li></li>
|
||||
<li></li>
|
||||
<li></li>
|
||||
</section>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
Загрузка…
Ссылка в новой задаче