Skip to content

Commit

Permalink
Merge pull request #8 from LegoStormtroopr/zoo2.0
Browse files Browse the repository at this point in the history
Zoo2.0
  • Loading branch information
LegoStormtroopr committed Aug 9, 2017
2 parents 4905d30 + 6e9651c commit f5df346
Show file tree
Hide file tree
Showing 12 changed files with 140 additions and 42 deletions.
2 changes: 1 addition & 1 deletion docs/development/scripts/node_wcag.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ temp.open('wcag', function(err, info) {
if (!err) {
fs.write(info.fd, "<html><head><body><h2>This is wrong, it should be h1");
fs.close(info.fd, function(err) {
exec("zookeeper tarsier '" + info.path + "' -J",
exec("zookeeper tarsier '" + info.path + "' -F",
function(err, stdout) {
results = stdout;
json_results = JSON.parse(results);
Expand Down
2 changes: 1 addition & 1 deletion docs/development/scripts/python_cli_wcag.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
tmp_file.seek(0)

process = subprocess.Popen(
["zookeeper", "tarsier", tmp_file.name, "-J"],
["zookeeper", "tarsier", tmp_file.name, "-F"],
stdout=subprocess.PIPE
)

Expand Down
2 changes: 1 addition & 1 deletion docs/development/scripts/ruby_wcag.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
tmp_file.write(my_html)
tmp_file.close

results = `zookeeper tarsier #{tmp_file.path} -J`
results = `zookeeper tarsier #{tmp_file.path} -F`
json_results = JSON.parse(results)
print json_results[0][0], " ", json_results[0][1]['failures'].size, " failures\n"
2 changes: 2 additions & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,7 @@ deps =
commands =
flake8: flake8
scripts: {toxinidir}/docs/run_demo_scripts.sh
; scripts: zookeeper
; scripts: /bin/bash -c 'node {toxinidir}/docs/development/scripts/node_wcag.js'
zoo-linux: /bin/bash -c 'export LC_ALL=C.UTF-8 && export LANG=C.UTF-8 && coverage run --branch --parallel-mode --source=wcag_zoo wcag_zoo/testrunner.py {toxinidir}/tests/html/*.html'
zoo-windows: coverage run --branch --parallel-mode --source=wcag_zoo wcag_zoo/testrunner.py ./tests/html/anteater-alt-tags.html
2 changes: 1 addition & 1 deletion wcag_zoo/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
version = '0.1.0'
version = '0.2.0'
10 changes: 7 additions & 3 deletions wcag_zoo/testrunner.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import sys
import os
from utils import get_wcag_class
from wcag_zoo.utils import make_flat


class ValidationError(Exception):
Expand Down Expand Up @@ -41,7 +42,9 @@ def test_file(filename):
error_attr = "data-wcag-%s-code" % level

# Test the nodes that we're told fail, are expected to fail
for result in results[level_plural]:
_results = make_flat(results[level_plural])
for result in _results:
# print(result)
err_code = tree.xpath(result['xpath'])[0].get(error_attr, "not given")
if result['error_code'] != err_code:
test_failures.append(
Expand All @@ -59,7 +62,7 @@ def test_file(filename):

for node in tree.xpath("//*[@%s]" % error_attr):
this_path = node.getroottree().getpath(node)
failed_paths = dict([(result['xpath'], result) for result in results[level_plural]])
failed_paths = dict([(result['xpath'], result) for result in _results])

error_code = node.get(error_attr, "")
if this_path not in failed_paths.keys():
Expand Down Expand Up @@ -99,6 +102,7 @@ def test_files(filenames):
print('\x1b[1;31m' + 'failed' + '\x1b[0m')
print(" ", v.message)
except:
raise
failed += 1
print('\x1b[1;31m' + 'error!' + '\x1b[0m')
if len(filenames) == 1:
Expand Down Expand Up @@ -183,7 +187,7 @@ def runner(filenames):
]
all_good = all([
test_files(filenames),
test_command_lines(filenames)
# test_command_lines(filenames)
])

if not all_good:
Expand Down
92 changes: 71 additions & 21 deletions wcag_zoo/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,19 +239,32 @@ def __init__(self, *args, **kwargs):
self.level = kwargs.get('level', "AA")
self.kwargs = kwargs

self.success = 0
self.failures = []
self.warnings = []
self.skipped = []
self.success = {}
self.failures = {}
self.warnings = {}
self.skipped = {}

def add_success(self, **kwargs):
self.add_to_dict(self.success, **kwargs)

def add_to_dict(self, _dict, **kwargs):
guideline = kwargs['guideline']
technique = kwargs['technique']
g = _dict.get(guideline, {})
g[technique] = g.get(technique, [])
g[technique].append(build_msg(**kwargs))
_dict[guideline] = g

def add_failure(self, **kwargs):
self.failures.append(build_msg(**kwargs))
self.add_to_dict(self.failures, **kwargs)

def add_warning(self, **kwargs):
self.warnings.append(build_msg(**kwargs))
self.add_to_dict(self.warnings, **kwargs)
# self.warnings.append(build_msg(**kwargs))

def add_skipped(self, **kwargs):
self.skipped.append(build_msg(**kwargs))
self.add_to_dict(self.skipped, **kwargs)
# self.skipped.append(build_msg(**kwargs))

def skip_element(self, node):
"""
Expand Down Expand Up @@ -300,12 +313,12 @@ def check_skip_element(self, node):
skip_node = True

if skip_node:
self.skipped.append({
'xpath': self.tree.getpath(node),
'message': "\n ".join(skip_message),
'classes': node.get('class'),
'id': node.get('id'),
})
self.add_skipped(
node=node,
message="\n ".join(skip_message),
guideline='skipped',
technique='skipped',
)
return skip_node

def validate_document(self, html):
Expand Down Expand Up @@ -418,7 +431,8 @@ def as_cli(cls):
@click.option('--animal', default=False, is_flag=True, help='')
@click.option('--warnings_as_errors', '-W', default=False, is_flag=True, help='Treat warnings as errors')
@click.option('--verbosity', '-v', type=int, default=1, help='Specify how much text to output during processing')
@click.option('--json', '-J', default=False, is_flag=True, help='Prints a json dump of results, instead of human readable results')
@click.option('--json', '-J', default=False, is_flag=True, help='Prints a json dump of results, with nested guidelines and techniques, instead of human readable results')
@click.option('--flat_json', '-F', default=False, is_flag=True, help='Prints a json dump of results as a collection of flat lists, instead of human readable results')
@click.option('--media_rules', "-M", multiple=True, type=str, help='Specify a media rule to enforce')
def cli(*args, **kwargs):
total_results = []
Expand All @@ -427,6 +441,7 @@ def cli(*args, **kwargs):
kwargs['level'] = kwargs['level'] or 'A' * min(short_level, 3) or 'AA'
verbosity = kwargs.get('verbosity')
json_dump = kwargs.get('json')
flat_json_dump = kwargs.get('flat_json')
warnings_as_errors = kwargs.pop('warnings_as_errors', False)
kwargs['skip_these_classes'] = [c.strip() for c in kwargs.get('skip_these_classes') if c]
kwargs['skip_these_ids'] = [c.strip() for c in kwargs.get('skip_these_ids') if c]
Expand All @@ -446,10 +461,32 @@ def cli(*args, **kwargs):
html = file.read()
results = klass.validate_document(html)
except:
raise
results = {'failures': ["Exception thrown"]}
output.append((file.name, results))
total_results.append(results)

print(json.dumps(output))
elif flat_json_dump:
import json
output = []
for file in filenames:
try:
html = file.read()
results = klass.validate_document(html)
except:
raise
results = {'failures': ["Exception thrown"]}
output.append((
file.name,
{
"failures": make_flat(results.get('failures', {})),
"warnings": make_flat(results.get('warnings', {})),
"skipped": make_flat(results.get('skipped', {})),
"success": make_flat(results.get('success', {}))
}
))

print(json.dumps(output))
else:
for f in filenames:
Expand All @@ -470,24 +507,29 @@ def cli(*args, **kwargs):
else:
print()

failures = make_flat(results.get('failures', {}))
warnings = make_flat(results.get('warnings', {}))
skipped = make_flat(results.get('skipped', {}))
success = make_flat(results.get('success', {}))

print_if(
"\n".join([
"ERROR - {message}".format(message=r['message'])
for r in results['failures']
for r in failures
]),
check=verbosity>1
)
print_if(
"\n".join([
"WARNING - {message}".format(message=r['message'])
for r in results['warnings']
for r in warnings
]),
check=verbosity>2
)
print_if(
"\n".join([
"Skipped - {message}".format(message=r['message'])
for r in results.get('skipped', [])
for r in skipped
]),
check=verbosity>2
)
Expand All @@ -503,10 +545,10 @@ def cli(*args, **kwargs):
" - {num_good} succeeded",
" - {num_skip} skipped",
]).format(
num_fail=len(results['failures']),
num_warn=len(results['warnings']),
num_skip=len(results['skipped']),
num_good=results['success']
num_fail=len(failures),
num_warn=len(warnings),
num_skip=len(skipped),
num_good=len(success)
),
check=verbosity>1
)
Expand All @@ -530,3 +572,11 @@ def cli(*args, **kwargs):
sys.exit(0)

return cli


def make_flat(_dict):
return [
r for guidelines in _dict.values()
for techniques in guidelines.values()
for r in techniques
]
6 changes: 5 additions & 1 deletion wcag_zoo/validators/anteater.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,11 @@ def validate_element(self, node):
'error_code': 'anteater-2'
})
else:
self.success += 1
self.add_success(
guideline='1.1.1',
technique='H37',
node=node
)

if __name__ == "__main__":
cli = Anteater.as_cli()
Expand Down
12 changes: 8 additions & 4 deletions wcag_zoo/validators/ayeaye.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def validate_document(self, html):
if len(self.tree.xpath('/html/body//*[@accesskey]')) == 0:
self.add_warning(
guideline='2.1.1',
technique='G20',
technique='G202',
node=self.tree.xpath('/html/body')[0],
message=Ayeaye.error_codes['ayeaye-3-warning'],
error_code='ayeaye-3-warning',
Expand All @@ -55,18 +55,22 @@ def validate_element(self, node):
# Blank or empty
self.add_failure(
guideline='2.1.1',
technique='G20',
technique='G202',
node=node,
error_code='ayeaye-2',
message=Ayeaye.error_codes['ayeaye-2'].format(elem=node.getroottree().getpath(node)),
)
elif access_key not in self.found_keys.keys():
self.success += 1
self.add_success(
guideline='2.1.1',
technique='G202',
node=node
)
self.found_keys[access_key] = node.getroottree().getpath(node)
else:
self.add_failure(
guideline='2.1.1',
technique='G20',
technique='G202',
node=node,
error_code='ayeaye-1',
message=Ayeaye.error_codes['ayeaye-1'].format(key=access_key, elem=self.found_keys[access_key]),
Expand Down
25 changes: 22 additions & 3 deletions wcag_zoo/validators/molerat.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,17 @@
}
}

TECHNIQUE = {
"AA": {
'normal': "G18",
'large': "G145",
},
"AAA": {
'normal': "G17",
'large': "G18",
}
}


def normalise_color(color):
rgba_color = None
Expand Down Expand Up @@ -216,11 +227,13 @@ def validate_element(self, node):

font_size_type = 'normal'
error_code = 'molerat-1'
technique = "G18"
if font_size >= 18 or font_size >= 14 and font_is_bold:
font_size_type = 'large'
error_code = 'molerat-2'

ratio_threshold = WCAG_LUMINOCITY_RATIO_THRESHOLD.get(self.level).get(font_size_type)
ratio_threshold = WCAG_LUMINOCITY_RATIO_THRESHOLD[self.level][font_size_type]
technique = TECHNIQUE[self.level][font_size_type]

if ratio < ratio_threshold:
disp_text = nice_console_text(node.text)
Expand Down Expand Up @@ -258,13 +271,19 @@ def validate_element(self, node):

self.add_failure(
guideline='1.4.3',
technique='H37',
technique=technique,
node=node,
message=message,
error_code=error_code
)
else:
self.success += 1 # I like what you got!
# I like what you got!
self.add_success(
guideline='1.4.3',
technique=technique,
node=node
)


if __name__ == "__main__":
cli = Molerat.as_cli()
Expand Down
7 changes: 5 additions & 2 deletions wcag_zoo/validators/parade.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ def __init__(self, *args, **kwargs):
super(Parade, self).__init__(*args, **kwargs)

def validate_document(self, html):
self.tree = self.get_tree(html)
rv = sorted([
filename[:-3]
for filename in os.listdir(os.path.dirname(__file__))
Expand All @@ -33,9 +34,11 @@ def validate_document(self, html):

for validator_name in rv:
cmd = get_wcag_class(validator_name)
results = cmd(**self.kwargs).validate_document(html)
instance = cmd(**self.kwargs)
instance._tree = self.tree
results = instance.validate_document(html)
for k, v in results.items():
total_results[k] = total_results[k] + v
total_results[k].update(v)
return total_results

@classmethod
Expand Down

0 comments on commit f5df346

Please sign in to comment.