Add tests for read only assignments

This commit is contained in:
Ramon Wenger 2021-07-01 16:58:56 +02:00
parent 9ea9b9be1b
commit e4bb4cc9ee
9 changed files with 137 additions and 5 deletions

View File

@ -1,11 +1,11 @@
export default { export default {
UUID: () => '123-456-789', UUID: () => '123-456-789',
GenericStreamFieldType: () => 'GenericStreamFieldType', GenericStreamFieldType: () => ({type: 'text_block', value: 'Generic Stream Field Type'}),
DateTime: () => '2021-01-01Z10:01:23', DateTime: () => '2021-01-01Z10:01:23',
SnapshotNode: () => ({ SnapshotNode: () => ({
// id: ID! // id: ID!
// module: ModuleNode! // module: ModuleNode!
chapters: [], chapters: [],
// chapters: [SnapshotChapterNode] // chapters: [SnapshotChapterNode]
// hiddenContentBlocks(offset: Int, before: String, after: String, first: Int, last: Int, slug: String, title: String): ContentBlockNodeConnection! // hiddenContentBlocks(offset: Int, before: String, after: String, first: Int, last: Int, slug: String, title: String): ContentBlockNodeConnection!
// created: DateTime! // created: DateTime!
@ -13,13 +13,31 @@ export default {
// shared: Boolean! // shared: Boolean!
// objectiveGroups: [SnapshotObjectiveGroupNode] // objectiveGroups: [SnapshotObjectiveGroupNode]
// hiddenObjectives(offset: Int, before: String, after: String, first: Int, last: Int, text: String): ObjectiveNodeConnection! // hiddenObjectives(offset: Int, before: String, after: String, first: Int, last: Int, text: String): ObjectiveNodeConnection!
title: 'MockSnapshotTitle', title: 'MockSnapshotTitle',
metaTitle: 'MockSnapshotMetaTitle' metaTitle: 'MockSnapshotMetaTitle',
// heroImage: String // heroImage: String
// changes: SnapshotChangesNode // changes: SnapshotChangesNode
// mine: Boolean // mine: Boolean
}), }),
ChapterNode: () => ({
slug: 'chapter-slug',
id: 'chapter-id',
title: 'chapter-title',
description: 'chapter-description',
}),
ContentBlockNode: () => ({ ContentBlockNode: () => ({
contents: [], contents: [],
title: 'content-block-title',
slug: 'content-block-slug',
userCreated: false,
type: '',
id: 'content-block-id',
}),
AssignmentNode: () => ({
id: 'assignment-id',
title: 'Assignment Title',
assignment: 'Assignment Text',
solution: 'Assignment Solution',
}), }),
}; };

View File

@ -0,0 +1,8 @@
describe('Assignment feedback read-only - Teacher', () => {
it('can not edit', () => {
cy.get('.not-implemented');
});
it('can not share', () => {
cy.get('.not-implemented');
});
});

View File

@ -0,0 +1,82 @@
import mocks from '../../fixtures/mocks';
import minimalModule from '../../fixtures/module.minimal';
const module = {
...minimalModule,
chapters: [
{
contentBlocks: [
{
type: 'task',
contents: [
{
type: 'text_block',
value: {
text: 'hallo velo',
},
id: 'bla-123',
},
{
type: 'assignment',
value: {
title: 'assignment-title',
assignment: 'assignment-assignment',
id: 'some-assignment',
},
id: '123-456',
},
],
},
],
},
],
};
const myText = 'submission text';
const operations = {
MeQuery: {
me: {
onboardingVisited: true,
},
},
ModuleDetailsQuery: {
module,
},
AssignmentQuery: {
assignment: {
submission: {
text: myText,
final: false,
document: '',
submissionFeedback: null
},
},
},
};
describe('Assignments read-only - Student', () => {
beforeEach(() => {
cy.fakeLogin('rahel.cueni', 'test');
cy.server();
cy.task('getSchema').then(schema => {
cy.mockGraphql({
schema,
mocks,
operations,
});
});
});
it('can not edit', () => {
cy.visit('module/module-with-assignment');
cy.get('.submission-form__textarea').invoke('val').should('contain', myText);
cy.getByDataCy('submission-form-submit').should('not.exist');
});
it('can not turn in', () => {
cy.get('.not-implemented');
});
});

View File

@ -16,6 +16,7 @@
v-if="!final"> v-if="!final">
<button <button
class="submission-form-container__submit button button--primary button--white-bg" class="submission-form-container__submit button button--primary button--white-bg"
data-cy="submission-form-submit"
@click="$emit('turnIn')" @click="$emit('turnIn')"
>{{ action }} >{{ action }}
</button> </button>

View File

@ -9,6 +9,7 @@ fragment UserParts on PrivateUserNode {
lastName lastName
avatarUrl avatarUrl
expiryDate expiryDate
readOnly
lastModule { lastModule {
id id
slug slug

View File

@ -0,0 +1,15 @@
from core.tests.base_test import SkillboxTestCase
class AssignmentReadOnlyTestCase(SkillboxTestCase):
def test_edit_assignment_fails(self):
raise NotImplementedError()
def test_share_assignment_fails(self):
raise NotImplementedError()
def test_edit_feedback_fails(self):
raise NotImplementedError()
def test_share_feedback_fails(self):
raise NotImplementedError()

View File

@ -788,6 +788,7 @@ type PrivateUserNode implements Node {
isTeacher: Boolean isTeacher: Boolean
oldClasses(offset: Int, before: String, after: String, first: Int, last: Int, name: String): SchoolClassNodeConnection oldClasses(offset: Int, before: String, after: String, first: Int, last: Int, name: String): SchoolClassNodeConnection
recentModules(offset: Int, before: String, after: String, first: Int, last: Int, recentModules: [ID], orderBy: String): ModuleNodeConnection recentModules(offset: Int, before: String, after: String, first: Int, last: Int, recentModules: [ID], orderBy: String): ModuleNodeConnection
readOnly: Boolean
} }
type PrivateUserNodeConnection { type PrivateUserNodeConnection {

View File

@ -7,6 +7,7 @@ from django.contrib.auth import get_user_model
from django.contrib.auth.models import AbstractUser, Permission from django.contrib.auth.models import AbstractUser, Permission
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
from django.db import models from django.db import models
from django.utils.functional import cached_property
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from core.hep_client import HepClient, MYSKILLBOX_LICENSES from core.hep_client import HepClient, MYSKILLBOX_LICENSES
@ -114,6 +115,10 @@ class User(AbstractUser):
def full_name(self): def full_name(self):
return self.get_full_name() return self.get_full_name()
@cached_property
def read_only(self):
return True
class Meta: class Meta:
ordering = ['pk', ] ordering = ['pk', ]

View File

@ -88,7 +88,7 @@ class PrivateUserNode(DjangoObjectType):
filter_fields = ['username', 'email'] filter_fields = ['username', 'email']
only_fields = ['username', 'email', 'first_name', 'last_name', 'school_classes', 'last_module', only_fields = ['username', 'email', 'first_name', 'last_name', 'school_classes', 'last_module',
'last_topic', 'avatar_url', 'last_topic', 'avatar_url',
'selected_class', 'expiry_date', 'onboarding_visited', 'team'] 'selected_class', 'expiry_date', 'onboarding_visited', 'team', 'read_only']
interfaces = (relay.Node,) interfaces = (relay.Node,)
pk = graphene.Int() pk = graphene.Int()
@ -99,6 +99,7 @@ class PrivateUserNode(DjangoObjectType):
old_classes = DjangoFilterConnectionField(SchoolClassNode) old_classes = DjangoFilterConnectionField(SchoolClassNode)
recent_modules = DjangoFilterConnectionField(ModuleNode, filterset_class=RecentModuleFilter) recent_modules = DjangoFilterConnectionField(ModuleNode, filterset_class=RecentModuleFilter)
team = graphene.Field(TeamNode) team = graphene.Field(TeamNode)
read_only = graphene.Boolean()
def resolve_pk(self, info, **kwargs): def resolve_pk(self, info, **kwargs):
return self.id return self.id