Skip to content

Commit

Permalink
Merge pull request #32 from moshthepitt/issue-16
Browse files Browse the repository at this point in the history
Add read action
  • Loading branch information
moshthepitt authored Dec 29, 2018
2 parents dc687b6 + dfac00c commit 07a5e87
Show file tree
Hide file tree
Showing 9 changed files with 277 additions and 22 deletions.
1 change: 1 addition & 0 deletions tests/artist_app/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
urlpatterns = [
path('list/artists/', views.ArtistListView.as_view()),
path('edit/artists/create/', views.ArtistCreate.as_view()),
path('view/artists/read/<int:pk>', views.ArtistRead.as_view()),
path('edit/artists/edit/<int:pk>', views.ArtistUpdate.as_view()),
path('edit/artists/delete/<int:pk>', views.ArtistDelete.as_view()),
] + artist_crud_patterns + song_crud_patterns + custom_artist_crud_patterns +\
Expand Down
23 changes: 19 additions & 4 deletions tests/artist_app/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from django_filters import FilterSet
from vega_admin.mixins import SimpleURLPatternMixin
from vega_admin.views import (VegaCreateView, VegaCRUDView, VegaDeleteView,
VegaListView, VegaUpdateView)
VegaListView, VegaUpdateView, VegaDetailView)

from .forms import ArtistForm, CustomSearchForm, SongForm
from .models import Artist, Song
Expand Down Expand Up @@ -59,6 +59,14 @@ def get_success_url(self):
return "/edit/artists/create/"


class ArtistRead(VegaDetailView): # pylint: disable=too-many-ancestors
"""
Artist detail view
"""

model = Artist


class ArtistListView(VegaListView): # pylint: disable=too-many-ancestors
"""
Artist list view
Expand All @@ -78,6 +86,7 @@ class SongCRUD(VegaCRUDView):
protected_actions = None
permissions_actions = None
list_fields = ["name", "artist", ]
read_fields = ["name", "artist", ]
table_attrs = {"class": "song-table"}
table_actions = ["create", "update", "delete", ]
create_fields = ["name", "artist", ]
Expand All @@ -97,7 +106,7 @@ class FooView(SimpleURLPatternMixin, TemplateView):
"""random template view"""
template_name = "artist_app/empty.html"

protected_actions = ["create", "update", "delete", "template"]
protected_actions = ["create", "update", "delete", "template", "read", ]
permissions_actions = None
crud_path = "private-songs"
view_classes = {
Expand All @@ -112,8 +121,9 @@ class PermsSongCRUD(CustomSongCRUD):
CRUD view for songs with permissions protection
"""

protected_actions = ["create", "update", "delete", "artists", "list"]
permissions_actions = ["create", "update", "delete", "artists"]
protected_actions = [
"create", "update", "delete", "artists", "list", "read", ]
permissions_actions = ["create", "update", "delete", "artists", "read", ]
crud_path = "hidden-songs"
form_class = SongForm

Expand Down Expand Up @@ -148,8 +158,13 @@ class CustomDeleteView(ArtistDelete):
"""custom Delete view"""
pass

class CustomReadView(ArtistRead):
"""custom Read view"""
pass

