Commit efec1fff by Matt Drayer Committed by Jonathan Piacenti

mattdrayer/api-projectreviews: Added new ProjectReview entity/views

parent 42ab8e11
......@@ -76,3 +76,5 @@ class SystemApiTests(TestCase):
self.assertGreater(len(response.data['name']), 0)
self.assertIsNotNone(response.data['description'])
self.assertGreater(len(response.data['description']), 0)
self.assertIsNotNone(response.data['resources'])
......@@ -51,6 +51,7 @@ class ApiDetail(SecureAPIView):
response_data['resources'] = []
response_data['resources'].append({'uri': base_uri + 'courses'})
response_data['resources'].append({'uri': base_uri + 'groups'})
response_data['resources'].append({'uri': base_uri + 'projects'})
response_data['resources'].append({'uri': base_uri + 'sessions'})
response_data['resources'].append({'uri': base_uri + 'system'})
response_data['resources'].append({'uri': base_uri + 'users'})
......
......@@ -32,9 +32,10 @@ router.register(r'organizations', OrganizationsViewSet)
# Project-related ViewSets
router.register(r'projects', project_views.ProjectsViewSet)
router.register(r'workgroups', project_views.WorkgroupsViewSet)
router.register(r'submissions', project_views.SubmissionsViewSet)
router.register(r'submission_reviews', project_views.SubmissionReviewsViewSet)
router.register(r'peer_reviews', project_views.PeerReviewsViewSet)
router.register(r'submissions', project_views.WorkgroupSubmissionsViewSet)
router.register(r'workgroup_reviews', project_views.WorkgroupReviewsViewSet)
router.register(r'submission_reviews', project_views.WorkgroupSubmissionReviewsViewSet)
router.register(r'peer_reviews', project_views.WorkgroupPeerReviewsViewSet)
router.register(r'groups', project_views.GroupViewSet)
router.register(r'users', project_views.UserViewSet)
urlpatterns += router.urls
......@@ -2,18 +2,9 @@
from django.contrib.auth.models import Group, User
from django.db import models
from model_utils.models import TimeStampedModel
class Workgroup(TimeStampedModel):
"""
Model representing the Workgroup concept. Workgroups are an
intersection of Users and CourseContent, although they can also be
related to other Groups.
"""
name = models.CharField(max_length=255, null=True, blank=True)
users = models.ManyToManyField(User, related_name="workgroups")
groups = models.ManyToManyField(Group, related_name="workgroups")
from model_utils.models import TimeStampedModel
from student.models import AnonymousUserId
class Project(TimeStampedModel):
......@@ -23,47 +14,71 @@ class Project(TimeStampedModel):
"""
course_id = models.CharField(max_length=255)
content_id = models.CharField(max_length=255)
workgroups = models.ManyToManyField(Workgroup, related_name="projects")
class Meta:
""" Meta class for defining additional model characteristics """
unique_together = ("course_id", "content_id")
class Submission(TimeStampedModel):
class Workgroup(TimeStampedModel):
"""
Model representing the Workgroup concept. Workgroups are an
intersection of Users and CourseContent, although they can also be
related to other Groups.
"""
name = models.CharField(max_length=255, null=True, blank=True)
project = models.ForeignKey(Project, related_name="workgroups")
users = models.ManyToManyField(User, related_name="workgroups", blank=True, null=True)
groups = models.ManyToManyField(Group, related_name="workgroups", blank=True, null=True)
class WorkgroupReview(TimeStampedModel):
"""
Model representing the Workgroup Review concept. A Workgroup Review is
a single question/answer combination for a particular Workgroup in the
context of a specific Project, as defined in the Group Project XBlock
schema. There can be more than one Project Review entry for a given Project.
"""
workgroup = models.ForeignKey(Workgroup, related_name="workgroup_reviews")
reviewer = models.CharField(max_length=255) # AnonymousUserId
question = models.CharField(max_length=255)
answer = models.CharField(max_length=255)
class WorkgroupSubmission(TimeStampedModel):
"""
Model representing the Submission concept. A Submission is a project artifact
created by the Users in a Workgroup. The document fields are defined by the
'Group Project' XBlock and data for a specific instance is persisted here
"""
user = models.ForeignKey(User)
workgroup = models.ForeignKey(Workgroup, related_name="submissions")
project = models.ForeignKey(Project, related_name="projects")
user = models.ForeignKey(User, related_name="submissions")
document_id = models.CharField(max_length=255)
document_url = models.CharField(max_length=255)
document_mime_type = models.CharField(max_length=255)
class SubmissionReview(TimeStampedModel):
class WorkgroupSubmissionReview(TimeStampedModel):
"""
Model representing the Submission Review concept. A Submission Review is
essentially a single question/answer combination for a particular Submission,
defined in the Group Project XBlock schema. There can be more than one
Submission Review for a given Submission.
Submission Review entry for a given Submission.
"""
submission = models.ForeignKey(Submission, related_name="submission_reviews")
reviewer = models.ForeignKey(User, related_name="submission_reviews")
submission = models.ForeignKey(WorkgroupSubmission, related_name="reviews")
reviewer = models.CharField(max_length=255) # AnonymousUserId
question = models.CharField(max_length=255)
answer = models.CharField(max_length=255)
class PeerReview(TimeStampedModel):
class WorkgroupPeerReview(TimeStampedModel):
"""
Model representing the Peer Review concept. A Peer Review is a record of a
specific question/answer defined in the Group Project XBlock schema. There
can be more than one Peer Review for a given User.
can be more than one Peer Review entry for a given User.
"""
user = models.ForeignKey(User, related_name="peer_reviewees")
reviewer = models.ForeignKey(User, related_name="peer_reviewers")
workgroup = models.ForeignKey(Workgroup, related_name="peer_reviews")
user = models.ForeignKey(User, related_name="workgroup_peer_reviewees")
reviewer = models.CharField(max_length=255) # AnonymousUserId
question = models.CharField(max_length=255)
answer = models.CharField(max_length=255)
......@@ -5,8 +5,8 @@ from django.core.exceptions import ObjectDoesNotExist
from rest_framework import serializers
from .models import Workgroup, Project, Submission
from .models import SubmissionReview, PeerReview
from .models import Project, Workgroup, WorkgroupSubmission
from .models import WorkgroupReview, WorkgroupSubmissionReview, WorkgroupPeerReview
class UserSerializer(serializers.HyperlinkedModelSerializer):
......@@ -40,56 +40,88 @@ class GroupSerializer(serializers.HyperlinkedModelSerializer):
fields = ('id', 'url', 'name')
class WorkgroupSerializer(serializers.HyperlinkedModelSerializer):
class ProjectSerializer(serializers.HyperlinkedModelSerializer):
""" Serializer for model interactions """
groups = GroupSerializer(many=True, required=False)
users = UserSerializer(many=True, required=False)
workgroups = serializers.PrimaryKeyRelatedField(many=True, required=False)
class Meta:
""" Meta class for defining additional serializer characteristics """
model = Workgroup
fields = ('id', 'url', 'created', 'modified', 'name', 'groups', 'users')
model = Project
fields = (
'id', 'url', 'created', 'modified', 'course_id', 'content_id',
'workgroups'
)
class ProjectSerializer(serializers.HyperlinkedModelSerializer):
class WorkgroupSubmissionSerializer(serializers.HyperlinkedModelSerializer):
""" Serializer for model interactions """
workgroups = WorkgroupSerializer(many=True, required=False)
user = serializers.PrimaryKeyRelatedField(required=True)
workgroup = serializers.PrimaryKeyRelatedField(required=True)
reviews = serializers.PrimaryKeyRelatedField(many=True, required=False)
class Meta:
""" Meta class for defining additional serializer characteristics """
model = Project
fields = ('id', 'url', 'created', 'modified', 'course_id', 'content_id', 'workgroups')
model = WorkgroupSubmission
fields = (
'id', 'url', 'created', 'modified', 'document_id', 'document_url', 'document_mime_type',
'user', 'workgroup', 'reviews'
)
class SubmissionSerializer(serializers.HyperlinkedModelSerializer):
class WorkgroupReviewSerializer(serializers.HyperlinkedModelSerializer):
""" Serializer for model interactions """
user = serializers.PrimaryKeyRelatedField(required=True)
project = serializers.PrimaryKeyRelatedField(required=True)
workgroup = serializers.PrimaryKeyRelatedField(required=True)
class Meta:
""" Meta class for defining additional serializer characteristics """
model = Submission
fields = ('id', 'url', 'created', 'modified', 'user', 'project', 'workgroup', 'document_id', 'document_url', 'document_mime_type')
model = WorkgroupReview
fields = (
'id', 'url', 'created', 'modified', 'question', 'answer',
'workgroup', 'reviewer'
)
class SubmissionReviewSerializer(serializers.HyperlinkedModelSerializer):
class WorkgroupSubmissionReviewSerializer(serializers.HyperlinkedModelSerializer):
""" Serializer for model interactions """
submission = serializers.PrimaryKeyRelatedField(required=True)
reviewer = serializers.PrimaryKeyRelatedField(required=True)
submission = serializers.PrimaryKeyRelatedField(required=True, queryset=WorkgroupSubmission.objects.all())
class Meta:
""" Meta class for defining additional serializer characteristics """
model = SubmissionReview
fields = ('id', 'url', 'created', 'modified', 'submission', 'reviewer', 'question', 'answer')
model = WorkgroupSubmissionReview
fields = (
'id', 'url', 'created', 'modified', 'question', 'answer',
'submission', 'reviewer'
)
class PeerReviewSerializer(serializers.HyperlinkedModelSerializer):
class WorkgroupPeerReviewSerializer(serializers.HyperlinkedModelSerializer):
""" Serializer for model interactions """
workgroup = serializers.PrimaryKeyRelatedField(required=True)
user = serializers.PrimaryKeyRelatedField(required=True)
reviewer = serializers.PrimaryKeyRelatedField(required=True)
class Meta:
""" Meta class for defining additional serializer characteristics """
model = PeerReview
fields = ('id', 'url', 'created', 'modified', 'user', 'reviewer', 'question', 'answer')
model = WorkgroupPeerReview
fields = (
'id', 'url', 'created', 'modified', 'question', 'answer',
'workgroup', 'user', 'reviewer'
)
class WorkgroupSerializer(serializers.HyperlinkedModelSerializer):
""" Serializer for model interactions """
project = serializers.PrimaryKeyRelatedField(required=True)
groups = GroupSerializer(many=True, required=False)
users = UserSerializer(many=True, required=False)
submissions = serializers.PrimaryKeyRelatedField(many=True, required=False)
workgroup_reviews = serializers.PrimaryKeyRelatedField(many=True, required=False)
peer_reviews = serializers.PrimaryKeyRelatedField(many=True, required=False)
class Meta:
""" Meta class for defining additional serializer characteristics """
model = Workgroup
fields = (
'id', 'url', 'created', 'modified', 'name', 'project',
'groups', 'users', 'submissions',
'workgroup_reviews', 'peer_reviews'
)
......@@ -13,6 +13,7 @@ from django.test import TestCase, Client
from django.test.utils import override_settings
from projects.models import Project, Workgroup
from student.models import anonymous_id_for_user
TEST_API_KEY = str(uuid.uuid4())
......@@ -58,21 +59,20 @@ class PeerReviewsApiTests(TestCase):
username="reviewer",
is_active=True
)
self.anonymous_user_id = anonymous_id_for_user(self.test_reviewer_user, self.test_course_id)
self.test_project = Project.objects.create(
course_id=self.test_course_id,
content_id=self.test_course_content_id,
)
self.test_workgroup = Workgroup.objects.create(
name="Test Workgroup",
project=self.test_project,
)
self.test_workgroup.users.add(self.test_peer_user)
self.test_workgroup.users.add(self.test_reviewer_user)
self.test_workgroup.save()
self.test_project = Project.objects.create(
course_id=self.test_course_id,
content_id=self.test_course_content_id,
)
self.test_project.workgroups.add(self.test_workgroup)
self.test_project.save()
self.client = SecureClient()
cache.clear()
......@@ -107,8 +107,9 @@ class PeerReviewsApiTests(TestCase):
def test_peer_reviews_list_post(self):
data = {
'workgroup': self.test_workgroup.id,
'user': self.test_peer_user.id,
'reviewer': self.test_reviewer_user.id,
'reviewer': self.anonymous_user_id,
'question': self.test_question,
'answer': self.test_answer,
}
......@@ -123,25 +124,17 @@ class PeerReviewsApiTests(TestCase):
self.assertEqual(response.data['url'], confirm_uri)
self.assertGreater(response.data['id'], 0)
self.assertEqual(response.data['user'], self.test_peer_user.id)
self.assertEqual(response.data['reviewer'], self.test_reviewer_user.id)
self.assertEqual(response.data['reviewer'], self.anonymous_user_id)
self.assertEqual(response.data['question'], self.test_question)
self.assertEqual(response.data['answer'], self.test_answer)
self.assertEqual(response.data['workgroup'], self.test_workgroup.id)
self.assertIsNotNone(response.data['created'])
self.assertIsNotNone(response.data['modified'])
def test_peer_reviews_list_post_invalid_relationships(self):
data = {
'user': 123456,
'reviewer': self.test_reviewer_user.id,
'question': self.test_question,
'answer': self.test_answer,
}
response = self.do_post(self.test_peer_reviews_uri, data)
self.assertEqual(response.status_code, 400)
data = {
'user': self.test_peer_user.id,
'reviewer': 123456,
'reviewer': self.anonymous_user_id,
'question': self.test_question,
'answer': self.test_answer,
}
......@@ -150,8 +143,9 @@ class PeerReviewsApiTests(TestCase):
def test_peer_reviews_detail_get(self):
data = {
'workgroup': self.test_workgroup.id,
'user': self.test_peer_user.id,
'reviewer': self.test_reviewer_user.id,
'reviewer': self.anonymous_user_id,
'question': self.test_question,
'answer': self.test_answer,
}
......@@ -168,7 +162,7 @@ class PeerReviewsApiTests(TestCase):
self.assertEqual(response.data['url'], confirm_uri)
self.assertGreater(response.data['id'], 0)
self.assertEqual(response.data['user'], self.test_peer_user.id)
self.assertEqual(response.data['reviewer'], self.test_reviewer_user.id)
self.assertEqual(response.data['reviewer'], self.anonymous_user_id)
self.assertEqual(response.data['question'], self.test_question)
self.assertEqual(response.data['answer'], self.test_answer)
self.assertIsNotNone(response.data['created'])
......@@ -181,8 +175,9 @@ class PeerReviewsApiTests(TestCase):
def test_peer_reviews_detail_delete(self):
data = {
'workgroup': self.test_workgroup.id,
'user': self.test_peer_user.id,
'reviewer': self.test_reviewer_user.id,
'reviewer': self.anonymous_user_id,
'question': self.test_question,
'answer': self.test_answer,
}
......
......@@ -7,11 +7,12 @@ Run these tests @ Devstack:
import json
import uuid
from django.contrib.auth.models import User
from django.core.cache import cache
from django.test import TestCase, Client
from django.test.utils import override_settings
from projects.models import Workgroup
from projects.models import Project, Workgroup
TEST_API_KEY = str(uuid.uuid4())
......@@ -41,9 +42,23 @@ class ProjectsApiTests(TestCase):
self.test_course_content_id = "i4x://blah"
self.test_bogus_course_content_id = "14x://foo/bar/baz"
self.test_user = User.objects.create(
email="test@edx.org",
username="testing",
is_active=True
)
self.test_project = Project.objects.create(
course_id=self.test_course_id,
content_id=self.test_course_content_id,
)
self.test_workgroup = Workgroup.objects.create(
name="Test Workgroup",
project=self.test_project,
)
self.test_workgroup.users.add(self.test_user)
self.test_workgroup.save()
self.client = SecureClient()
cache.clear()
......@@ -78,10 +93,11 @@ class ProjectsApiTests(TestCase):
return response
def test_projects_list_post(self):
test_course_content_id = "i4x://blahblah1234"
data = {
'name': self.test_project_name,
'course_id': self.test_course_id,
'content_id': self.test_course_content_id
'content_id': test_course_content_id
}
response = self.do_post(self.test_projects_uri, data)
self.assertEqual(response.status_code, 201)
......@@ -94,20 +110,13 @@ class ProjectsApiTests(TestCase):
self.assertEqual(response.data['url'], confirm_uri)
self.assertGreater(response.data['id'], 0)
self.assertEqual(response.data['course_id'], self.test_course_id)
self.assertEqual(response.data['content_id'], self.test_course_content_id)
self.assertEqual(response.data['content_id'], test_course_content_id)
self.assertIsNotNone(response.data['workgroups'])
self.assertIsNotNone(response.data['created'])
self.assertIsNotNone(response.data['modified'])
def test_projects_detail_get(self):
data = {
'name': self.test_project_name,
'course_id': self.test_course_id,
'content_id': self.test_course_content_id
}
response = self.do_post(self.test_projects_uri, data)
self.assertEqual(response.status_code, 201)
test_uri = '{}{}/'.format(self.test_projects_uri, str(response.data['id']))
test_uri = '{}{}/'.format(self.test_projects_uri, self.test_project.id)
response = self.do_get(test_uri)
self.assertEqual(response.status_code, 200)
confirm_uri = self.test_server_prefix + test_uri
......@@ -120,36 +129,20 @@ class ProjectsApiTests(TestCase):
self.assertIsNotNone(response.data['modified'])
def test_projects_workgroups_post(self):
data = {
'name': self.test_project_name,
'course_id': self.test_course_id,
'content_id': self.test_course_content_id
}
response = self.do_post(self.test_projects_uri, data)
self.assertEqual(response.status_code, 201)
test_uri = '{}{}/'.format(self.test_projects_uri, str(response.data['id']))
workgroups_uri = '{}workgroups/'.format(test_uri)
test_uri = '{}{}/workgroups/'.format(self.test_projects_uri, self.test_project.id)
data = {"id": self.test_workgroup.id}
response = self.do_post(workgroups_uri, data)
response = self.do_post(test_uri, data)
self.assertEqual(response.status_code, 201)
response = self.do_get(test_uri)
self.assertEqual(response.status_code, 200)
self.assertEqual(response.data['workgroups'][0]['id'], self.test_workgroup.id)
self.assertEqual(response.data[0]['id'], self.test_workgroup.id)
def test_projects_workgroups_post_invalid_workgroup(self):
data = {
'name': self.test_project_name,
'course_id': self.test_course_id,
'content_id': self.test_course_content_id
}
response = self.do_post(self.test_projects_uri, data)
self.assertEqual(response.status_code, 201)
test_uri = '{}{}/'.format(self.test_projects_uri, str(response.data['id']))
workgroups_uri = '{}workgroups/'.format(test_uri)
test_uri = '{}{}/workgroups/'.format(self.test_projects_uri, self.test_project.id)
data = {
'id': 123456,
}
response = self.do_post(workgroups_uri, data)
response = self.do_post(test_uri, data)
self.assertEqual(response.status_code, 400)
def test_projects_detail_get_undefined(self):
......@@ -158,14 +151,7 @@ class ProjectsApiTests(TestCase):
self.assertEqual(response.status_code, 404)
def test_projects_detail_delete(self):
data = {
'name': self.test_project_name,
'course_id': self.test_course_id,
'content_id': self.test_course_content_id
}
response = self.do_post(self.test_projects_uri, data)
self.assertEqual(response.status_code, 201)
test_uri = '{}{}/'.format(self.test_projects_uri, str(response.data['id']))
test_uri = '{}{}/'.format(self.test_projects_uri, self.test_project.id)
response = self.do_get(test_uri)
self.assertEqual(response.status_code, 200)
response = self.do_delete(test_uri)
......
......@@ -12,7 +12,8 @@ from django.core.cache import cache
from django.test import TestCase, Client
from django.test.utils import override_settings
from projects.models import Project, Workgroup, Submission
from projects.models import Project, Workgroup, WorkgroupSubmission
from student.models import anonymous_id_for_user
TEST_API_KEY = str(uuid.uuid4())
......@@ -52,24 +53,23 @@ class SubmissionReviewsApiTests(TestCase):
username="testing",
is_active=True
)
self.anonymous_user_id = anonymous_id_for_user(self.test_user, self.test_course_id)
self.test_project = Project.objects.create(
course_id=self.test_course_id,
content_id=self.test_course_content_id,
)
self.test_workgroup = Workgroup.objects.create(
name="Test Workgroup",
project=self.test_project,
)
self.test_workgroup.users.add(self.test_user)
self.test_workgroup.save()
self.test_project = Project.objects.create(
course_id=self.test_course_id,
content_id=self.test_course_content_id,
)
self.test_project.workgroups.add(self.test_workgroup)
self.test_project.save()
self.test_submission = Submission.objects.create(
self.test_submission = WorkgroupSubmission.objects.create(
user=self.test_user,
workgroup=self.test_workgroup,
project=self.test_project,
document_id="Document12345.pdf",
document_url="http://test-s3.amazonaws.com/bucketname",
document_mime_type="application/pdf"
......@@ -110,7 +110,7 @@ class SubmissionReviewsApiTests(TestCase):
def test_submission_reviews_list_post(self):
data = {
'submission': self.test_submission.id,
'reviewer': self.test_user.id,
'reviewer': self.anonymous_user_id,
'question': self.test_question,
'answer': self.test_answer,
}
......@@ -124,7 +124,7 @@ class SubmissionReviewsApiTests(TestCase):
)
self.assertEqual(response.data['url'], confirm_uri)
self.assertGreater(response.data['id'], 0)
self.assertEqual(response.data['reviewer'], self.test_user.id)
self.assertEqual(response.data['reviewer'], self.anonymous_user_id)
self.assertEqual(response.data['submission'], self.test_submission.id)
self.assertEqual(response.data['question'], self.test_question)
self.assertEqual(response.data['answer'], self.test_answer)
......@@ -134,7 +134,7 @@ class SubmissionReviewsApiTests(TestCase):
def test_submission_reviews_detail_get(self):
data = {
'submission': self.test_submission.id,
'reviewer': self.test_user.id,
'reviewer': self.anonymous_user_id,
'question': self.test_question,
'answer': self.test_answer,
}
......@@ -150,7 +150,7 @@ class SubmissionReviewsApiTests(TestCase):
)
self.assertEqual(response.data['url'], confirm_uri)
self.assertGreater(response.data['id'], 0)
self.assertEqual(response.data['reviewer'], self.test_user.id)
self.assertEqual(response.data['reviewer'], self.anonymous_user_id)
self.assertEqual(response.data['submission'], self.test_submission.id)
self.assertEqual(response.data['question'], self.test_question)
self.assertEqual(response.data['answer'], self.test_answer)
......@@ -165,11 +165,12 @@ class SubmissionReviewsApiTests(TestCase):
def test_submission_reviews_detail_delete(self):
data = {
'submission': self.test_submission.id,
'reviewer': self.test_user.id,
'reviewer': self.anonymous_user_id,
'question': self.test_question,
'answer': self.test_answer,
}
response = self.do_post(self.test_submission_reviews_uri, data)
print response.data
self.assertEqual(response.status_code, 201)
test_uri = '{}{}/'.format(self.test_submission_reviews_uri, str(response.data['id']))
response = self.do_get(test_uri)
......
# pylint: disable=E1103
"""
Run these tests @ Devstack:
rake fasttest_lms[common/djangoapps/projects/tests/test_workgroup_reviews.py]
"""
import json
import uuid
from django.contrib.auth.models import User
from django.core.cache import cache
from django.test import TestCase, Client
from django.test.utils import override_settings
from projects.models import Project, Workgroup, WorkgroupSubmission
from student.models import anonymous_id_for_user
TEST_API_KEY = str(uuid.uuid4())
class SecureClient(Client):
""" Django test client using a "secure" connection. """
def __init__(self, *args, **kwargs):
kwargs = kwargs.copy()
kwargs.update({'SERVER_PORT': 443, 'wsgi.url_scheme': 'https'})
super(SecureClient, self).__init__(*args, **kwargs)
@override_settings(EDX_API_KEY=TEST_API_KEY)
class WorkgroupReviewsApiTests(TestCase):
""" Test suite for Users API views """
def setUp(self):
self.test_server_prefix = 'https://testserver'
self.test_users_uri = '/api/users/'
self.test_workgroups_uri = '/api/workgroups/'
self.test_projects_uri = '/api/projects/'
self.test_workgroup_reviews_uri = '/api/workgroup_reviews/'
self.test_course_id = 'edx/demo/course'
self.test_bogus_course_id = 'foo/bar/baz'
self.test_course_content_id = "i4x://blah"
self.test_bogus_course_content_id = "14x://foo/bar/baz"
self.test_question = "Does the question data come from the XBlock definition?"
self.test_answer = "It sure does! And so does the answer data!"
self.test_user = User.objects.create(
email="test@edx.org",
username="testing",
is_active=True
)
self.anonymous_user_id = anonymous_id_for_user(self.test_user, self.test_course_id)
self.test_project = Project.objects.create(
course_id=self.test_course_id,
content_id=self.test_course_content_id,
)
self.test_workgroup = Workgroup.objects.create(
name="Test Workgroup",
project=self.test_project,
)
self.test_workgroup.users.add(self.test_user)
self.test_workgroup.save()
self.test_submission = WorkgroupSubmission.objects.create(
user=self.test_user,
workgroup=self.test_workgroup,
document_id="Document12345.pdf",
document_url="http://test-s3.amazonaws.com/bucketname",
document_mime_type="application/pdf"
)
self.client = SecureClient()
cache.clear()
def do_post(self, uri, data):
"""Submit an HTTP POST request"""
headers = {
'X-Edx-Api-Key': str(TEST_API_KEY),
}
json_data = json.dumps(data)
response = self.client.post(
uri, headers=headers, content_type='application/json', data=json_data)
return response
def do_get(self, uri):
"""Submit an HTTP GET request"""
headers = {
'Content-Type': 'application/json',
'X-Edx-Api-Key': str(TEST_API_KEY),
}
response = self.client.get(uri, headers=headers)
return response
def do_delete(self, uri):
"""Submit an HTTP DELETE request"""
headers = {
'Content-Type': 'application/json',
'X-Edx-Api-Key': str(TEST_API_KEY),
}
response = self.client.delete(uri, headers=headers)
return response
def test_workgroup_reviews_list_post(self):
data = {
'workgroup': self.test_workgroup.id,
'reviewer': self.anonymous_user_id,
'question': self.test_question,
'answer': self.test_answer,
}
response = self.do_post(self.test_workgroup_reviews_uri, data)
self.assertEqual(response.status_code, 201)
self.assertGreater(response.data['id'], 0)
confirm_uri = '{}{}{}/'.format(
self.test_server_prefix,
self.test_workgroup_reviews_uri,
str(response.data['id'])
)
self.assertEqual(response.data['url'], confirm_uri)
self.assertGreater(response.data['id'], 0)
self.assertEqual(response.data['reviewer'], self.anonymous_user_id)
self.assertEqual(response.data['workgroup'], self.test_workgroup.id)
self.assertEqual(response.data['question'], self.test_question)
self.assertEqual(response.data['answer'], self.test_answer)
self.assertIsNotNone(response.data['created'])
self.assertIsNotNone(response.data['modified'])
def test_workgroup_reviews_detail_get(self):
data = {
'workgroup': self.test_workgroup.id,
'reviewer': self.anonymous_user_id,
'question': self.test_question,
'answer': self.test_answer,
}
response = self.do_post(self.test_workgroup_reviews_uri, data)
self.assertEqual(response.status_code, 201)
test_uri = '{}{}/'.format(self.test_workgroup_reviews_uri, str(response.data['id']))
response = self.do_get(test_uri)
self.assertEqual(response.status_code, 200)
confirm_uri = '{}{}{}/'.format(
self.test_server_prefix,
self.test_workgroup_reviews_uri,
str(response.data['id'])
)
self.assertEqual(response.data['url'], confirm_uri)
self.assertGreater(response.data['id'], 0)
self.assertEqual(response.data['reviewer'], self.anonymous_user_id)
self.assertEqual(response.data['workgroup'], self.test_workgroup.id)
self.assertEqual(response.data['question'], self.test_question)
self.assertEqual(response.data['answer'], self.test_answer)
self.assertIsNotNone(response.data['created'])
self.assertIsNotNone(response.data['modified'])
def test_workgroup_reviews_detail_get_undefined(self):
test_uri = '/api/workgroup_reviews/123456789/'
response = self.do_get(test_uri)
self.assertEqual(response.status_code, 404)
def test_workgroup_reviews_detail_delete(self):
data = {
'workgroup': self.test_workgroup.id,
'reviewer': self.anonymous_user_id,
'question': self.test_question,
'answer': self.test_answer,
}
response = self.do_post(self.test_workgroup_reviews_uri, data)
self.assertEqual(response.status_code, 201)
test_uri = '{}{}/'.format(self.test_workgroup_reviews_uri, str(response.data['id']))
response = self.do_get(test_uri)
self.assertEqual(response.status_code, 200)
response = self.do_delete(test_uri)
self.assertEqual(response.status_code, 204)
response = self.do_get(test_uri)
self.assertEqual(response.status_code, 404)
......@@ -54,19 +54,18 @@ class SubmissionsApiTests(TestCase):
is_active=True
)
self.test_project = Project.objects.create(
course_id=self.test_course_id,
content_id=self.test_course_content_id,
)
self.test_workgroup = Workgroup.objects.create(
name="Test Workgroup",
project=self.test_project,
)
self.test_workgroup.users.add(self.test_user)
self.test_workgroup.save()
self.test_project = Project.objects.create(
course_id=self.test_course_id,
content_id=self.test_course_content_id,
)
self.test_project.workgroups.add(self.test_workgroup)
self.test_project.save()
self.client = SecureClient()
cache.clear()
......@@ -102,7 +101,6 @@ class SubmissionsApiTests(TestCase):
def test_submissions_list_post(self):
submission_data = {
'user': self.test_user.id,
'project': self.test_project.id,
'workgroup': self.test_workgroup.id,
'document_id': self.test_document_id,
'document_url': self.test_document_url,
......@@ -116,32 +114,21 @@ class SubmissionsApiTests(TestCase):
self.test_submissions_uri,
str(response.data['id'])
)
self.assertEqual(response.data['url'], confirm_uri)
self.assertGreater(response.data['id'], 0)
self.assertEqual(response.data['user'], self.test_user.id)
self.assertEqual(response.data['workgroup'], self.test_workgroup.id)
self.assertEqual(response.data['project'], self.test_project.id)
self.assertEqual(response.data['document_id'], self.test_document_id)
self.assertEqual(response.data['document_url'], self.test_document_url)
self.assertEqual(response.data['document_mime_type'], self.test_document_mime_type)
self.assertIsNotNone(response.data['reviews'])
self.assertIsNotNone(response.data['created'])
self.assertIsNotNone(response.data['modified'])
def test_submissions_list_post_invalid_relationships(self):
submission_data = {
'user': 123456,
'project': self.test_project.id,
'workgroup': self.test_workgroup.id,
'document_id': self.test_document_id,
'document_url': self.test_document_url,
'document_mime_type': self.test_document_mime_type,
}
response = self.do_post(self.test_submissions_uri, submission_data)
self.assertEqual(response.status_code, 400)
submission_data = {
'user': self.test_user.id,
'project': 123456,
'workgroup': self.test_workgroup.id,
'document_id': self.test_document_id,
'document_url': self.test_document_url,
......@@ -152,7 +139,6 @@ class SubmissionsApiTests(TestCase):
submission_data = {
'user': self.test_user.id,
'project': self.test_project.id,
'workgroup': 123456,
'document_id': self.test_document_id,
'document_url': self.test_document_url,
......@@ -164,7 +150,6 @@ class SubmissionsApiTests(TestCase):
def test_submissions_detail_get(self):
submission_data = {
'user': self.test_user.id,
'project': self.test_project.id,
'workgroup': self.test_workgroup.id,
'document_id': self.test_document_id,
'document_url': self.test_document_url,
......@@ -184,10 +169,10 @@ class SubmissionsApiTests(TestCase):
self.assertGreater(response.data['id'], 0)
self.assertEqual(response.data['user'], self.test_user.id)
self.assertEqual(response.data['workgroup'], self.test_workgroup.id)
self.assertEqual(response.data['project'], self.test_project.id)
self.assertEqual(response.data['document_id'], self.test_document_id)
self.assertEqual(response.data['document_url'], self.test_document_url)
self.assertEqual(response.data['document_mime_type'], self.test_document_mime_type)
self.assertIsNotNone(response.data['reviews'])
self.assertIsNotNone(response.data['created'])
self.assertIsNotNone(response.data['modified'])
......@@ -196,10 +181,9 @@ class SubmissionsApiTests(TestCase):
response = self.do_get(test_uri)
self.assertEqual(response.status_code, 404)
def test_submnissions_detail_delete(self):
def test_submissions_detail_delete(self):
submission_data = {
'user': self.test_user.id,
'project': self.test_project.id,
'workgroup': self.test_workgroup.id,
'document_id': self.test_document_id,
'document_url': self.test_document_url,
......
......@@ -13,6 +13,7 @@ from django.test import TestCase, Client
from django.test.utils import override_settings
from api_manager.models import GroupProfile
from projects.models import Project
TEST_API_KEY = str(uuid.uuid4())
......@@ -53,6 +54,11 @@ class WorkgroupsApiTests(TestCase):
group_type="series"
)
self.test_project = Project.objects.create(
course_id=self.test_course_id,
content_id=self.test_course_content_id
)
self.test_user_email = str(uuid.uuid4())
self.test_user_username = str(uuid.uuid4())
self.test_user = User.objects.create(
......@@ -95,6 +101,7 @@ class WorkgroupsApiTests(TestCase):
def test_workgroups_list_post(self):
data = {
'name': self.test_workgroup_name,
'project': self.test_project.id
}
response = self.do_post(self.test_workgroups_uri, data)
self.assertEqual(response.status_code, 201)
......@@ -106,14 +113,20 @@ class WorkgroupsApiTests(TestCase):
)
self.assertEqual(response.data['url'], confirm_uri)
self.assertGreater(response.data['id'], 0)
self.assertEqual(response.data['name'], self.test_workgroup_name)
self.assertEqual(response.data['project'], self.test_project.id)
self.assertIsNotNone(response.data['users'])
self.assertIsNotNone(response.data['groups'])
self.assertIsNotNone(response.data['submissions'])
self.assertIsNotNone(response.data['workgroup_reviews'])
self.assertIsNotNone(response.data['peer_reviews'])
self.assertIsNotNone(response.data['created'])
self.assertIsNotNone(response.data['modified'])
def test_workgroups_detail_get(self):
data = {
'name': self.test_workgroup_name,
'project': self.test_project.id
}
response = self.do_post(self.test_workgroups_uri, data)
self.assertEqual(response.status_code, 201)
......@@ -123,14 +136,20 @@ class WorkgroupsApiTests(TestCase):
confirm_uri = self.test_server_prefix + test_uri
self.assertEqual(response.data['url'], confirm_uri)
self.assertGreater(response.data['id'], 0)
self.assertEqual(response.data['name'], self.test_workgroup_name)
self.assertEqual(response.data['project'], self.test_project.id)
self.assertIsNotNone(response.data['users'])
self.assertIsNotNone(response.data['groups'])
self.assertIsNotNone(response.data['submissions'])
self.assertIsNotNone(response.data['workgroup_reviews'])
self.assertIsNotNone(response.data['peer_reviews'])
self.assertIsNotNone(response.data['created'])
self.assertIsNotNone(response.data['modified'])
def test_workgroups_groups_post(self):
data = {
'name': self.test_workgroup_name,
'project': self.test_project.id
}
response = self.do_post(self.test_workgroups_uri, data)
self.assertEqual(response.status_code, 201)
......@@ -142,6 +161,7 @@ class WorkgroupsApiTests(TestCase):
response = self.do_get(test_uri)
self.assertEqual(response.status_code, 200)
self.assertEqual(response.data['groups'][0]['id'], self.test_group.id)
self.assertEqual(response.data['groups'][0]['name'], self.test_group.name)
test_groupnoprofile_name = str(uuid.uuid4())
test_groupnoprofile = Group.objects.create(
......@@ -155,11 +175,30 @@ class WorkgroupsApiTests(TestCase):
self.assertEqual(response.data['groups'][1]['id'], test_groupnoprofile.id)
self.assertEqual(response.data['groups'][1]['name'], test_groupnoprofile_name)
def test_workgroups_groups_get(self):
data = {
'name': self.test_workgroup_name,
'project': self.test_project.id
}
response = self.do_post(self.test_workgroups_uri, data)
self.assertEqual(response.status_code, 201)
test_uri = '{}{}/'.format(self.test_workgroups_uri, str(response.data['id']))
groups_uri = '{}groups/'.format(test_uri)
data = {"id": self.test_group.id}
response = self.do_post(groups_uri, data)
self.assertEqual(response.status_code, 201)
response = self.do_get(groups_uri)
self.assertEqual(response.status_code, 200)
self.assertEqual(response.data[0]['id'], self.test_group.id)
self.assertEqual(response.data[0]['name'], self.test_group.name)
def test_workgroups_users_post(self):
data = {
'name': self.test_workgroup_name,
'project': self.test_project.id
}
response = self.do_post(self.test_workgroups_uri, data)
print response.data
self.assertEqual(response.status_code, 201)
test_uri = '{}{}/'.format(self.test_workgroups_uri, str(response.data['id']))
users_uri = '{}users/'.format(test_uri)
......@@ -170,9 +209,54 @@ class WorkgroupsApiTests(TestCase):
self.assertEqual(response.status_code, 200)
self.assertEqual(response.data['users'][0]['id'], self.test_user.id)
def test_workgroups_users_get(self):
data = {
'name': self.test_workgroup_name,
'project': self.test_project.id
}
response = self.do_post(self.test_workgroups_uri, data)
self.assertEqual(response.status_code, 201)
test_uri = '{}{}/'.format(self.test_workgroups_uri, str(response.data['id']))
users_uri = '{}users/'.format(test_uri)
data = {"id": self.test_user.id}
response = self.do_post(users_uri, data)
self.assertEqual(response.status_code, 201)
response = self.do_get(users_uri)
self.assertEqual(response.status_code, 200)
self.assertEqual(response.data[0]['id'], self.test_user.id)
self.assertEqual(response.data[0]['username'], self.test_user.username)
self.assertEqual(response.data[0]['email'], self.test_user.email)
def test_workgroups_peer_reviews_get(self):
data = {
'name': self.test_workgroup_name,
'project': self.test_project.id
}
response = self.do_post(self.test_workgroups_uri, data)
self.assertEqual(response.status_code, 201)
workgroup_id = response.data['id']
pr_data = {
'workgroup': workgroup_id,
'user': self.test_user.id,
'reviewer': self.test_user.username,
'question': 'Test question?',
'answer': 'Test answer!'
}
response = self.do_post('/api/peer_reviews/', pr_data)
self.assertEqual(response.status_code, 201)
pr_id = response.data['id']
test_uri = '{}{}/'.format(self.test_workgroups_uri, workgroup_id)
peer_reviews_uri = '{}peer_reviews/'.format(test_uri)
response = self.do_get(peer_reviews_uri)
self.assertEqual(response.status_code, 200)
self.assertEqual(response.data[0]['id'], pr_id)
self.assertEqual(response.data[0]['reviewer'], self.test_user.username)
def test_submissions_list_post_invalid_relationships(self):
data = {
'name': self.test_workgroup_name,
'project': self.test_project.id
}
response = self.do_post(self.test_workgroups_uri, data)
self.assertEqual(response.status_code, 201)
......@@ -188,6 +272,7 @@ class WorkgroupsApiTests(TestCase):
response = self.do_post(groups_uri, data)
self.assertEqual(response.status_code, 400)
def test_workgroups_detail_get_undefined(self):
test_uri = '/api/workgroups/123456789/'
response = self.do_get(test_uri)
......@@ -196,6 +281,7 @@ class WorkgroupsApiTests(TestCase):
def test_workgroups_detail_delete(self):
data = {
'name': self.test_workgroup_name,
'project': self.test_project.id
}
response = self.do_post(self.test_workgroups_uri, data)
self.assertEqual(response.status_code, 201)
......
......@@ -6,15 +6,15 @@ from django.contrib.auth.models import Group, User
from django.core.exceptions import ObjectDoesNotExist
from rest_framework import viewsets
from rest_framework.decorators import action
from rest_framework.decorators import action, link
from rest_framework import status
from rest_framework.response import Response
from .models import Workgroup, Project, Submission
from .models import SubmissionReview, PeerReview
from .models import Project, Workgroup, WorkgroupSubmission
from .models import WorkgroupReview, WorkgroupSubmissionReview, WorkgroupPeerReview
from .serializers import UserSerializer, GroupSerializer
from .serializers import WorkgroupSerializer, ProjectSerializer, SubmissionSerializer
from .serializers import SubmissionReviewSerializer, PeerReviewSerializer
from .serializers import ProjectSerializer, WorkgroupSerializer, WorkgroupSubmissionSerializer
from .serializers import WorkgroupReviewSerializer, WorkgroupSubmissionReviewSerializer, WorkgroupPeerReviewSerializer
class GroupViewSet(viewsets.ModelViewSet):
......@@ -40,11 +40,20 @@ class WorkgroupsViewSet(viewsets.ModelViewSet):
serializer_class = WorkgroupSerializer
model = Workgroup
@action()
@action(methods=['get', 'post'])
def groups(self, request, pk):
"""
Add a Group to a Workgroup
"""
if request.method == 'GET':
groups = Group.objects.filter(workgroups=pk)
response_data = []
if groups:
for group in groups:
serializer = GroupSerializer(group)
response_data.append(serializer.data)
return Response(response_data, status=status.HTTP_200_OK)
else:
group_id = request.DATA.get('id')
try:
group = Group.objects.get(id=group_id)
......@@ -54,13 +63,23 @@ class WorkgroupsViewSet(viewsets.ModelViewSet):
workgroup = self.get_object()
workgroup.groups.add(group)
workgroup.save()
print workgroup.groups.all()
return Response({}, status=status.HTTP_201_CREATED)
@action()
@action(methods=['get', 'post'])
def users(self, request, pk):
"""
Add a User to a Workgroup
"""
if request.method == 'GET':
users = User.objects.filter(workgroups=pk)
response_data = []
if users:
for user in users:
serializer = UserSerializer(user)
response_data.append(serializer.data)
return Response(response_data, status=status.HTTP_200_OK)
else:
user_id = request.DATA.get('id')
try:
user = User.objects.get(id=user_id)
......@@ -72,6 +91,19 @@ class WorkgroupsViewSet(viewsets.ModelViewSet):
workgroup.save()
return Response({}, status=status.HTTP_201_CREATED)
@link()
def peer_reviews(self, request, pk):
"""
View Peer Reviews for a specific Workgroup
"""
peer_reviews = WorkgroupPeerReview.objects.filter(workgroup=pk)
response_data = []
if peer_reviews:
for peer_review in peer_reviews:
serializer = WorkgroupPeerReviewSerializer(peer_review)
response_data.append(serializer.data)
return Response(response_data, status=status.HTTP_200_OK)
class ProjectsViewSet(viewsets.ModelViewSet):
"""
......@@ -80,11 +112,20 @@ class ProjectsViewSet(viewsets.ModelViewSet):
serializer_class = ProjectSerializer
model = Project
@action()
@action(methods=['get', 'post'])
def workgroups(self, request, pk):
"""
Add a Workgroup to a Project
"""
if request.method == 'GET':
workgroups = Workgroup.objects.filter(project=pk)
response_data = []
if workgroups:
for workgroup in workgroups:
serializer = WorkgroupSerializer(workgroup)
response_data.append(serializer.data)
return Response(response_data, status=status.HTTP_200_OK)
else:
workgroup_id = request.DATA.get('id')
try:
workgroup = Workgroup.objects.get(id=workgroup_id)
......@@ -97,25 +138,33 @@ class ProjectsViewSet(viewsets.ModelViewSet):
return Response({}, status=status.HTTP_201_CREATED)
class SubmissionsViewSet(viewsets.ModelViewSet):
class WorkgroupSubmissionsViewSet(viewsets.ModelViewSet):
"""
Django Rest Framework ViewSet for the Submission model.
"""
serializer_class = SubmissionSerializer
model = Submission
serializer_class = WorkgroupSubmissionSerializer
model = WorkgroupSubmission
class WorkgroupReviewsViewSet(viewsets.ModelViewSet):
"""
Django Rest Framework ViewSet for the ProjectReview model.
"""
serializer_class = WorkgroupReviewSerializer
model = WorkgroupReview
class SubmissionReviewsViewSet(viewsets.ModelViewSet):
class WorkgroupSubmissionReviewsViewSet(viewsets.ModelViewSet):
"""
Django Rest Framework ViewSet for the SubmissionReview model.
"""
serializer_class = SubmissionReviewSerializer
model = SubmissionReview
serializer_class = WorkgroupSubmissionReviewSerializer
model = WorkgroupSubmissionReview
class PeerReviewsViewSet(viewsets.ModelViewSet):
class WorkgroupPeerReviewsViewSet(viewsets.ModelViewSet):
"""
Django Rest Framework ViewSet for the PeerReview model.
"""
serializer_class = PeerReviewSerializer
model = PeerReview
serializer_class = WorkgroupPeerReviewSerializer
model = WorkgroupPeerReview
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment