From 5f9e3a19c2f596f92f4d0eeae7396cf5c00f3bf8 Mon Sep 17 00:00:00 2001 From: Janine vN Date: Mon, 14 Mar 2022 14:31:38 -0400 Subject: Add new unittestsFailed public_state field New field to determine if a unittest failed and provide feedback to the user. --- src/components/Question.tsx | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/components/Question.tsx b/src/components/Question.tsx index 2914ae6..3b63f07 100644 --- a/src/components/Question.tsx +++ b/src/components/Question.tsx @@ -37,6 +37,9 @@ class RenderedQuestion extends React.Component { this.setPublicState("valid", true); this.setPublicState("error", ""); + if (props.question.type === QuestionType.Code) { + this.setPublicState("unittestsFailed", false); + } if (!skip_normal_state.includes(props.question.type)) { this.setPublicState("value", ""); @@ -155,6 +158,7 @@ class RenderedQuestion extends React.Component { } let invalid = false; + let unittest_failed = false; const options: string | string[] = this.props.question.data["options"]; switch (this.props.question.type) { case QuestionType.TextArea: @@ -163,6 +167,9 @@ class RenderedQuestion extends React.Component { if (this.props.public_state.get("value") === "") { invalid = true; } + if (this.props.public_state.get("unittestsFailed")) { + unittest_failed = true; + } break; case QuestionType.Select: @@ -189,7 +196,11 @@ class RenderedQuestion extends React.Component { if (invalid) { this.setPublicState("error", "Field must be filled."); this.setPublicState("valid", false); - } else { + } else if (unittest_failed) { + this.setPublicState("error", "1 or more unittests failed."); + this.setPublicState("valid", false); + } + else { this.setPublicState("error", ""); this.setPublicState("valid", true); } -- cgit v1.2.3 From 85fbf45e0584b157c15b096af177a2e51a486496 Mon Sep 17 00:00:00 2001 From: Janine vN Date: Mon, 14 Mar 2022 14:33:47 -0400 Subject: Add processing for POST request response We now process the POST request response, catching the error. It re-runs the code validationField() function. It currently processes it assuming there's only one failed codeblock. This will be updated later. --- src/pages/FormPage.tsx | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/pages/FormPage.tsx b/src/pages/FormPage.tsx index 082be23..c281729 100644 --- a/src/pages/FormPage.tsx +++ b/src/pages/FormPage.tsx @@ -232,6 +232,9 @@ function FormPage(): JSX.Element { const questionRef = refMap.get(question.id); if (questionRef && questionRef.current) { + if(questionRef.current.props.question.type == QuestionType.Code){ + questionRef.current.props.public_state.set("unittestsFailed", false); + } questionRef.current.validateField(); } // In case when field is invalid, add this to invalid fields list. @@ -263,7 +266,6 @@ function FormPage(): JSX.Element { return; } - setSending(true); const answers: { [key: string]: unknown } = {}; questions.forEach(prop => { @@ -297,9 +299,25 @@ function FormPage(): JSX.Element { } }); - await ApiClient.post(`forms/submit/${id}`, {response: answers}); - setSending(false); - setSent(true); + await ApiClient.post(`forms/submit/${id}`, {response: answers}) + .then(() => { + setSending(true); + setSending(false); + setSent(true); + }) + .catch(err => { + // Validation on a submitted code questions + const questionId = err.response.data.test_results[0].question_id; + + questions.forEach((prop) => { + const question: Question = prop.props.question; + const questionRef = refMap.get(question.id); + if (question.id === questionId){ + prop.props.public_state.set("unittestsFailed", true); + questionRef.current.validateField(); + } + }); + }); } return ( -- cgit v1.2.3 From 442f8d3fbd0cbc200900643e3ba882159a8dcb67 Mon Sep 17 00:00:00 2001 From: DavinderJolly <34959171+DavinderJolly@users.noreply.github.com> Date: Sat, 18 Jun 2022 03:50:49 +0530 Subject: Fix rendering error message for failed unit tests. fix rendering of error message by updating public_state prop before updating state, and only catch 422 status code in FormPage --- src/components/Question.tsx | 2 +- src/pages/FormPage.tsx | 36 +++++++++++++++++++++--------------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/components/Question.tsx b/src/components/Question.tsx index 3b63f07..ebacb4a 100644 --- a/src/components/Question.tsx +++ b/src/components/Question.tsx @@ -47,8 +47,8 @@ class RenderedQuestion extends React.Component { } setPublicState(target: string, value: string | boolean | null, callback?:() => void): void { - this.setState({[target]: value}, callback); this.props.public_state.set(target, value); + this.setState({[target]: value}, callback); } // This is here to allow dynamic selection between the general handler, textarea, and code field handlers. diff --git a/src/pages/FormPage.tsx b/src/pages/FormPage.tsx index c281729..f21e4f0 100644 --- a/src/pages/FormPage.tsx +++ b/src/pages/FormPage.tsx @@ -5,6 +5,7 @@ import { Link } from "react-router-dom"; import React, { SyntheticEvent, useEffect, useState, createRef } from "react"; import { useParams } from "react-router"; import { PropagateLoader } from "react-spinners"; +import { AxiosError } from "axios"; import HeaderBar from "../components/HeaderBar"; import RenderedQuestion from "../components/Question"; @@ -89,7 +90,7 @@ class Navigation extends React.Component { constructor(props: NavigationProps) { super(props); - this.setState({"logged_in": false}); + this.state = {"logged_in": false}; } render(): JSX.Element { @@ -298,28 +299,33 @@ function FormPage(): JSX.Element { answers[question.id] = prop.props.public_state.get("value"); } }); - - await ApiClient.post(`forms/submit/${id}`, {response: answers}) + await ApiClient.post(`forms/submit/${id}`, { response: answers }) .then(() => { setSending(true); setSending(false); setSent(true); }) - .catch(err => { - // Validation on a submitted code questions - const questionId = err.response.data.test_results[0].question_id; - - questions.forEach((prop) => { - const question: Question = prop.props.question; - const questionRef = refMap.get(question.id); - if (question.id === questionId){ - prop.props.public_state.set("unittestsFailed", true); - questionRef.current.validateField(); + .catch((err: AxiosError) => { + switch (err.response.status) { + case 422: { + // Validation on a submitted code questions + const questionId = + err.response.data.test_results[0].question_id; + questions.forEach((prop) => { + const question: Question = prop.props.question; + const questionRef = refMap.get(question.id); + if (question.id === questionId) { + prop.props.public_state.set("unittestsFailed", true); + questionRef.current.validateField(); + } + }); + break; } - }); + default: + throw err; + } }); } - return (
-- cgit v1.2.3