diff --git a/server/djrandom/test/test_frontend_api.py b/server/djrandom/test/test_frontend_api.py
index 6b1e322c9f948c261205f4286832b0fea829c4c2..2a3f717b315f6aa5294aecc2f4890c14671cb408 100644
--- a/server/djrandom/test/test_frontend_api.py
+++ b/server/djrandom/test/test_frontend_api.py
@@ -1,4 +1,3 @@
-import urllib
 import json
 from datetime import datetime
 from djrandom.test import WsgiTestCase
@@ -13,7 +12,6 @@ class FrontendApiTest(WsgiTestCase):
 
     FLASK_APP = frontend.app
 
-
     def setUp(self):
         WsgiTestCase.setUp(self)
         self.searcher = svcs['searcher'] = self.mox.CreateMockAnything()
diff --git a/server/djrandom/test/test_frontend_views.py b/server/djrandom/test/test_frontend_views.py
new file mode 100644
index 0000000000000000000000000000000000000000..97ddf16310f3eeaa55160d373076e2158bdbd303
--- /dev/null
+++ b/server/djrandom/test/test_frontend_views.py
@@ -0,0 +1,120 @@
+import mox
+import os
+import json
+from datetime import datetime
+from djrandom.test import WsgiTestCase
+from djrandom import frontend
+from djrandom.database import Session
+from djrandom.frontend import svcs
+from djrandom.frontend import views
+from djrandom.model.mp3 import MP3
+from djrandom.model.user import User
+from werkzeug.contrib.cache import SimpleCache
+
+
+class FrontendViewsTest(WsgiTestCase):
+
+    FLASK_APP = frontend.app
+
+    def setUp(self):
+        WsgiTestCase.setUp(self)
+        svcs['cache'] = SimpleCache()
+
+        self._load_data(
+            [MP3(sha1='1', artist=u'artist 1', album=u'album',
+                 title=u'song 1', path='/root/1', play_count=3,
+                 size=100, state=MP3.READY),
+             MP3(sha1='2', artist=u'artist 1', album=u'album 2',
+                 title=u'song 2', path='/root/2', size=100,
+                 state=MP3.READY),
+             MP3(sha1='3', artist=u'artist 2', album=u'album',
+                 title=u'song 3', path='/root/3', size=100,
+                 state=MP3.READY),
+             MP3(sha1='4', path='/root/4', state=MP3.DUPLICATE,
+                 duplicate_of='1'),
+             MP3(sha1='5', path='/root/5', state=MP3.ERROR),
+             User('testuser', 'testpass'),
+             ])
+
+        views.use_xsendfile = 1
+
+    def test_autocomplete(self):
+        rv = self.app.get('/autocomplete?term=art')
+        self.assertEquals(200, rv.status_code)
+        rv = json.loads(rv.data)
+        self.assertTrue('results' in rv)
+        self.assertEquals([u'artist 1', u'artist 2'], rv['results'])
+
+        # test twice to hit the cache.
+        rv2 = self.app.get('/autocomplete?term=art')
+        rv2 = json.loads(rv2.data)
+        self.assertEquals(rv, rv2)
+
+    def test_homepage(self):
+        rv = self.app.get('/')
+        self.assertEquals(200, rv.status_code)
+
+    def test_about(self):
+        rv = self.app.get('/about')
+        self.assertEquals(200, rv.status_code)
+
+    def test_songs_fragment(self):
+        rv = self.app.post('/fragment/songs',
+                           data={'h': '1,3'})
+        self.assertEquals(200, rv.status_code)
+        self.assertTrue('artist 1' in rv.data)
+        self.assertTrue('artist 2' in rv.data)
+
+    def test_download_xsendfile_ok(self):
+        self.mox.StubOutWithMock(os.path, 'exists')
+        os.path.exists('/root/1').AndReturn(True)
+        self.mox.ReplayAll()
+
+        rv = self.app.get('/dl/1')
+        self.assertEquals(200, rv.status_code)
+        self.assertEquals('audio/mpeg', rv.content_type)
+        self.assertEquals('/root/1', rv.headers['X-SENDFILE'])
+
+    def test_download_python_ok(self):
+        views.use_xsendfile = 0
+        self.mox.StubOutWithMock(os.path, 'exists')
+        os.path.exists('/root/1').AndReturn(True)
+
+        self.mox.StubOutWithMock(os.path, 'getsize')
+        os.path.getsize('/root/1').AndReturn(100)
+
+        self.mox.StubOutWithMock(views, 'fileiter')
+        views.fileiter('/root/1', 0, 100).AndReturn(['contents'])
+
+        self.mox.ReplayAll()
+
+        rv = self.app.get('/dl/1')
+        self.assertEquals(200, rv.status_code)
+        self.assertEquals('audio/mpeg', rv.content_type)
+        self.assertEquals('contents', rv.data)
+
+    def test_download_duplicate_ok(self):
+        self.mox.StubOutWithMock(os.path, 'exists')
+        os.path.exists('/root/1').AndReturn(True)
+
+        self.mox.ReplayAll()
+
+        rv = self.app.get('/dl/4')
+        self.assertEquals(200, rv.status_code)
+        self.assertEquals('audio/mpeg', rv.content_type)
+
+    def test_download_nonexisting(self):
+        rv = self.app.get('/dl/nonexisting')
+        self.assertEquals(404, rv.status_code)
+
+    def test_download_notready(self):
+        rv = self.app.get('/dl/5')
+        self.assertEquals(404, rv.status_code)
+
+    def test_download_file_disappeared(self):
+        self.mox.StubOutWithMock(os.path, 'exists')
+        os.path.exists('/root/1').AndReturn(False)
+        self.mox.ReplayAll()
+
+        rv = self.app.get('/dl/1')
+        self.assertEquals(404, rv.status_code)