view_classes = {
"list": CustomListView,
"read": CustomReadView,
"update": CustomUpdateView,
"create": CustomCreateView,
"delete": CustomDeleteView,
Expand Down
96 changes: 88 additions & 8 deletions tests/test_crud.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ def test_url_patterns(self):
f"/artist_app.artist/delete/{artist.pk}/",
reverse("artist_app.artist-delete", kwargs={"pk": artist.pk}),
)
self.assertEqual(
f"/artist_app.artist/read/{artist.pk}/",
reverse("artist_app.artist-read", kwargs={"pk": artist.pk}),
)
self.assertEqual(
f"/artist_app.artist/update/{artist.pk}/",
reverse("artist_app.artist-update", kwargs={"pk": artist.pk}),
Expand Down Expand Up @@ -82,6 +86,34 @@ def test_create(self):
html = f"""<!doctype html><html lang="en"><head><meta charset="utf-8"><title> Create professional artist</title></head><body><form id="artist-form" method="post" > <input type="hidden" name="csrfmiddlewaretoken" value="{csrf_token}"><div id="div_id_name" class="control-group"> <label for="id_name" class="control-label requiredField"> Name<span class="asteriskField">*</span> </label><div class="controls"> <input type="text" name="name" maxlength="100" class="textinput textInput" required id="id_name"></div></div><div class="form-actions"><div class="row" ><div class="col-md-12" ><div class="col-md-6" > <a href="/artist_app.artist/list/" class="btn vega-cancel"> Cancel </a></div><div class="col-md-6" > <input type="submit" name="submit" value="Submit" class="btn btn-primary vega-submit" id="submit-id-submit" /></div></div></div></div></form></body></html>""" # noqa
self.assertHTMLEqual(html, res.content.decode("utf-8"))

def test_read(self):
"""
Test CRUD read
"""
artist = mommy.make("artist_app.Artist", name="tt", id=436)
url = reverse("artist_app.artist-read", kwargs={"pk": artist.id})

# test content
res = self.client.get(url)
self.assertEqual(
"/artist_app.artist/list/", res.context_data["vega_list_url"])
self.assertEqual(
"/artist_app.artist/create/", res.context_data["vega_create_url"]
)
self.assertEqual(artist.name, res.context_data["vega_object_title"])
self.assertEqual(
["id", "name", ], res.context_data["vega_read_fields"])
self.assertDictEqual(
{"name": artist.name, "ID": artist.id},
res.context_data["vega_object_data"]
)
self.assertEqual(
f"/artist_app.artist/read/{artist.pk}/",
res.context_data["vega_read_url"],
)
html = f"""<!doctype html><html lang="en"><head><meta charset="utf-8"><title> tt | professional artist</title></head><body><h3>tt</h3> <strong>ID</strong>: 436 <br /> <strong>name</strong>: tt <br /></body></html>""" # noqa
self.assertHTMLEqual(html, res.content.decode("utf-8"))

def test_update(self):
"""
Test CRUD update
Expand All @@ -102,14 +134,13 @@ def test_update(self):

# test content
res = self.client.get(url)
self.assertEqual(
"/artist_app.artist/list/", res.context_data["vega_list_url"])
self.assertEqual(
"/artist_app.artist/create/", res.context_data["vega_create_url"]
)
self.assertEqual(
"/artist_app.artist/list/", res.context_data["vega_cancel_url"]
)
self.assertEqual("/artist_app.artist/list/",
res.context_data["vega_list_url"])
self.assertEqual("/artist_app.artist/create/",
res.context_data["vega_create_url"])
self.assertEqual("/artist_app.artist/list/",
res.context_data["vega_cancel_url"])
self.assertEqual(artist.name, res.context_data["vega_object_title"])
self.assertEqual(
f"/artist_app.artist/update/{artist.pk}/",
res.context_data["vega_update_url"],
Expand Down Expand Up @@ -155,6 +186,7 @@ def test_delete(self):
self.assertEqual(
"/artist_app.artist/list/", res.context_data["vega_cancel_url"]
)
self.assertEqual(str(artist2), res.context_data["vega_object_title"])
self.assertEqual(
f"/artist_app.artist/delete/{artist2.pk}/",
res.context_data["vega_delete_url"],
Expand Down Expand Up @@ -221,6 +253,13 @@ def test_custom_default_views(self):
self.assertIsInstance(res.context["view"],
CustomDefaultActions.CustomUpdateView)

url = reverse(
"custom-default-actions-read", kwargs={"pk": artist.pk})
res = self.client.get(url)
self.assertEqual(res.status_code, 200)
self.assertIsInstance(res.context["view"],
CustomDefaultActions.CustomReadView)

url = reverse(
"custom-default-actions-delete", kwargs={"pk": artist.pk})
res = self.client.get(url)
Expand Down Expand Up @@ -256,6 +295,25 @@ def test_create_options(self):
html = f"""<!doctype html><html lang="en"><head><meta charset="utf-8"><title> Create Song</title></head><body><form id="song-form" method="post" > <input type="hidden" name="csrfmiddlewaretoken" value="{csrf_token}"><div id="div_id_name" class="control-group"> <label for="id_name" class="control-label requiredField"> Name<span class="asteriskField">*</span> </label><div class="controls"> <input type="text" name="name" maxlength="100" class="textinput textInput" required id="id_name"></div></div><div id="div_id_artist" class="control-group"> <label for="id_artist" class="control-label requiredField"> Artist<span class="asteriskField">*</span> </label><div class="controls"> <select name="artist" class="select" required id="id_artist"><option value="" selected>---------</option></select></div></div><div class="form-actions"><div class="row" ><div class="col-md-12" ><div class="col-md-6" > <a href="/artist_app.song/list/" class="btn vega-cancel"> Cancel </a></div><div class="col-md-6" > <input type="submit" name="submit" value="Submit" class="btn btn-primary vega-submit" id="submit-id-submit" /></div></div></div></div></form></body></html>""" # noqa
self.assertHTMLEqual(html, res.content.decode("utf-8"))

def test_read_options(self):
"""
Test CRUD update with options
"""
artist = mommy.make("artist_app.Artist", name="Mosh")
song = mommy.make("artist_app.Song", name="Song 1", artist=artist)
url = reverse("artist_app.song-read", kwargs={"pk": song.id})
# test content
res = self.client.get(url)
self.assertEqual(
["name", "artist", ], res.context_data["vega_read_fields"])
self.assertDictEqual(
{"name": song.name, "artist": str(artist)},
res.context_data["vega_object_data"]
)
self.assertEqual(res.status_code, 200)
html = f"""<!doctype html><html lang="en"><head><meta charset="utf-8"><title> Song 1 | Song</title></head><body><h3>Song 1</h3> <strong>name</strong>: Song 1 <br /> <strong>artist</strong>: Mosh <br /></body></html>""" # noqa
self.assertHTMLEqual(html, res.content.decode("utf-8"))

def test_update_options(self):
"""
Test CRUD update with options
Expand Down Expand Up @@ -309,19 +367,27 @@ def test_login_protection(self):
song = mommy.make("artist_app.Song", name="Song 1", artist=artist)
create_url = reverse("private-songs-create")
update_url = reverse("private-songs-update", kwargs={"pk": song.id})
read_url = reverse("private-songs-read", kwargs={"pk": song.id})
delete_url = reverse("private-songs-delete", kwargs={"pk": song.id})
list_url = reverse("private-songs-list")

# first check that login is required
create_res = self.client.get(create_url)
self.assertEqual(302, create_res.status_code)
self.assertRedirects(create_res, f"/list/artists/?next={create_url}")

update_res = self.client.get(update_url)
self.assertEqual(302, update_res.status_code)
self.assertRedirects(update_res, f"/list/artists/?next={update_url}")

read_res = self.client.get(read_url)
self.assertEqual(302, read_res.status_code)
self.assertRedirects(read_res, f"/list/artists/?next={read_url}")

delete_res = self.client.get(delete_url)
self.assertEqual(302, delete_res.status_code)
self.assertRedirects(delete_res, f"/list/artists/?next={delete_url}")

list_res = self.client.get(list_url)
# the list action is not set to be protected
self.assertEqual(200, list_res.status_code)
Expand All @@ -335,6 +401,8 @@ def test_login_protection(self):
self.assertEqual(200, update_res.status_code)
delete_res = self.client.get(delete_url)
self.assertEqual(200, delete_res.status_code)
read_res = self.client.get(read_url)
self.assertEqual(200, read_res.status_code)
list_res = self.client.get(list_url)
self.assertEqual(200, list_res.status_code)

Expand Down Expand Up @@ -367,6 +435,7 @@ def test_permission_protection(self):
song = mommy.make("artist_app.Song", name="Song 42", artist=artist)
create_url = reverse("hidden-songs-create")
update_url = reverse("hidden-songs-update", kwargs={"pk": song.id})
read_url = reverse("hidden-songs-read", kwargs={"pk": song.id})
delete_url = reverse("hidden-songs-delete", kwargs={"pk": song.id})
artists_url = reverse("hidden-songs-artists")
list_url = reverse("hidden-songs-list") # not protected
Expand All @@ -381,6 +450,10 @@ def test_permission_protection(self):
self.assertEqual(302, update_res.status_code)
self.assertRedirects(update_res, f"/list/artists/?next={update_url}")

read_res = self.client.get(read_url)
self.assertEqual(302, read_res.status_code)
self.assertRedirects(read_res, f"/list/artists/?next={read_url}")

delete_res = self.client.get(delete_url)
self.assertEqual(302, delete_res.status_code)
self.assertRedirects(delete_res, f"/list/artists/?next={delete_url}")
Expand Down Expand Up @@ -409,6 +482,10 @@ def test_permission_protection(self):
self.assertEqual(302, update_res.status_code)
self.assertRedirects(update_res, f"/list/artists/?next={update_url}")

read_res = self.client.get(read_url)
self.assertEqual(302, read_res.status_code)
self.assertRedirects(read_res, f"/list/artists/?next={read_url}")

delete_res = self.client.get(delete_url)
self.assertEqual(302, delete_res.status_code)
self.assertRedirects(delete_res, f"/list/artists/?next={delete_url}")
Expand Down Expand Up @@ -437,6 +514,9 @@ def test_permission_protection(self):
update_res = self.client.get(update_url)
self.assertEqual(200, update_res.status_code)

read_res = self.client.get(read_url)
self.assertEqual(200, read_res.status_code)

delete_res = self.client.get(delete_url)
self.assertEqual(200, delete_res.status_code)

Expand Down
36 changes: 31 additions & 5 deletions tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@
from model_mommy import mommy

from vega_admin.views import (VegaCreateView, VegaCRUDView, VegaDeleteView,
VegaListView, VegaUpdateView)
VegaListView, VegaDetailView, VegaUpdateView)

