Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CMPUT401-Backend Code #1079

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 72 additions & 69 deletions Pipfile
Original file line number Diff line number Diff line change
@@ -1,69 +1,72 @@
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true

[dev-packages]
black = ">=19.10b0"
pytest = "==6.2.5"
pytest-django = "==4.4.0"
pytest-cov = "*"
pytest-datadir = "*"
pytest-mypy = "*"
hypothesis = {version = "~=4.34", extras = ["django"]}
codecov = "*"
pysnooper = "*"
python-levenshtein = "*"
django-debug-toolbar = "*"
isort = {extras = ["pyproject"],version = "*"}
toml = "*"
mypy = "*"
pytest-env = "*"
jupyterlab = "*"
appnope = "*"
nb_black = "*"
pandas = "*"
statsmodels = "*"
pandas-stubs = "*"
pytest-pythonpath = "*"
sphinx = "*"
myst-parser = "*"

[packages]
colorama = "~=0.4"
coverage = "*"
cree-sro-syllabics = ">=2020.6.23"
pytz = "==2019.2"
Django = "~=3.2"
typing-extensions = "~=3.7"
attrs = "~=19.1"
django-js-reverse = "~=0.9"
secure = "*"
snowballstemmer = "*"
dawg = "~=0.8"
environs = {extras = ["django"], version = "*"}
hfst-optimized-lookup = "*"
tqdm = "*"
whitenoise = "*"
foma = {subdirectory = "foma/python", git = "https://github.com/andrewdotn/foma"}
uwsgi = "*"
gensim = "*"
more-itertools = "~=8.7.0"
types-requests = "*"
requests = "*"

[scripts]
# unit tests
test = "pytest --mypy src"
runserver_for_tests = "env USE_TEST_DB=true ./crkeng-manage runserver"
# format
format = "black src"
# building the test db takes about half a minute
ensuretestdb = "env USE_TEST_DB=true ./crkeng-manage ensuretestdb"

[requires]
python_version = "3.9"

[pipenv]
# this allows "black>=19.10b0" to work
allow_prereleases = true
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true

[dev-packages]
black = ">=19.10b0"
pytest = "==6.2.5"
pytest-django = "==4.4.0"
pytest-cov = "*"
pytest-datadir = "*"
pytest-mypy = "*"
hypothesis = {version = "~=4.34", extras = ["django"]}
codecov = "*"
pathlib = "*"
pysnooper = "*"
python-levenshtein = "*"
django-debug-toolbar = "*"
isort = {extras = ["pyproject"],version = "*"}
toml = "*"
mypy = "*"
pytest-env = "*"
jupyterlab = "*"
appnope = "*"
nb_black = "*"
pandas = "*"
statsmodels = "*"
pandas-stubs = "*"
pytest-pythonpath = "*"
sphinx = "*"
myst-parser = "*"

[packages]
colorama = "~=0.4"
coverage = "*"
cree-sro-syllabics = ">=2020.6.23"
pytz = "==2019.2"
Django = "~=3.2"
typing-extensions = "~=3.7"
attrs = "~=19.1"
django-js-reverse = "~=0.9"
secure = "*"
snowballstemmer = "*"
dawg = "~=0.8"
environs = {extras = ["django"], version = "*"}
hfst-optimized-lookup = "*"
tqdm = "*"
whitenoise = "*"
foma = {subdirectory = "foma/python", git = "https://github.com/andrewdotn/foma"}
uwsgi = "*"
gensim = "*"
more-itertools = "~=8.7.0"
types-requests = "*"
requests = "*"
boto3 = "*"
paradigm-panes = "*"

[scripts]
# unit tests
test = "pytest --mypy src"
runserver_for_tests = "env USE_TEST_DB=true ./crkeng-manage runserver"
# format
format = "black src"
# building the test db takes about half a minute
ensuretestdb = "env USE_TEST_DB=true ./crkeng-manage ensuretestdb"

[requires]
python_version = "3.9"

[pipenv]
# this allows "black>=19.10b0" to work
allow_prereleases = true
213 changes: 213 additions & 0 deletions src/CreeDictionary/REST_API/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
# mypy: ignore-errors
import json
from urllib import response
from django.urls import reverse
from rest_framework import status
from rest_framework.authtoken.models import Token
from rest_framework.test import APITestCase
from rest_framework.test import APIRequestFactory
from .views import word_details_api, search_api


import requests

'''
By using https://www.sisense.com/blog/rest-api-testing-strategy-what-exactly-should-you-test/ as a resource on
RESTful application testing
'''

class Testing(APITestCase):
def test_database_search(self):
self.factory = APIRequestFactory()
'''
1. case where the search data in the database
'''
word = "atâhk"
expectedResponse1 = {"atâhk" : {
"Latn-x-macron": "atāhk",
"Latn": "atâhk",
"Cans": "ᐊᑖᕽ"},

}
expectedResponse2 = {"atâhk" : True}
expectedResponse3 = {"atâhk" : "atâhk"}
data = {"name": word}
request = self.factory.post('/api/search/', data, format='json')
#TESTING CORRECT STATUS CODE HTTP 200
response = search_api(request)
self.assertEqual(response.status_code, status.HTTP_200_OK)
#TESTING RESPONSE PAYLOAD
content = json.loads(response.content)
self.assertEqual(content["search_results"][0]["lemma_wordform"]["text"], expectedResponse1[word])
self.assertEqual(content["search_results"][0]["lemma_wordform"]["is_lemma"], expectedResponse2[word])
self.assertEqual(content["search_results"][0]["lemma_wordform"]["slug"], expectedResponse3[word])
return

def test_simple_word_search(self):
self.factory = APIRequestFactory()
'''
2. in database simple word
'''
word = "one"
expectedResponse1 = { word: {
"Latn-x-macron": "awa",
"Latn": "awa",
"Cans": "ᐊᐘ"},
}
expectedResponse2 = {"one": True}
expectedResponse3 = {"one": "awa@pra"}
data = {"name": word}
request = self.factory.post('/api/search/', data, format='json')
#TESTING CORRECT STATUS CODE HTTP 200
response = search_api(request)
self.assertEqual(response.status_code, status.HTTP_200_OK)
#TESTING RESPONSE PAYLOAD
content = json.loads(response.content)
self.assertEqual(content["search_results"][0]["lemma_wordform"]["text"], expectedResponse1[word])
self.assertEqual(content["search_results"][0]["lemma_wordform"]["is_lemma"], expectedResponse2[word])
self.assertEqual(content["search_results"][0]["lemma_wordform"]["slug"], expectedResponse3[word])
return

def test_word_space(self):
self.factory = APIRequestFactory()
'''
3. in database with space
'''
word = "to run"
expectedResponse1 = {word: {
"Latn-x-macron": "nōhtēpayiw",
"Latn": "nôhtêpayiw",
"Cans": "ᓅᐦᑌᐸᔨᐤ"}
}
expectedResponse2 = {"to run": True}
expectedResponse3 = {"to run": "nôhtêpayiw@vai"}
data = {"name": word}
request = self.factory.post('/api/search/', data, format='json')
#TESTING CORRECT STATUS CODE HTTP 200
response = search_api(request)
self.assertEqual(response.status_code, status.HTTP_200_OK)
#TESTING RESPONSE PAYLOAD
content = json.loads(response.content)
self.assertEqual(content["search_results"][0]["lemma_wordform"]["text"], expectedResponse1[word])
self.assertEqual(content["search_results"][0]["lemma_wordform"]["is_lemma"], expectedResponse2[word])
self.assertEqual(content["search_results"][0]["lemma_wordform"]["slug"], expectedResponse3[word])
return

def test_not_in_database(self):
self.factory = APIRequestFactory()
'''
4. SAD PATH testing: not in the database
'''
word = "%yes@yes"
data = {"name": word}
request = self.factory.post('/api/search/', data, format='json')
#TESTING CORRECT STATUS CODE HTTP 200
response = search_api(request)
self.assertEqual(response.status_code, status.HTTP_200_OK)
#TESTING RESPONSE PAYLOAD
content = json.loads(response.content)
self.assertEqual(content["search_results"], [])
return

def test_word_with_a_path(self):
self.factory = APIRequestFactory()
'''
5. SAD PATH testing: not in the database
'''
word = "/dsadasdas/asdafasfafasasf"
data = {"name": word}
request = self.factory.post('/api/search/', data, format='json')
#TESTING CORRECT STATUS CODE HTTP 200
response = search_api(request)
self.assertEqual(response.status_code, status.HTTP_200_OK)
#TESTING RESPONSE PAYLOAD
content = json.loads(response.content)
self.assertEqual(content["search_results"], [])
return

