mirror of
https://github.com/ets-cfuhrman-pfe/EvalueTonSavoir.git
synced 2025-08-11 21:23:54 -04:00
baby steps (getting tests running)
This commit is contained in:
parent
d047c787b7
commit
8a7a444718
9 changed files with 181 additions and 194 deletions
|
|
@ -17,15 +17,19 @@ const question = questions[0];
|
||||||
|
|
||||||
describe('MultipleChoiceQuestionDisplay', () => {
|
describe('MultipleChoiceQuestionDisplay', () => {
|
||||||
const mockHandleOnSubmitAnswer = jest.fn();
|
const mockHandleOnSubmitAnswer = jest.fn();
|
||||||
|
const sampleProps = {
|
||||||
|
question: question,
|
||||||
|
handleOnSubmitAnswer: mockHandleOnSubmitAnswer,
|
||||||
|
showAnswer: false
|
||||||
|
};
|
||||||
|
|
||||||
const choices = question.choices;
|
const choices = question.choices;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
render(
|
render(
|
||||||
<MemoryRouter>
|
<MemoryRouter>
|
||||||
<MultipleChoiceQuestionDisplay
|
<MultipleChoiceQuestionDisplay
|
||||||
question={question}
|
{...sampleProps}
|
||||||
handleOnSubmitAnswer={mockHandleOnSubmitAnswer}
|
|
||||||
showAnswer={false}
|
|
||||||
/>
|
/>
|
||||||
</MemoryRouter>);
|
</MemoryRouter>);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -2,29 +2,48 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { render, screen, fireEvent } from '@testing-library/react';
|
import { render, screen, fireEvent } from '@testing-library/react';
|
||||||
import '@testing-library/jest-dom';
|
import '@testing-library/jest-dom';
|
||||||
import NumericalQuestion from 'src/components/Questions/NumericalQuestion/NumericalQuestion';
|
import NumericalQuestionDisplay from 'src/components/Questions/NumericalQuestionDisplay/NumericalQuestionDisplay';
|
||||||
|
import { NumericalQuestion, parse, ParsedGIFTQuestion } from 'gift-pegjs';
|
||||||
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
|
|
||||||
|
const questions = parse(
|
||||||
|
`
|
||||||
|
::Sample Question 1:: Question stem
|
||||||
|
{
|
||||||
|
#5..10
|
||||||
|
}`
|
||||||
|
) as ParsedGIFTQuestion[];
|
||||||
|
|
||||||
|
const question = questions[0] as NumericalQuestion;
|
||||||
|
|
||||||
|
describe('NumericalQuestion parse', () => {
|
||||||
|
const q = questions[0];
|
||||||
|
|
||||||
|
it('The question is Numerical', () => {
|
||||||
|
expect(q.type).toBe('Numerical');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('NumericalQuestion Component', () => {
|
describe('NumericalQuestion Component', () => {
|
||||||
const mockHandleSubmitAnswer = jest.fn();
|
const mockHandleOnSubmitAnswer = jest.fn();
|
||||||
const sampleStem = 'Sample question stem';
|
|
||||||
|
|
||||||
const sampleProps = {
|
const sampleProps = {
|
||||||
questionTitle: 'Sample Question',
|
question: question,
|
||||||
correctAnswers: {
|
handleOnSubmitAnswer: mockHandleOnSubmitAnswer,
|
||||||
numberHigh: 10,
|
|
||||||
numberLow: 5,
|
|
||||||
type: 'high-low'
|
|
||||||
},
|
|
||||||
handleOnSubmitAnswer: mockHandleSubmitAnswer,
|
|
||||||
showAnswer: false
|
showAnswer: false
|
||||||
};
|
};
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
render(<NumericalQuestion questionContent={{text: sampleStem, format: 'plain'}} {...sampleProps} />);
|
render(
|
||||||
|
<MemoryRouter>
|
||||||
|
<NumericalQuestionDisplay
|
||||||
|
{...sampleProps}
|
||||||
|
/>
|
||||||
|
</MemoryRouter>);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders correctly', () => {
|
it('renders correctly', () => {
|
||||||
expect(screen.getByText(sampleStem)).toBeInTheDocument();
|
expect(screen.getByText(question.formattedStem.text)).toBeInTheDocument();
|
||||||
expect(screen.getByTestId('number-input')).toBeInTheDocument();
|
expect(screen.getByTestId('number-input')).toBeInTheDocument();
|
||||||
expect(screen.getByText('Répondre')).toBeInTheDocument();
|
expect(screen.getByText('Répondre')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
@ -48,7 +67,7 @@ describe('NumericalQuestion Component', () => {
|
||||||
|
|
||||||
fireEvent.click(submitButton);
|
fireEvent.click(submitButton);
|
||||||
|
|
||||||
expect(mockHandleSubmitAnswer).not.toHaveBeenCalled();
|
expect(mockHandleOnSubmitAnswer).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('submits answer correctly', () => {
|
it('submits answer correctly', () => {
|
||||||
|
|
@ -59,6 +78,6 @@ describe('NumericalQuestion Component', () => {
|
||||||
|
|
||||||
fireEvent.click(submitButton);
|
fireEvent.click(submitButton);
|
||||||
|
|
||||||
expect(mockHandleSubmitAnswer).toHaveBeenCalledWith(7);
|
expect(mockHandleOnSubmitAnswer).toHaveBeenCalledWith(7);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -1,71 +1,40 @@
|
||||||
// Question.test.tsx
|
// Question.test.tsx
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { render, screen, fireEvent } from '@testing-library/react';
|
import { render, screen, fireEvent, within } from '@testing-library/react';
|
||||||
import '@testing-library/jest-dom';
|
import '@testing-library/jest-dom';
|
||||||
import Questions from 'src/components/Questions/QuestionDisplay';
|
import QuestionDisplay from 'src/components/Questions/QuestionDisplay';
|
||||||
import { GIFTQuestion } from 'gift-pegjs';
|
import { parse, Question } from 'gift-pegjs';
|
||||||
|
|
||||||
//
|
|
||||||
describe('Questions Component', () => {
|
describe('Questions Component', () => {
|
||||||
const mockHandleSubmitAnswer = jest.fn();
|
const mockHandleSubmitAnswer = jest.fn();
|
||||||
|
|
||||||
const sampleTrueFalseQuestion: GIFTQuestion = {
|
const sampleTrueFalseQuestion =
|
||||||
type: 'TF',
|
parse('::Sample True/False Question:: Sample True/False Question {T}')[0];
|
||||||
stem: { format: 'plain', text: 'Sample True/False Question' },
|
|
||||||
isTrue: true,
|
const sampleMultipleChoiceQuestion =
|
||||||
falseFeedback: null,
|
parse('::Sample Multiple Choice Question:: Sample Multiple Choice Question {=Choice 1 ~Choice 2}')[0];
|
||||||
trueFeedback: null,
|
|
||||||
title: 'True/False Question',
|
const sampleNumericalQuestion =
|
||||||
hasEmbeddedAnswers: false,
|
parse('::Sample Numerical Question:: Sample Numerical Question {#5..10}')[0];
|
||||||
globalFeedback: null,
|
|
||||||
|
const sampleShortAnswerQuestion =
|
||||||
|
parse('::Sample Short Answer Question:: Sample Short Answer Question {=Correct Answer =Another Answer}')[0];
|
||||||
|
|
||||||
|
const sampleProps = {
|
||||||
|
handleOnSubmitAnswer: mockHandleSubmitAnswer,
|
||||||
|
showAnswer: false
|
||||||
};
|
};
|
||||||
|
|
||||||
const sampleMultipleChoiceQuestion: GIFTQuestion = {
|
const renderComponent = (question: Question) => {
|
||||||
type: 'MC',
|
render(<QuestionDisplay question={question} {...sampleProps} />);
|
||||||
stem: { format: 'plain', text: 'Sample Multiple Choice Question' },
|
|
||||||
title: 'Multiple Choice Question',
|
|
||||||
hasEmbeddedAnswers: false,
|
|
||||||
globalFeedback: null,
|
|
||||||
choices: [
|
|
||||||
{ feedback: null, isCorrect: true, text: { format: 'plain', text: 'Choice 1' }, weight: 1 },
|
|
||||||
{ feedback: null, isCorrect: false, text: { format: 'plain', text: 'Choice 2' }, weight: 0 },
|
|
||||||
],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const sampleNumericalQuestion: GIFTQuestion = {
|
it('parsed questions correctly', () => {
|
||||||
type: 'Numerical',
|
expect(sampleTrueFalseQuestion.type).toBe('TF');
|
||||||
stem: { format: 'plain', text: 'Sample Numerical Question' },
|
expect(sampleMultipleChoiceQuestion.type).toBe('MC');
|
||||||
title: 'Numerical Question',
|
expect(sampleNumericalQuestion.type).toBe('Numerical');
|
||||||
hasEmbeddedAnswers: false,
|
expect(sampleShortAnswerQuestion.type).toBe('Short');
|
||||||
globalFeedback: null,
|
});
|
||||||
choices: { numberHigh: 10, numberLow: 5, type: 'high-low' },
|
|
||||||
};
|
|
||||||
|
|
||||||
const sampleShortAnswerQuestion: GIFTQuestion = {
|
|
||||||
type: 'Short',
|
|
||||||
stem: { format: 'plain', text: 'Sample short answer question' },
|
|
||||||
title: 'Short Answer Question Title',
|
|
||||||
hasEmbeddedAnswers: false,
|
|
||||||
globalFeedback: null,
|
|
||||||
choices: [
|
|
||||||
{
|
|
||||||
feedback: { format: 'html', text: 'Correct answer feedback' },
|
|
||||||
isCorrect: true,
|
|
||||||
text: { format: 'html', text: 'Correct Answer' },
|
|
||||||
weight: 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
feedback: { format: 'html', text: 'Incorrect answer feedback' },
|
|
||||||
isCorrect: false,
|
|
||||||
text: { format: 'html', text: 'Incorrect Answer' },
|
|
||||||
weight: 0,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
const renderComponent = (question: GIFTQuestion) => {
|
|
||||||
render(<Questions question={question} handleOnSubmitAnswer={mockHandleSubmitAnswer} />);
|
|
||||||
};
|
|
||||||
|
|
||||||
it('renders correctly for True/False question', () => {
|
it('renders correctly for True/False question', () => {
|
||||||
renderComponent(sampleTrueFalseQuestion);
|
renderComponent(sampleTrueFalseQuestion);
|
||||||
|
|
@ -120,15 +89,19 @@ describe('Questions Component', () => {
|
||||||
it('renders correctly for Short Answer question', () => {
|
it('renders correctly for Short Answer question', () => {
|
||||||
renderComponent(sampleShortAnswerQuestion);
|
renderComponent(sampleShortAnswerQuestion);
|
||||||
|
|
||||||
expect(screen.getByText('Sample short answer question')).toBeInTheDocument();
|
expect(screen.getByText('Sample Short Answer Question')).toBeInTheDocument();
|
||||||
expect(screen.getByTestId('text-input')).toBeInTheDocument();
|
const container = screen.getByLabelText('short-answer-input');
|
||||||
|
const inputElement = within(container).getByRole('textbox') as HTMLInputElement;
|
||||||
|
expect(inputElement).toBeInTheDocument();
|
||||||
expect(screen.getByText('Répondre')).toBeInTheDocument();
|
expect(screen.getByText('Répondre')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handles input and submission for Short Answer question', () => {
|
it('handles input and submission for Short Answer question', () => {
|
||||||
renderComponent(sampleShortAnswerQuestion);
|
renderComponent(sampleShortAnswerQuestion);
|
||||||
|
|
||||||
const inputElement = screen.getByTestId('text-input') as HTMLInputElement;
|
const container = screen.getByLabelText('short-answer-input');
|
||||||
|
const inputElement = within(container).getByRole('textbox') as HTMLInputElement;
|
||||||
|
|
||||||
fireEvent.change(inputElement, { target: { value: 'User Input' } });
|
fireEvent.change(inputElement, { target: { value: 'User Input' } });
|
||||||
|
|
||||||
const submitButton = screen.getByText('Répondre');
|
const submitButton = screen.getByText('Répondre');
|
||||||
|
|
|
||||||
|
|
@ -1,54 +1,35 @@
|
||||||
// ShortAnswerQuestion.test.tsx
|
// ShortAnswerQuestion.test.tsx
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { render, screen, fireEvent } from '@testing-library/react';
|
import { render, screen, fireEvent, within } from '@testing-library/react';
|
||||||
import '@testing-library/jest-dom';
|
import '@testing-library/jest-dom';
|
||||||
import ShortAnswerQuestion from 'src/components/Questions/ShortAnswerQuestion/ShortAnswerQuestion';
|
import ShortAnswerQuestionDisplay from 'src/components/Questions/ShortAnswerQuestionDisplay/ShortAnswerQuestionDisplay';
|
||||||
|
import { parse, ShortAnswerQuestion } from 'gift-pegjs';
|
||||||
|
|
||||||
describe('ShortAnswerQuestion Component', () => {
|
describe('ShortAnswerQuestion Component', () => {
|
||||||
const mockHandleSubmitAnswer = jest.fn();
|
const mockHandleSubmitAnswer = jest.fn();
|
||||||
const sampleStem = 'Sample question stem';
|
const question =
|
||||||
|
parse('::Sample Short Answer Question:: Sample Short Answer Question {=Correct Answer ~Incorrect Answer}')[0] as ShortAnswerQuestion;
|
||||||
|
|
||||||
const sampleProps = {
|
const sampleProps = {
|
||||||
questionTitle: 'Sample Question',
|
|
||||||
choices: [
|
|
||||||
{
|
|
||||||
id: '1',
|
|
||||||
feedback: {
|
|
||||||
format: 'text',
|
|
||||||
text: 'Correct answer feedback'
|
|
||||||
},
|
|
||||||
isCorrect: true,
|
|
||||||
text: {
|
|
||||||
format: 'text',
|
|
||||||
text: 'Correct Answer'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '2',
|
|
||||||
feedback: null,
|
|
||||||
isCorrect: false,
|
|
||||||
text: {
|
|
||||||
format: 'text',
|
|
||||||
text: 'Incorrect Answer'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
handleOnSubmitAnswer: mockHandleSubmitAnswer,
|
handleOnSubmitAnswer: mockHandleSubmitAnswer,
|
||||||
showAnswer: false
|
showAnswer: false
|
||||||
};
|
};
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
render(<ShortAnswerQuestion questionContent={{text: sampleStem, format: 'plain'}} {...sampleProps} />);
|
render(<ShortAnswerQuestionDisplay question={question} {...sampleProps} />);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders correctly', () => {
|
it('renders correctly', () => {
|
||||||
expect(screen.getByText(sampleStem)).toBeInTheDocument();
|
expect(screen.getByText(question.formattedStem.text)).toBeInTheDocument();
|
||||||
expect(screen.getByTestId('text-input')).toBeInTheDocument();
|
const container = screen.getByLabelText('short-answer-input');
|
||||||
|
const inputElement = within(container).getByRole('textbox') as HTMLInputElement;
|
||||||
|
expect(inputElement).toBeInTheDocument();
|
||||||
expect(screen.getByText('Répondre')).toBeInTheDocument();
|
expect(screen.getByText('Répondre')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handles input change correctly', () => {
|
it('handles input change correctly', () => {
|
||||||
const inputElement = screen.getByTestId('text-input') as HTMLInputElement;
|
const container = screen.getByLabelText('short-answer-input');
|
||||||
|
const inputElement = within(container).getByRole('textbox') as HTMLInputElement;
|
||||||
|
|
||||||
fireEvent.change(inputElement, { target: { value: 'User Input' } });
|
fireEvent.change(inputElement, { target: { value: 'User Input' } });
|
||||||
|
|
||||||
|
|
@ -70,7 +51,10 @@ describe('ShortAnswerQuestion Component', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('submits answer correctly', () => {
|
it('submits answer correctly', () => {
|
||||||
const inputElement = screen.getByTestId('text-input') as HTMLInputElement;
|
const container = screen.getByLabelText('short-answer-input');
|
||||||
|
const inputElement = within(container).getByRole('textbox') as HTMLInputElement;
|
||||||
|
|
||||||
|
// const inputElement = screen.getByRole('textbox', { name: 'short-answer-input'}) as HTMLInputElement;
|
||||||
const submitButton = screen.getByText('Répondre');
|
const submitButton = screen.getByText('Répondre');
|
||||||
|
|
||||||
fireEvent.change(inputElement, { target: { value: 'User Input' } });
|
fireEvent.change(inputElement, { target: { value: 'User Input' } });
|
||||||
|
|
|
||||||
30
client/src/__tests__/smoke-test.test.ts
Normal file
30
client/src/__tests__/smoke-test.test.ts
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
import { parse, NumericalQuestion, SimpleNumericalAnswer, } from "gift-pegjs";
|
||||||
|
import { isSimpleNumericalAnswer } from "gift-pegjs/typeGuards";
|
||||||
|
|
||||||
|
describe('Numerical Question Tests', () => {
|
||||||
|
// ::Ulysses birthdate::When was Ulysses S. Grant born? {#1822}
|
||||||
|
it('should produce a valid Question object for a Numerical question with Title', () => {
|
||||||
|
const input = `
|
||||||
|
::Ulysses birthdate::When was Ulysses S. Grant born? {#1822}
|
||||||
|
`;
|
||||||
|
const result = parse(input);
|
||||||
|
|
||||||
|
// Type assertion to ensure result matches the Question interface
|
||||||
|
const question = result[0];
|
||||||
|
|
||||||
|
// Example assertions to check specific properties
|
||||||
|
expect(question).toHaveProperty('type', 'Numerical');
|
||||||
|
const numericalQuestion = question as NumericalQuestion;
|
||||||
|
expect(numericalQuestion.title).toBe('Ulysses birthdate');
|
||||||
|
expect(numericalQuestion.formattedStem.text).toBe('When was Ulysses S. Grant born?');
|
||||||
|
expect(numericalQuestion.choices).toBeDefined();
|
||||||
|
expect(numericalQuestion.choices).toHaveLength(1);
|
||||||
|
|
||||||
|
const choice = numericalQuestion.choices[0];
|
||||||
|
expect(isSimpleNumericalAnswer(choice)).toBe(true);
|
||||||
|
const c = choice as SimpleNumericalAnswer;
|
||||||
|
expect(c.type).toBe('simple');
|
||||||
|
expect(c.number).toBe(1822);
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -3,71 +3,70 @@ import React, { useState } from 'react';
|
||||||
import '../questionStyle.css';
|
import '../questionStyle.css';
|
||||||
import { Button, TextField } from '@mui/material';
|
import { Button, TextField } from '@mui/material';
|
||||||
import { textType } from '../../GiftTemplate/templates/TextType';
|
import { textType } from '../../GiftTemplate/templates/TextType';
|
||||||
import { TextFormat, NumericalAnswer, isHighLowNumericalAnswer, isMultipleNumericalAnswer, isRangeNumericalAnswer, isSimpleNumericalAnswer, SimpleNumericalAnswer, RangeNumericalAnswer, HighLowNumericalAnswer } from 'gift-pegjs';
|
import { NumericalQuestion, SimpleNumericalAnswer, RangeNumericalAnswer, HighLowNumericalAnswer } from 'gift-pegjs';
|
||||||
|
import { isSimpleNumericalAnswer, isRangeNumericalAnswer, isHighLowNumericalAnswer, isMultipleNumericalAnswer } from 'gift-pegjs/typeGuards';
|
||||||
import DOMPurify from 'dompurify';
|
import DOMPurify from 'dompurify';
|
||||||
|
|
||||||
// type CorrectAnswer = {
|
|
||||||
// numberHigh?: number;
|
|
||||||
// numberLow?: number;
|
|
||||||
// number?: number;
|
|
||||||
// type: string;
|
|
||||||
// };
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
questionContent: TextFormat;
|
question: NumericalQuestion;
|
||||||
correctAnswers: NumericalAnswer;
|
|
||||||
globalFeedback?: string | undefined;
|
|
||||||
handleOnSubmitAnswer?: (answer: number) => void;
|
handleOnSubmitAnswer?: (answer: number) => void;
|
||||||
showAnswer?: boolean;
|
showAnswer?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const NumericalQuestion: React.FC<Props> = (props) => {
|
const NumericalQuestionDisplay: React.FC<Props> = (props) => {
|
||||||
const { questionContent, correctAnswers, showAnswer, handleOnSubmitAnswer, globalFeedback } =
|
const { question, showAnswer, handleOnSubmitAnswer } =
|
||||||
props;
|
props;
|
||||||
|
|
||||||
const [answer, setAnswer] = useState<number>();
|
const [answer, setAnswer] = useState<number>();
|
||||||
|
|
||||||
let correctAnswer= '';
|
const correctAnswers = question.choices;
|
||||||
|
let correctAnswer = '';
|
||||||
|
|
||||||
if (isSimpleNumericalAnswer(correctAnswers)) {
|
//const isSingleAnswer = correctAnswers.length === 1;
|
||||||
correctAnswer = `${(correctAnswers as SimpleNumericalAnswer).number}`;
|
|
||||||
} else if (isRangeNumericalAnswer(correctAnswers)) {
|
if (isSimpleNumericalAnswer(correctAnswers[0])) {
|
||||||
const choice = correctAnswers as RangeNumericalAnswer;
|
correctAnswer = `${(correctAnswers[0] as SimpleNumericalAnswer).number}`;
|
||||||
|
} else if (isRangeNumericalAnswer(correctAnswers[0])) {
|
||||||
|
const choice = correctAnswers[0] as RangeNumericalAnswer;
|
||||||
correctAnswer = `Entre ${choice.number - choice.range} et ${choice.number + choice.range}`;
|
correctAnswer = `Entre ${choice.number - choice.range} et ${choice.number + choice.range}`;
|
||||||
} else if (isHighLowNumericalAnswer(correctAnswers)) {
|
} else if (isHighLowNumericalAnswer(correctAnswers[0])) {
|
||||||
const choice = correctAnswers as HighLowNumericalAnswer;
|
const choice = correctAnswers[0] as HighLowNumericalAnswer;
|
||||||
correctAnswer = `Entre ${choice.numberLow} et ${choice.numberHigh}`;
|
correctAnswer = `Entre ${choice.numberLow} et ${choice.numberHigh}`;
|
||||||
} else if (isMultipleNumericalAnswer(correctAnswers)) {
|
} else if (isMultipleNumericalAnswer(correctAnswers[0])) {
|
||||||
correctAnswer = `MultipleNumericalAnswer is not supported yet`;
|
correctAnswer = `MultipleNumericalAnswer is not supported yet`;
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Unknown numerical answer type');
|
throw new Error('Unknown numerical answer type');
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="question-wrapper">
|
<div className="question-wrapper">
|
||||||
<div>
|
<div>
|
||||||
<div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(textType({text: questionContent})) }} />
|
<div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(textType({ text: question.formattedStem })) }} />
|
||||||
</div>
|
</div>
|
||||||
{showAnswer ? (
|
{showAnswer ? (
|
||||||
<>
|
<>
|
||||||
<div className="correct-answer-text mb-2">{correctAnswer}</div>
|
<div className="correct-answer-text mb-2">{correctAnswer}</div>
|
||||||
{globalFeedback && <div className="global-feedback mb-2">{globalFeedback}</div>}
|
{question.formattedGlobalFeedback && <div className="global-feedback mb-2">
|
||||||
|
<div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(textType({ text: question.formattedGlobalFeedback })) }} />
|
||||||
|
</div>}
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<div className="answer-wrapper mb-1">
|
<div className="answer-wrapper mb-1">
|
||||||
<TextField
|
<TextField
|
||||||
type="number"
|
type="number"
|
||||||
id={questionContent.text}
|
id={question.formattedStem.text}
|
||||||
name={questionContent.text}
|
name={question.formattedStem.text}
|
||||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
setAnswer(e.target.valueAsNumber);
|
setAnswer(e.target.valueAsNumber);
|
||||||
}}
|
}}
|
||||||
inputProps={{ 'data-testid': 'number-input' }}
|
inputProps={{ 'data-testid': 'number-input' }}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{globalFeedback && showAnswer && (
|
{question.formattedGlobalFeedback && showAnswer && (
|
||||||
<div className="global-feedback mb-2">{globalFeedback}</div>
|
<div className="global-feedback mb-2">
|
||||||
|
<div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(textType({ text: question.formattedGlobalFeedback })) }} />
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
{handleOnSubmitAnswer && (
|
{handleOnSubmitAnswer && (
|
||||||
<Button
|
<Button
|
||||||
|
|
@ -88,4 +87,4 @@ const NumericalQuestion: React.FC<Props> = (props) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default NumericalQuestion;
|
export default NumericalQuestionDisplay;
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
// Question;tsx
|
// Question;tsx
|
||||||
import React, { useMemo } from 'react';
|
import React from 'react';
|
||||||
import { Question } from 'gift-pegjs';
|
import { Question } from 'gift-pegjs';
|
||||||
|
|
||||||
import TrueFalseQuestion from './TrueFalseQuestion/TrueFalseQuestion';
|
import TrueFalseQuestion from './TrueFalseQuestion/TrueFalseQuestion';
|
||||||
import MultipleChoiceQuestionDisplay from './MultipleChoiceQuestionDisplay/MultipleChoiceQuestionDisplay';
|
import MultipleChoiceQuestionDisplay from './MultipleChoiceQuestionDisplay/MultipleChoiceQuestionDisplay';
|
||||||
import NumericalQuestion from './NumericalQuestion/NumericalQuestion';
|
import NumericalQuestionDisplay from './NumericalQuestionDisplay/NumericalQuestionDisplay';
|
||||||
import ShortAnswerQuestion from './ShortAnswerQuestion/ShortAnswerQuestion';
|
import ShortAnswerQuestionDisplay from './ShortAnswerQuestionDisplay/ShortAnswerQuestionDisplay';
|
||||||
import useCheckMobileScreen from '../../services/useCheckMobileScreen';
|
// import useCheckMobileScreen from '../../services/useCheckMobileScreen';
|
||||||
|
|
||||||
interface QuestionProps {
|
interface QuestionProps {
|
||||||
question: Question;
|
question: Question;
|
||||||
|
|
@ -18,10 +18,10 @@ const QuestionDisplay: React.FC<QuestionProps> = ({
|
||||||
handleOnSubmitAnswer,
|
handleOnSubmitAnswer,
|
||||||
showAnswer,
|
showAnswer,
|
||||||
}) => {
|
}) => {
|
||||||
const isMobile = useCheckMobileScreen();
|
// const isMobile = useCheckMobileScreen();
|
||||||
const imgWidth = useMemo(() => {
|
// const imgWidth = useMemo(() => {
|
||||||
return isMobile ? '100%' : '20%';
|
// return isMobile ? '100%' : '20%';
|
||||||
}, [isMobile]);
|
// }, [isMobile]);
|
||||||
|
|
||||||
let questionTypeComponent = null;
|
let questionTypeComponent = null;
|
||||||
switch (question?.type) {
|
switch (question?.type) {
|
||||||
|
|
@ -49,22 +49,18 @@ const QuestionDisplay: React.FC<QuestionProps> = ({
|
||||||
if (question.choices) {
|
if (question.choices) {
|
||||||
if (!Array.isArray(question.choices)) {
|
if (!Array.isArray(question.choices)) {
|
||||||
questionTypeComponent = (
|
questionTypeComponent = (
|
||||||
<NumericalQuestion
|
<NumericalQuestionDisplay
|
||||||
questionContent={question.formattedStem}
|
question={question}
|
||||||
correctAnswers={question.choices}
|
|
||||||
handleOnSubmitAnswer={handleOnSubmitAnswer}
|
handleOnSubmitAnswer={handleOnSubmitAnswer}
|
||||||
showAnswer={showAnswer}
|
showAnswer={showAnswer}
|
||||||
globalFeedback={question.formattedGlobalFeedback?.text}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
questionTypeComponent = ( // TODO fix NumericalQuestion (correctAnswers is borked)
|
questionTypeComponent = ( // TODO fix NumericalQuestion (correctAnswers is borked)
|
||||||
<NumericalQuestion
|
<NumericalQuestionDisplay
|
||||||
questionContent={question.formattedStem}
|
question={question}
|
||||||
correctAnswers={question.choices}
|
|
||||||
handleOnSubmitAnswer={handleOnSubmitAnswer}
|
handleOnSubmitAnswer={handleOnSubmitAnswer}
|
||||||
showAnswer={showAnswer}
|
showAnswer={showAnswer}
|
||||||
globalFeedback={question.formattedGlobalFeedback?.text}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -72,12 +68,10 @@ const QuestionDisplay: React.FC<QuestionProps> = ({
|
||||||
break;
|
break;
|
||||||
case 'Short':
|
case 'Short':
|
||||||
questionTypeComponent = (
|
questionTypeComponent = (
|
||||||
<ShortAnswerQuestion
|
<ShortAnswerQuestionDisplay
|
||||||
questionContent={question.formattedStem}
|
question={question}
|
||||||
choices={question.choices.map((choice, index) => ({ ...choice, id: index.toString() }))}
|
|
||||||
handleOnSubmitAnswer={handleOnSubmitAnswer}
|
handleOnSubmitAnswer={handleOnSubmitAnswer}
|
||||||
showAnswer={showAnswer}
|
showAnswer={showAnswer}
|
||||||
globalFeedback={question.formattedGlobalFeedback?.text}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
@ -86,13 +80,6 @@ const QuestionDisplay: React.FC<QuestionProps> = ({
|
||||||
<div className="question-container">
|
<div className="question-container">
|
||||||
{questionTypeComponent ? (
|
{questionTypeComponent ? (
|
||||||
<>
|
<>
|
||||||
{imageUrl && (
|
|
||||||
<img
|
|
||||||
src={imageUrl}
|
|
||||||
alt="QuestionImage"
|
|
||||||
style={{ width: imgWidth, marginBottom: '2rem' }}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{questionTypeComponent}
|
{questionTypeComponent}
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
|
|
|
||||||
|
|
@ -1,59 +1,50 @@
|
||||||
// ShortAnswerQuestion.tsx
|
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import '../questionStyle.css';
|
import '../questionStyle.css';
|
||||||
import { Button, TextField } from '@mui/material';
|
import { Button, TextField } from '@mui/material';
|
||||||
import textType from '../../GiftTemplate/templates/TextType';
|
import { textType } from '../../GiftTemplate/templates/TextType';
|
||||||
import { TextFormat } from '../../GiftTemplate/templates/types';
|
import { ShortAnswerQuestion } from 'gift-pegjs';
|
||||||
import DOMPurify from 'dompurify';
|
import DOMPurify from 'dompurify';
|
||||||
|
|
||||||
type Choices = {
|
|
||||||
feedback: { format: string; text: string } | null;
|
|
||||||
isCorrect: boolean;
|
|
||||||
text: { format: string; text: string };
|
|
||||||
weigth?: number;
|
|
||||||
id: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
questionContent: TextFormat;
|
question: ShortAnswerQuestion;
|
||||||
choices: Choices[];
|
|
||||||
globalFeedback?: string | undefined;
|
|
||||||
handleOnSubmitAnswer?: (answer: string) => void;
|
handleOnSubmitAnswer?: (answer: string) => void;
|
||||||
showAnswer?: boolean;
|
showAnswer?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ShortAnswerQuestion: React.FC<Props> = (props) => {
|
const ShortAnswerQuestionDisplay: React.FC<Props> = (props) => {
|
||||||
const { questionContent, choices, showAnswer, handleOnSubmitAnswer, globalFeedback } = props;
|
const { question, showAnswer, handleOnSubmitAnswer } = props;
|
||||||
const [answer, setAnswer] = useState<string>();
|
const [answer, setAnswer] = useState<string>();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="question-wrapper">
|
<div className="question-wrapper">
|
||||||
<div className="question content">
|
<div className="question content">
|
||||||
<div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(textType({text: questionContent})) }} />
|
<div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(textType({text: question.formattedStem})) }} />
|
||||||
</div>
|
</div>
|
||||||
{showAnswer ? (
|
{showAnswer ? (
|
||||||
<>
|
<>
|
||||||
<div className="correct-answer-text mb-1">
|
<div className="correct-answer-text mb-1">
|
||||||
{choices.map((choice) => (
|
{question.choices.map((choice) => (
|
||||||
<div key={choice.id} className="mb-1">
|
<div key={choice.text} className="mb-1">
|
||||||
{choice.text.text}
|
{choice.text}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
{globalFeedback && <div className="global-feedback mb-2">{globalFeedback}</div>}
|
{question.formattedGlobalFeedback && <div className="global-feedback mb-2">
|
||||||
|
<div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(textType({text: question.formattedGlobalFeedback})) }} />
|
||||||
|
</div>}
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<div className="answer-wrapper mb-1">
|
<div className="answer-wrapper mb-1">
|
||||||
<TextField
|
<TextField
|
||||||
type="text"
|
type="text"
|
||||||
id={questionContent.text}
|
id={question.formattedStem.text}
|
||||||
name={questionContent.text}
|
name={question.formattedStem.text}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setAnswer(e.target.value);
|
setAnswer(e.target.value);
|
||||||
}}
|
}}
|
||||||
disabled={showAnswer}
|
disabled={showAnswer}
|
||||||
inputProps={{ 'data-testid': 'text-input' }}
|
aria-label="short-answer-input"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{handleOnSubmitAnswer && (
|
{handleOnSubmitAnswer && (
|
||||||
|
|
@ -75,4 +66,4 @@ const ShortAnswerQuestion: React.FC<Props> = (props) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ShortAnswerQuestion;
|
export default ShortAnswerQuestionDisplay;
|
||||||
|
|
@ -2,8 +2,8 @@
|
||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import '../questionStyle.css';
|
import '../questionStyle.css';
|
||||||
import { Button } from '@mui/material';
|
import { Button } from '@mui/material';
|
||||||
import textType from '../../GiftTemplate/templates/TextType';
|
import { textType } from '../../GiftTemplate/templates/TextType';
|
||||||
import { TextFormat } from '../../GiftTemplate/templates/types';
|
import { TextFormat } from 'gift-pegjs';
|
||||||
import DOMPurify from 'dompurify';
|
import DOMPurify from 'dompurify';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue