diff --git a/client/src/components/ui/ItRadioGroup.vue b/client/src/components/ui/ItRadioGroup.vue index 734fd3c1..2c52116c 100644 --- a/client/src/components/ui/ItRadioGroup.vue +++ b/client/src/components/ui/ItRadioGroup.vue @@ -15,6 +15,7 @@ as="template" class="flex-1" :value="item.value" + :data-cy="`radio-${item.value}`" >
{{ description }}
diff --git a/cypress/e2e/feedback/feedbackStudent.cy.js b/cypress/e2e/feedback/feedbackStudent.cy.js new file mode 100644 index 00000000..134a0990 --- /dev/null +++ b/cypress/e2e/feedback/feedbackStudent.cy.js @@ -0,0 +1,127 @@ +import { TEST_STUDENT1_USER_ID } from "../../consts"; +import { login } from "../helpers"; + +describe("assignmentStudent.cy.js", () => { + beforeEach(() => { + cy.manageCommand("cypress_reset"); + login("test-student1@example.com", "test"); + cy.visit("/course/test-lehrgang/learn/fahrzeug/feedback"); + }); + + it("can open feedback page", () => { + cy.testLearningContentTitle("Wie zufrieden bist du?"); + cy.testLearningContentSubtitle("Feedback"); + }); + + it.only("can create feedback by giving answers to all steps", () => { + cy.get('[data-cy="next-step"]').click({ force: true }); + + // fill feedback form + // step 1 + cy.url().should("include", "step=1"); + cy.get('[data-cy="next-step"]').should("be.disabled"); + cy.get('[data-cy="radio-4"]').click(); + cy.get('[data-cy="next-step"]').click({ force: true }); + + // the system should store after every step -> check stored data + cy.loadFeedbackResponse("feedback_user_id", TEST_STUDENT1_USER_ID).then( + (ac) => { + expect(ac.submitted).to.be.false; + expect(ac.data.satisfaction).to.equal(4); + expect(ac.data.instructor_competence).to.equal(null); + } + ); + + // step 2 + cy.url().should("include", "step=2"); + cy.get('[data-cy="next-step"]').should("be.disabled"); + cy.get('[data-cy="radio-3"]').click(); + cy.get('[data-cy="next-step"]').click({ force: true }); + + // step 3 + cy.url().should("include", "step=3"); + cy.get('[data-cy="next-step"]').should("be.disabled"); + cy.get('[data-cy="radio-80"]').click(); + cy.get('[data-cy="next-step"]').click({ force: true }); + + // step 4 + cy.url().should("include", "step=4"); + cy.get('[data-cy="next-step"]').should("be.disabled"); + cy.get('[data-cy="radio-false"]').click(); + cy.get('[data-cy="next-step"]').click({ force: true }); + + // step 5 + cy.url().should("include", "step=5"); + cy.get('[data-cy="next-step"]').should("be.disabled"); + cy.get('[data-cy="radio-2"]').click(); + cy.get('[data-cy="next-step"]').click({ force: true }); + + // step 6 + cy.url().should("include", "step=6"); + cy.get('[data-cy="next-step"]').should("be.disabled"); + cy.get('[data-cy="radio-1"]').click(); + cy.get('[data-cy="next-step"]').click({ force: true }); + + // step 7 + cy.url().should("include", "step=7"); + cy.get('[data-cy="next-step"]').should("be.disabled"); + cy.get('[data-cy="it-textarea-instructor_open_feedback"]').type( + "Der Kursleiter ist eigentlich ganz nett." + ); + cy.get('[data-cy="next-step"]').click({ force: true }); + + // step 8 + cy.url().should("include", "step=8"); + cy.get('[data-cy="next-step"]').should("be.disabled"); + cy.get('[data-cy="radio-true"]').click(); + cy.get('[data-cy="next-step"]').click({ force: true }); + + // step 9 + cy.url().should("include", "step=9"); + cy.get('[data-cy="next-step"]').should("be.disabled"); + cy.get('[data-cy="it-textarea-course_negative_feedback"]').type( + "Ich bin unzufrieden mit einigen Sachen." + ); + cy.get('[data-cy="next-step"]').click({ force: true }); + + // step 10 + cy.url().should("include", "step=10"); + cy.get('[data-cy="next-step"]').should("be.disabled"); + cy.get('[data-cy="it-textarea-course_positive_feedback"]').type( + "Ich bin zufrieden mit den meisten Dingen." + ); + cy.get('[data-cy="next-step"]').click({ force: true }); + + cy.url().should("include", "step=11"); + cy.get('[data-cy="sendFeedbackButton"]').click(); + cy.get('[data-cy="complete-and-continue"]').click({ force: true }); + + // marked complete in circle + cy.get( + '[data-cy="test-lehrgang-lp-circle-fahrzeug-lc-feedback-checkbox"]' + ).should("have.class", "cy-checked"); + + // reopening page should get directly to last step + cy.reload(); + cy.visit("/course/test-lehrgang/learn/fahrzeug/feedback"); + + // check stored data + cy.loadFeedbackResponse("feedback_user_id", TEST_STUDENT1_USER_ID).then( + (ac) => { + expect(ac.submitted).to.be.true; + expect(ac.data).to.deep.equal({ + course_negative_feedback: "Ich bin unzufrieden mit einigen Sachen.", + course_positive_feedback: "Ich bin zufrieden mit den meisten Dingen.", + goal_attainment: 3, + instructor_competence: 2, + instructor_open_feedback: "Der Kursleiter ist eigentlich ganz nett.", + instructor_respect: 1, + preparation_task_clarity: false, + proficiency: 80, + satisfaction: 4, + would_recommend: true, + }); + } + ); + }); +}); diff --git a/cypress/support/commands.js b/cypress/support/commands.js index fde5a99c..e66cc567 100644 --- a/cypress/support/commands.js +++ b/cypress/support/commands.js @@ -120,6 +120,7 @@ function loadObjectJson( `.replace(/(?:\r\n|\r|\n)/g, ""); return cy.manageShellCommand(command).then((result) => { const objectJson = JSON.parse(result.stdout); + // console.log(command); console.log(objectJson); return objectJson; }); @@ -135,6 +136,16 @@ Cypress.Commands.add("loadAssignmentCompletion", (key, value) => { ); }); +Cypress.Commands.add("loadFeedbackResponse", (key, value) => { + return loadObjectJson( + key, + value, + "vbv_lernwelt.feedback.models.FeedbackResponse", + "vbv_lernwelt.feedback.serializers.CypressFeedbackResponseSerializer", + true + ); +}); + Cypress.Commands.add("makeSelfEvaluation", (answers) => { for (let i = 0; i < answers.length; i++) { const answer = answers[i]; diff --git a/server/vbv_lernwelt/core/management/commands/cypress_reset.py b/server/vbv_lernwelt/core/management/commands/cypress_reset.py index 0d498e8b..8580d942 100644 --- a/server/vbv_lernwelt/core/management/commands/cypress_reset.py +++ b/server/vbv_lernwelt/core/management/commands/cypress_reset.py @@ -13,6 +13,7 @@ from vbv_lernwelt.course.creators.test_course import ( create_test_assignment_submitted_data, ) from vbv_lernwelt.course.models import CourseCompletion, CourseSession +from vbv_lernwelt.feedback.models import FeedbackResponse from vbv_lernwelt.notify.models import Notification @@ -41,6 +42,7 @@ def command( CourseCompletion.objects.all().delete() Notification.objects.all().delete() AssignmentCompletion.objects.all().delete() + FeedbackResponse.objects.all().delete() User.objects.all().update(language="de") User.objects.all().update(additional_json_data={}) diff --git a/server/vbv_lernwelt/feedback/serializers.py b/server/vbv_lernwelt/feedback/serializers.py index 7fc8a92c..bfa9c8a1 100644 --- a/server/vbv_lernwelt/feedback/serializers.py +++ b/server/vbv_lernwelt/feedback/serializers.py @@ -1,6 +1,8 @@ import structlog from rest_framework import serializers +from vbv_lernwelt.feedback.models import FeedbackResponse + logger = structlog.get_logger(__name__) @@ -29,3 +31,9 @@ class CourseFeedbackSerializer(serializers.Serializer): course_negative_feedback = serializers.CharField( required=False, allow_null=True, allow_blank=True ) + + +class CypressFeedbackResponseSerializer(serializers.ModelSerializer): + class Meta: + model = FeedbackResponse + fields = "__all__"