mirror of
https://expo.survex.com/repositories/troggle/.git
synced 2024-11-22 07:11:52 +00:00
fix side effects in tests: git and file upload
This commit is contained in:
parent
252fcc4716
commit
2869f228d4
@ -121,7 +121,8 @@ class SubprocessTest(TestCase):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def test_installs(self):
|
def test_installs(self):
|
||||||
''' Tests whether the external software is installed (but not whether it actually works)
|
'''Expects external software installed: cavern, survexport, git
|
||||||
|
(but not whether it actually works)
|
||||||
'''
|
'''
|
||||||
import troggle.settings as settings
|
import troggle.settings as settings
|
||||||
|
|
||||||
|
@ -7,10 +7,12 @@ Modified for Expo April 2021.
|
|||||||
|
|
||||||
import unittest
|
import unittest
|
||||||
import re
|
import re
|
||||||
|
import pathlib
|
||||||
from http import HTTPStatus
|
from http import HTTPStatus
|
||||||
|
|
||||||
from django.test import TestCase, SimpleTestCase, TransactionTestCase, Client
|
from django.test import TestCase, SimpleTestCase, TransactionTestCase, Client
|
||||||
|
|
||||||
|
import troggle.settings as settings
|
||||||
|
|
||||||
class DataTests(TestCase ):
|
class DataTests(TestCase ):
|
||||||
'''These check that the NULL and NON-UNIQUE constraints are working in the database '''
|
'''These check that the NULL and NON-UNIQUE constraints are working in the database '''
|
||||||
@ -77,7 +79,8 @@ class PostTests(TestCase):
|
|||||||
self.client = Client()
|
self.client = Client()
|
||||||
|
|
||||||
def test_scan_upload(self):
|
def test_scan_upload(self):
|
||||||
'''Test file upload. Need to login first.
|
'''Expect scan upload to wallet to work on any file
|
||||||
|
Need to login first.
|
||||||
'''
|
'''
|
||||||
c = self.client
|
c = self.client
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
@ -91,18 +94,22 @@ class PostTests(TestCase):
|
|||||||
content = response.content.decode()
|
content = response.content.decode()
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertEqual(response.status_code, HTTPStatus.OK)
|
self.assertEqual(response.status_code, HTTPStatus.OK)
|
||||||
# with open('testresponse.html', 'w') as f:
|
# with open('_test_response.html', 'w') as f:
|
||||||
# f.write(content)
|
# f.write(content)
|
||||||
for ph in [ r'test_upload_',
|
for ph in [ r'test_upload_',
|
||||||
r'← 2020#00 →',
|
r'← 2020#00 →',
|
||||||
r'Upload more?']:
|
r'Upload more?']:
|
||||||
phmatch = re.search(ph, content)
|
phmatch = re.search(ph, content)
|
||||||
self.assertIsNotNone(phmatch, "Failed to find expected text: '" + ph +"'")
|
self.assertIsNotNone(phmatch, "Failed to find expected text: '" + ph +"'")
|
||||||
|
|
||||||
|
# Does not use the filename Django actually uses, assumes it is unchanged. Potential bug.
|
||||||
|
remove_file = pathlib.Path(settings.SURVEY_SCANS) / '2020' / '2020#00'/ 'test_upload_file.txt'
|
||||||
|
remove_file.unlink()
|
||||||
|
|
||||||
def test_dwg_upload(self):
|
|
||||||
'''Test file upload. Need to login first.
|
def test_dwg_upload_txt(self):
|
||||||
First upload is refused as it is a TXT file
|
'''Expect .txt file to be refused upload
|
||||||
Second upload is an image and suceeds.
|
Need to login first.
|
||||||
'''
|
'''
|
||||||
c = self.client
|
c = self.client
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
@ -118,17 +125,32 @@ class PostTests(TestCase):
|
|||||||
t = re.search('Files refused:', content)
|
t = re.search('Files refused:', content)
|
||||||
self.assertIsNotNone(t, 'Logged in but failed to see "Files refused:"' )
|
self.assertIsNotNone(t, 'Logged in but failed to see "Files refused:"' )
|
||||||
|
|
||||||
|
def test_dwg_upload_drawing(self):
|
||||||
|
'''Expect no-suffix file to upload
|
||||||
|
Need to login first.
|
||||||
|
'''
|
||||||
|
c = self.client
|
||||||
|
from django.contrib.auth.models import User
|
||||||
|
u = User.objects.get(username='expotest')
|
||||||
|
|
||||||
|
self.assertTrue(u.is_active, 'User \'' + u.username + '\' is INACTIVE')
|
||||||
|
logged_in = c.login(username=u.username, password='secretword')
|
||||||
|
|
||||||
with open('core/fixtures/test_upload_nosuffix','r') as testf:
|
with open('core/fixtures/test_upload_nosuffix','r') as testf:
|
||||||
response = self.client.post('/dwgupload/uploads', data={'name': 'test_upload_nosuffix', 'uploadfiles': testf })
|
response = self.client.post('/dwguploadnogit/uploads', data={'name': 'test_upload_nosuffix', 'uploadfiles': testf })
|
||||||
content = response.content.decode()
|
content = response.content.decode()
|
||||||
with open('testresponse.html', 'w') as f:
|
# with open('_test_response.html', 'w') as f:
|
||||||
f.write(content)
|
# f.write(content)
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
for ph in [ r'Upload more',
|
for ph in [ r'Upload more',
|
||||||
r' saved as ',
|
r' saved as ',
|
||||||
r'Clicking on a filename only']:
|
r'Clicking on a filename only']:
|
||||||
phmatch = re.search(ph, content)
|
phmatch = re.search(ph, content)
|
||||||
self.assertIsNotNone(phmatch, "Failed to find expected text: '" + ph +"'")
|
self.assertIsNotNone(phmatch, "Failed to find expected text: '" + ph +"'")
|
||||||
|
|
||||||
|
# Does not use the filename Django actually uses, assumes it is unchanged. Potential bug.
|
||||||
|
remove_file = pathlib.Path(settings.DRAWINGS_DATA) / 'uploads' / 'test_upload_nosuffix'
|
||||||
|
remove_file.unlink()
|
||||||
|
|
||||||
|
|
||||||
class ComplexLoginTests(TestCase):
|
class ComplexLoginTests(TestCase):
|
||||||
|
@ -54,51 +54,5 @@ def dwgfilesingle(request, path):
|
|||||||
return HttpResponse(content=open(tfile, errors='ignore'), content_type="text/xhtml")
|
return HttpResponse(content=open(tfile, errors='ignore'), content_type="text/xhtml")
|
||||||
else:
|
else:
|
||||||
return HttpResponse(content="Unable to understand the encoding for this file: not UTF-8 nor iso-8859-1, or some other read error happened.")
|
return HttpResponse(content="Unable to understand the encoding for this file: not UTF-8 nor iso-8859-1, or some other read error happened.")
|
||||||
|
|
||||||
|
|
||||||
# def dwgfileupload(request, path):
|
|
||||||
# '''Use bits of this to REGISTEr a recently uploaded dwg file which used dwgupload
|
|
||||||
# '''
|
|
||||||
# try:
|
|
||||||
# dwgfile = DrawingFile.objects.get(dwgpath=urlunquote(path)) # need to check if inavlid query string and produce friendly error
|
|
||||||
# except:
|
|
||||||
# message = f'Drawing file error or not found \'{path}\' .'
|
|
||||||
# return render(request, 'errors/generic.html', {'message': message})
|
|
||||||
# tfile = Path(settings.DRAWINGS_DATA, dwgfile.dwgpath)
|
|
||||||
|
|
||||||
# project, user, password, tunnelversion = request.POST["tunnelproject"], request.POST["tunneluser"], request.POST["tunnelpassword"], request.POST["tunnelversion"]
|
|
||||||
# print(project, user, tunnelversion)
|
|
||||||
|
|
||||||
|
|
||||||
# if not (len(list(request.FILES.values())) == 1): # "only one file to upload"
|
|
||||||
# return HttpResponse(content="Error: more than one file selected for upload", content_type="text/plain")
|
|
||||||
|
|
||||||
# uploadedfile = list(request.FILES.values())[0]
|
|
||||||
|
|
||||||
# if uploadedfile.field_name != "sketch":
|
|
||||||
# return HttpResponse(content="Error: non-sketch file uploaded", content_type="text/plain")
|
|
||||||
# if uploadedfile.content_type != "text/plain":
|
|
||||||
# return HttpResponse(content="Error: non-plain content type", content_type="text/plain")
|
|
||||||
|
|
||||||
# # could use this to add new files
|
|
||||||
# if os.path.split(path)[1] != uploadedfile.name:
|
|
||||||
# return HttpResponse(content="Error: name disagrees", content_type="text/plain")
|
|
||||||
|
|
||||||
# orgsize = dwgfile.filesize # = os.stat(tfile)[stat.ST_SIZE]
|
|
||||||
|
|
||||||
# ttext = uploadedfile.read()
|
|
||||||
|
|
||||||
# # could check that the user and projects agree here
|
|
||||||
|
|
||||||
# fout = open(tfile, "w")
|
|
||||||
# fout.write(ttext)
|
|
||||||
# fout.close()
|
|
||||||
|
|
||||||
# # redo its settings of
|
|
||||||
# parsers.surveys.SetTunnelfileInfo(dwgfile) # commented out
|
|
||||||
# dwgfile.save()
|
|
||||||
|
|
||||||
# uploadedfile.close()
|
|
||||||
# message = "File size %d overwritten with size %d" % (orgsize, dwgfile.filesize)
|
|
||||||
# return HttpResponse(content=message, content_type="text/plain")
|
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ def scanupload(request, wallet=None):
|
|||||||
{'form': form, 'wallet': wallet, **context, 'files': files, 'dirs': dirs, 'filesaved': filesaved, 'actual_saved': actual_saved})
|
{'form': form, 'wallet': wallet, **context, 'files': files, 'dirs': dirs, 'filesaved': filesaved, 'actual_saved': actual_saved})
|
||||||
|
|
||||||
@login_required_if_public
|
@login_required_if_public
|
||||||
def dwgupload(request, folder=None):
|
def dwgupload(request, folder=None, gitdisable='no'):
|
||||||
'''Upload DRAWING files (tunnel or therion) into the upload folder in :drawings:
|
'''Upload DRAWING files (tunnel or therion) into the upload folder in :drawings:
|
||||||
This does NOT use a Django model linked to a Django form. Just a simple Django form.
|
This does NOT use a Django model linked to a Django form. Just a simple Django form.
|
||||||
|
|
||||||
@ -115,14 +115,14 @@ def dwgupload(request, folder=None):
|
|||||||
if name in [ '.gitignore', '.hgignore', ]:
|
if name in [ '.gitignore', '.hgignore', ]:
|
||||||
return False
|
return False
|
||||||
if Path(name).suffix.lower() in ['.xml', '.th', '.th2', '', '.svg', '.jpg', '.pdf', 'jpeg']:
|
if Path(name).suffix.lower() in ['.xml', '.th', '.th2', '', '.svg', '.jpg', '.pdf', 'jpeg']:
|
||||||
return True
|
return True # dangerous, we should check the actual file binary signature
|
||||||
return False
|
return False
|
||||||
|
|
||||||
filesaved = False
|
filesaved = False
|
||||||
actual_saved = []
|
actual_saved = []
|
||||||
refused = []
|
refused = []
|
||||||
doesnotexist = ''
|
doesnotexist = ''
|
||||||
#print(f'! - FORM dwgupload - start "{folder}"')
|
# print(f'! - FORM dwgupload - start "{folder}" - gitdisable "{gitdisable}"')
|
||||||
if folder is None:
|
if folder is None:
|
||||||
folder = "" # improve this later
|
folder = "" # improve this later
|
||||||
dirpath = Path(settings.DRAWINGS_DATA)
|
dirpath = Path(settings.DRAWINGS_DATA)
|
||||||
@ -144,28 +144,31 @@ def dwgupload(request, folder=None):
|
|||||||
|
|
||||||
actual_saved = []
|
actual_saved = []
|
||||||
refused = []
|
refused = []
|
||||||
git = settings.GIT
|
if gitdisable != 'yes': # set in url 'dwguploadnogit/'
|
||||||
|
git = settings.GIT
|
||||||
|
else:
|
||||||
|
git = 'echo'
|
||||||
|
|
||||||
if multiple:
|
if multiple:
|
||||||
for f in multiple:
|
for f in multiple:
|
||||||
if dwgvalid(f.name):
|
if dwgvalid(f.name):
|
||||||
saved_filename = fs.save(f.name, content=f)
|
saved_filename = fs.save(f.name, content=f)
|
||||||
actual_saved.append(saved_filename)
|
actual_saved.append(saved_filename)
|
||||||
subprocess.call([git, "add", saved_filename], cwd=dirpath)
|
if gitdisable != 'yes':
|
||||||
# dwgfile = DrawingFile(dwgpath=f.name, dwgname=Path(f.name).stem, filesize=f.size)
|
subprocess.call([git, "add", saved_filename], cwd=dirpath)
|
||||||
dwgfile, created = DrawingFile.objects.get_or_create(dwgpath=saved_filename, dwgname=Path(f.name).stem, filesize=f.size)
|
dwgfile, created = DrawingFile.objects.get_or_create(dwgpath=saved_filename, dwgname=Path(f.name).stem, filesize=f.size)
|
||||||
# if not created:
|
|
||||||
# print(f'FAILED to create {saved_filename} in {dirpath}')
|
|
||||||
# else:
|
|
||||||
# print(f'{dwgfile}')
|
|
||||||
dwgfile.save()
|
dwgfile.save()
|
||||||
else:
|
else:
|
||||||
refused.append(f.name)
|
refused.append(f.name)
|
||||||
# print(f'! - FORM dwgupload multiple {actual_saved}')
|
if actual_saved: # maybe all were refused by the suffix test in dwgvalid()
|
||||||
filesaved = True
|
filesaved = True
|
||||||
subprocess.call([git, "commit", "-m", 'dwgupload'], cwd=dirpath)
|
if gitdisable != 'yes':
|
||||||
|
subprocess.call([git, "commit", "-m", 'dwgupload'], cwd=dirpath)
|
||||||
|
|
||||||
|
|
||||||
files = []
|
files = []
|
||||||
dirs = []
|
dirs = []
|
||||||
#print(f'! - FORM dwgupload - start {folder} \n"{dirpath}" \n"{dirpath.parent}" \n"{dirpath.exists()}"')
|
# print(f'! - FORM dwgupload - start {folder} \n"{dirpath}" \n"{dirpath.parent}" \n"{dirpath.exists()}"')
|
||||||
try:
|
try:
|
||||||
for f in dirpath.iterdir():
|
for f in dirpath.iterdir():
|
||||||
if f.is_dir():
|
if f.is_dir():
|
||||||
|
16
urls.py
16
urls.py
@ -39,7 +39,11 @@ which is vital to writing code for the webapp. So the URL dispatch is declarativ
|
|||||||
The API urls return TSV or JSON and are new in July 2020.
|
The API urls return TSV or JSON and are new in July 2020.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
todo = '''Replace most re_path() with modern and simpler path(). Test VERY CAREFULLY for each chnage. It is fragile.
|
todo = '''Replace most re_path() with modern and simpler path().
|
||||||
|
The admin and logout paths need to stay using re_path() as they
|
||||||
|
have to be locked to the start.
|
||||||
|
The final _edit and CATCHALL also have to use re_path().
|
||||||
|
Test VERY CAREFULLY for each change. It is fragile.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
# Many of these patterns do not work because troggle spent many years broken and we have
|
# Many of these patterns do not work because troggle spent many years broken and we have
|
||||||
@ -80,9 +84,11 @@ trogglepatterns = [
|
|||||||
re_path(r'^admin/', admin.site.urls), # includes admin login & logout urls
|
re_path(r'^admin/', admin.site.urls), # includes admin login & logout urls
|
||||||
|
|
||||||
# Uploads - uploading a file
|
# Uploads - uploading a file
|
||||||
path('scanupload/<wallet>', scanupload, name='scanupload'), # wallet=2020#01, not a path
|
path('scanupload/<wallet>', scanupload, name='scanupload'), # wallet=2020#01, not a path
|
||||||
path('dwgupload/<path:folder>', dwgupload, name='dwgupload'),
|
path('dwgupload/<path:folder>', dwgupload, name='dwgupload'),
|
||||||
path('dwgupload/', dwgupload, name='dwgupload'),
|
path('dwgupload/', dwgupload, name='dwgupload'),
|
||||||
|
path('dwguploadnogit/', dwgupload, {'gitdisable': 'yes'}, name='dwguploadnogit'), # used in testing
|
||||||
|
path('dwguploadnogit/<path:folder>', dwgupload, {'gitdisable': 'yes'}, name='dwguploadnogit'), # used in testing
|
||||||
|
|
||||||
# setting LOGIN_URL = '/accounts/login/' is default
|
# setting LOGIN_URL = '/accounts/login/' is default
|
||||||
# url ENDS WITH this string
|
# url ENDS WITH this string
|
||||||
@ -160,8 +166,6 @@ trogglepatterns = [
|
|||||||
path('dwgfiles', dwgallfiles, name="dwgallfiles"),
|
path('dwgfiles', dwgallfiles, name="dwgallfiles"),
|
||||||
path('dwgfiles/', dwgallfiles, name="dwgallfiles"),
|
path('dwgfiles/', dwgallfiles, name="dwgallfiles"),
|
||||||
path('dwgdataraw/<path:path>', dwgfilesingle, name="dwgfilesingle"),
|
path('dwgdataraw/<path:path>', dwgfilesingle, name="dwgfilesingle"),
|
||||||
# path('dwgdataraw/<path:path>/upload', dwgfileupload, name="dwgfileupload"), # Not working
|
|
||||||
|
|
||||||
|
|
||||||
# QMs pages - must precede other /caves pages?
|
# QMs pages - must precede other /caves pages?
|
||||||
re_path(r'^cave/qms/([^/]+)/?$', caves.caveQMs), # Broken- QMs have no proper link to cave id
|
re_path(r'^cave/qms/([^/]+)/?$', caves.caveQMs), # Broken- QMs have no proper link to cave id
|
||||||
|
Loading…
Reference in New Issue
Block a user