from .artist_app.forms import ArtistForm
from .artist_app.models import Artist, Song
from .artist_app.views import (ArtistCreate, ArtistDelete, ArtistListView,
ArtistUpdate)
ArtistRead, ArtistUpdate)


class TestViewsBase(TestCase):
Expand All @@ -37,6 +37,11 @@ def _song_permissions(self):
content_type=content_type,
defaults=dict(name='Can Create Songs'),
)
read_permission, _ = Permission.objects.get_or_create(
codename='read_song',
content_type=content_type,
defaults=dict(name='Can View Songs'),
)
update_permission, _ = Permission.objects.get_or_create(
codename='update_song',
content_type=content_type,
Expand All @@ -53,7 +58,7 @@ def _song_permissions(self):
defaults=dict(name='Can List Song Artists'),
)
return [list_permission, create_permission, update_permission,
delete_permission, artists_permission, ]
delete_permission, artists_permission, read_permission, ]

def _artist_permissions(self):
"""
Expand Down Expand Up @@ -84,7 +89,7 @@ def setUp(self):

def tearDown(self):
"""tearDown"""
super().setUp()
super().tearDown()
Song.objects.all().delete()
Artist.objects.all().delete()
Permission.objects.filter(
Expand All @@ -104,7 +109,7 @@ def test_vega_crud_view(self):
"""
Test VegaCRUDView
"""
default_actions = ["create", "update", "list", "delete"]
default_actions = ["create", "read", "update", "list", "delete"]

class ArtistCrud(VegaCRUDView):
model = Artist
Expand All @@ -126,6 +131,8 @@ class ArtistCrud(VegaCRUDView):
Artist, view.get_view_class_for_action("delete")().model)
self.assertEqual(
Artist, view.get_view_class_for_action("list")().model)
self.assertEqual(
Artist, view.get_view_class_for_action("read")().model)

self.assertIsInstance(
view.get_view_class_for_action("create")(), VegaCreateView
Expand All @@ -138,13 +145,21 @@ class ArtistCrud(VegaCRUDView):
)
self.assertIsInstance(
view.get_view_class_for_action("list")(), VegaListView)
self.assertIsInstance(
view.get_view_class_for_action("read")(), VegaDetailView)

self.assertEqual(
f"{view.crud_path}/create/",
view.get_url_pattern_for_action(
view.get_view_class_for_action("create"), "create"
),
)
self.assertEqual(
f"{view.crud_path}/read/<int:pk>/",
view.get_url_pattern_for_action(
view.get_view_class_for_action("read"), "read"
),
)
self.assertEqual(
f"{view.crud_path}/list/",
view.get_url_pattern_for_action(
Expand Down Expand Up @@ -194,6 +209,17 @@ def test_vega_list_view(self):
self.assertEqual(res.context["object_list"].count(), 1)
self.assertEqual(res.context["object_list"].first(), artist)

def test_vega_read_view(self):
"""
Test VegaReadView
"""
artist = mommy.make("artist_app.Artist", name="Bob")
res = self.client.get(f"/view/artists/read/{artist.id}")
self.assertEqual(res.status_code, 200)
self.assertIsInstance(res.context["view"], ArtistRead)
self.assertIsInstance(res.context["view"], VegaDetailView)
self.assertTemplateUsed(res, "vega_admin/basic/read.html")

def test_vega_create_view(self):
"""
Test VegaCreateView
Expand Down
2 changes: 1 addition & 1 deletion vega_admin/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""
Main init file for vega_admin
"""
VERSION = (0, 0, 4)
VERSION = (0, 0, 5)
__version__ = '.'.join(str(v) for v in VERSION)
# pylint: disable=invalid-name
default_app_config = 'vega_admin.apps.VegaAdminConfig' # noqa
Loading

0 comments on commit 07a5e87

Please sign in to comment.