|
a/AlluraTesting/alluratest/validation.py |
|
b/AlluraTesting/alluratest/validation.py |
|
... |
|
... |
18 |
from paste.deploy import loadapp
|
18 |
from paste.deploy import loadapp
|
19 |
from paste.script.appinstall import SetupCommand
|
19 |
from paste.script.appinstall import SetupCommand
|
20 |
from pylons import c, g, url, request, response, session
|
20 |
from pylons import c, g, url, request, response, session
|
21 |
from webtest import TestApp
|
21 |
from webtest import TestApp
|
22 |
from webob import Request, Response
|
22 |
from webob import Request, Response
|
23 |
from tidylib import tidy_document
|
|
|
24 |
from nose.tools import ok_, assert_true, assert_false
|
23 |
from nose.tools import ok_, assert_true, assert_false
|
25 |
from poster.encode import multipart_encode
|
24 |
from poster.encode import multipart_encode
|
26 |
from poster.streaminghttp import register_openers
|
25 |
from poster.streaminghttp import register_openers
|
27 |
from ming.utils import LazyProperty
|
26 |
from ming.utils import LazyProperty
|
28 |
|
27 |
|
|
... |
|
... |
108 |
else:
|
107 |
else:
|
109 |
html = html_or_response
|
108 |
html = html_or_response
|
110 |
|
109 |
|
111 |
html = html.lstrip()
|
110 |
html = html.lstrip()
|
112 |
|
111 |
|
113 |
if html.startswith('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"'):
|
|
|
114 |
return validate_xhtml(html)
|
|
|
115 |
elif html.startswith('<!DOCTYPE html>'):
|
112 |
if html.startswith('<!DOCTYPE html>'):
|
116 |
return validate_html5(html)
|
113 |
return validate_html5(html)
|
117 |
else:
|
114 |
else:
|
118 |
assert False, 'Non-valid HTML: ' + html[:100] + '...'
|
115 |
assert False, 'Non-valid HTML: ' + html[:100] + '...'
|
119 |
|
|
|
120 |
def validate_xhtml(html):
|
|
|
121 |
ok_warnings = ('inserting implicit <span>',
|
|
|
122 |
'replacing unexpected button by </button>',
|
|
|
123 |
'missing </button>',
|
|
|
124 |
'trimming empty <',
|
|
|
125 |
'<form> lacks "action" attribute',
|
|
|
126 |
'replacing invalid character code',
|
|
|
127 |
'discarding invalid character code',
|
|
|
128 |
'<a> proprietary attribute "alt"', # event RSS feed generated this
|
|
|
129 |
'<table> lacks "summary" attribute',
|
|
|
130 |
|
|
|
131 |
# parser appears to get mightily confused
|
|
|
132 |
# see also http://sourceforge.net/tracker/?func=detail&atid=390963&aid=1986717&group_id=27659
|
|
|
133 |
'<span> anchor "login_openid" already defined',
|
|
|
134 |
)
|
|
|
135 |
|
|
|
136 |
doc_tidied, errors = tidy_document(html)
|
|
|
137 |
if errors:
|
|
|
138 |
lines = html.split('\n')
|
|
|
139 |
#print html
|
|
|
140 |
errors_prettified = ""
|
|
|
141 |
for e in errors.split('\n'):
|
|
|
142 |
if not e:
|
|
|
143 |
continue
|
|
|
144 |
if '- Warning: ' in e:
|
|
|
145 |
ok = False
|
|
|
146 |
for ok_warning in ok_warnings:
|
|
|
147 |
if ok_warning in e:
|
|
|
148 |
ok = True
|
|
|
149 |
continue
|
|
|
150 |
if ok:
|
|
|
151 |
continue
|
|
|
152 |
if '- Info:' in e:
|
|
|
153 |
continue
|
|
|
154 |
if '- Info:' in e:
|
|
|
155 |
continue
|
|
|
156 |
line_num = int(e.split(' ',2)[1])
|
|
|
157 |
errors_prettified += e + "\n"
|
|
|
158 |
for offset in range(-2,2+1):
|
|
|
159 |
try:
|
|
|
160 |
errors_prettified += "%s: %s\n" % (line_num+offset, lines[line_num+offset-1])
|
|
|
161 |
except IndexError as e:
|
|
|
162 |
pass
|
|
|
163 |
#print lines[line_num-1]
|
|
|
164 |
errors_prettified += "\n"
|
|
|
165 |
assert_false(errors_prettified, "HTML Tidy errors:\n" + errors_prettified)
|
|
|
166 |
|
|
|
167 |
def validate_xhtml_chunk(html):
|
|
|
168 |
""" When you don't have a html & body tags - this adds it"""
|
|
|
169 |
html = '''<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|
|
170 |
<html xmlns="http://www.w3.org/1999/xhtml">
|
|
|
171 |
<head><title></title></head>
|
|
|
172 |
<body>
|
|
|
173 |
%s
|
|
|
174 |
</body></html>''' % html
|
|
|
175 |
return validate_xhtml(html)
|
|
|
176 |
|
116 |
|
177 |
def validate_json(json_or_response):
|
117 |
def validate_json(json_or_response):
|
178 |
if hasattr(json_or_response, 'body'):
|
118 |
if hasattr(json_or_response, 'body'):
|
179 |
j = json_or_response.body
|
119 |
j = json_or_response.body
|
180 |
else:
|
120 |
else:
|