def test_views(self):
        c = Client()

        # Connecting to dashboard without auth redirects to /
        res = c.get('/dashboard/', follow=True)
        self.assertFalse(res.context['user'].is_authenticated)
        self.assertRedirects(res, '/login/?next=/dashboard/')

        res = c.get('/processingnode/1/', follow=True)
        self.assertRedirects(res, '/login/?next=/processingnode/1/')

        res = c.get('/map/project/1/', follow=True)
        self.assertRedirects(res, '/login/?next=/map/project/1/')

        res = c.get('/3d/project/1/task/1/', follow=True)
        self.assertRedirects(res, '/login/?next=/3d/project/1/task/1/')

        # Login
        c.post('/login/', data=self.credentials, follow=True)

        # We should have a project created from the dashboard
        self.assertTrue(Project.objects.count() >= 1)

        # Can access API page
        res = c.get('/api/')
        self.assertTrue(res.status_code == status.HTTP_200_OK)

        # We can access a processingnode view that exists
        res = c.get('/processingnode/1/')
        self.assertTrue(res.status_code == 200)
        self.assertTemplateUsed(res, 'app/processing_node.html')

        # We can access a processingnode that is offline
        # (and there's a warning message when we do that)
        res = c.get('/processingnode/2/')
        self.assertTrue(res.status_code == 200)
        self.assertTemplateUsed(res, 'app/processing_node.html')

        message = list(res.context['messages'])[0]
        self.assertEqual(message.tags, 'warning')
        self.assertTrue("offline" in message.message)

        res = c.get('/processingnode/9999/')
        self.assertTrue(res.status_code == 404)

        res = c.get('/processingnode/abc/')
        self.assertTrue(res.status_code == 404)

        # /map/ and /3d/ views
        user = User.objects.get(username="testuser")
        other_user = User.objects.get(username="testuser2")

        project = Project.objects.create(owner=user)
        task = Task.objects.create(project=project)
        other_project = Project.objects.create(owner=other_user)
        other_task = Task.objects.create(project=other_project)

        # Cannot access a project that we have no access to, or that does not exist
        for project_id in [other_project.id, 99999]:
            res = c.get('/map/project/{}/'.format(project_id))
            self.assertTrue(res.status_code == status.HTTP_404_NOT_FOUND)

        # We can access a project that we have access to
        res = c.get('/map/project/{}/'.format(project.id))
        self.assertTrue(res.status_code == status.HTTP_200_OK)

        # 3D views need project and task parameters
        res = c.get('/3d/project/{}/'.format(project.id))
        self.assertTrue(res.status_code == status.HTTP_404_NOT_FOUND)

        # Cannot access a 3d view for a task we have no access to
        res = c.get('/3d/project/{}/task/{}/'.format(other_project.id, other_task.id))
        self.assertTrue(res.status_code == status.HTTP_404_NOT_FOUND)

        # Can access 3d view for task we have access to
        res = c.get('/3d/project/{}/task/{}/'.format(project.id, task.id))
        self.assertTrue(res.status_code == status.HTTP_200_OK)

        # Cannot access public URLs unless a task is shared
        def test_public_views(client, expectedStatus):
            res = client.get('/public/task/{}/map/'.format(task.id))
            self.assertTrue(res.status_code == expectedStatus)
            res = client.get('/public/task/{}/3d/'.format(task.id))
            self.assertTrue(res.status_code == expectedStatus)
            res = client.get('/public/task/{}/iframe/3d/'.format(task.id))
            self.assertTrue(res.status_code == expectedStatus)
            res = client.get('/public/task/{}/iframe/map/'.format(task.id))
            self.assertTrue(res.status_code == expectedStatus)
            res = client.get('/public/task/{}/json/'.format(task.id))
            self.assertTrue(res.status_code == expectedStatus)

        test_public_views(c, status.HTTP_404_NOT_FOUND)

        # Share task
        task.public = True
        task.save()

        # Can now access URLs even as anonymous user
        ac = Client()
        test_public_views(ac, status.HTTP_200_OK)