mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 06:11:37 +00:00
bug 348731, 348554, unify test harness, one ring to test them all, one page to watch it
This commit is contained in:
parent
4864773bb2
commit
d076e64b5e
@ -51,7 +51,10 @@ exceptions = [
|
||||
__regify(('mail|browser', 'defines.inc', 'MOZ_LANGPACK_CONTRIBUTORS')),
|
||||
# ignore search engine order for browser
|
||||
__regify(('browser', 'chrome\\/browser-region\\/region\\.properties',
|
||||
'browser\\.search\\.order\.[1-9]'))]
|
||||
'browser\\.search\\.order\.[1-9]')),
|
||||
# ignore feed engine order for browser
|
||||
__regify(('browser', 'chrome\\/browser-region\\/region\\.properties',
|
||||
'browser\\.contentHandlers\\.types\.[0-5]'))]
|
||||
|
||||
def __dont_ignore(tpl):
|
||||
for mod, path, key in exceptions:
|
||||
|
300
testing/tests/l10n/lib/Mozilla/Tests.py
Executable file
300
testing/tests/l10n/lib/Mozilla/Tests.py
Executable file
@ -0,0 +1,300 @@
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is l10n test automation.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Mozilla Foundation
|
||||
# Portions created by the Initial Developer are Copyright (C) 2006
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Axel Hecht <l10n@mozilla.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
import logging
|
||||
import Paths
|
||||
import Parser
|
||||
|
||||
class Base:
|
||||
'''Base class for all tests'''
|
||||
def __init__(self):
|
||||
if not hasattr(self, 'leafName'):
|
||||
self.leafName = 'TODO'
|
||||
logging.warning(' ' + self + ' does not have leafName set, writing to TODO')
|
||||
def run(self):
|
||||
'''Run this test for all locales, returns a dictionary with results'''
|
||||
pass
|
||||
def serialize(self, result, saveHandler):
|
||||
'''Serialize the previously generated result, writes the dictionary
|
||||
by default'''
|
||||
return saveHandler(result, self.leafName)
|
||||
pass
|
||||
def failureTest(self, myResult, failureResult):
|
||||
pass
|
||||
|
||||
import CompareLocales
|
||||
class CompareTest(Base):
|
||||
'''Test class to compare locales'''
|
||||
def __init__(self):
|
||||
'''Initializes the test object'''
|
||||
# nothing to be done here
|
||||
pass
|
||||
def run(self):
|
||||
'''Runs CompareLocales.compare()'''
|
||||
return CompareLocales.compare()
|
||||
def serialize(self, result, saveHandler):
|
||||
'''Serialize the CompareLocales result by locale into
|
||||
cmp-details-ab-CD
|
||||
and a compacted version into
|
||||
cmp-data
|
||||
|
||||
'''
|
||||
class Separator:
|
||||
def __init__(self):
|
||||
self.leafBase = 'cmp-details-'
|
||||
def getDetails(self, res, locale):
|
||||
dic = {}
|
||||
res[locale]['tested'].sort()
|
||||
self.collectList('missing', res[locale], dic)
|
||||
self.collectList('obsolete', res[locale], dic)
|
||||
saveHandler(dic, self.leafBase + locale + '.json')
|
||||
def collectList(self, name, res, dic):
|
||||
dic[name] = {}
|
||||
if not res.has_key(name):
|
||||
res[name] = []
|
||||
counts = dict([(mod,0) for mod in res['tested']])
|
||||
counts['total'] = len(res[name])
|
||||
for mod, path, key in res[name]:
|
||||
counts[Paths.components[mod]] +=1
|
||||
if not dic[name].has_key(mod):
|
||||
dic[name][mod] = {path:[key]}
|
||||
continue
|
||||
if not dic[name][mod].has_key(path):
|
||||
dic[name][mod][path] = [key]
|
||||
else:
|
||||
dic[name][mod][path].append(key)
|
||||
res[name] = counts
|
||||
name += 'Files'
|
||||
dic[name] = {}
|
||||
if not res.has_key(name):
|
||||
res[name] = []
|
||||
counts = dict([(mod,0) for mod in res['tested']])
|
||||
counts['total'] = len(res[name])
|
||||
for mod, path in res[name]:
|
||||
counts[Paths.components[mod]] +=1
|
||||
if not dic[name].has_key(mod):
|
||||
dic[name][mod] = [path]
|
||||
else:
|
||||
dic[name][mod].append(path)
|
||||
res[name] = counts
|
||||
|
||||
s = Separator()
|
||||
for loc, lResult in result.iteritems():
|
||||
s.getDetails(result, loc)
|
||||
|
||||
saveHandler(result, 'cmp-data.json')
|
||||
|
||||
def failureTest(self, myResult, failureResult):
|
||||
'''signal pass/warn/failure for each locale'''
|
||||
def sumdata(data, part):
|
||||
res = 0
|
||||
for mod in [u'browser', u'toolkit']:
|
||||
res += data[part][mod] + data[part + u'Files'][mod]
|
||||
return res
|
||||
def getState(data):
|
||||
ret = 0
|
||||
if sumdata(data, u'obsolete') > 0:
|
||||
ret |= 1
|
||||
if sumdata(data, u'missing') > 0:
|
||||
ret |= 2
|
||||
return ret
|
||||
for loc, val in myResult.iteritems():
|
||||
if not failureResult.has_key(loc):
|
||||
failureResult[loc] = getState(val)
|
||||
else:
|
||||
failureResult |= getState(val)
|
||||
|
||||
from xml import sax
|
||||
from types import DictType, FunctionType
|
||||
import md5
|
||||
from codecs import utf_8_encode
|
||||
import re
|
||||
import os
|
||||
|
||||
class SearchTest(Base):
|
||||
"""Test class to collect information from search plugins and to
|
||||
verify that they're doing something good.
|
||||
|
||||
"""
|
||||
def __init__(self):
|
||||
'''Set up the test class with a good leaf name'''
|
||||
self.leafName = 'search-results.json'
|
||||
pass
|
||||
def run(self):
|
||||
'''Collect all data from the MozSearch plugins in both the /cvsroot
|
||||
repository for en-US and the /l10n repository for locales
|
||||
|
||||
'''
|
||||
class DummyHandler(sax.handler.ContentHandler):
|
||||
def startDocument(self):
|
||||
self.md5 = md5.new()
|
||||
self.indent = ''
|
||||
self.engine = {'urls':[]}
|
||||
self.lNames = []
|
||||
self.textField = None
|
||||
return
|
||||
def endDocument(self):
|
||||
self.engine['md5'] = self.md5.hexdigest()
|
||||
return
|
||||
def startElementNS(self, (ns, local), qname, attrs):
|
||||
self.indent += ' '
|
||||
if ns != u'http://www.mozilla.org/2006/browser/search/':
|
||||
raise UserWarning, ('bad namespace: ' + ns)
|
||||
self.lNames.append(local)
|
||||
handler = self.getOpenHandler()
|
||||
if handler:
|
||||
handler(self, attrs)
|
||||
self.update(ns+local)
|
||||
for qna in attrs.getQNames():
|
||||
self.update(qna[0] + qna[1] + attrs.getValueByQName(qna))
|
||||
return
|
||||
def endElementNS(self, (ns, local), qname):
|
||||
self.lNames.pop()
|
||||
self.indent = self.indent[0:-2]
|
||||
def characters(self, content):
|
||||
self.update(content)
|
||||
if not self.textField:
|
||||
return
|
||||
self.engine[self.textField] = content
|
||||
self.textField = None
|
||||
def update(self, content):
|
||||
self.md5.update(utf_8_encode(content)[0])
|
||||
def openURL(self, attrs):
|
||||
entry = {'params':{},
|
||||
'type': attrs.getValueByQName(u'type'),
|
||||
'template': attrs.getValueByQName(u'template')}
|
||||
self.engine['urls'].append(entry)
|
||||
def handleParam(self, attrs):
|
||||
try:
|
||||
self.engine['urls'][-1]['params'][attrs.getValueByQName(u'name')] = attrs.getValueByQName(u'value')
|
||||
except KeyError:
|
||||
raise UserWarning, 'bad param'
|
||||
return
|
||||
def handleMozParam(self, attrs):
|
||||
try:
|
||||
self.engine['urls'][-1]['MozParams'] = {
|
||||
'name': attrs.getValueByQName(u'name'),
|
||||
'condition': attrs.getValueByQName(u'condition'),
|
||||
'trueValue': attrs.getValueByQName(u'trueValue'),
|
||||
'falseValue': attrs.getValueByQName(u'falseValue')}
|
||||
except KeyError:
|
||||
raise UserWarning, 'bad mozParam'
|
||||
return
|
||||
def handleShortName(self, attrs):
|
||||
self.textField = 'ShortName'
|
||||
return
|
||||
def handleImage(self, attrs):
|
||||
self.textField = 'Image'
|
||||
return
|
||||
def getOpenHandler(self):
|
||||
return self.getHandler(DummyHandler.openHandlers)
|
||||
def getHandler(self, handlers):
|
||||
for local in self.lNames:
|
||||
if type(handlers) != DictType or not handlers.has_key(local):
|
||||
return
|
||||
handlers = handlers[local]
|
||||
if handlers.has_key('_handler'):
|
||||
return handlers['_handler']
|
||||
return
|
||||
openHandlers = {'SearchPlugin':
|
||||
{'ShortName': {'_handler': handleShortName},
|
||||
'Image': {'_handler': handleImage},
|
||||
'Url':{'_handler': openURL,
|
||||
'Param': {'_handler':handleParam},
|
||||
'MozParam': {'_handler':handleMozParam}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handler = DummyHandler()
|
||||
parser = sax.make_parser()
|
||||
parser.setContentHandler(handler)
|
||||
parser.setFeature(sax.handler.feature_namespaces, True)
|
||||
|
||||
locales = [loc.strip() for loc in open('mozilla/browser/locales/all-locales')]
|
||||
locales.insert(0, 'en-US')
|
||||
sets = {}
|
||||
details = {}
|
||||
|
||||
for loc in locales:
|
||||
try:
|
||||
lst = open(Paths.get_path('browser',loc,'searchplugins/list.txt'),'r')
|
||||
except IOError:
|
||||
logging.error("Locale " + loc + " doesn't have search plugins")
|
||||
details[Paths.get_path('browser',loc,'searchplugins/list.txt')] = {
|
||||
'error': 'not found'
|
||||
}
|
||||
continue
|
||||
sets[loc] = {'list': []}
|
||||
regprop = Paths.get_path('browser', loc, 'chrome/browser-region/region.properties')
|
||||
p = Parser.getParser(regprop)
|
||||
p.read(regprop)
|
||||
orders = {}
|
||||
for key, val in p:
|
||||
m = re.match('browser.search.order.([1-9])', key)
|
||||
if m:
|
||||
orders[val.strip()] = int(m.group(1))
|
||||
sets[loc]['orders'] = orders
|
||||
for fn in lst:
|
||||
name = fn.strip()
|
||||
leaf = 'searchplugins/' + name + '.xml'
|
||||
_path = Paths.get_path('browser','en-US', leaf)
|
||||
if not os.access(_path, os.R_OK):
|
||||
_path = Paths.get_path('browser', loc, leaf)
|
||||
logging.info('testing ' + _path)
|
||||
sets[loc]['list'].append(_path)
|
||||
try:
|
||||
parser.parse(_path)
|
||||
except IOError:
|
||||
logging.error("can't open " + _path)
|
||||
details[_path] = {'_name': name, 'error': 'not found'}
|
||||
continue
|
||||
except UserWarning, ex:
|
||||
logging.error("error in searchplugin " + _path)
|
||||
details[_path] = {'_name': name, 'error': ex.args[0]}
|
||||
continue
|
||||
except sax._exceptions.SAXParseException, ex:
|
||||
logging.error("error in searchplugin " + _path)
|
||||
details[_path] = {'_name': name, 'error': ex.args[0]}
|
||||
continue
|
||||
details[_path] = handler.engine
|
||||
details[_path]['_name'] = name
|
||||
|
||||
engines = {'locales': sets,
|
||||
'details': details}
|
||||
return engines
|
||||
|
165
testing/tests/l10n/scripts/test-locales
Executable file
165
testing/tests/l10n/scripts/test-locales
Executable file
@ -0,0 +1,165 @@
|
||||
#! python
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is l10n test automation.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Mozilla Foundation
|
||||
# Portions created by the Initial Developer are Copyright (C) 2006
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Axel Hecht <l10n@mozilla.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
|
||||
import logging
|
||||
import sys
|
||||
import os
|
||||
import os.path
|
||||
from datetime import datetime
|
||||
import time
|
||||
from optparse import OptionParser
|
||||
import gzip
|
||||
import codecs
|
||||
|
||||
from Mozilla import Parser, CompareLocales, Paths, Tests
|
||||
import simplejson
|
||||
|
||||
testLocales = []
|
||||
lvl = logging.WARNING
|
||||
date = datetime.utcnow().replace(minute=0,second=0,microsecond=0).isoformat(' ')
|
||||
# parse commandline arguments
|
||||
cp = OptionParser(version='0.2')
|
||||
cp.add_option('-v', '--verbose', action='count', dest='v', default=0,
|
||||
help='Make more noise')
|
||||
cp.add_option('-q', '--quiet', action='count', dest='q', default=0,
|
||||
help='Make less noise')
|
||||
cp.add_option('-O', '--base-dir', type='string', dest='target',
|
||||
default='results',
|
||||
help='Destination base directory')
|
||||
cp.add_option('-d', '--date', type='string', dest='date', default=date,
|
||||
help='Explicit start date [Default: last full hour]')
|
||||
cp.add_option('-z',action="store_true", dest="gzip", default=False,
|
||||
help='Use gzip compression for output')
|
||||
cp.add_option('-w','--enable-waterfall', action="store_true",
|
||||
dest="waterfall", default=False,
|
||||
help='Update waterfall data')
|
||||
cp.add_option('--end-date', type='string', dest='enddate',
|
||||
help='Explicit (faked) end date')
|
||||
opts, optlist = cp.parse_args(sys.argv[1:])
|
||||
|
||||
logging.basicConfig(level=(logging.WARNING + 10*(opts.q - opts.v)))
|
||||
|
||||
logging.debug(' Ensure output directory')
|
||||
# replace : with -
|
||||
opts.date = opts.date.replace(':','-')
|
||||
if not os.path.isdir(opts.target):
|
||||
sys.exit('error: ' + opts.target + ' is not a directory')
|
||||
startdate = time.mktime(time.strptime(opts.date, '%Y-%m-%d %H-%M-%S'))
|
||||
basePath = os.path.join(opts.target, opts.date)
|
||||
if not os.path.isdir(basePath):
|
||||
os.mkdir(basePath)
|
||||
|
||||
class Wrapper:
|
||||
def __init__(self, path, name):
|
||||
self.p = os.path.join(path, name)
|
||||
self.n = name
|
||||
self.f = None
|
||||
if opts.gzip:
|
||||
self.p += '.gz'
|
||||
def open(self, mode):
|
||||
if self.f:
|
||||
self.f.close()
|
||||
if opts.gzip:
|
||||
mode += 'b'
|
||||
self.f = open(self.p, mode)
|
||||
if opts.gzip:
|
||||
self.f = gzip.GzipFile(fileobj = self.f, filename = self.n)
|
||||
self.w = codecs.getwriter('utf-8')(self.f)
|
||||
self.r = codecs.getreader('utf-8')(self.f)
|
||||
def write(self, str):
|
||||
self.w.write(str)
|
||||
def read(self, size = -1):
|
||||
return self.r.read(size)
|
||||
def rewind(self):
|
||||
if opts.gzip:
|
||||
self.f.rewind()
|
||||
else:
|
||||
self.f.seek(0,0)
|
||||
def close(self):
|
||||
if opts.gzip:
|
||||
f = self.f.fileobj;
|
||||
self.f.close()
|
||||
if opts.gzip:
|
||||
f.close()
|
||||
self.w = self.r = self.f = None
|
||||
|
||||
def saveJSON(dic, localName):
|
||||
name = os.path.join(basePath, localName) ;
|
||||
if opts.gzip:
|
||||
f = open(name + '.gz', 'wb')
|
||||
s = gzip.GzipFile(fileobj = f, filename = localName)
|
||||
else:
|
||||
f = open(name, 'w')
|
||||
s = f
|
||||
sw = codecs.getwriter('utf-8')(s)
|
||||
sw.write(simplejson.dumps(dic, sort_keys=True))
|
||||
sw.reset()
|
||||
if opts.gzip:
|
||||
s.close()
|
||||
f.close()
|
||||
|
||||
tests = [Tests.SearchTest(),Tests.CompareTest()]
|
||||
drop = {}
|
||||
for test in tests:
|
||||
res = test.run()
|
||||
test.serialize(res, saveJSON)
|
||||
if opts.waterfall:
|
||||
test.failureTest(res, drop)
|
||||
|
||||
if not opts.waterfall:
|
||||
sys.exit()
|
||||
|
||||
|
||||
if opts.enddate:
|
||||
endtime = time.mktime(time.strptime(opts.enddate, '%Y-%m-%d %H:%M:%S'))
|
||||
else:
|
||||
endtime = time.mktime(datetime.utcnow().timetuple())
|
||||
f = None
|
||||
w = Wrapper(opts.target, 'waterfall.json')
|
||||
if os.path.isfile(w.p):
|
||||
w.open('r')
|
||||
water = simplejson.load(w)
|
||||
else:
|
||||
water = []
|
||||
|
||||
water.append((opts.date, (startdate, endtime), drop))
|
||||
|
||||
w.open('w')
|
||||
simplejson.dump(water, w, sort_keys=True)
|
||||
w.close()
|
@ -1,9 +1,31 @@
|
||||
from distutils.core import setup
|
||||
|
||||
from distutils.cmd import Command
|
||||
import glob
|
||||
|
||||
class web(Command):
|
||||
description = 'install web files'
|
||||
user_options = [('target=','d','base directory for installation')]
|
||||
|
||||
def initialize_options(self):
|
||||
self.target = None
|
||||
pass
|
||||
def finalize_options(self):
|
||||
pass
|
||||
def run(self):
|
||||
self.ensure_dirname('target')
|
||||
for f in glob.glob('web/*.*'):
|
||||
if f.find('/CVS') >=0 or f.find('~') >= 0:
|
||||
continue
|
||||
self.copy_file(f, self.target)
|
||||
|
||||
setup(name="l10n-tools",
|
||||
version="0.1",
|
||||
version="0.2",
|
||||
author="Axel Hecht",
|
||||
author_email="l10n@mozilla.com",
|
||||
scripts=['scripts/compare-locales', 'scripts/verify-search'],
|
||||
scripts=['scripts/compare-locales', 'scripts/verify-search',
|
||||
'scripts/test-locales'],
|
||||
package_dir={'': 'lib'},
|
||||
packages=['Mozilla']
|
||||
packages=['Mozilla'],
|
||||
cmdclass={'web': web}
|
||||
)
|
||||
|
309
testing/tests/l10n/web/code-base.js
Executable file
309
testing/tests/l10n/web/code-base.js
Executable file
@ -0,0 +1,309 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2006
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Axel Hecht <axel@pike.org>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
var controller = {}, view = {};
|
||||
|
||||
const kModules = ['browser','mail','toolkit'];
|
||||
const Tier1 = ['en-GB', 'fr', 'de', 'ja', 'ja-JP-mac', 'pl', 'es-ES'];
|
||||
const Tier2 = ['zh-CN', 'zh-TW', 'cs', 'da', 'nl', 'fi', 'hu', 'it', 'ko', 'pt-BR', 'pt-PT', 'ru', 'es-AR', 'sv-SE', 'tr'];
|
||||
|
||||
tierMap = {};
|
||||
for each (var loc in Tier1) tierMap[loc] = 'Tier-1';
|
||||
for each (var loc in Tier2) tierMap[loc] = 'Tier-2';
|
||||
|
||||
|
||||
function keys(obj) {
|
||||
var k = [];
|
||||
for (var f in obj) k.push(f);
|
||||
k.sort();
|
||||
return k;
|
||||
}
|
||||
|
||||
function JSON_c() {
|
||||
this._requests = [];
|
||||
this._getRequest = function() {
|
||||
for each (var req in this._requests) {
|
||||
if (!req.status)
|
||||
return req;
|
||||
}
|
||||
req = new XMLHttpRequest();
|
||||
this._requests.push(req);
|
||||
return req;
|
||||
};
|
||||
};
|
||||
JSON_c.prototype = {
|
||||
get : function(aURL, aCallback) {
|
||||
var _t = this;
|
||||
var req = this._getRequest();
|
||||
req.overrideMimeType("text/plain"); // don't parse XML, this is js
|
||||
req.onerror = function(event) {
|
||||
_t.handleFailure(event.target);
|
||||
event.stopPropagation();
|
||||
};
|
||||
req.onload = function(event) {
|
||||
_t.handleSuccess(event.target);
|
||||
event.stopPropagation();
|
||||
};
|
||||
if (aCallback) {
|
||||
req.callback = aCallback;
|
||||
}
|
||||
req.open("GET", aURL, true);
|
||||
try {
|
||||
req.send(null);
|
||||
} catch (e) {
|
||||
// work around send sending errors, but not the callback
|
||||
controller.handleFailure(req);
|
||||
}
|
||||
return req;
|
||||
},
|
||||
// callbacks
|
||||
handleSuccess : function(o) {
|
||||
if (o.responseText === undefined)
|
||||
throw "expected response text in handleSuccess";
|
||||
if (o.callback) {
|
||||
var obj = eval('('+o.responseText+')');
|
||||
o.callback(obj);
|
||||
delete o.callback;
|
||||
}
|
||||
},
|
||||
handleFailure : function(o) {
|
||||
if (o.callback) {
|
||||
o.callback.handleFailure();
|
||||
delete o.callback;
|
||||
return;
|
||||
}
|
||||
throw("load failed with " + o.status + " " + o.statusText);
|
||||
}
|
||||
};
|
||||
var JSON = new JSON_c();
|
||||
|
||||
|
||||
baseView = {
|
||||
init: function() {
|
||||
this.content = document.getElementById('content');
|
||||
var checks = document.getElementById('checks');
|
||||
checks.addEventListener("click", view.onClickDisplay, true);
|
||||
for (var i = 0; i < checks.childNodes.length; i++) {
|
||||
if (checks.childNodes[i] instanceof HTMLInputElement) {
|
||||
this.setTierDisplay(checks.childNodes[i]);
|
||||
}
|
||||
}
|
||||
},
|
||||
showHeader: function() {
|
||||
document.getElementById('head').innerHTML='<td class="locale">Locale</td>';
|
||||
},
|
||||
updateView: function(aLocales, aClosure) {
|
||||
YAHOO.widget.Logger.log('updateView called');
|
||||
this.showHeader();
|
||||
var oldIndex = 0;
|
||||
var selection = null;
|
||||
for each (loc in aLocales) {
|
||||
var id = "row-" + loc;
|
||||
var oldChild = this.content.childNodes[oldIndex++];
|
||||
var t;
|
||||
if (oldChild) {
|
||||
t = oldChild;
|
||||
t.innerHTML = '';
|
||||
if (t.id != id) {
|
||||
// we don't have the right row, make sure to remove the ID
|
||||
// from the pre-existing one, just in case
|
||||
var obsRow = document.getElementById(id);
|
||||
if (obsRow) {
|
||||
obsRow.id = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
t = document.createElement("tr");
|
||||
this.content.appendChild(t);
|
||||
}
|
||||
t.id = id;
|
||||
t.className = '';
|
||||
if (tierMap[loc])
|
||||
t.className += ' ' + tierMap[loc];
|
||||
else
|
||||
t.className += ' Tier-3';
|
||||
t.innerHTML = '<td class="locale">' + loc + '</td>';
|
||||
t.appendChild(controller.getContent(loc));
|
||||
};
|
||||
while ((oldChild = this.content.childNodes[oldIndex])) {
|
||||
this.content.removeChild(oldChild);
|
||||
}
|
||||
},
|
||||
addTab: function(aName, aKey) {
|
||||
var tab = document.createElement('li');
|
||||
tab.textContent = aName;
|
||||
tab.id = '_tab_' + aKey;
|
||||
document.getElementById('tabs').appendChild(tab);
|
||||
tab.onclick = function(event){return controller.select(aKey);};
|
||||
},
|
||||
selectTab: function(aKey) {
|
||||
var tabs = document.getElementById('tabs');
|
||||
var id = '_tab_' + aKey;
|
||||
for (var i=0; i < tabs.childNodes.length; i++) {
|
||||
var tab = tabs.childNodes[i];
|
||||
var toBeSelected = tab.id == id;
|
||||
if (toBeSelected) {
|
||||
tab.setAttribute('selected','selected');
|
||||
}
|
||||
else {
|
||||
tab.removeAttribute('selected');
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
onClickDisplay: function(event) {
|
||||
if (event.target.localName != 'INPUT') {
|
||||
return false;
|
||||
}
|
||||
var handler = function() {return function(){view.setTierDisplay(event.target)}};
|
||||
window.setTimeout(handler(),10);
|
||||
return true;
|
||||
},
|
||||
setTierDisplay: function(aTier, aTruth) {
|
||||
if (aTruth === undefined && aTier instanceof HTMLInputElement) {
|
||||
aTruth = aTier.checked;
|
||||
}
|
||||
var disable = aTruth;
|
||||
var name = aTier;
|
||||
if (aTier instanceof HTMLInputElement) {
|
||||
name = aTier.name;
|
||||
}
|
||||
var id = 'style-' + name;
|
||||
document.getElementById(id).disabled = disable;
|
||||
return false;
|
||||
},
|
||||
setTag: function(aTag) {
|
||||
document.getElementById('tag-view').value = aTag;
|
||||
},
|
||||
getCell: function() {
|
||||
return document.createElement('td');
|
||||
},
|
||||
getClass: function(aLoc) {
|
||||
if (tierMap[aLoc]) {
|
||||
return tierMap[aLoc];
|
||||
}
|
||||
return 'Tier-3';
|
||||
}
|
||||
};
|
||||
|
||||
baseController = {
|
||||
_l: [],
|
||||
_c: null,
|
||||
_pending: [],
|
||||
_target: null,
|
||||
_tag: '.',
|
||||
beforeUnSelect: function(){},
|
||||
beforeSelect: function(){},
|
||||
get locales() {
|
||||
return this._l;
|
||||
},
|
||||
get tag() {
|
||||
return baseController._tag;
|
||||
},
|
||||
set tag(aTag) {
|
||||
baseController._tag = aTag;
|
||||
view.setTag(aTag);
|
||||
},
|
||||
addLocales: function(lst) {
|
||||
var nl = lst.filter(function(el,i,a) {return this._l.indexOf(el) < 0;}, this);
|
||||
this._l = this._l.concat(nl);
|
||||
this._l.sort();
|
||||
},
|
||||
select: function(aKey) {
|
||||
if (this._target == aKey) {
|
||||
return;
|
||||
}
|
||||
if (this._target)
|
||||
this._c[this._target].controller.beforeUnSelect();
|
||||
this._target = aKey;
|
||||
var nCV = this._c[this._target];
|
||||
view = nCV.view;
|
||||
controller = nCV.controller;
|
||||
controller.beforeSelect();
|
||||
controller._target = aKey;
|
||||
view.selectTab(aKey);
|
||||
this.delay(controller, controller.showView, []);
|
||||
},
|
||||
showView: function(aClosure) {
|
||||
view.updateView(controller.locales, aClosure);
|
||||
},
|
||||
getContent: function(aLoc) {
|
||||
if (! this._target) return;
|
||||
return this._c[this._target].getContent(aLoc);
|
||||
},
|
||||
addPane: function(aName, aKey, aController, aView) {
|
||||
if (! this._c) {
|
||||
this._pending.push([aName, aKey, aController, aView]);
|
||||
return;
|
||||
}
|
||||
view.addTab(aName, aKey);
|
||||
this._c[aKey] = {controller: aController, view: aView};
|
||||
},
|
||||
loaded: function() {
|
||||
this._c = {};
|
||||
for each (var c in this._pending) {
|
||||
this.addPane.apply(this, c);
|
||||
}
|
||||
this.select(this._pending[0][1]);
|
||||
delete this._pending;
|
||||
},
|
||||
delay: function(context, f, args) {
|
||||
window.setTimeout(function(){f.apply(context,args);}, 10);
|
||||
}
|
||||
};
|
||||
|
||||
var outlineController = {
|
||||
__proto__: baseController,
|
||||
getHeader: function() {
|
||||
var h = document.createElement('th');
|
||||
h.textContent = 'Details';
|
||||
return h;
|
||||
},
|
||||
getContent: function(aLoc) {
|
||||
var cell = view.getCell();
|
||||
cell.innerHTML = 'Details for ' + aLoc;
|
||||
return cell;
|
||||
}
|
||||
};
|
||||
var outlineView = {
|
||||
__proto__: baseView
|
||||
};
|
||||
//baseController.addPane('Outline', 'outline', outlineController, outlineView);
|
||||
|
||||
view = baseView;
|
||||
controller = baseController;
|
@ -1,344 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2006
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Axel Hecht <axel@pike.org>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
var controller, view;
|
||||
|
||||
const kModules = ['browser','mail','toolkit'];
|
||||
const Tier1 = ['en-GB', 'fr', 'de', 'ja', 'ja-JP-mac', 'pl', 'es-ES'];
|
||||
const Tier2 = ['zh-CN', 'zh-TW', 'cs', 'da', 'nl', 'fi', 'hu', 'it', 'ko', 'pt-BR', 'pt-PT', 'ru', 'es-AR', 'sv-SE', 'tr'];
|
||||
tierMap = {};
|
||||
for each (var loc in Tier1) tierMap[loc] = 'Tier-1';
|
||||
for each (var loc in Tier2) tierMap[loc] = 'Tier-2';
|
||||
|
||||
var calHelper = {
|
||||
formatDate : function(aDate) {
|
||||
function format(aNum) {
|
||||
if (aNum < 10)
|
||||
return '0' + aNum;
|
||||
return String(aNum);
|
||||
}
|
||||
return aDate.getUTCFullYear() + '-'
|
||||
+ format(aDate.getUTCMonth() + 1) + '-'
|
||||
+ format(aDate.getUTCDate());
|
||||
}
|
||||
};
|
||||
|
||||
function Observer(aLoc, aNode, aDate) {
|
||||
this._loc = aLoc;
|
||||
this._node = aNode;
|
||||
this._date = aDate;
|
||||
}
|
||||
Observer.prototype = {
|
||||
handleSuccess: function(aData) {
|
||||
r = eval('('+aData+')');
|
||||
view.createFullTree(r, this._node, "missing");
|
||||
view.createFullTree(r, this._node, "obsolete");
|
||||
delete this._node.__do_load;
|
||||
this._node.tree.removeNode(this._node.children[0]);
|
||||
this._node.refresh();
|
||||
},
|
||||
handleFailure: function() {
|
||||
throw "couldn't load details";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
view = {
|
||||
setupResults: function(responseText) {
|
||||
res = eval('(' + responseText + ')');
|
||||
this._locales = [];
|
||||
for (var loc in res) {
|
||||
this._locales.push(loc);
|
||||
}
|
||||
this._locales.sort();
|
||||
this._results = res;
|
||||
},
|
||||
updateDateView: function(aDate) {
|
||||
if (!aDate)
|
||||
throw "Date expected in view.updateDateView";
|
||||
this._gView = document.getElementById("view");
|
||||
document.getElementById('currentDate').textContent = aDate;
|
||||
var oldIndex = 0;
|
||||
for each (loc in this._locales) {
|
||||
var r = this._results[loc];
|
||||
var id = "tree-" + loc;
|
||||
var oldChild = this._gView.childNodes[oldIndex++];
|
||||
var t;
|
||||
if (oldChild) {
|
||||
t = oldChild;
|
||||
t.innerHTML = '';
|
||||
if (t.id != id) {
|
||||
// we don't have the right div, make sure to remove the ID
|
||||
// from the pre-existing one, just in case
|
||||
var obsDiv = document.getElementById(id);
|
||||
if (obsDiv) {
|
||||
obsDiv.id = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
t = document.createElement("div");
|
||||
}
|
||||
t.id = id;
|
||||
var hasDetails = true;
|
||||
if (r.missing.total + r.missingFiles.total) {
|
||||
t.className = "has_missing";
|
||||
}
|
||||
else if (r.obsolete.total + r.obsoleteFiles.total) {
|
||||
t.className = "has_obsolete";
|
||||
}
|
||||
else {
|
||||
t.className = "is_good";
|
||||
hasDetails = false;
|
||||
}
|
||||
if (tierMap[loc])
|
||||
t.className += ' ' + tierMap[loc];
|
||||
else
|
||||
t.className += ' Tier-3';
|
||||
if (!oldChild) {
|
||||
this._gView.appendChild(t);
|
||||
}
|
||||
t = new YAHOO.widget.TreeView("tree-" + loc);
|
||||
var closure = function() {
|
||||
var _loc = loc;
|
||||
var _d = aDate;
|
||||
return function(node) {
|
||||
if (!node.__do_load)
|
||||
return true;
|
||||
var callback = new Observer(_loc, node, _d);
|
||||
controller.getDetails(callback._date, callback._loc, callback);
|
||||
delete callback;
|
||||
return true;
|
||||
};
|
||||
}
|
||||
if (hasDetails) {
|
||||
t.onExpand = closure();
|
||||
}
|
||||
var row = {
|
||||
_c : '',
|
||||
pushCell: function(content, class) {
|
||||
this._c += '<td';
|
||||
if (content == 0)
|
||||
class += ' zero'
|
||||
if (class)
|
||||
this._c += ' class="' + class + '"';
|
||||
this._c += '>' + content + '</td>';
|
||||
},
|
||||
get content() {return '<table class="locale-row"><tr>' +
|
||||
this._c + '</tr></table>';}
|
||||
};
|
||||
row.pushCell(loc, "locale");
|
||||
var res = r;
|
||||
for each (app in kModules) {
|
||||
var class;
|
||||
if (res.tested.indexOf(app) < 0) {
|
||||
class = 'void';
|
||||
}
|
||||
else if (res.missing[app] + res.missingFiles[app]) {
|
||||
class = 'missing';
|
||||
}
|
||||
else if (res.obsolete[app] + res.obsoleteFiles[app]) {
|
||||
class = 'obsolete';
|
||||
}
|
||||
else {
|
||||
class = "good";
|
||||
}
|
||||
row.pushCell(app, 'app-res ' + class);
|
||||
}
|
||||
|
||||
row.pushCell(r.missingFiles.total, "missing count");
|
||||
row.pushCell(r.missing.total, "missing count");
|
||||
row.pushCell(r.obsoleteFiles.total, "obsolete count");
|
||||
row.pushCell(r.obsolete.total, "obsolete count");
|
||||
row.pushCell(r.unchanged +r.changed, "good count");
|
||||
var tld = new YAHOO.widget.HTMLNode(row.content, t.getRoot(), false, hasDetails);
|
||||
if (hasDetails) {
|
||||
tld.__cl_locale = loc;
|
||||
tld.__cl_date = aDate;
|
||||
tld.__do_load = true;
|
||||
tmp = new YAHOO.widget.HTMLNode("<span class='ygtvloading'> </span> loading…", tld, true, true);
|
||||
}
|
||||
t.draw();
|
||||
var rowToggle = function(e){
|
||||
this.toggle()
|
||||
};
|
||||
YAHOO.util.Event.addListener(tld.getContentEl(), "click", rowToggle, tld, true);
|
||||
};
|
||||
while ((oldChild = this._gView.childNodes[oldIndex])) {
|
||||
this._gView.removeChild(oldChild);
|
||||
}
|
||||
},
|
||||
onClickDisplay: function(event) {
|
||||
YAHOO.util.Event.stopEvent(event);
|
||||
if (event.target.localName != 'INPUT') {
|
||||
return false;
|
||||
}
|
||||
var handler = function() {return function(){view.onCDReal(event.target)}};
|
||||
window.setTimeout(handler(),0);
|
||||
return false;
|
||||
},
|
||||
onCDReal: function(target) {
|
||||
var dsp = !target.checked;
|
||||
target.checked = dsp;
|
||||
dsp = dsp ? 'block' : 'none';
|
||||
var layout = document.styleSheets[2];
|
||||
layout.insertRule('div.' + target.name + ' {display: ' + dsp + ';}',
|
||||
layout.cssRules.length);
|
||||
return false;
|
||||
},
|
||||
// Helper methods
|
||||
createFullTree: function ct(aDetails, aNode, aName) {
|
||||
if (!aDetails || ! (aDetails instanceof Object))
|
||||
return;
|
||||
var cat = new YAHOO.widget.TextNode(aName, aNode, true);
|
||||
for each (postfix in ["Files", ""]) {
|
||||
var subRes = aDetails[aName + postfix];
|
||||
var append = postfix ? ' (files)' : '';
|
||||
for (mod in subRes) {
|
||||
var mn = new YAHOO.widget.TextNode(mod + append, cat, true);
|
||||
for (fl in subRes[mod]) {
|
||||
if (postfix) {
|
||||
new YAHOO.widget.TextNode(subRes[mod][fl], mn, false);
|
||||
continue;
|
||||
}
|
||||
var fn = new YAHOO.widget.TextNode(fl, mn, false);
|
||||
var keys = [];
|
||||
for each (k in subRes[mod][fl]) {
|
||||
keys.push(k);
|
||||
}
|
||||
new YAHOO.widget.HTMLNode("<pre>" + keys.join("\n") + "</pre>", fn, true, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
return cat;
|
||||
}
|
||||
};
|
||||
|
||||
controller = {
|
||||
_requests : [],
|
||||
getDataForCal : function() {
|
||||
var d = cal.getSelectedDates()[0];
|
||||
d.setHours(12);
|
||||
d = new Date(d.valueOf() - d.getTimezoneOffset() * 60000)
|
||||
var callback = {
|
||||
_date: calHelper.formatDate(d),
|
||||
handleSuccess: function(aData) {
|
||||
view.setupResults(aData);
|
||||
view.updateDateView(this._date);
|
||||
},
|
||||
handleFailure: function() {
|
||||
throw "couldn't load something";
|
||||
}
|
||||
};
|
||||
this.getData(callback._date, callback);
|
||||
},
|
||||
kPrefix: 'results/',
|
||||
getData : function _gda(aDate, aCallback) {
|
||||
return this._getInternal(aDate, 'data-', null, aCallback);
|
||||
},
|
||||
getDetails : function _gde(aDate, aLocale, aCallback) {
|
||||
return this._getInternal(aDate, 'details-', aLocale, aCallback);
|
||||
},
|
||||
_getInternal : function _gi(aDate, aName, aPostfix, aCallback) {
|
||||
var url = this.kPrefix + aName + aDate;
|
||||
if (aPostfix)
|
||||
url += '-' + aPostfix;
|
||||
url += '.js';
|
||||
var req = this._getRequest();
|
||||
req.overrideMimeType("text/plain"); // don't parse XML, this is js
|
||||
req.onerror = function(event) {controller.handleFailure(event.target);event.stopPropagation();};
|
||||
req.onload = function(event) {controller.handleSuccess(event.target);event.stopPropagation();};
|
||||
if (aCallback) {
|
||||
req.callback = aCallback;
|
||||
}
|
||||
req.open("GET", url, true);
|
||||
try {
|
||||
req.send(null);
|
||||
} catch (e) {
|
||||
// work around send sending errors, but not the callback
|
||||
controller.handleFailure(req);
|
||||
}
|
||||
return true;
|
||||
},
|
||||
_getRequest : function() {
|
||||
for each (var req in this._requests) {
|
||||
if (!req.status)
|
||||
return req;
|
||||
}
|
||||
req = new XMLHttpRequest();
|
||||
this._requests.push(req);
|
||||
return req;
|
||||
},
|
||||
// Ajax interface
|
||||
handleSuccess : function(o) {
|
||||
if (o.responseText === undefined)
|
||||
throw "expected response text in handleSuccess";
|
||||
if (o.callback) {
|
||||
o.callback.handleSuccess(o.responseText);
|
||||
delete o.callback;
|
||||
}
|
||||
},
|
||||
handleFailure : function(o) {
|
||||
if (o.callback) {
|
||||
o.callback.handleFailure();
|
||||
delete o.callback;
|
||||
return;
|
||||
}
|
||||
throw("load failed with " + o.status + " " + o.statusText);
|
||||
}
|
||||
}
|
||||
|
||||
var cal;
|
||||
function onLoad(event) {
|
||||
document.removeEventListener("load", onLoad, true);
|
||||
document.getElementById("checks").addEventListener("click", view.onClickDisplay, true);
|
||||
cal = new YAHOO.widget.Calendar('cal', 'calDiv');
|
||||
cal.minDate = new Date(2006, 5, 1);
|
||||
// cal.maxDate = new Date();
|
||||
cal.render();
|
||||
cal.onSelect = function() {controller.getDataForCal();};
|
||||
|
||||
var n = new Date();
|
||||
if (n.getUTCHours() < 12 && n.getUTCDate() == n.getDate()) {
|
||||
// do yesterday, we didn't check out today yet
|
||||
n = new Date(n - YAHOO.widget.DateMath.ONE_DAY_MS);
|
||||
}
|
||||
n = new Date(n.getFullYear(), n.getMonth(), n.getDate());
|
||||
cal.select(n);
|
||||
|
||||
return true;
|
||||
}
|
196
testing/tests/l10n/web/comparison-code.js
Executable file
196
testing/tests/l10n/web/comparison-code.js
Executable file
@ -0,0 +1,196 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2006
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Axel Hecht <axel@pike.org>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
||||
var comparisonView = {
|
||||
__proto__: baseView,
|
||||
setUpHandlers: function() {
|
||||
_t = this;
|
||||
//this.omv = function(event){_t.onMouseOver.apply(_t, [event]);};
|
||||
//this.omo = function(event){_t.onMouseOut.apply(_t, [event]);};
|
||||
//this.content.addEventListener("mouseover", this.omv, true);
|
||||
//this.content.addEventListener("mouseout", this.omv, true);
|
||||
},
|
||||
destroyHandlers: function() {
|
||||
//this.content.removeEventListener("mouseover", this.omv, true);
|
||||
//this.content.removeEventListener("mouseout", this.omv, true);
|
||||
},
|
||||
// Helper methods
|
||||
createFullTree: function ct(aDetails, aNode, aName) {
|
||||
if (!aDetails || ! (aDetails instanceof Object))
|
||||
return;
|
||||
var cat = new YAHOO.widget.TextNode(aName, aNode, true);
|
||||
for each (postfix in ["Files", ""]) {
|
||||
var subRes = aDetails[aName + postfix];
|
||||
var append = postfix ? ' (files)' : '';
|
||||
for (mod in subRes) {
|
||||
var mn = new YAHOO.widget.TextNode(mod + append, cat, true);
|
||||
for (fl in subRes[mod]) {
|
||||
if (postfix) {
|
||||
new YAHOO.widget.TextNode(subRes[mod][fl], mn, false);
|
||||
continue;
|
||||
}
|
||||
var fn = new YAHOO.widget.TextNode(fl, mn, false);
|
||||
var keys = [];
|
||||
for each (k in subRes[mod][fl]) {
|
||||
keys.push(k);
|
||||
}
|
||||
new YAHOO.widget.HTMLNode("<pre>" + keys.join("\n") + "</pre>", fn, true, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
return cat;
|
||||
}
|
||||
};
|
||||
var comparisonController = {
|
||||
__proto__: baseController,
|
||||
beforeSelect: function() {
|
||||
this.result = {};
|
||||
this.isShown = false;
|
||||
comparisonView.setUpHandlers();
|
||||
var _t = this;
|
||||
var callback = function(obj) {
|
||||
delete _t.req;
|
||||
if (view != comparisonView) {
|
||||
// ignore, we have switched again
|
||||
return;
|
||||
}
|
||||
_t.result = obj;
|
||||
comparisonView.updateView(keys(_t.result));
|
||||
};
|
||||
this.req = JSON.get('results/' + this.tag + '/cmp-data.json', callback);
|
||||
},
|
||||
beforeUnSelect: function() {
|
||||
if (this.req) {
|
||||
this.req.abort();
|
||||
delete this.req;
|
||||
}
|
||||
comparisonView.destroyHandlers();
|
||||
},
|
||||
showView: function(aClosure) {
|
||||
// json onload handler does this;
|
||||
},
|
||||
getContent: function(aLoc) {
|
||||
var row = view.getCell();
|
||||
var inner = document.createElement('div');
|
||||
row.appendChild(inner);
|
||||
var r = this.result[aLoc];
|
||||
var id = "tree-" + aLoc;
|
||||
inner.id = id;
|
||||
var hasDetails = true;
|
||||
if (r.missing.total + r.missingFiles.total) {
|
||||
inner.className = "has_missing";
|
||||
}
|
||||
else if (r.obsolete.total + r.obsoleteFiles.total) {
|
||||
inner.className = "has_obsolete";
|
||||
}
|
||||
else {
|
||||
inner.className = "is_good";
|
||||
hasDetails = false;
|
||||
}
|
||||
t = new YAHOO.widget.TreeView(inner);
|
||||
var _l = aLoc;
|
||||
var rowCollector = {
|
||||
_c : '',
|
||||
pushCell: function(content, class) {
|
||||
this._c += '<td';
|
||||
if (content == 0)
|
||||
class += ' zero'
|
||||
if (class)
|
||||
this._c += ' class="' + class + '"';
|
||||
this._c += '>' + content + '</td>';
|
||||
},
|
||||
get content() {return '<table class="locale-row"><tr>' +
|
||||
this._c + '</tr></table>';}
|
||||
};
|
||||
for each (app in kModules) {
|
||||
var class;
|
||||
if (r.tested.indexOf(app) < 0) {
|
||||
class = 'void';
|
||||
}
|
||||
else if (r.missing[app] + r.missingFiles[app]) {
|
||||
class = 'missing';
|
||||
}
|
||||
else if (r.obsolete[app] + r.obsoleteFiles[app]) {
|
||||
class = 'obsolete';
|
||||
}
|
||||
else {
|
||||
class = "good";
|
||||
}
|
||||
rowCollector.pushCell(app, 'app-res ' + class);
|
||||
}
|
||||
|
||||
rowCollector.pushCell(r.missingFiles.total, "missing count");
|
||||
rowCollector.pushCell(r.missing.total, "missing count");
|
||||
rowCollector.pushCell(r.obsoleteFiles.total, "obsolete count");
|
||||
rowCollector.pushCell(r.obsolete.total, "obsolete count");
|
||||
rowCollector.pushCell(r.unchanged +r.changed, "good count");
|
||||
var tld = new YAHOO.widget.HTMLNode(rowCollector.content, t.getRoot(), false, hasDetails);
|
||||
if (hasDetails) {
|
||||
tld.__cl_locale = aLoc;
|
||||
tld.__do_load = true;
|
||||
tmp = new YAHOO.widget.HTMLNode("<span class='ygtvloading'> </span> loading…", tld, true, true);
|
||||
var l = aLoc;
|
||||
var _c = this;
|
||||
var expander = function(node) {
|
||||
if (!node.__do_load)
|
||||
return true;
|
||||
var callback = function(aRes) {
|
||||
comparisonView.createFullTree(aRes, node, 'missing');
|
||||
comparisonView.createFullTree(aRes, node, 'obsolete');
|
||||
delete node.__do_load;
|
||||
node.tree.removeNode(node.children[0]);
|
||||
node.refresh();
|
||||
};
|
||||
JSON.get('results/' + _c.tag + '/cmp-details-'+aLoc+'.json', callback);
|
||||
}
|
||||
t.onExpand = expander;
|
||||
delete expander;
|
||||
}
|
||||
t.draw();
|
||||
var rowToggle = function(){
|
||||
YAHOO.util.Event.addListener(tld.getContentEl(), "click",
|
||||
function(){tld.toggle();}, tld, true);
|
||||
};
|
||||
YAHOO.util.Event.onAvailable(tld.contentElId, rowToggle, tld);
|
||||
//YAHOO.util.Event.addListener(tld.getContentEl(), "click", rowToggle, tld, true);
|
||||
return row;
|
||||
}
|
||||
};
|
||||
controller.addPane('Compare', 'comparison', comparisonController,
|
||||
comparisonView);
|
||||
//controller.addLocales(keys(results.locales));
|
@ -39,35 +39,54 @@
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Locales status</title>
|
||||
<link rel="stylesheet" type="text/css" href="yui/examples/treeview/css/local/tree.css">
|
||||
<link rel="stylesheet" type="text/css" href="yui/build/calendar/assets/calendar.css">
|
||||
<link rel="stylesheet" type="text/css" href="layout.css">
|
||||
<script type="text/javascript" src="yui/build/yahoo/yahoo.js"></script>
|
||||
<script type="text/javascript" src="yui/build/dom/dom.js"></script>
|
||||
<script type="text/javascript" src="yui/build/event/event.js"></script>
|
||||
<script type="text/javascript" src="yui/build/treeview/treeview.js"></script>
|
||||
<script type="text/javascript" src="yui/build/calendar/calendar.js"></script>
|
||||
<script type="application/javascript" src="code.js"></script>
|
||||
<title>1.8.1 Locales status</title>
|
||||
<style type="text/css" id="style-Tier-1">
|
||||
.Tier-1 {display: none}
|
||||
</style>
|
||||
<style type="text/css" id="style-Tier-2">
|
||||
.Tier-2 {display: none}
|
||||
</style>
|
||||
<style type="text/css" id="style-Tier-3">
|
||||
.Tier-3 {display: none}
|
||||
</style>
|
||||
<style type="text/css">
|
||||
div {min-height: 5px;}
|
||||
</style>
|
||||
<link rel="stylesheet" type="text/css" href="yui/examples/treeview/css/local/tree.css">
|
||||
<link rel="stylesheet" type="text/css" href="yui/build/container/assets/container.css">
|
||||
<link rel="stylesheet" type="text/css" href="layout.css">
|
||||
<script type="text/javascript" src="yui/build/yahoo/yahoo.js"></script>
|
||||
<script type="text/javascript" src="yui/build/dom/dom.js"></script>
|
||||
<script type="text/javascript" src="yui/build/event/event.js"></script>
|
||||
<script type="text/javascript" src="yui/build/logger/logger.js"></script>
|
||||
<script type="text/javascript" src="yui/build/treeview/treeview.js"></script>
|
||||
<script type="text/javascript" src="yui/build/calendar/calendar.js"></script>
|
||||
<script type="text/javascript" src="yui/build/dragdrop/dragdrop.js"></script>
|
||||
<script type="text/javascript" src="yui/build/container/container.js"></script>
|
||||
<script type="text/javascript" src="code-base.js"></script>
|
||||
<script type="text/javascript" src="waterfall-code.js"></script>
|
||||
<script type="text/javascript" src="search-code.js"></script>
|
||||
<script type="text/javascript" src="comparison-code.js"></script>
|
||||
</head>
|
||||
<body onload="return onLoad(event)">
|
||||
<h1>Locales overview</h1>
|
||||
<p><strong>Legend:</strong> For each locale, this chart shows locale name, an indication of status for browser, mail, toolkit, and then, more importantly, number of missing files, missing entities, obsolete files and entities, and good entities, in red, orange and green, resp. You can click on the summary row to get (and hide) all the details for a particular locale.</p>
|
||||
<div id="calContainer"><div id="currentDate">date</div><div id="calDiv"></div>
|
||||
<p id="checks">
|
||||
<input type="checkbox" name="Tier-1" checked> Tier 1<br>
|
||||
<input type="checkbox" name="Tier-2" checked> Tier 2<br>
|
||||
<input type="checkbox" name="Tier-3" checked> Tier 3<br>
|
||||
</p>
|
||||
</div>
|
||||
<table><tr><td class="ygtvlph" style="background-image: none;"> </td><td class="locale"> </td>
|
||||
<td class="app-res"> </td><td class="app-res"> </td>
|
||||
<td class="app-res"> </td>
|
||||
<td class="count missing" title="missing Files">m.F.</td>
|
||||
<td class="count missing" title="missing Entities">m.E.</td>
|
||||
<td class="count obsolete" title="obsolete Files">o.F.</td>
|
||||
<td class="count obsolete" title="obsolete Entities">o.E.</td>
|
||||
<td class="count good" title="unchanged or localized Entities">good</td></tr></table>
|
||||
<div id="view"></div>
|
||||
<body onload="">
|
||||
<div id="sidebar">
|
||||
<p id="checks">Showing Tier 1
|
||||
<input type="checkbox" name="Tier-1" checked>
|
||||
2 <input type="checkbox" name="Tier-2" checked>
|
||||
3 <input type="checkbox" name="Tier-3" checked> for
|
||||
</p>
|
||||
<input type="text" id="tag-view" size="30">
|
||||
</div>
|
||||
<h1>Locale Tests</h1>
|
||||
<div id="menu">
|
||||
<ul id="tabs"></ul>
|
||||
</div>
|
||||
<table id="main">
|
||||
<thead>
|
||||
<tr id="head"></tr>
|
||||
</thead>
|
||||
<tbody id="content"></tbody>
|
||||
</table>
|
||||
<script type="text/javascript" src="post.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -35,29 +35,60 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#sidebar {
|
||||
float: right;
|
||||
margin-top: -8px;
|
||||
}
|
||||
|
||||
#menu li[selected] {
|
||||
background-color: lightgrey;
|
||||
border-style: inset inset none inset;
|
||||
}
|
||||
#menu li {
|
||||
display: block;
|
||||
float: left;
|
||||
font-weight: bold;
|
||||
padding: .5em;
|
||||
margin-left:1px;
|
||||
margin-right:1px;
|
||||
border-style: outset outset none outset;
|
||||
-moz-border-radius-topleft: 15px;
|
||||
-moz-border-radius-topright: 15px;
|
||||
}
|
||||
|
||||
#main {
|
||||
clear: left;
|
||||
}
|
||||
body {
|
||||
overflow: scroll;
|
||||
}
|
||||
#content {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
div.is_good {
|
||||
padding-left: 16px;
|
||||
}
|
||||
|
||||
td.missing {
|
||||
.missing, .busted {
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
td.obsolete {
|
||||
.obsolete, .fair {
|
||||
background-color: orange;
|
||||
}
|
||||
|
||||
td.zero {
|
||||
.zero {
|
||||
opacity: .3;
|
||||
background-color: green !important;
|
||||
}
|
||||
|
||||
|
||||
td.good {
|
||||
.good {
|
||||
background-color: limegreen;
|
||||
}
|
||||
|
||||
td.void {
|
||||
.void {
|
||||
color: grey;
|
||||
background-color: lightgrey;
|
||||
}
|
||||
@ -79,10 +110,6 @@ td.count {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
div#calContainer {
|
||||
float: right;
|
||||
margin-top: -8px;
|
||||
}
|
||||
div.calbordered {
|
||||
float: none;
|
||||
}
|
||||
|
40
testing/tests/l10n/web/post.js
Executable file
40
testing/tests/l10n/web/post.js
Executable file
@ -0,0 +1,40 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2006
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Axel Hecht <axel@pike.org>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
view.init();
|
||||
controller.addLocales(keys(tierMap));
|
||||
controller.loaded();
|
@ -35,106 +35,105 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
var controller, view;
|
||||
|
||||
const Tier1 = ['en-GB', 'fr', 'de', 'ja', 'ja-JP-mac', 'pl', 'es-ES'];
|
||||
const Tier2 = ['zh-CN', 'zh-TW', 'cs', 'da', 'nl', 'fi', 'hu', 'it', 'ko', 'pt-BR', 'pt-PT', 'ru', 'es-AR', 'sv-SE', 'tr'];
|
||||
tierMap = {};
|
||||
var loc;
|
||||
for each (loc in Tier1) tierMap[loc] = 'Tier-1';
|
||||
for each (loc in Tier2) tierMap[loc] = 'Tier-2';
|
||||
|
||||
var view;
|
||||
view = {
|
||||
hashes: {},
|
||||
updateView: function() {
|
||||
this._gView = document.getElementById("view");
|
||||
var cmp = function(l,r) {
|
||||
var lName = results.details[l].ShortName;
|
||||
var rName = results.details[r].ShortName;
|
||||
if (lName) lName = lName.toLowerCase();
|
||||
if (rName) rName = rName.toLowerCase();
|
||||
return lName < rName ? -1 : lName > rName ? 1 : 0;
|
||||
}
|
||||
for (loc in results.locales) {
|
||||
var row = document.createElement("tr");
|
||||
if (tierMap[loc])
|
||||
row.className += ' ' + tierMap[loc];
|
||||
else
|
||||
row.className += ' Tier-3';
|
||||
this._gView.appendChild(row);
|
||||
var lst = results.locales[loc].list;
|
||||
lst.sort(cmp);
|
||||
var orders = results.locales[loc].orders;
|
||||
if (orders) {
|
||||
var explicit = [];
|
||||
var implicit = [];
|
||||
for (var sn in orders) {
|
||||
if (explicit[sn]) {
|
||||
fatal = true;
|
||||
break;
|
||||
}
|
||||
explicit[sn] = orders[sn];
|
||||
}
|
||||
explicit = [];
|
||||
for each (var path in lst) {
|
||||
var shortName = results.details[path].ShortName;
|
||||
if (orders[shortName]) {
|
||||
explicit[orders[shortName] - 1] = path;
|
||||
}
|
||||
else {
|
||||
implicit.push(path);
|
||||
}
|
||||
}
|
||||
lst = explicit.concat(implicit);
|
||||
var searchController = {
|
||||
__proto__: baseController,
|
||||
beforeSelect: function() {
|
||||
this.hashes = {};
|
||||
searchView.setUpHandlers();
|
||||
var _t = this;
|
||||
var callback = function(obj) {
|
||||
delete _t.req;
|
||||
if (view != searchView) {
|
||||
// ignore, we have switched again
|
||||
return;
|
||||
}
|
||||
row.innerHTML = '<td class="locale"><a href="https://bugzilla.mozilla.org/buglist.cgi?query_format=advanced&short_desc_type=regexp&short_desc=' + loc + '%5B%20-%5D&chfieldto=Now&field0-0-0=blocked&type0-0-0=substring&value0-0-0=347914">' + loc + '</a></td>';
|
||||
for each (var path in lst) {
|
||||
//YAHOO.widget.Logger.log('testing ' + path);
|
||||
var innerContent;
|
||||
var cl = '';
|
||||
if (path.match(/^mozilla/)) {
|
||||
cl += ' enUS';
|
||||
_t.result = obj;
|
||||
searchView.updateView(keys(_t.result.locales));
|
||||
};
|
||||
this.req = JSON.get('results/' + this.tag + '/search-results.json',
|
||||
callback);
|
||||
},
|
||||
beforeUnSelect: function() {
|
||||
searchView.destroyHandlers();
|
||||
},
|
||||
showView: function(aClosure) {
|
||||
// json onload handler does this;
|
||||
},
|
||||
getContent: function(aLoc) {
|
||||
var row = document.createDocumentFragment();
|
||||
var lst = this.result.locales[aLoc].list;
|
||||
var _t = this;
|
||||
lst.sort(function(a,b){return _t.cmp.apply(_t,[a,b])});
|
||||
var orders = this.result.locales[aLoc].orders;
|
||||
if (orders) {
|
||||
var explicit = [];
|
||||
var implicit = [];
|
||||
for (var sn in orders) {
|
||||
if (explicit[sn]) {
|
||||
fatal = true;
|
||||
break;
|
||||
}
|
||||
var localName = path.substr(path.lastIndexOf('/') + 1)
|
||||
if (results.details[path].error) {
|
||||
innerContent = 'error in ' + localName;
|
||||
cl += ' error';
|
||||
explicit[sn] = orders[sn];
|
||||
}
|
||||
explicit = [];
|
||||
for each (var path in lst) {
|
||||
var shortName = this.result.details[path].ShortName;
|
||||
if (orders[shortName]) {
|
||||
explicit[orders[shortName] - 1] = path;
|
||||
}
|
||||
else {
|
||||
var shortName = results.details[path].ShortName;
|
||||
var img = results.details[path].Image;
|
||||
if (results.locales[loc].orders && results.locales[loc].orders[shortName]) {
|
||||
cl += " ordered";
|
||||
}
|
||||
innerContent = '<img src="' + img + '">' + shortName;
|
||||
implicit.push(path);
|
||||
}
|
||||
var td = document.createElement('td');
|
||||
td.className = 'searchplugin' + cl;
|
||||
td.innerHTML = innerContent;
|
||||
row.appendChild(td);
|
||||
td.details = results.details[path];
|
||||
// test the hash code
|
||||
if (td.details.error) {
|
||||
// ignore errorenous plugins
|
||||
continue;
|
||||
}
|
||||
lst = explicit.concat(implicit);
|
||||
}
|
||||
row.innerHTML = '<td class="locale"><a href="https://bugzilla.mozilla.org/buglist.cgi?query_format=advanced&short_desc_type=regexp&short_desc=' + aLoc + '%5B%20-%5D&chfieldto=Now&field0-0-0=blocked&type0-0-0=substring&value0-0-0=347914">bug</a></td>';
|
||||
for each (var path in lst) {
|
||||
//YAHOO.widget.Logger.log('testing ' + path);
|
||||
var innerContent;
|
||||
var cl = '';
|
||||
if (path.match(/^mozilla/)) {
|
||||
cl += ' enUS';
|
||||
}
|
||||
var localName = path.substr(path.lastIndexOf('/') + 1);
|
||||
if (this.result.details[path].error) {
|
||||
innerContent = 'error in ' + localName;
|
||||
cl += ' error';
|
||||
}
|
||||
else {
|
||||
var shortName = this.result.details[path].ShortName;
|
||||
var img = this.result.details[path].Image;
|
||||
if (this.result.locales[aLoc].orders && this.result.locales[aLoc].orders[shortName]) {
|
||||
cl += " ordered";
|
||||
}
|
||||
if (this.hashes[localName]) {
|
||||
this.hashes[localName].nodes.push(td);
|
||||
if (this.hashes[localName].conflict) {
|
||||
innerContent = '<img src="' + img + '">' + shortName;
|
||||
}
|
||||
var td = document.createElement('td');
|
||||
td.className = 'searchplugin' + cl;
|
||||
td.innerHTML = innerContent;
|
||||
row.appendChild(td);
|
||||
td.details = this.result.details[path];
|
||||
// test the hash code
|
||||
if (td.details.error) {
|
||||
// ignore errorenous plugins
|
||||
continue;
|
||||
}
|
||||
if (this.hashes[localName]) {
|
||||
this.hashes[localName].nodes.push(td);
|
||||
if (this.hashes[localName].conflict) {
|
||||
td.className += ' conflict';
|
||||
}
|
||||
else if (this.hashes[localName].key != td.details.md5) {
|
||||
this.hashes[localName].conflict = true;
|
||||
for each (td in this.hashes[localName].nodes) {
|
||||
td.className += ' conflict';
|
||||
}
|
||||
else if (this.hashes[localName].key != td.details.md5) {
|
||||
this.hashes[localName].conflict = true;
|
||||
for each (td in this.hashes[localName].nodes) {
|
||||
td.className += ' conflict';
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.hashes[localName] = {key: td.details.md5, nodes: [td]};
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.hashes[localName] = {key: td.details.md5, nodes: [td]};
|
||||
}
|
||||
}
|
||||
for (localName in this.hashes) {
|
||||
if ( ! ('conflict' in this.hashes[localName])) {
|
||||
@ -146,6 +145,31 @@ view = {
|
||||
}
|
||||
YAHOO.widget.Logger.log('difference in ' + localName + ' for ' + locs.join(', '));
|
||||
}
|
||||
return row;
|
||||
},
|
||||
cmp: function(l,r) {
|
||||
var lName = this.result.details[l].ShortName;
|
||||
var rName = this.result.details[r].ShortName;
|
||||
if (lName) lName = lName.toLowerCase();
|
||||
if (rName) rName = rName.toLowerCase();
|
||||
return lName < rName ? -1 : lName > rName ? 1 : 0;
|
||||
}
|
||||
};
|
||||
var searchView = {
|
||||
__proto__: baseView,
|
||||
setUpHandlers: function() {
|
||||
_t = this;
|
||||
this.omv = function(event){_t.onMouseOver.apply(_t, [event]);};
|
||||
this.omo = function(event){_t.onMouseOut.apply(_t, [event]);};
|
||||
this.content.addEventListener("mouseover", this.omv, true);
|
||||
this.content.addEventListener("mouseout", this.omv, true);
|
||||
},
|
||||
destroyHandlers: function() {
|
||||
this.content.removeEventListener("mouseover", this.omv, true);
|
||||
this.content.removeEventListener("mouseout", this.omv, true);
|
||||
if (this._dv) {
|
||||
this._dv.hide();
|
||||
}
|
||||
},
|
||||
onMouseOver: function(event) {
|
||||
if (!event.target.details)
|
||||
@ -155,30 +179,30 @@ view = {
|
||||
clientX: event.clientX,
|
||||
clientY: event.clientY
|
||||
};
|
||||
view.pending = setTimeout(function(){view.showDetail(_e);}, 500);
|
||||
this.pending = setTimeout(function(){searchView.showDetail(_e);}, 500);
|
||||
},
|
||||
onMouseOut: function(event) {
|
||||
if (view.pending) {
|
||||
clearTimeout(view.pending);
|
||||
delete view.pending;
|
||||
if (this.pending) {
|
||||
clearTimeout(this.pending);
|
||||
delete this.pending;
|
||||
return;
|
||||
}
|
||||
if (!event.target.details)
|
||||
return;
|
||||
},
|
||||
showDetail: function(event) {
|
||||
delete view.pending;
|
||||
if (!view._dv) {
|
||||
view._dv = new YAHOO.widget.Panel('dv', {visible:true,draggable:true,constraintoviewport:true});
|
||||
view._dv.beforeHideEvent.subscribe(function(){delete view._dv;}, null);
|
||||
delete this.pending;
|
||||
if (!this._dv) {
|
||||
this._dv = new YAHOO.widget.Panel('dv', {visible:true,draggable:true,constraintoviewport:true});
|
||||
this._dv.beforeHideEvent.subscribe(function(){delete this._dv;}, null);
|
||||
}
|
||||
var dt = event.details;
|
||||
if (dt.error) {
|
||||
view._dv.setHeader("Error");
|
||||
view._dv.setBody(dt.error);
|
||||
this._dv.setHeader("Error");
|
||||
this._dv.setBody(dt.error);
|
||||
}
|
||||
else {
|
||||
view._dv.setHeader("Details");
|
||||
this._dv.setHeader("Details");
|
||||
var c = '';
|
||||
var q = 'test';
|
||||
var len = 0;
|
||||
@ -193,41 +217,12 @@ view = {
|
||||
c += '<button onclick="window.open(this.textContent)">' + uc + '</button><br>';
|
||||
len = len < c.length ? c.length : len;
|
||||
}
|
||||
view._dv.setBody(c);
|
||||
this._dv.setBody(c);
|
||||
}
|
||||
view._dv.render(document.body);
|
||||
view._dv.moveTo(event.clientX + window.scrollX, event.clientY + window.scrollY);
|
||||
},
|
||||
onClickDisplay: function(event) {
|
||||
if (event.target.localName != 'INPUT') {
|
||||
return false;
|
||||
}
|
||||
YAHOO.widget.Logger.log('clicking ' + event);
|
||||
var handler = function() {return function(){view.onCDReal(event.target)}};
|
||||
window.setTimeout(handler(),0);
|
||||
return false;
|
||||
},
|
||||
onCDReal: function(target) {
|
||||
var dsp = target.checked;
|
||||
target.checked = dsp;
|
||||
dsp = dsp ? 'table-row' : 'none';
|
||||
var layout = document.styleSheets[document.styleSheets.length - 1];
|
||||
var i = Number(target.name);
|
||||
layout.deleteRule(i);
|
||||
layout.insertRule('.Tier-' + (i+1) + ' {display: ' + dsp + ';}', i);
|
||||
return false;
|
||||
this._dv.render(document.body);
|
||||
this._dv.moveTo(event.clientX + window.scrollX, event.clientY + window.scrollY);
|
||||
this._dv.show();
|
||||
}
|
||||
};
|
||||
|
||||
controller = {
|
||||
kPrefix: 'results/',
|
||||
}
|
||||
|
||||
function onLoad(event) {
|
||||
document.removeEventListener("load", onLoad, true);
|
||||
document.getElementById("checks").addEventListener("click", view.onClickDisplay, true);
|
||||
view.updateView();
|
||||
document.getElementById("view").addEventListener("mouseover", view.onMouseOver, true);
|
||||
document.getElementById("view").addEventListener("mouseout", view.onMouseOut, true);
|
||||
return true;
|
||||
}
|
||||
controller.addPane('Search', 'search', searchController, searchView);
|
||||
//controller.addLocales(keys(results.locales));
|
||||
|
@ -1,84 +0,0 @@
|
||||
<!-- ***** BEGIN LICENSE BLOCK *****
|
||||
- Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
-
|
||||
- The contents of this file are subject to the Mozilla Public License Version
|
||||
- 1.1 (the "License"); you may not use this file except in compliance with
|
||||
- the License. You may obtain a copy of the License at
|
||||
- http://www.mozilla.org/MPL/
|
||||
-
|
||||
- Software distributed under the License is distributed on an "AS IS" basis,
|
||||
- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
- for the specific language governing rights and limitations under the
|
||||
- License.
|
||||
-
|
||||
- The Original Code is Mozilla.
|
||||
-
|
||||
- The Initial Developer of the Original Code is
|
||||
- Mozilla Foundation.
|
||||
- Portions created by the Initial Developer are Copyright (C) 2006
|
||||
- the Initial Developer. All Rights Reserved.
|
||||
-
|
||||
- Contributor(s):
|
||||
- Axel Hecht <axel@pike.org>
|
||||
-
|
||||
- Alternatively, the contents of this file may be used under the terms of
|
||||
- either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
- the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
- in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
- of those above. If you wish to allow use of your version of this file only
|
||||
- under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
- use your version of this file under the terms of the MPL, indicate your
|
||||
- decision by deleting the provisions above and replace them with the notice
|
||||
- and other provisions required by the LGPL or the GPL. If you do not delete
|
||||
- the provisions above, a recipient may use your version of this file under
|
||||
- the terms of any one of the MPL, the GPL or the LGPL.
|
||||
-
|
||||
- ***** END LICENSE BLOCK ***** -->
|
||||
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>l10n search engines</title>
|
||||
<link rel="stylesheet" type="text/css" href="yui/examples/treeview/css/local/tree.css">
|
||||
<link rel="stylesheet" type="text/css" href="yui/build/container/assets/container.css">
|
||||
<link rel="stylesheet" type="text/css" href="layout.css">
|
||||
<script type="text/javascript" src="yui/build/yahoo/yahoo.js"></script>
|
||||
<script type="text/javascript" src="yui/build/dom/dom.js"></script>
|
||||
<script type="text/javascript" src="yui/build/event/event.js"></script>
|
||||
<script type="text/javascript" src="yui/build/logger/logger.js"></script>
|
||||
<script type="text/javascript" src="yui/build/treeview/treeview.js"></script>
|
||||
<script type="text/javascript" src="yui/build/dragdrop/dragdrop.js"></script>
|
||||
<script type="text/javascript" src="yui/build/container/container.js"></script>
|
||||
<script type="application/javascript" src="results/search-results.js"></script>
|
||||
<script type="application/javascript" src="search-code.js"></script>
|
||||
<style type="text/css">
|
||||
td.ordered {border: 2px solid black;}
|
||||
td.error {background-color: coral;}
|
||||
td.conflict {background-color: grey;}
|
||||
td.enUS {opacity: .5;}
|
||||
</style>
|
||||
<style type="text/css">
|
||||
.Tier-1 {display: table-row;}
|
||||
.Tier-2 {display: table-row;}
|
||||
.Tier-3 {display: table-row;}
|
||||
</style>
|
||||
</head>
|
||||
<body onload="return onLoad(event)">
|
||||
<h1>Locales overview</h1>
|
||||
<p><strong>Legend:</strong> For each locale, this chart shows search engine name.</p>
|
||||
<div id="calContainer">
|
||||
<p id="checks">
|
||||
<input type="checkbox" name="0" checked> Tier 1<br>
|
||||
<input type="checkbox" name="1" checked> Tier 2<br>
|
||||
<input type="checkbox" name="2" checked> Tier 3<br>
|
||||
</p>
|
||||
</div>
|
||||
<table>
|
||||
<tbody id="view">
|
||||
<tr><td class="locale"> </td><td class="searchplugin"> </td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
160
testing/tests/l10n/web/waterfall-code.js
Executable file
160
testing/tests/l10n/web/waterfall-code.js
Executable file
@ -0,0 +1,160 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2006
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Axel Hecht <axel@pike.org>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
||||
var waterfallView = {
|
||||
__proto__: baseView,
|
||||
scale: 1/60,
|
||||
unstyle: function() {
|
||||
this.content.innerHTML = '';
|
||||
},
|
||||
updateView: function(aResult) {
|
||||
YAHOO.widget.Logger.log('waterfallView.updateView called');
|
||||
var head = document.getElementById('head');
|
||||
head.innerHTML = '<th></th>';
|
||||
this.content.innerHTML = '';
|
||||
for each (var loc in controller.locales) {
|
||||
var h = document.createElement('th');
|
||||
h.className = 'wf-locale-head ' + view.getClass(loc);
|
||||
h.textContent = loc;
|
||||
head.appendChild(h);
|
||||
}
|
||||
var heads = head.childNodes;
|
||||
for (var i = aResult.length - 1; i >= 0; i--) {
|
||||
var wf = document.createElement('tr');
|
||||
wf.className = 'waterfall-row';
|
||||
wf.setAttribute('style','vertical-align: top;');
|
||||
this.content.appendChild(wf);
|
||||
var b = aResult[i];
|
||||
var height = Math.floor((b[1][1] - b[1][0]) * this.scale);
|
||||
var style = "height: " + height + "px;";
|
||||
wf.setAttribute('style', style);
|
||||
var cell = view.getCell();
|
||||
cell.className = 'cell-label';
|
||||
cell.textContent = b[0];
|
||||
wf.appendChild(cell);
|
||||
var locs = keys(b[2]);
|
||||
var h = 1;
|
||||
for each (loc in locs) {
|
||||
if (h >= heads.length) {
|
||||
YAHOO.widget.Logger.log("dropping result for " + loc);
|
||||
continue;
|
||||
}
|
||||
while (heads[h].textContent < loc) {
|
||||
// we don't have a result for this column in this build
|
||||
wf.appendChild(view.getCell());
|
||||
h++;
|
||||
if (h >= heads.length) {
|
||||
YAHOO.widget.Logger.log("dropping result for " + loc);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (heads[h].textContent > loc) {
|
||||
YAHOO.widget.Logger.log("dropping result for " + loc);
|
||||
continue;
|
||||
}
|
||||
cell = view.getCell();
|
||||
cell.innerHTML = ' ';
|
||||
if (b[2][loc] & 2) {
|
||||
cell.className = 'busted ';
|
||||
}
|
||||
else if (b[2][loc] & 1) {
|
||||
cell.className = 'fair ';
|
||||
}
|
||||
else {
|
||||
cell.className = 'good ';
|
||||
}
|
||||
cell.className += ' ' + view.getClass(loc);
|
||||
wf.appendChild(cell);
|
||||
h++;
|
||||
}
|
||||
if (i == 0) {
|
||||
continue;
|
||||
}
|
||||
// XXX don't make output sparse
|
||||
continue;
|
||||
wf = document.createElement('tr');
|
||||
wf.className = 'waterfall-row';
|
||||
wf.setAttribute('style','vertical-align: top;');
|
||||
this.content.appendChild(wf);
|
||||
var b = aResult[i];
|
||||
var height = Math.floor((b[1][0] - aResult[i-1][1][1]) * this.scale);
|
||||
var style = "height: " + height + "px;";
|
||||
wf.setAttribute('style', style);
|
||||
//var cell = view.getCell();
|
||||
}
|
||||
},
|
||||
setUpHandlers: function() {
|
||||
_t = this;
|
||||
},
|
||||
destroyHandlers: function() {
|
||||
}
|
||||
};
|
||||
var waterfallController = {
|
||||
__proto__: baseController,
|
||||
beforeSelect: function() {
|
||||
this.result = {};
|
||||
this.isShown = false;
|
||||
waterfallView.setUpHandlers();
|
||||
var _t = this;
|
||||
var callback = function(obj) {
|
||||
delete _t.req;
|
||||
if (view != waterfallView) {
|
||||
// ignore, we have switched again
|
||||
return;
|
||||
}
|
||||
_t.result = obj;
|
||||
_t.tag = obj[obj.length - 1][0]; // set the subdir to latest build
|
||||
controller.addLocales(keys(obj[obj.length - 1][2]));
|
||||
waterfallView.updateView(_t.result);
|
||||
};
|
||||
this.req = JSON.get('results/waterfall.json', callback);
|
||||
},
|
||||
beforeUnSelect: function() {
|
||||
if (this.req) {
|
||||
this.req.abort();
|
||||
delete this.req;
|
||||
}
|
||||
waterfallView.unstyle();
|
||||
waterfallView.destroyHandlers();
|
||||
},
|
||||
showView: function(aClosure) {
|
||||
// json onload handler does this;
|
||||
}
|
||||
};
|
||||
controller.addPane('Tinder', 'waterfall', waterfallController,
|
||||
waterfallView);
|
Loading…
Reference in New Issue
Block a user