Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[XI-6385] Change the set of questions the user can start the quiz with #83

Merged
merged 4 commits into from
May 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified docs/assets/quiz-recap-intro.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
78 changes: 59 additions & 19 deletions src/App.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { render, screen } from '@testing-library/react';
import userEvent, { UserEvent } from '@testing-library/user-event';
import { within } from '@testing-library/dom';
import App from './App';
import { testData as data, testDataWithFourQuestions } from './static/data';
import { testData as data } from './static/data';
import { translationsProvider } from './util';

const answerQuestionCorrectly = async (user: UserEvent) => {
Expand Down Expand Up @@ -114,16 +114,16 @@ describe('App component', () => {
expect(result).toBeInTheDocument();
});

it('shows the result page after answering a quick set of questions', async () => {
it('shows the result page after answering all questions', async () => {
const user = userEvent.setup();
render(<App data={testDataWithFourQuestions}></App>, {
const testDataWith1Question = data.slice(0, 1);
render(<App data={testDataWith1Question}></App>, {
wrapper: translationsProvider,
});

const button = screen.getByText(/Quick set/i);
const button = screen.getByText(/Complete set/i);
await user.click(button);

// Quick set only contains one question
// We conduct the quiz with exactly one question
// To test if the App respects the number of questions
const numberOfQuestions = 1;
Expand Down Expand Up @@ -194,16 +194,57 @@ describe('App component', () => {
});
});

describe('quiz sets', () => {
it('has 4 available sets when the quiz has more than 50 questions', () => {
const testDataWith52Questions = data.flatMap((item) =>
Array(13).fill(item),
);
render(<App data={testDataWith52Questions}></App>, {
wrapper: translationsProvider,
});

const completeSet = screen.getByRole('button', {
name: /Complete set/i,
});
const largeSet = screen.getByRole('button', { name: /Large set/i });
const mediumSet = screen.getByRole('button', { name: /Medium set/i });
const quickSet = screen.getByRole('button', { name: /Quick set/i });
expect(completeSet).toBeInTheDocument();
expect(largeSet).toBeInTheDocument();
expect(mediumSet).toBeInTheDocument();
expect(quickSet).toBeInTheDocument();
});

it('does not show any set with more questions than the complete one', () => {
const testDataWith16Questions = data.flatMap((item) =>
Array(4).fill(item),
);
render(<App data={testDataWith16Questions}></App>, {
wrapper: translationsProvider,
});

const completeSet = screen.getByRole('button', {
name: /Complete set/i,
});
const largeSet = screen.queryByRole('button', { name: /Large set/i });
const mediumSet = screen.queryByRole('button', { name: /Medium set/i });
const quickSet = screen.getByRole('button', { name: /Quick set/i });
expect(completeSet).toBeInTheDocument();
expect(largeSet).not.toBeInTheDocument();
expect(mediumSet).not.toBeInTheDocument();
expect(quickSet).toBeInTheDocument();
});
});

describe('multiple attempts feature', () => {
it('shows a wrongly answered question again up to 3 times', async () => {
const user = userEvent.setup();

render(<App data={testDataWithFourQuestions}></App>, {
const testDataWith1Question = data.slice(0, 1);
render(<App data={testDataWith1Question}></App>, {
wrapper: translationsProvider,
});

// A quick set of a test with four questions contains 1 question
const button = screen.getByText(/Quick set/i);
const button = screen.getByText(/Complete set/i);
await user.click(button);

// Answer wrongly 3 times
Expand All @@ -219,14 +260,14 @@ describe('App component', () => {

it('shows the attempts needed for each question', async () => {
const user = userEvent.setup();
render(<App data={testDataWithFourQuestions}></App>, {
const testDataWith2Questions = data.slice(0, 2);
render(<App data={testDataWith2Questions}></App>, {
wrapper: translationsProvider,
});

const button = screen.getByText(/Medium set/i);
const button = screen.getByText(/Complete set/i);
await user.click(button);

// A medium set of a test with four questions contains 2 questions
let indexTextEl = screen.getByText('1 of 2');
expect(indexTextEl).toBeInTheDocument();

Expand Down Expand Up @@ -268,14 +309,14 @@ describe('App component', () => {

it('displays the quiz progress', async () => {
const user = userEvent.setup();
render(<App data={testDataWithFourQuestions}></App>, {
const testDataWith2Questions = data.slice(0, 2);
render(<App data={testDataWith2Questions}></App>, {
wrapper: translationsProvider,
});

const button = screen.getByText(/Medium set/i);
const button = screen.getByText(/Complete set/i);
await user.click(button);

// A medium set of a test with four questions contains 2 questions
let indexTextEl = screen.getByText('1 of 2');

for (let i = 0; i < 5; i++) {
christophblessing marked this conversation as resolved.
Show resolved Hide resolved
Expand All @@ -292,13 +333,12 @@ describe('App component', () => {

it('displays the remaining attempts after wrongly answering a question', async () => {
const user = userEvent.setup();

render(<App data={testDataWithFourQuestions}></App>, {
const testDataWith1Question = data.slice(0, 1);
render(<App data={testDataWith1Question}></App>, {
wrapper: translationsProvider,
});

// A quick set of a test with four questions contains 1 question
const button = screen.getByText(/Quick set/i);
const button = screen.getByText(/Complete set/i);
await user.click(button);

for (let i = 0; i < 2; i++) {
Expand Down
55 changes: 31 additions & 24 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,28 @@ function App({ data, locale = 'en' }: { data: Data; locale?: string }) {
setQuestions(getRandomSet(data, questionsCount));
};

const completeSet = data.length;
const mediumSet = Math.ceil(completeSet / 2);
const quickSet = Math.ceil(completeSet / 5);
const completeSet = {
text: t('app.completeBtn', { count: data.length }),
count: data.length,
};
const largeSet = {
text: t('app.largeBtn', { count: 50 }),
count: 50,
};
const mediumSet = {
text: t('app.mediumBtn', { count: 20 }),
count: 20,
};
const quickSet = {
text: t('app.quickBtn', { count: 10 }),
count: 10,
};

const fixedSets = [quickSet, mediumSet, largeSet].filter(
(set) => set.count < completeSet.count,
);

const buttons = [...fixedSets, completeSet];

return (
<Context.Provider
Expand Down Expand Up @@ -60,27 +79,15 @@ function App({ data, locale = 'en' }: { data: Data; locale?: string }) {
<p className={styles.p}>{t('app.intro')}</p>
<p className={styles.p}>{t('app.instructions')}</p>
<ul className={styles.ul}>
<li className={styles.li}>
<Button
text={t('app.completeBtn', { count: completeSet })}
onClickAction={() => startQuiz(completeSet)}
additionalClasses={styles.button}
/>
</li>
<li className={styles.li}>
<Button
text={t('app.mediumBtn', { count: mediumSet })}
onClickAction={() => startQuiz(mediumSet)}
additionalClasses={styles.button}
/>
</li>
<li className={styles.li}>
<Button
text={t('app.quickBtn', { count: quickSet })}
onClickAction={() => startQuiz(quickSet)}
additionalClasses={styles.button}
/>
</li>
{buttons.map((button, i) => (
<li className={styles.li} key={i}>
<Button
text={button.text}
onClickAction={() => startQuiz(button.count)}
additionalClasses={styles.button}
/>
</li>
))}
</ul>
</>
)}
Expand Down
2 changes: 2 additions & 0 deletions src/locales/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ const de = {
instructions: 'Wählen Sie die Anzahl der Fragen aus die Sie üben möchten:',
completeBtn_one: 'Komplettes Set ({{count}} Frage)',
completeBtn_other: 'Komplettes Set (alle {{count}} Fragen)',
largeBtn_one: 'Großes Set ({{count}} Frage)',
largeBtn_other: 'Großes Set ({{count}} Fragen)',
mediumBtn_one: 'Mittleres Set ({{count}} Frage)',
mediumBtn_other: 'Mittleres Set ({{count}} Fragen)',
quickBtn_one: 'Schnelles Set ({{count}} Frage)',
Expand Down
2 changes: 2 additions & 0 deletions src/locales/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ const en = {
'Choose a quiz type below depending on how many questions you want to practice.',
completeBtn_one: 'Complete set ({{count}} question)',
completeBtn_other: 'Complete set ({{count}} questions)',
largeBtn_one: 'Large set ({{count}} question)',
largeBtn_other: 'Large set ({{count}} questions)',
mediumBtn_one: 'Medium set ({{count}} question)',
mediumBtn_other: 'Medium set ({{count}} questions)',
quickBtn_one: 'Quick set ({{count}} question)',
Expand Down
105 changes: 3 additions & 102 deletions src/static/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,103 +192,6 @@ export const testData: Data = [
type: QuestionTypes.SingleChoice,
text: 'What is the answer?',
referenceLink: 'https://www.example.com',
courseId: 'courseId-01',
quizId: 'quizId-01',
answers: [
{
id: 'answer_01',
correct: true,
text: 'Correct Answer',
},
{
id: 'answer_02',
correct: false,
text: 'Answer 2',
},
],
},
{
id: 'id-02',
type: QuestionTypes.SingleChoice,
text: 'What is the answer?',
courseId: 'courseId-01',
quizId: 'quizId-02',
answers: [
{
id: 'answer_03',
correct: true,
text: 'Correct Answer',
},
{
id: 'answer_04',
correct: false,
text: 'Answer 4',
},
],
},
{
id: 'id-03',
type: QuestionTypes.MultipleChoice,
text: 'What is the answer?',
answers: [
{
id: 'answer_05',
correct: true,
text: 'Correct Answer',
},
{
id: 'answer_06',
correct: false,
text: 'Answer 6',
},
{
id: 'answer_07',
correct: true,
text: 'Correct Answer',
},
{
id: 'answer_08',
correct: false,
text: 'Answer 8',
},
],
},
{
id: 'id-04',
type: QuestionTypes.MultipleChoice,
text: 'What is the answer?',
answers: [
{
id: 'answer_09',
correct: false,
text: 'Answer 9',
},
{
id: 'answer_10',
correct: false,
text: 'Answer 10',
},
{
id: 'answer_11',
correct: false,
text: 'Answer 11',
},
{
id: 'answer_12',
correct: false,
text: 'Answer 12',
},
],
},
] as Data;

export const testDataWithFourQuestions: Data = [
{
id: 'id-01',
type: QuestionTypes.SingleChoice,
text: 'Q1: What is the answer?',
courseId: 'courseId-01',
quizId: 'quizId-01',
answers: [
{
id: 'answer_01',
Expand All @@ -305,9 +208,7 @@ export const testDataWithFourQuestions: Data = [
{
id: 'id-02',
type: QuestionTypes.SingleChoice,
text: 'Q2: What is the answer?',
courseId: 'courseId-01',
quizId: 'quizId-02',
text: 'What is the answer?',
answers: [
{
id: 'answer_03',
Expand All @@ -324,7 +225,7 @@ export const testDataWithFourQuestions: Data = [
{
id: 'id-03',
type: QuestionTypes.MultipleChoice,
text: 'Q3: What is the answer?',
text: 'What is the answer?',
answers: [
{
id: 'answer_05',
Expand All @@ -351,7 +252,7 @@ export const testDataWithFourQuestions: Data = [
{
id: 'id-04',
type: QuestionTypes.MultipleChoice,
text: 'Q4: What is the answer?',
text: 'What is the answer?',
answers: [
{
id: 'answer_09',
Expand Down