298:7a103296a019
Anton Shestakov <av6@dwimlabs.net>, Wed, 20 Sep 2017 11:25:26 +0800
viewer: use two columns for info lists on check page for small screens too Since lists themselves switch to one column on small screens, there's enough space for both of them side by side.

next change 303:cfaaf0b0ec71
previous change 294:df33e25d8960

tests/test_viewer.py

Permissions: -rw-r--r--

Other formats: Feeds:
from datetime import datetime
from xml.etree import ElementTree
from pytest import raises
from tornado.escape import json_encode
from tornado.testing import AsyncHTTPTestCase
from tornado.web import HTTPError
from candolint.handlers import get_project_or_404
from candolint.models import database, Project, Change, Check
from viewer import CandolintViewer
XMLNS = {
'atom': 'http://www.w3.org/2005/Atom',
'svg': 'http://www.w3.org/2000/svg'
}
def setup_module():
with database.transaction():
project = Project.create(
url='https://example.com/alice/test-viewer',
domain='example.com',
user='alice',
name='test-viewer')
change = Change.create(
rev=42,
node='92cfceb39d57d914ed8b14d0e37643de0797ae56',
branch='default',
date='2016-07-19 22:23 +0800',
author='alice',
message='component: do a thing',
project=project)
Check.create(
ordinal=Check.get_next_ordinal(project),
errors=0,
warnings=0,
lines='[]',
success=True,
started=datetime.fromtimestamp(0),
finished=datetime.fromtimestamp(0),
change=change,
project=project)
lines = [{
'text': '# C&O job started: 2016-08-20T02:38:06+00:00',
'cls': 'meta'
}, {
'text': '# C&O task: setup',
'task': 'setup',
'cls': 'task'
}, {
'text': '$ ../venv2/bin/flake8 --version',
'task': 'setup'
}, {
'text': '3.0.3',
'task': 'setup'
}, {
'text': '# C&O task: checks',
'task': 'checks',
'cls': 'task'
}, {
'line_number': 20,
'task': 'checks',
'link_start': 0,
'text': 'test.py:20:80: E501 line too long (82 > 79 characters)',
'filename': 'test.py',
'link_end': 10,
'cls': 'warning'
}, {
'text': '# C&O job finished: 2016-08-20T02:38:53+00:00',
'cls': 'meta'
}]
Check.create(
ordinal=Check.get_next_ordinal(project),
errors=1,
warnings=1,
lines=json_encode(lines),
success=True,
started=datetime(2016, 8, 20, 2, 38, 6),
finished=datetime(2016, 8, 20, 2, 38, 53),
change=change,
project=project)
def test_get_project_or_404():
with raises(HTTPError) as error:
get_project_or_404('butt.cloud', 'cyber', 'wizard-attack')
assert error.value.status_code == 404
project = get_project_or_404('example.com', 'alice', 'test-viewer')
assert project.id is not None
assert project.url == 'https://example.com/alice/test-viewer'
class ViewerTestCase(AsyncHTTPTestCase):
def get_app(self):
return CandolintViewer()
def test_index(self):
response = self.fetch('/')
assert response.code == 200
assert 'online linter' in response.body
assert '1 error' in response.body
assert '1 warning' in response.body
assert '<a href="#">default</a>' in response.body
def test_404(self):
response = self.fetch('/nobodyhere')
assert response.code == 404
assert 'online linter' in response.body
def test_project(self):
response = self.fetch('/butt.cloud/cyber/wizard-attack')
assert response.code == 404
assert 'online linter' in response.body
response = self.fetch('/example.com/alice/test-viewer')
assert response.code == 200
assert 'Clone URL' in response.body
assert 'status.svg' in response.body
assert '.. image:: http' in response.body
assert '1 error' in response.body
assert '1 warning' in response.body
assert '<a href="#">default</a>' in response.body
assert ('<link rel="alternate"'
' href="/example.com/alice/test-viewer/atom"'
' type="application/atom+xml"'
' title="test-viewer feed">') in response.body
def test_atom(self):
response = self.fetch('/example.com/alice/test-viewer/atom')
assert response.code == 200
assert 'atom+xml' in response.headers['Content-Type']
root = ElementTree.fromstring(response.body)
assert root.tag == '{%s}%s' % (XMLNS['atom'], 'feed')
title = root.find('./atom:entry/atom:title', XMLNS)
assert title is not None
assert title.text.startswith('Check #')
assert title.text.endswith(' 1 error, 1 warning')
updates = [el.text for el in root.findall('.//atom:updated', XMLNS)]
assert len(updates) == min(Check.select().count(), 20) + 1
assert updates[0] == updates[1] == '2016-08-20T02:38:53Z'
def test_check(self):
response = self.fetch('/butt.cloud/cyber/wizard-attack/latest')
assert response.code == 404
assert 'online linter' in response.body
response = self.fetch('/example.com/alice/test-viewer/latest')
assert response.code == 200
assert '1 error' in response.body
assert '1 warning' in response.body
assert '<a href="#">default</a>' in response.body
assert '<a href="#" class="filelink">test.py:20</a>' in response.body
assert ('<time datetime="2016-08-20T02:38:53Z"'
' title="2016-08-20 02:38:53 UTC">'
'2016-08-20 02:38:53 UTC</time>') in response.body
assert ('<time datetime="2016-07-19T22:23+0800"'
' title="2016-07-19 22:23 +0800">'
'2016-07-19 22:23 +0800</time>') in response.body
response = self.fetch('/example.com/alice/test-viewer/latest/raw')
assert response.code == 200
assert response.headers['Content-Type'] == 'text/plain; charset=utf-8'
assert 'test.py' in response.body
def test_compare(self):
base_url = '/example.com/alice/test-viewer/latest'
response = self.fetch(base_url + '/compare/latest')
assert response.code == 200
assert 'same commit' in response.body
assert 'Diff is empty' in response.body
response = self.fetch(base_url + '/compare/1')
assert response.code == 200
assert 'same commit' in response.body
assert 'E501' in response.body
def test_status(self):
response = self.fetch('/butt.cloud/cyber/wizard-attack/status.svg')
assert response.code == 404
assert 'online linter' in response.body
response = self.fetch('/example.com/alice/test-viewer/status.svg')
assert response.code == 200
root = ElementTree.fromstring(response.body)
assert root.tag == '{%s}%s' % (XMLNS['svg'], 'svg')
assert root.attrib.get('height') == '20'
text = [el.text for el in root.findall('./svg:g/svg:text', XMLNS)]
assert text[::2] == ['lint', '1 error', '1 warning']
def test_dot(self):
response = self.fetch('/example.com/alice/test-viewer/latest/dot.svg')
assert response.code == 200
root = ElementTree.fromstring(response.body)
assert root.tag == '{%s}%s' % (XMLNS['svg'], 'svg')
assert root.attrib.get('height') == '12'
circles = root.findall('./svg:circle', XMLNS)
assert len(circles) == 1
assert circles[0].attrib.get('fill').startswith('#')