def test_slug_word_edgecase1(self):
self.factory = APIRequestFactory()
word = "atâhk"
expectedResponse1 = {word : {
"Latn-x-macron": "atāhk",
"Latn": "atâhk",
"Cans": "ᐊᑖᕽ"},
}
sluglist = {"atâhk" : "atâhk"}
url = "/api/word/" + sluglist[word] + "/"
request = self.factory.get(url, format='json')
response = word_details_api(request, sluglist[word])
content = json.loads(response.content)
#TESTING CORRECT STATUS CODE HTTP 200
self.assertEqual(response.status_code, status.HTTP_200_OK)
#TESTING RESPONSE PAYLOAD
self.assertEqual(content["nipaw_wordform"]["wordform"]["text"], expectedResponse1[word])

def test_slug_word_edgecase2(self):
self.factory = APIRequestFactory()
word = "one"
expectedResponse1 = {word : {
"Latn-x-macron": "awa",
"Latn": "awa",
"Cans": "ᐊᐘ"},
}
sluglist = {"one": "awa@pra"}
url = "/api/word/" + sluglist[word] + "/"
request = self.factory.get(url, format='json')
response = word_details_api(request, sluglist[word])
content = json.loads(response.content)
#TESTING CORRECT STATUS CODE HTTP 200
self.assertEqual(response.status_code, status.HTTP_200_OK)
#TESTING RESPONSE PAYLOAD
self.assertEqual(content["nipaw_wordform"]["wordform"]["text"], expectedResponse1[word])

def test_slug_word_edgecase3(self):
self.factory = APIRequestFactory()
word = "to run"
expectedResponse1 = {word : {
"Latn-x-macron": "nōhtēpayiw",
"Latn": "nôhtêpayiw",
"Cans": "ᓅᐦᑌᐸᔨᐤ"}
}
sluglist = {"to run": "nôhtêpayiw@vai"}
url = "/api/word/" + sluglist[word] + "/"
request = self.factory.get(url, format='json')
response = word_details_api(request, sluglist[word])
content = json.loads(response.content)
#TESTING CORRECT STATUS CODE HTTP 200
self.assertEqual(response.status_code, status.HTTP_200_OK)
#TESTING RESPONSE PAYLOAD
self.assertEqual(content["nipaw_wordform"]["wordform"]["text"], expectedResponse1[word])

def test_slug_word_bad_path(self):
#bad path
self.factory = APIRequestFactory()
word = "helloitsme" #random characters
url = "/api/word/" + word + "/"
request = self.factory.get(url, format='json')
response = word_details_api(request, word)
#TESTING CORRECT STATUS CODE HTTP 200
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)

def test_slug_word_bad_path_sql_injection(self):
#bad path
self.factory = APIRequestFactory()
word = "`SELECT`*`DROP" #random characters
url = "/api/word/" + word + "/"
request = self.factory.get(url, format='json')
response = word_details_api(request, word)
#TESTING CORRECT STATUS CODE HTTP 200
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)

if __name__ == "__main__":
test = Testing()
test.test_database_search()
test.test_simple_word_search()
test.test_word_space()
test.test_not_in_database()
test.test_word_with_a_path()
test.test_slug_word_edgecase1()
test.test_slug_word_edgecase2()
test.test_slug_word_edgecase3()
test.test_slug_word_bad_path()
test.test_slug_word_bad_path_sql_injection()
33 changes: 33 additions & 0 deletions src/CreeDictionary/REST_API/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
"""
Definition of urls for CreeDictionary.
"""

from django.conf import settings
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from django.urls import include, path

from CreeDictionary.CreeDictionary import views
from CreeDictionary.CreeDictionary.sitemaps import sitemaps
from . import views

urlpatterns = [
################################# Primary URLs #################################
path("api/", views.search_api, name="cree-dictionary-search"), #main page
path("api/search/", views.search_api, name="cree-dictionary-search"), #word_search returns wordforms as json
path(
"api/word/<str:slug>/",
views.word_details_api,
name="cree-dictionary-index-with-lemma",
), #returns details related to a spesific word
]


if settings.DEBUG:
# saves the need to `manage.py collectstatic` in development
urlpatterns += staticfiles_urlpatterns()

if settings.DEBUG and settings.ENABLE_DJANGO_DEBUG_TOOLBAR:
import debug_toolbar

# necessary for debug_toolbar to work
urlpatterns.append(path("api/__debug__/", include(debug_toolbar.urls)))
Loading