OpenDroneMap-WebODM/app/tests/test_app.py

271 wiersze
10 KiB
Python

from django.contrib.auth.models import User, Group
from django.test import Client
from rest_framework import status
from guardian.shortcuts import assign_perm
from nodeodm.models import ProcessingNode
from app.models import Project, Task
from app.models import Setting
from app.models import Theme
from webodm import settings
from .classes import BootTestCase
from django.core.exceptions import ValidationError
class TestApp(BootTestCase):
fixtures = ['test_processingnodes', ]
def setUp(self):
self.credentials = {
'username': 'testuser',
'password': 'test1234',
'email': 'test@mail.com'}
# Create a test Group
my_group, created = Group.objects.get_or_create(name='test_group')
# Add user to test Group
User.objects.get(pk=1).groups.add(my_group)
# Add view permissions
user = User.objects.get(username=self.credentials['username'])
pns = ProcessingNode.objects.all()
for pn in pns:
assign_perm('view_processingnode', user, pn)
def test_user_login(self):
c = Client()
# User points the browser to the landing page
res = c.post('/', follow=True)
# the user is not logged in
self.assertFalse(res.context['user'].is_authenticated)
# and is redirected to the login page
self.assertRedirects(res, '/login/')
# The login page is being rendered by the correct template
self.assertTemplateUsed(res, 'registration/login.html')
# asks the user to login using a set of valid credentials
res = c.post('/login/', data=self.credentials, follow=True)
# The system acknowledges him
self.assertTrue(res.context['user'].is_authenticated)
# and moves him at the dashboard
self.assertTemplateUsed(res, 'app/dashboard.html')
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)
# The menu should have 3 processing nodes
res = c.get('/dashboard/', follow=True)
self.assertEqual(res.content.decode("utf-8").count('href="/processingnode/'), 3)
self.assertTemplateUsed(res, 'app/dashboard.html')
# The API should return 3 nodes
res = c.get('/api/processingnodes/')
self.assertEqual(len(res.data), 3)
# We can change that with a setting
settings.UI_MAX_PROCESSING_NODES = 1
res = c.get('/dashboard/', follow=True)
self.assertEqual(res.content.decode("utf-8").count('href="/processingnode/'), 1)
self.assertTemplateUsed(res, 'app/dashboard.html')
res = c.get('/api/processingnodes/')
self.assertEqual(len(res.data), 1)
settings.UI_MAX_PROCESSING_NODES = None
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)
def test_admin_views(self):
c = Client()
c.login(username='testsuperuser', password='test1234')
settingId = Setting.objects.all()[0].id # During tests, sometimes this is != 1
themeId = Theme.objects.all()[0].id # During tests, sometimes this is != 1
# Can access admin menu items
admin_menu_items = ['/admin/app/setting/{}/change/'.format(settingId),
'/admin/app/theme/{}/change/'.format(themeId),
'/admin/',
'/admin/app/plugin/',
'/admin/auth/user/',
'/admin/auth/group/',
]
for url in admin_menu_items:
res = c.get(url)
self.assertEqual(res.status_code, status.HTTP_200_OK)
# Cannot access dev tools (not in dev mode)
settings.DEV = False
self.assertEqual(c.get('/dev-tools/').status_code, status.HTTP_404_NOT_FOUND)
settings.DEV = True
# Can access in dev mode
self.assertEqual(c.get('/dev-tools/').status_code, status.HTTP_200_OK)
# Cannot access admin views as normal user
c.logout()
c.login(username='testuser', password='test1234')
# Can never access dev tools as user, even in dev mode
self.assertRedirects(c.get('/dev-tools/', follow=True), '/login/?next=/dev-tools/')
settings.DEV = False
for url in admin_menu_items:
res = c.get(url, follow=True)
self.assertRedirects(res, '/admin/login/?next={}'.format(url))
def test_default_group(self):
# It exists
self.assertTrue(Group.objects.filter(name='Default').count() == 1)
# Verify that all new users are assigned to default group
u = User.objects.create_user(username="default_user")
u.refresh_from_db()
self.assertTrue(u.groups.filter(name='Default').count() == 1)
def test_projects(self):
# Get a normal user
user = User.objects.get(username="testuser")
self.assertFalse(user.is_superuser)
# Create a new project
p = Project.objects.create(owner=user, name="test")
# Have the proper permissions been set?
self.assertTrue(user.has_perm("view_project", p))
self.assertTrue(user.has_perm("add_project", p))
self.assertTrue(user.has_perm("change_project", p))
self.assertTrue(user.has_perm("delete_project", p))
# Get a superuser
superUser = User.objects.get(username="testsuperuser")
self.assertTrue(superUser.is_superuser)
# He should also have permissions, although not explicitly set
self.assertTrue(superUser.has_perm("delete_project", p))
# Get another user
anotherUser = User.objects.get(username="testuser2")
self.assertFalse(anotherUser.is_superuser)
# Should not have permission
self.assertFalse(anotherUser.has_perm("delete_project", p))
def test_tasks(self):
# Create a new task
p = Project.objects.create(owner=User.objects.get(username="testuser"), name="test")
task = Task.objects.create(project=p)
# Test options validation
task.options = [{'name': 'test', 'value': 1}]
self.assertTrue(task.save() is None)
task.options = {'test': 1}
self.assertRaises(ValidationError, task.save)
task.options = [{'name': 'test', 'value': 1}, {"invalid": 1}]
self.assertRaises(ValidationError, task.save)